OSDN Git Service

RISC-V: Align the shadow stack
[tomoyo/tomoyo-test1.git] / arch / riscv / kernel / traps.c
index 1357abf..acdfcac 100644 (file)
@@ -25,8 +25,6 @@
 
 int show_unhandled_signals = 1;
 
-extern asmlinkage void handle_exception(void);
-
 static DEFINE_SPINLOCK(die_lock);
 
 void die(struct pt_regs *regs, const char *str)
@@ -197,6 +195,59 @@ int is_valid_bugaddr(unsigned long pc)
 #endif /* CONFIG_GENERIC_BUG */
 
 /* stvec & scratch is already set from head.S */
-void trap_init(void)
+void __init trap_init(void)
+{
+}
+
+#ifdef CONFIG_VMAP_STACK
+static DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)],
+               overflow_stack)__aligned(16);
+/*
+ * shadow stack, handled_ kernel_ stack_ overflow(in kernel/entry.S) is used
+ * to get per-cpu overflow stack(get_overflow_stack).
+ */
+long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE/sizeof(long)] __aligned(16);
+asmlinkage unsigned long get_overflow_stack(void)
+{
+       return (unsigned long)this_cpu_ptr(overflow_stack) +
+               OVERFLOW_STACK_SIZE;
+}
+
+/*
+ * A pseudo spinlock to protect the shadow stack from being used by multiple
+ * harts concurrently.  This isn't a real spinlock because the lock side must
+ * be taken without a valid stack and only a single register, it's only taken
+ * while in the process of panicing anyway so the performance and error
+ * checking a proper spinlock gives us doesn't matter.
+ */
+unsigned long spin_shadow_stack;
+
+asmlinkage void handle_bad_stack(struct pt_regs *regs)
 {
+       unsigned long tsk_stk = (unsigned long)current->stack;
+       unsigned long ovf_stk = (unsigned long)this_cpu_ptr(overflow_stack);
+
+       /*
+        * We're done with the shadow stack by this point, as we're on the
+        * overflow stack.  Tell any other concurrent overflowing harts that
+        * they can proceed with panicing by releasing the pseudo-spinlock.
+        *
+        * This pairs with an amoswap.aq in handle_kernel_stack_overflow.
+        */
+       smp_store_release(&spin_shadow_stack, 0);
+
+       console_verbose();
+
+       pr_emerg("Insufficient stack space to handle exception!\n");
+       pr_emerg("Task stack:     [0x%016lx..0x%016lx]\n",
+                       tsk_stk, tsk_stk + THREAD_SIZE);
+       pr_emerg("Overflow stack: [0x%016lx..0x%016lx]\n",
+                       ovf_stk, ovf_stk + OVERFLOW_STACK_SIZE);
+
+       __show_regs(regs);
+       panic("Kernel stack overflow");
+
+       for (;;)
+               wait_for_interrupt();
 }
+#endif