[kernel][thread] Make stack info easier to reach from exception vectors

Move stack info to start of thread struct and add a stack_high entry.
This makes it easier validate or set the stack pointer from the
exceptions vectors.

Bug: 165825378
Change-Id: I16f0e84b29efc4173d6a052cff131aba192f9b2a
diff --git a/arch/arm/arm/thread.c b/arch/arm/arm/thread.c
index a14528c..ab98e91 100644
--- a/arch/arm/arm/thread.c
+++ b/arch/arm/arm/thread.c
@@ -64,6 +64,16 @@
     thread_exit(ret);
 }
 
+void arch_init_thread_initialize(struct thread *thread, uint cpu)
+{
+    extern uint8_t abort_stack[];
+    size_t stack_size = ARCH_DEFAULT_STACK_SIZE;
+    uint8_t *cpu_stack = abort_stack + cpu * stack_size;
+    thread->stack = cpu_stack;
+    thread->stack_high = cpu_stack + stack_size;
+    thread->stack_size = stack_size;
+}
+
 void arch_thread_initialize(thread_t *t)
 {
     // create a default stack frame on the stack
diff --git a/arch/arm64/thread.c b/arch/arm64/thread.c
index cc3e8bd..8bc6b6e 100644
--- a/arch/arm64/thread.c
+++ b/arch/arm64/thread.c
@@ -71,6 +71,16 @@
     thread_exit(ret);
 }
 
+void arch_init_thread_initialize(struct thread *thread, uint cpu)
+{
+    extern uint8_t __stack_end[];
+    size_t stack_size = ARCH_DEFAULT_STACK_SIZE;
+    uint8_t *cpu_stack_end = __stack_end - stack_size * cpu;
+    thread->stack = cpu_stack_end - stack_size;
+    thread->stack_high = cpu_stack_end;
+    thread->stack_size = stack_size;
+}
+
 void arch_thread_initialize(thread_t *t)
 {
     // create a default stack frame on the stack
diff --git a/arch/x86/thread.c b/arch/x86/thread.c
index aac0db6..a85f2dc 100644
--- a/arch/x86/thread.c
+++ b/arch/x86/thread.c
@@ -47,6 +47,17 @@
     thread_exit(ret);
 }
 
+void arch_init_thread_initialize(struct thread *thread, uint cpu)
+{
+    extern uint8_t _kstack[];
+    size_t stack_size = PAGE_SIZE;
+    uint8_t *cpu_stack = _kstack;
+    ASSERT(cpu == 0);
+    thread->stack = cpu_stack;
+    thread->stack_high = cpu_stack + stack_size;
+    thread->stack_size = stack_size;
+}
+
 void arch_thread_initialize(thread_t *t)
 {
     // create a default stack frame on the stack
diff --git a/include/arch/thread.h b/include/arch/thread.h
index 06de51d..792a959 100644
--- a/include/arch/thread.h
+++ b/include/arch/thread.h
@@ -29,6 +29,7 @@
 struct thread;
 
 void arch_thread_initialize(struct thread *);
+void arch_init_thread_initialize(struct thread *thread, uint cpu);
 void arch_context_switch(struct thread *oldthread, struct thread *newthread);
 
 #endif
diff --git a/include/kernel/thread.h b/include/kernel/thread.h
index b38b9e8..05619f9 100644
--- a/include/kernel/thread.h
+++ b/include/kernel/thread.h
@@ -84,6 +84,11 @@
 #define THREAD_MAGIC (0x74687264) // 'thrd'
 
 typedef struct thread {
+    /* stack stuff, don't move, used by assembly code to validate stack */
+    void *stack;
+    void *stack_high;
+    size_t stack_size;
+
     int magic;
     struct list_node thread_list_node;
 
@@ -108,10 +113,6 @@
     /* architecture stuff */
     struct arch_thread arch;
 
-    /* stack stuff */
-    void *stack;
-    size_t stack_size;
-
     /* entry point */
     thread_start_routine entry;
     void *arg;
diff --git a/kernel/thread.c b/kernel/thread.c
index 3dfd086..04a0fec 100644
--- a/kernel/thread.c
+++ b/kernel/thread.c
@@ -209,6 +209,7 @@
     memset(t->stack, STACK_DEBUG_BYTE, stack_size);
 #endif
 
+    t->stack_high = t->stack + stack_size;
     t->stack_size = stack_size;
 
     /* save whether or not we need to free the thread struct and/or stack */
@@ -966,6 +967,8 @@
     thread_t *t = idle_thread(0);
     init_thread_struct(t, "bootstrap");
 
+    arch_init_thread_initialize(t, 0);
+
     /* half construct this thread, since we're already running */
     t->priority = HIGHEST_PRIORITY;
     t->state = THREAD_RUNNING;
@@ -1096,6 +1099,8 @@
     thread_set_pinned_cpu(t, cpu);
     wait_queue_init(&t->retcode_wait_queue);
 
+    arch_init_thread_initialize(t, cpu);
+
     THREAD_LOCK(state);
 
     list_add_head(&thread_list, &t->thread_list_node);