vmbase: Clients separate eh_stack from .data+.bss
Remove the assumption that .data, .bss, and EH stack region are
contiguous e.g. when mapping or clearing them. This prepares the code
for an upcoming change moving the EH stack to a different part of the
writable_data region.
Bug: 377276983
Bug: 381440625
Test: m {pvmfw,rialto,vmbase_example_{bios,kernel}}_bin
Change-Id: Iae6220b1623b81ff9d7b6595be74504f6ec80865
diff --git a/guest/pvmfw/src/entry.rs b/guest/pvmfw/src/entry.rs
index ce911b8..39e51c5 100644
--- a/guest/pvmfw/src/entry.rs
+++ b/guest/pvmfw/src/entry.rs
@@ -189,7 +189,7 @@
const SCTLR_EL1_VAL: u64 = SCTLR_EL1_RES1 | SCTLR_EL1_ITD | SCTLR_EL1_SED | SCTLR_EL1_I;
- let scratch = layout::scratch_range();
+ let scratch = layout::data_bss_range();
assert_ne!(scratch.end - scratch.start, 0, "scratch memory is empty.");
assert_eq!(scratch.start.0 % ASM_STP_ALIGN, 0, "scratch memory is misaligned.");
@@ -205,6 +205,12 @@
assert_eq!(stack.start.0 % ASM_STP_ALIGN, 0, "Misaligned stack region.");
assert_eq!(stack.end.0 % ASM_STP_ALIGN, 0, "Misaligned stack region.");
+ let eh_stack = layout::eh_stack_range();
+
+ assert_ne!(eh_stack.end - eh_stack.start, 0, "EH stack region is empty.");
+ assert_eq!(eh_stack.start.0 % ASM_STP_ALIGN, 0, "Misaligned EH stack region.");
+ assert_eq!(eh_stack.end.0 % ASM_STP_ALIGN, 0, "Misaligned EH stack region.");
+
// Zero all memory that could hold secrets and that can't be safely written to from Rust.
// Disable the exception vector, caches and page table and then jump to the payload at the
// given address, passing it the given FDT pointer.
@@ -250,6 +256,18 @@
"cmp {cache_line}, {stack_end}",
"b.lo 0b",
+ "mov {cache_line}, {eh_stack}",
+ // Zero EH stack region.
+ "0: stp xzr, xzr, [{eh_stack}], 16",
+ "cmp {eh_stack}, {eh_stack_end}",
+ "b.lo 0b",
+
+ // Flush d-cache over EH stack region.
+ "0: dc cvau, {cache_line}",
+ "add {cache_line}, {cache_line}, {dcache_line_size}",
+ "cmp {cache_line}, {eh_stack_end}",
+ "b.lo 0b",
+
"msr sctlr_el1, {sctlr_el1_val}",
"isb",
"mov x1, xzr",
@@ -293,6 +311,8 @@
scratch_end = in(reg) u64::try_from(scratch.end.0).unwrap(),
stack = in(reg) u64::try_from(stack.start.0).unwrap(),
stack_end = in(reg) u64::try_from(stack.end.0).unwrap(),
+ eh_stack = in(reg) u64::try_from(eh_stack.start.0).unwrap(),
+ eh_stack_end = in(reg) u64::try_from(eh_stack.end.0).unwrap(),
dcache_line_size = in(reg) u64::try_from(min_dcache_line_size()).unwrap(),
in("x0") fdt_address,
in("x30") payload_start,
diff --git a/guest/pvmfw/src/memory.rs b/guest/pvmfw/src/memory.rs
index 8e8b338..67a95f4 100644
--- a/guest/pvmfw/src/memory.rs
+++ b/guest/pvmfw/src/memory.rs
@@ -54,7 +54,8 @@
// Stack and scratch ranges are explicitly zeroed and flushed before jumping to payload,
// so dirty state management can be omitted.
- page_table.map_data(&layout::scratch_range().into())?;
+ page_table.map_data(&layout::data_bss_range().into())?;
+ page_table.map_data(&layout::eh_stack_range().into())?;
page_table.map_data(&stack_range().into())?;
page_table.map_code(&layout::text_range().into())?;
page_table.map_rodata(&layout::rodata_range().into())?;
diff --git a/guest/rialto/src/main.rs b/guest/rialto/src/main.rs
index ec26e0f..61e9948 100644
--- a/guest/rialto/src/main.rs
+++ b/guest/rialto/src/main.rs
@@ -73,7 +73,8 @@
fn new_page_table() -> Result<PageTable> {
let mut page_table = PageTable::default();
- page_table.map_data(&layout::scratch_range().into())?;
+ page_table.map_data(&layout::data_bss_range().into())?;
+ page_table.map_data(&layout::eh_stack_range().into())?;
page_table.map_data(&layout::stack_range(40 * PAGE_SIZE).into())?;
page_table.map_code(&layout::text_range().into())?;
page_table.map_rodata(&layout::rodata_range().into())?;
diff --git a/guest/vmbase_example/src/main.rs b/guest/vmbase_example/src/main.rs
index c7ef061..f00effa 100644
--- a/guest/vmbase_example/src/main.rs
+++ b/guest/vmbase_example/src/main.rs
@@ -37,7 +37,10 @@
bionic, configure_heap,
fdt::pci::PciInfo,
generate_image_header,
- layout::{console_uart_page, crosvm::FDT_MAX_SIZE, rodata_range, scratch_range, text_range},
+ layout::{
+ console_uart_page, crosvm::FDT_MAX_SIZE, data_bss_range, eh_stack_range, rodata_range,
+ text_range,
+ },
linker, logger, main,
memory::{PageTable, SIZE_64KB},
};
@@ -54,7 +57,8 @@
page_table.map_device(&console_uart_page().into())?;
page_table.map_code(&text_range().into())?;
page_table.map_rodata(&rodata_range().into())?;
- page_table.map_data(&scratch_range().into())?;
+ page_table.map_data(&data_bss_range().into())?;
+ page_table.map_data(&eh_stack_range().into())?;
page_table.map_data(&boot_stack_range().into())?;
info!("Activating IdMap...");
diff --git a/libs/libvmbase/src/layout.rs b/libs/libvmbase/src/layout.rs
index adcb2fa..2f710ef 100644
--- a/libs/libvmbase/src/layout.rs
+++ b/libs/libvmbase/src/layout.rs
@@ -80,6 +80,11 @@
linker_region!(bss_begin, bss_end)
}
+/// Writable data region for .data and .bss.
+pub fn data_bss_range() -> Range<VirtualAddress> {
+ linker_region!(data_begin, bss_end)
+}
+
/// Writable data region for the stack.
pub fn stack_range(stack_size: usize) -> Range<VirtualAddress> {
let end = linker_addr!(init_stack_pointer);
@@ -89,9 +94,9 @@
start..end
}
-/// All writable sections, excluding the stack.
-pub fn scratch_range() -> Range<VirtualAddress> {
- linker_region!(eh_stack_limit, bss_end)
+/// Writable data region for the exception handler stack.
+pub fn eh_stack_range() -> Range<VirtualAddress> {
+ linker_region!(eh_stack_limit, init_eh_stack_pointer)
}
/// Range of the page at UART_PAGE_ADDR of PAGE_SIZE.
diff --git a/libs/libvmbase/src/linker.rs b/libs/libvmbase/src/linker.rs
index 97bef3f..40afce5 100644
--- a/libs/libvmbase/src/linker.rs
+++ b/libs/libvmbase/src/linker.rs
@@ -35,6 +35,8 @@
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 exception handler stack.
+ pub static init_eh_stack_pointer: u8;
/// First byte past the region available for the stack.
pub static init_stack_pointer: u8;
/// First byte of the `.rodata` section.