This patch adds ASM macros for saving, restoring and checking
the KUAP state, and modifies setup_32 to call them on exceptions
from kernel.

The macros are defined as empty by default for when CONFIG_PPC_KUAP
is not selected and/or for platforms which don't handle (yet) KUAP.

Signed-off-by: Christophe Leroy <christophe.le...@c-s.fr>
---
 arch/powerpc/include/asm/kup.h         | 15 ++++++++++++++-
 arch/powerpc/kernel/entry_32.S         | 16 ++++++++++++----
 arch/powerpc/platforms/Kconfig.cputype |  2 +-
 3 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h
index 082f50ad41a7..51a55be70cbc 100644
--- a/arch/powerpc/include/asm/kup.h
+++ b/arch/powerpc/include/asm/kup.h
@@ -6,7 +6,20 @@
 #include <asm/book3s/64/kup-radix.h>
 #endif
 
-#ifndef __ASSEMBLY__
+#ifdef __ASSEMBLY__
+#ifndef CONFIG_PPC_KUAP
+.macro kuap_save_and_lock      sp, thread, gpr1, gpr2, gpr3
+.endm
+
+.macro kuap_restore    sp, current, gpr1, gpr2, gpr3
+.endm
+
+.macro kuap_check      current, gpr
+.endm
+
+#endif
+
+#else /* !__ASSEMBLY__ */
 
 #include <asm/pgtable.h>
 
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index b61cfd29c76f..7b7752d6ab2f 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -36,6 +36,7 @@
 #include <asm/asm-405.h>
 #include <asm/feature-fixups.h>
 #include <asm/barrier.h>
+#include <asm/kup.h>
 
 /*
  * MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE.
@@ -150,8 +151,8 @@ transfer_to_handler:
        stw     r12,_CTR(r11)
        stw     r2,_XER(r11)
        mfspr   r12,SPRN_SPRG_THREAD
-       addi    r2,r12,-THREAD
        beq     2f                      /* if from user, fix up THREAD.regs */
+       addi    r2, r12, -THREAD
        addi    r11,r1,STACK_FRAME_OVERHEAD
        stw     r11,PT_REGS(r12)
 #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
@@ -186,6 +187,8 @@ transfer_to_handler:
 2:     /* if from kernel, check interrupted DOZE/NAP mode and
          * check for stack overflow
          */
+       kuap_save_and_lock r11, r12, r9, r2, r0
+       addi    r2, r12, -THREAD
        lwz     r9,KSP_LIMIT(r12)
        cmplw   r1,r9                   /* if r1 <= ksp_limit */
        ble-    stack_ovf               /* then the kernel stack overflowed */
@@ -272,6 +275,7 @@ reenable_mmu:                               /* re-enable 
mmu so we can */
        lwz     r9,_MSR(r11)            /* if sleeping, clear MSR.EE */
        rlwinm  r9,r9,0,~MSR_EE
        lwz     r12,_LINK(r11)          /* and return to address in LR */
+       kuap_restore r11, r2, r3, r4, r5
        b       fast_exception_return
 #endif
 
@@ -428,6 +432,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
        ACCOUNT_CPU_USER_EXIT(r2, r5, r7)
 3:
 #endif
+       kuap_check r2, r4
        lwz     r4,_LINK(r1)
        lwz     r5,_CCR(r1)
        mtlr    r4
@@ -678,6 +683,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPE)
        stw     r10,_CCR(r1)
        stw     r1,KSP(r3)      /* Set old stack pointer */
 
+       kuap_check r2, r4
 #ifdef CONFIG_SMP
        /* We need a sync somewhere here to make sure that if the
         * previous task gets rescheduled on another CPU, it sees all
@@ -866,12 +872,12 @@ resume_kernel:
        /* check current_thread_info->preempt_count */
        lwz     r0,TI_PREEMPT(r2)
        cmpwi   0,r0,0          /* if non-zero, just restore regs and return */
-       bne     restore
+       bne     restore_kuap
        andi.   r8,r8,_TIF_NEED_RESCHED
-       beq+    restore
+       beq+    restore_kuap
        lwz     r3,_MSR(r1)
        andi.   r0,r3,MSR_EE    /* interrupts off? */
-       beq     restore         /* don't schedule if so */
+       beq     restore_kuap    /* don't schedule if so */
 #ifdef CONFIG_TRACE_IRQFLAGS
        /* Lockdep thinks irqs are enabled, we need to call
         * preempt_schedule_irq with IRQs off, so we inform lockdep
@@ -890,6 +896,8 @@ resume_kernel:
        bl      trace_hardirqs_on
 #endif
 #endif /* CONFIG_PREEMPT */
+restore_kuap:
+       kuap_restore r1, r2, r9, r10, r0
 
        /* interrupts are hard-disabled at this point */
 restore:
diff --git a/arch/powerpc/platforms/Kconfig.cputype 
b/arch/powerpc/platforms/Kconfig.cputype
index 08966e3127bb..00fa0d110dcb 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -374,7 +374,7 @@ config PPC_KUAP
 
 config PPC_KUAP_DEBUG
        bool "Extra debugging for Kernel Userspace Access Protection"
-       depends on PPC_HAVE_KUAP && PPC_RADIX_MMU
+       depends on PPC_HAVE_KUAP && (PPC_RADIX_MMU || PPC_32)
        help
          Add extra debugging for Kernel Userspace Access Protection (KUAP)
          If you're unsure, say N.
-- 
2.13.3

Reply via email to