vmbase: Move stack to end of writable_data

Instead of imposing an arbitrary size for the stack, allows clients to
query a validated address range of a given size with boot_stack_range(),
which places the stack at the largest address possible, extending
downwards (common on AArch64).

Keep allocating 40 pages of stack in vmbase_example, rialto, and pvmfw.

Bug: 279209532
Bug: 270684188
Test: atest vmbase_example.integration_test
Test: atest rialto_test
Test: atest MicrodroidTests
Change-Id: If205ccd4fa408e32e5533b880a85f4cccbd3f005
diff --git a/pvmfw/src/helpers.rs b/pvmfw/src/helpers.rs
index 8c05217..1f0a764 100644
--- a/pvmfw/src/helpers.rs
+++ b/pvmfw/src/helpers.rs
@@ -22,6 +22,7 @@
 pub const SIZE_4MB: usize = 4 << 20;
 
 pub const GUEST_PAGE_SIZE: usize = SIZE_4KB;
+pub const PVMFW_PAGE_SIZE: usize = SIZE_4KB;
 
 /// Read a value from a system register.
 #[macro_export]
diff --git a/pvmfw/src/mmu.rs b/pvmfw/src/mmu.rs
index 455edad..ee99710 100644
--- a/pvmfw/src/mmu.rs
+++ b/pvmfw/src/mmu.rs
@@ -15,6 +15,7 @@
 //! Memory management.
 
 use crate::helpers;
+use crate::helpers::PVMFW_PAGE_SIZE;
 use aarch64_paging::idmap::IdMap;
 use aarch64_paging::paging::Attributes;
 use aarch64_paging::paging::MemoryRegion;
@@ -44,6 +45,13 @@
     start..end
 }
 
+/// Region allocated for the stack.
+fn stack_range() -> Range<usize> {
+    const STACK_PAGES: usize = 40;
+
+    layout::stack_range(STACK_PAGES * PVMFW_PAGE_SIZE)
+}
+
 impl PageTable {
     const ASID: usize = 1;
     const ROOT_LEVEL: usize = 1;
@@ -54,7 +62,7 @@
 
         page_table.map_code(&layout::text_range())?;
         page_table.map_data(&layout::scratch_range())?;
-        page_table.map_data(&layout::boot_stack_range())?;
+        page_table.map_data(&stack_range())?;
         page_table.map_rodata(&layout::rodata_range())?;
         page_table.map_data(&appended_payload_range())?;
 
diff --git a/rialto/src/main.rs b/rialto/src/main.rs
index 6b87e01..4163428 100644
--- a/rialto/src/main.rs
+++ b/rialto/src/main.rs
@@ -34,6 +34,7 @@
 use vmbase::{layout, main, power::reboot};
 
 const SZ_1K: usize = 1024;
+const SZ_4K: usize = 4 * SZ_1K;
 const SZ_64K: usize = 64 * SZ_1K;
 const SZ_1M: usize = 1024 * SZ_1K;
 const SZ_1G: usize = 1024 * SZ_1M;
@@ -82,7 +83,7 @@
     let reg_text = into_memreg(&layout::text_range());
     let reg_rodata = into_memreg(&layout::rodata_range());
     let reg_scratch = into_memreg(&layout::scratch_range());
-    let reg_stack = into_memreg(&layout::boot_stack_range());
+    let reg_stack = into_memreg(&layout::stack_range(40 * SZ_4K));
 
     debug!("Preparing kernel page table.");
     debug!("  dev:    {}-{}", reg_dev.start(), reg_dev.end());
diff --git a/vmbase/entry.S b/vmbase/entry.S
index 408f5d1..177c9aa 100644
--- a/vmbase/entry.S
+++ b/vmbase/entry.S
@@ -209,7 +209,7 @@
 	b 2b
 
 3:	/* Prepare the stack. */
-	adr_l x30, boot_stack_end
+	adr_l x30, init_stack_pointer
 	mov sp, x30
 
 	/* Set up exception vector. */
diff --git a/vmbase/example/src/layout.rs b/vmbase/example/src/layout.rs
index 0a33995..2e9d27a 100644
--- a/vmbase/example/src/layout.rs
+++ b/vmbase/example/src/layout.rs
@@ -55,7 +55,8 @@
 
 /// Writable data region for the stack.
 pub fn boot_stack_range() -> Range<VirtualAddress> {
-    into_va_range(layout::boot_stack_range())
+    const PAGE_SIZE: usize = 4 << 10;
+    into_va_range(layout::stack_range(40 * PAGE_SIZE))
 }
 
 /// Writable data region for allocations.
diff --git a/vmbase/sections.ld b/vmbase/sections.ld
index 9ed2455..8118363 100644
--- a/vmbase/sections.ld
+++ b/vmbase/sections.ld
@@ -89,11 +89,10 @@
 		bss_end = .;
 	} >writable_data
 
+	init_stack_pointer = ORIGIN(writable_data) + LENGTH(writable_data);
 	.stack (NOLOAD) : ALIGN(4096) {
-		boot_stack_begin = .;
-		. += 40 * 4096;
-		. = ALIGN(4096);
-		boot_stack_end = .;
+		stack_limit = .;
+		. = init_stack_pointer;
 	} >writable_data
 
 	/*
diff --git a/vmbase/src/layout.rs b/vmbase/src/layout.rs
index 0d824bb..d07dac4 100644
--- a/vmbase/src/layout.rs
+++ b/vmbase/src/layout.rs
@@ -62,8 +62,12 @@
 }
 
 /// Writable data region for the stack.
-pub fn boot_stack_range() -> Range<usize> {
-    linker_region!(boot_stack_begin, boot_stack_end)
+pub fn stack_range(stack_size: usize) -> Range<usize> {
+    let end = linker_addr!(init_stack_pointer);
+    let start = end.checked_sub(stack_size).unwrap();
+    assert!(start >= linker_addr!(stack_limit));
+
+    start..end
 }
 
 /// All writable sections, excluding the stack.
diff --git a/vmbase/src/linker.rs b/vmbase/src/linker.rs
index f4baae8..5f6e05e 100644
--- a/vmbase/src/linker.rs
+++ b/vmbase/src/linker.rs
@@ -19,10 +19,6 @@
     pub static __stack_chk_guard: u64;
     /// First byte beyond the pre-loaded binary.
     pub static bin_end: u8;
-    /// First byte of the `.stack` section.
-    pub static boot_stack_begin: u8;
-    /// First byte beyond the `.stack` section.
-    pub static boot_stack_end: u8;
     /// First byte of the `.bss` section.
     pub static bss_begin: u8;
     /// First byte beyond the `.bss` section.
@@ -37,10 +33,14 @@
     pub static dtb_begin: u8;
     /// First byte beyond the `.dtb` section.
     pub static dtb_end: u8;
+    /// First byte past the region available for the stack.
+    pub static init_stack_pointer: u8;
     /// First byte of the `.rodata` section.
     pub static rodata_begin: u8;
     /// First byte beyond the `.rodata` section.
     pub static rodata_end: u8;
+    /// First byte of the region available for the stack.
+    pub static stack_limit: u8;
     /// First byte of the `.text` section.
     pub static text_begin: u8;
     /// First byte beyond the `.text` section.