Merge "vmbase: Handle stack overflows"
diff --git a/vmbase/entry.S b/vmbase/entry.S
index 177c9aa..9f6993a 100644
--- a/vmbase/entry.S
+++ b/vmbase/entry.S
@@ -208,8 +208,14 @@
 	stp q0, q1, [x28], #32
 	b 2b
 
-3:	/* Prepare the stack. */
+3:	/* Prepare the exception handler stack (SP_EL1). */
+	adr_l x30, init_eh_stack_pointer
+	msr spsel, #1
+	mov sp, x30
+
+	/* Prepare the main thread stack (SP_EL0). */
 	adr_l x30, init_stack_pointer
+	msr spsel, #0
 	mov sp, x30
 
 	/* Set up exception vector. */
diff --git a/vmbase/sections.ld b/vmbase/sections.ld
index 8118363..5232d30 100644
--- a/vmbase/sections.ld
+++ b/vmbase/sections.ld
@@ -60,6 +60,17 @@
 	} >image
 	rodata_end = .;
 
+	.eh_stack (NOLOAD) : ALIGN(4096) {
+		/*
+		 * Get stack overflow guard from the previous page being from
+		 * .rodata and mapped read-only or left unmapped.
+		 */
+		eh_stack_limit = .;
+		. += 4096;
+		. = ALIGN(4096);
+		init_eh_stack_pointer = .;
+	} >writable_data
+
 	/*
 	 * Collect together the read-write data including .bss at the end which
 	 * will be zero'd by the entry code. This is page aligned so it can be
@@ -91,6 +102,7 @@
 
 	init_stack_pointer = ORIGIN(writable_data) + LENGTH(writable_data);
 	.stack (NOLOAD) : ALIGN(4096) {
+		. += 4096; /* Ensure we have one guard page for overflow. */
 		stack_limit = .;
 		. = init_stack_pointer;
 	} >writable_data
diff --git a/vmbase/src/layout.rs b/vmbase/src/layout.rs
index d07dac4..ead4f8e 100644
--- a/vmbase/src/layout.rs
+++ b/vmbase/src/layout.rs
@@ -72,7 +72,7 @@
 
 /// All writable sections, excluding the stack.
 pub fn scratch_range() -> Range<usize> {
-    linker_region!(data_begin, bss_end)
+    linker_region!(eh_stack_limit, bss_end)
 }
 
 /// Read-write data (original).
diff --git a/vmbase/src/linker.rs b/vmbase/src/linker.rs
index 5f6e05e..97bef3f 100644
--- a/vmbase/src/linker.rs
+++ b/vmbase/src/linker.rs
@@ -33,6 +33,8 @@
     pub static dtb_begin: u8;
     /// First byte beyond the `.dtb` section.
     pub static dtb_end: u8;
+    /// First byte of the region available for the exception handler stack.
+    pub static eh_stack_limit: u8;
     /// First byte past the region available for the stack.
     pub static init_stack_pointer: u8;
     /// First byte of the `.rodata` section.