]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
powerpc/64s: Dedicated system reset interrupt stack
authorNicholas Piggin <npiggin@gmail.com>
Mon, 19 Dec 2016 18:30:06 +0000 (04:30 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 28 Apr 2017 11:02:25 +0000 (21:02 +1000)
The system reset interrupt is used for crash/debug situations, so it is
desirable to have as little impact on the normal state of the system as
possible.

Currently it uses the current kernel stack to process the exception.
This stores into the stack which may be involved with the crash. The
stack pointer may be corrupted, or it may have overflowed.

Avoid or minimise these problems by creating a dedicated NMI stack for
the system reset interrupt to use.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/paca.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/setup_64.c
arch/powerpc/xmon/xmon.c

index 59134ebd7d495c17237e91e154a306e8fb5efc1e..38c5c0b33af992ce9d48018b96c4bd44ddbd902d 100644 (file)
@@ -563,6 +563,19 @@ END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
        bl      hdlr;                                           \
        b       ret
 
+/*
+ * Exception where stack is already set in r1, r1 is saved in r10, and it
+ * continues rather than returns.
+ */
+#define EXCEPTION_COMMON_NORET_STACK(area, trap, label, hdlr, additions) \
+       EXCEPTION_PROLOG_COMMON_1();                            \
+       EXCEPTION_PROLOG_COMMON_2(area);                        \
+       EXCEPTION_PROLOG_COMMON_3(trap);                        \
+       /* Volatile regs are potentially clobbered here */      \
+       additions;                                              \
+       addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
+       bl      hdlr
+
 #define STD_EXCEPTION_COMMON(trap, label, hdlr)                        \
        EXCEPTION_COMMON(PACA_EXGEN, trap, label, hdlr,         \
                ret_from_except, ADD_NVGPRS;ADD_RECONCILE)
index b1197c1affacd153d7c99a0286e498fb31fae229..1c09f8fe2ee88a44d5d26c2bc30d363387d6176c 100644 (file)
@@ -185,7 +185,8 @@ struct paca_struct {
        u64 exmc[13];           /* used for machine checks */
 #endif
 #ifdef CONFIG_PPC_BOOK3S_64
-       /* Exclusive emergency stack pointer for machine check exception. */
+       /* Exclusive stacks for system reset and machine check exception. */
+       void *nmi_emergency_sp;
        void *mc_emergency_sp;
 
        u16 in_nmi;                     /* In nmi handler */
index 1466e96d36cff6fdf3c1ea38bc6d5e83c190e181..439c257dec4a3542380030ec5368521db801fbd5 100644 (file)
@@ -234,6 +234,7 @@ int main(void)
        OFFSET(PACAEMERGSP, paca_struct, emergency_sp);
 #ifdef CONFIG_PPC_BOOK3S_64
        OFFSET(PACAMCEMERGSP, paca_struct, mc_emergency_sp);
+       OFFSET(PACA_NMI_EMERG_SP, paca_struct, nmi_emergency_sp);
        OFFSET(PACA_IN_MCE, paca_struct, in_mce);
        OFFSET(PACA_IN_NMI, paca_struct, in_nmi);
 #endif
index 4be62568fbc27b5700bc694679ab22fa1a2f5f11..3840a77002853fe41b8b02ccf97c9bc326d30d3d 100644 (file)
@@ -144,10 +144,12 @@ EXC_COMMON_BEGIN(system_reset_common)
        li      r10,MSR_RI
        mtmsrd  r10,1
 
-       EXCEPTION_COMMON(PACA_EXNMI, 0x100,
-                       system_reset, system_reset_exception, 1f,
+       mr      r10,r1
+       ld      r1,PACA_NMI_EMERG_SP(r13)
+       subi    r1,r1,INT_FRAME_SIZE
+       EXCEPTION_COMMON_NORET_STACK(PACA_EXNMI, 0x100,
+                       system_reset, system_reset_exception,
                        ADD_NVGPRS;ADD_RECONCILE)
-1: /* EXCEPTION_COMMON continues here */
 
        /*
         * The stack is no longer in use, decrement in_nmi.
index 729e990a019d379e198caba001fbee396a5601b5..0f7b15860a06788ba37632eaa57467b8d9a8b52c 100644 (file)
@@ -628,6 +628,11 @@ void __init emergency_stack_init(void)
                paca[i].emergency_sp = (void *)ti + THREAD_SIZE;
 
 #ifdef CONFIG_PPC_BOOK3S_64
+               /* emergency stack for NMI exception handling. */
+               ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
+               klp_init_thread_info(ti);
+               paca[i].nmi_emergency_sp = (void *)ti + THREAD_SIZE;
+
                /* emergency stack for machine check exception handling. */
                ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
                klp_init_thread_info(ti);
index 99348a2961b83a4d22c89074142f18ecf4ed6ac5..682506821bba0f647ac52f3da03dadbafdbb2a1f 100644 (file)
@@ -2235,6 +2235,7 @@ static void dump_one_paca(int cpu)
        DUMP(p, kernel_msr, "lx");
        DUMP(p, emergency_sp, "p");
 #ifdef CONFIG_PPC_BOOK3S_64
+       DUMP(p, nmi_emergency_sp, "p");
        DUMP(p, mc_emergency_sp, "p");
        DUMP(p, in_nmi, "x");
        DUMP(p, in_mce, "x");