powerpc: Fix denormalized exception handler
authorPaul Mackerras <paulus@samba.org>
Mon, 12 Aug 2013 06:12:06 +0000 (16:12 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 14 Aug 2013 05:00:09 +0000 (15:00 +1000)
The denormalized exception handler (denorm_exception_hv) has a couple
of bugs.  If the CONFIG_PPC_DENORMALISATION option is not selected,
or the HSRR1_DENORM bit is not set in HSRR1, we don't test whether the
interrupt occurred within a KVM guest.  On the other hand, if the
HSRR1_DENORM bit is set and CONFIG_PPC_DENORMALISATION is enabled,
we corrupt the CFAR and PPR.

To correct these problems, this replaces the open-coded version of
EXCEPTION_PROLOG_1 that is there currently, and that is missing the
saving of PPR and CFAR values to the PACA, with an instance of
EXCEPTION_PROLOG_1.  This adds an explicit KVMTEST after testing
whether the exception is one we can handle, and adds code to restore
the CFAR on exit.

Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/kernel/exceptions-64s.S

index 4e00d22..2e00b26 100644 (file)
@@ -367,11 +367,7 @@ denorm_exception_hv:
        HMT_MEDIUM_PPR_DISCARD
        mtspr   SPRN_SPRG_HSCRATCH0,r13
        EXCEPTION_PROLOG_0(PACA_EXGEN)
-       std     r11,PACA_EXGEN+EX_R11(r13)
-       std     r12,PACA_EXGEN+EX_R12(r13)
-       mfspr   r9,SPRN_SPRG_HSCRATCH0
-       std     r9,PACA_EXGEN+EX_R13(r13)
-       mfcr    r9
+       EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0x1500)
 
 #ifdef CONFIG_PPC_DENORMALISATION
        mfspr   r10,SPRN_HSRR1
@@ -381,6 +377,7 @@ denorm_exception_hv:
        bne+    denorm_assist
 #endif
 
+       KVMTEST(0x1500)
        EXCEPTION_PROLOG_PSERIES_1(denorm_common, EXC_HV)
        KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x1500)
 
@@ -501,6 +498,10 @@ denorm_done:
        mtcrf   0x80,r9
        ld      r9,PACA_EXGEN+EX_R9(r13)
        RESTORE_PPR_PACA(PACA_EXGEN, r10)
+BEGIN_FTR_SECTION
+       ld      r10,PACA_EXGEN+EX_CFAR(r13)
+       mtspr   SPRN_CFAR,r10
+END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
        ld      r10,PACA_EXGEN+EX_R10(r13)
        ld      r11,PACA_EXGEN+EX_R11(r13)
        ld      r12,PACA_EXGEN+EX_R12(r13)