summaryrefslogtreecommitdiff
path: root/arch/mips/kernel/genex.S
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2014-12-02 13:44:13 +0000
committerJames Hogan <james.hogan@imgtec.com>2015-03-27 21:25:06 +0000
commit64bedffe496820dbb6b53302d80dd0f04db33d8e (patch)
tree06182951bfbd45ccc884708b2e760194920dc4cd /arch/mips/kernel/genex.S
parent98119ad53376885819d93dfb8737b6a9a61ca0ba (diff)
MIPS: Clear [MSA]FPE CSR.Cause after notify_die()
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.hogan@imgtec.com> Acked-by: Ralf Baechle <ralf@linux-mips.org> Cc: Paul Burton <paul.burton@imgtec.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Gleb Natapov <gleb@kernel.org> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org
Diffstat (limited to 'arch/mips/kernel/genex.S')
-rw-r--r--arch/mips/kernel/genex.S14
1 files changed, 4 insertions, 10 deletions
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)
.set mips1
SET_HARDFLOAT
cfc1 a1, fcr31
- li a2, ~(0x3f << 12)
- and a2, a1
- ctc1 a2, fcr31
.set pop
- 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