Re: [PATCH 02/20] MIPS: Clear [MSA]FPE CSR.Cause after notify_die()

2015-04-07 Thread Maciej W. Rozycki
On Wed, 11 Mar 2015, James Hogan wrote:

 When handling floating point exceptions (FPEs) and MSA FPEs the Cause
 bits of the appropriate control and status register (FCSR for FPEs and
 MSACSR for MSA FPEs) are read and cleared before enabling interrupts,
 presumably so that it doesn't have to go through the pain of restoring
 those bits if the process is pre-empted, since writing those bits would
 cause another immediate exception while still in the kernel.

 Another reason is MIPS I processors (and for the record I believe the 
R6000 MIPS II implementation as well) signal FPA exceptions using an 
ordinary interrupt, seen on one of the IP[7:2] bits in the CP0 Cause 
register.  Consequently reenabling interrupts without first clearing at 
least all the unmasked FCSR.Cause bits would retrigger the interrupt and 
cause an infinite loop.

 We don't ever mask the FPA interrupt with the relevant IM[7:2] bit in the 
CP0 Status register, because for simplicity we reuse the whole of the FPE 
exception handling path for FPA interrupts as well.  Except that we enter 
it via the `handle_fpe_int' alternative entry point rather than the usual 
`handle_fpe' one, bypassing the register save sequence as it was already 
done by the interrupt handler.

  Maciej
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 02/20] MIPS: Clear [MSA]FPE CSR.Cause after notify_die()

2015-03-23 Thread Ralf Baechle
On Wed, Mar 11, 2015 at 02:44:38PM +, James Hogan wrote:

Acked-by: Ralf Baechle r...@linux-mips.org

Feel free to merge this through the KVM tree along with the remainder of
the series.

  Ralf
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/20] MIPS: Clear [MSA]FPE CSR.Cause after notify_die()

2015-03-11 Thread James Hogan
When handling floating point exceptions (FPEs) and MSA FPEs the Cause
bits of the appropriate control and status register (FCSR for FPEs and
MSACSR for MSA FPEs) are read and cleared before enabling interrupts,
presumably so that it doesn't have to go through the pain of restoring
those bits if the process is pre-empted, since writing those bits would
cause another immediate exception while still in the kernel.

The bits aren't normally ever restored again, since userland never
expects to see them set.

However for virtualisation it is necessary for the kernel to be able to
restore these Cause bits, as the guest may have been interrupted in an
FP exception handler but before it could read the Cause bits. This can
be done by registering a die notifier, to get notified of the exception
when such a value is restored, and if the PC was at the instruction
which is used to restore the guest state, the handler can step over it
and continue execution. The Cause bits can then remain set without
causing further exceptions.

For this to work safely a few changes are made:
- __build_clear_fpe and __build_clear_msa_fpe no longer clear the Cause
  bits, and now return from exception level with interrupts disabled
  instead of enabled.
- do_fpe() now clears the Cause bits and enables interrupts after
  notify_die() is called, so that the notifier can chose to return from
  exception without this happening.
- do_msa_fpe() acts similarly, but now actually makes use of the second
  argument (msacsr) and calls notify_die() with the new DIE_MSAFP,
  allowing die notifiers to be informed of MSA FPEs too.

Signed-off-by: James Hogan james.ho...@imgtec.com
Cc: Ralf Baechle r...@linux-mips.org
Cc: Paul Burton paul.bur...@imgtec.com
Cc: Paolo Bonzini pbonz...@redhat.com
Cc: Gleb Natapov g...@kernel.org
Cc: linux-m...@linux-mips.org
Cc: kvm@vger.kernel.org
---
 arch/mips/include/asm/kdebug.h |  3 ++-
 arch/mips/kernel/genex.S   | 14 --
 arch/mips/kernel/traps.c   | 16 +++-
 3 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/arch/mips/include/asm/kdebug.h b/arch/mips/include/asm/kdebug.h
index 6a9af5fcb5d7..cba22ab7ad4d 100644
--- a/arch/mips/include/asm/kdebug.h
+++ b/arch/mips/include/asm/kdebug.h
@@ -10,7 +10,8 @@ enum die_val {
DIE_RI,
DIE_PAGE_FAULT,
DIE_BREAK,
-   DIE_SSTEPBP
+   DIE_SSTEPBP,
+   DIE_MSAFP
 };
 
 #endif /* _ASM_MIPS_KDEBUG_H */
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 86e22422d08c..af42e7003f12 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -360,21 +360,15 @@ NESTED(nmi_handler, PT_SIZE, sp)
.setmips1
SET_HARDFLOAT
cfc1a1, fcr31
-   li  a2, ~(0x3f  12)
-   and a2, a1
-   ctc1a2, fcr31
.setpop
-   TRACE_IRQS_ON
-   STI
+   CLI
+   TRACE_IRQS_OFF
.endm
 
.macro  __build_clear_msa_fpe
_cfcmsa a1, MSA_CSR
-   li  a2, ~(0x3f  12)
-   and a1, a1, a2
-   _ctcmsa MSA_CSR, a1
-   TRACE_IRQS_ON
-   STI
+   CLI
+   TRACE_IRQS_OFF
.endm
 
.macro  __build_clear_ade
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 8943ebe4d154..5b4d711f878d 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -788,6 +788,11 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long 
fcr31)
if (notify_die(DIE_FP, FP exception, regs, 0, regs_to_trapnr(regs),
   SIGFPE) == NOTIFY_STOP)
goto out;
+
+   /* Clear FCSR.Cause before enabling interrupts */
+   write_32bit_cp1_register(CP1_STATUS, fcr31  ~FPU_CSR_ALL_X);
+   local_irq_enable();
+
die_if_kernel(FP exception in kernel code, regs);
 
if (fcr31  FPU_CSR_UNI_X) {
@@ -1393,13 +1398,22 @@ out:
exception_exit(prev_state);
 }
 
-asmlinkage void do_msa_fpe(struct pt_regs *regs)
+asmlinkage void do_msa_fpe(struct pt_regs *regs, unsigned int msacsr)
 {
enum ctx_state prev_state;
 
prev_state = exception_enter();
+   if (notify_die(DIE_MSAFP, MSA FP exception, regs, 0,
+  regs_to_trapnr(regs), SIGFPE) == NOTIFY_STOP)
+   goto out;
+
+   /* Clear MSACSR.Cause before enabling interrupts */
+   write_msa_csr(msacsr  ~MSA_CSR_CAUSEF);
+   local_irq_enable();
+
die_if_kernel(do_msa_fpe invoked from kernel context!, regs);
force_sig(SIGFPE, current);
+out:
exception_exit(prev_state);
 }
 
-- 
2.0.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html