Construct page table in Rust.
Bug: 223166344
Test: atest vmbase_example.integration_test
Change-Id: I023fd99395fcd795c608f78568945341c8354127
diff --git a/vmbase/example/Android.bp b/vmbase/example/Android.bp
index a0d84b4..d540f4d 100644
--- a/vmbase/example/Android.bp
+++ b/vmbase/example/Android.bp
@@ -13,6 +13,7 @@
"libcore.rust_sysroot",
],
rustlibs: [
+ "libaarch64_paging",
"libbuddy_system_allocator",
"libvmbase",
],
diff --git a/vmbase/example/idmap.S b/vmbase/example/idmap.S
index f1df6cc..7fc5d5e 100644
--- a/vmbase/example/idmap.S
+++ b/vmbase/example/idmap.S
@@ -38,13 +38,13 @@
.align 12
idmap:
/* level 1 */
- .quad .L_BLOCK_DEV | 0x0 // 1 GB of device mappings
- .quad .L_BLOCK_DEV | 0x40000000 // Another 1 GB of device mapppings
- .quad .L_TT_TYPE_TABLE + 0f // up to 1 GB of DRAM
- .fill 509, 8, 0x0 // 509 GB of remaining VA space
+ .quad .L_BLOCK_DEV | 0x0 // 1 GiB of device mappings
+ .quad 0x0 // 1 GiB unmapped
+ .quad .L_TT_TYPE_TABLE + 0f // up to 1 GiB of DRAM
+ .fill 509, 8, 0x0 // 509 GiB of remaining VA space
/* level 2 */
0: .quad .L_BLOCK_RO | 0x80000000 // DT provided by VMM
- .quad .L_BLOCK_MEM_XIP | 0x80200000 // 2 MB of DRAM containing image
- .quad .L_BLOCK_MEM | 0x80400000 // 2 MB of writable DRAM
+ .quad .L_BLOCK_MEM_XIP | 0x80200000 // 2 MiB of DRAM containing image
+ .quad .L_BLOCK_MEM | 0x80400000 // 2 MiB of writable DRAM
.fill 509, 8, 0x0
diff --git a/vmbase/example/src/main.rs b/vmbase/example/src/main.rs
index 3b1786c..99aca1d 100644
--- a/vmbase/example/src/main.rs
+++ b/vmbase/example/src/main.rs
@@ -22,6 +22,10 @@
extern crate alloc;
+use aarch64_paging::{
+ idmap::IdMap,
+ paging::{Attributes, MemoryRegion},
+};
use alloc::{vec, vec::Vec};
use buddy_system_allocator::LockedHeap;
use vmbase::{main, println};
@@ -30,11 +34,17 @@
static mut ZEROED_DATA: [u32; 10] = [0; 10];
static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
+const ASID: usize = 1;
+const ROOT_LEVEL: usize = 1;
+
#[global_allocator]
static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
static mut HEAP: [u8; 65536] = [0; 65536];
+/// The first 1 GiB of memory are used for MMIO.
+const DEVICE_REGION: MemoryRegion = MemoryRegion::new(0, 0x40000000);
+
main!(main);
/// Entry point for VM bootloader.
@@ -49,6 +59,56 @@
}
check_alloc();
+
+ let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
+ idmap.map_range(&DEVICE_REGION, Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER).unwrap();
+ idmap
+ .map_range(
+ &text_region(),
+ Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
+ )
+ .unwrap();
+ idmap
+ .map_range(
+ &rodata_region(),
+ Attributes::NORMAL
+ | Attributes::NON_GLOBAL
+ | Attributes::READ_ONLY
+ | Attributes::EXECUTE_NEVER,
+ )
+ .unwrap();
+ idmap
+ .map_range(
+ &writable_region(),
+ Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::EXECUTE_NEVER,
+ )
+ .unwrap();
+
+ println!("Activating IdMap...");
+ println!("{:?}", idmap);
+ idmap.activate();
+ println!("Activated.");
+
+ check_data();
+}
+
+/// Executable code.
+fn text_region() -> MemoryRegion {
+ unsafe { MemoryRegion::new(&text_begin as *const u8 as usize, &text_end as *const u8 as usize) }
+}
+
+/// Read-only data.
+fn rodata_region() -> MemoryRegion {
+ unsafe {
+ MemoryRegion::new(&rodata_begin as *const u8 as usize, &rodata_end as *const u8 as usize)
+ }
+}
+
+/// Writable data, including the stack.
+fn writable_region() -> MemoryRegion {
+ unsafe {
+ MemoryRegion::new(&data_begin as *const u8 as usize, &boot_stack_end as *const u8 as usize)
+ }
}
fn print_addresses() {
@@ -121,6 +181,8 @@
assert_eq!(MUTABLE_DATA[3], 4);
MUTABLE_DATA[0] += 41;
assert_eq!(MUTABLE_DATA[0], 42);
+ MUTABLE_DATA[0] -= 41;
+ assert_eq!(MUTABLE_DATA[0], 1);
}
println!("Data looks good");
}