powerpc/pseries: Limit machine check stack to 4GB
authorNicholas Piggin <npiggin@gmail.com>
Fri, 8 May 2020 04:34:01 +0000 (14:34 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 18 May 2020 14:10:34 +0000 (00:10 +1000)
This allows rtas_args to be put on the machine check stack, which
avoids a lot of complications with re-entrancy deadlocks.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Reviewed-by: Christophe Leroy <christophe.leroy@c-s.fr>
Reviewed-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
Link: https://lore.kernel.org/r/20200508043408.886394-10-npiggin@gmail.com
arch/powerpc/kernel/setup_64.c

index 438a9be..defe05b 100644 (file)
@@ -709,7 +709,7 @@ void __init exc_lvl_early_init(void)
  */
 void __init emergency_stack_init(void)
 {
-       u64 limit;
+       u64 limit, mce_limit;
        unsigned int i;
 
        /*
@@ -726,7 +726,16 @@ void __init emergency_stack_init(void)
         * initialized in kernel/irq.c. These are initialized here in order
         * to have emergency stacks available as early as possible.
         */
-       limit = min(ppc64_bolted_size(), ppc64_rma_size);
+       limit = mce_limit = min(ppc64_bolted_size(), ppc64_rma_size);
+
+       /*
+        * Machine check on pseries calls rtas, but can't use the static
+        * rtas_args due to a machine check hitting while the lock is held.
+        * rtas args have to be under 4GB, so the machine check stack is
+        * limited to 4GB so args can be put on stack.
+        */
+       if (firmware_has_feature(FW_FEATURE_LPAR) && mce_limit > SZ_4G)
+               mce_limit = SZ_4G;
 
        for_each_possible_cpu(i) {
                paca_ptrs[i]->emergency_sp = alloc_stack(limit, i) + THREAD_SIZE;
@@ -736,7 +745,7 @@ void __init emergency_stack_init(void)
                paca_ptrs[i]->nmi_emergency_sp = alloc_stack(limit, i) + THREAD_SIZE;
 
                /* emergency stack for machine check exception handling. */
-               paca_ptrs[i]->mc_emergency_sp = alloc_stack(limit, i) + THREAD_SIZE;
+               paca_ptrs[i]->mc_emergency_sp = alloc_stack(mce_limit, i) + THREAD_SIZE;
 #endif
        }
 }