From c77891b364f11cb3583ed520c379bac8bb468027 Mon Sep 17 00:00:00 2001 From: Jakob Vukalovic Date: Tue, 11 Apr 2023 11:51:03 +0100 Subject: [PATCH] Add new tests, and update existing --- src/idmap.rs | 60 ++++++++++++++++++++++++++++++++++++-------- src/lib.rs | 2 +- src/linearmap.rs | 65 +++++++++++++++++++++++++++++++++++++++--------- src/paging.rs | 7 +++--- 4 files changed, 108 insertions(+), 26 deletions(-) diff --git a/src/idmap.rs b/src/idmap.rs index 8d52d76..870ccf8 100644 --- a/src/idmap.rs +++ b/src/idmap.rs @@ -71,7 +71,7 @@ impl Translation for IdTranslation { /// // Map a 2 MiB region of memory as read-write. /// idmap.map_range( /// &MemoryRegion::new(0x80200000, 0x80400000), -/// Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::EXECUTE_NEVER, +/// Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::EXECUTE_NEVER | Attributes::VALID, /// ).unwrap(); /// // Set `TTBR0_EL1` to activate the page table. /// # #[cfg(target_arch = "aarch64")] @@ -85,7 +85,7 @@ impl Translation for IdTranslation { /// // Now change the mapping to read-only and executable. /// idmap.map_range( /// &MemoryRegion::new(0x80200000, 0x80400000), -/// Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY, +/// Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY | Attributes::VALID, /// ).unwrap(); /// # #[cfg(target_arch = "aarch64")] /// idmap.activate(); @@ -182,14 +182,20 @@ mod tests { // A single byte at the start of the address space. let mut idmap = IdMap::new(1, 1); assert_eq!( - idmap.map_range(&MemoryRegion::new(0, 1), Attributes::NORMAL), + idmap.map_range( + &MemoryRegion::new(0, 1), + Attributes::NORMAL | Attributes::VALID + ), Ok(()) ); // Two pages at the start of the address space. let mut idmap = IdMap::new(1, 1); assert_eq!( - idmap.map_range(&MemoryRegion::new(0, PAGE_SIZE * 2), Attributes::NORMAL), + idmap.map_range( + &MemoryRegion::new(0, PAGE_SIZE * 2), + Attributes::NORMAL | Attributes::VALID + ), Ok(()) ); @@ -201,7 +207,7 @@ mod tests { MAX_ADDRESS_FOR_ROOT_LEVEL_1 - 1, MAX_ADDRESS_FOR_ROOT_LEVEL_1 ), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Ok(()) ); @@ -211,7 +217,7 @@ mod tests { assert_eq!( idmap.map_range( &MemoryRegion::new(PAGE_SIZE * 1023, PAGE_SIZE * 1025), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Ok(()) ); @@ -221,7 +227,7 @@ mod tests { assert_eq!( idmap.map_range( &MemoryRegion::new(0, MAX_ADDRESS_FOR_ROOT_LEVEL_1), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Ok(()) ); @@ -238,7 +244,7 @@ mod tests { MAX_ADDRESS_FOR_ROOT_LEVEL_1, MAX_ADDRESS_FOR_ROOT_LEVEL_1 + 1, ), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Err(MapError::AddressRange(VirtualAddress( MAX_ADDRESS_FOR_ROOT_LEVEL_1 + PAGE_SIZE @@ -249,7 +255,7 @@ mod tests { assert_eq!( idmap.map_range( &MemoryRegion::new(0, MAX_ADDRESS_FOR_ROOT_LEVEL_1 + 1,), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Err(MapError::AddressRange(VirtualAddress( MAX_ADDRESS_FOR_ROOT_LEVEL_1 + PAGE_SIZE @@ -262,7 +268,10 @@ mod tests { idmap .map_range( &MemoryRegion::new(0, PAGE_SIZE * 2), - Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY, + Attributes::NORMAL + | Attributes::NON_GLOBAL + | Attributes::READ_ONLY + | Attributes::VALID, ) .unwrap(); idmap @@ -305,4 +314,35 @@ mod tests { }) .unwrap(); } + + #[test] + fn breakup_invalid_block() { + const BLOCK_RANGE: usize = 0x200000; + let mut idmap = IdMap::new(1, 1); + idmap + .map_range( + &MemoryRegion::new(0, BLOCK_RANGE), + Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::SWFLAG_0, + ) + .unwrap(); + idmap + .map_range( + &MemoryRegion::new(0, PAGE_SIZE), + Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::VALID, + ) + .unwrap(); + idmap + .modify_range( + &MemoryRegion::new(0, BLOCK_RANGE), + &|range, entry, level| { + if level == 3 { + let has_swflag = entry.flags().unwrap().contains(Attributes::SWFLAG_0); + let is_first_page = range.start().0 == 0usize; + assert!(has_swflag != is_first_page); + } + Ok(()) + }, + ) + .unwrap(); + } } diff --git a/src/lib.rs b/src/lib.rs index 479c902..3d4aeac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,7 @@ //! // Map a 2 MiB region of memory as read-only. //! idmap.map_range( //! &MemoryRegion::new(0x80200000, 0x80400000), -//! Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY, +//! Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY | Attributes::VALID, //! ).unwrap(); //! // Set `TTBR0_EL1` to activate the page table. //! # #[cfg(target_arch = "aarch64")] diff --git a/src/linearmap.rs b/src/linearmap.rs index bfc5370..921a683 100644 --- a/src/linearmap.rs +++ b/src/linearmap.rs @@ -200,14 +200,20 @@ mod tests { // A single byte at the start of the address space. let mut pagetable = LinearMap::new(1, 1, 4096, VaRange::Lower); assert_eq!( - pagetable.map_range(&MemoryRegion::new(0, 1), Attributes::NORMAL), + pagetable.map_range( + &MemoryRegion::new(0, 1), + Attributes::NORMAL | Attributes::VALID + ), Ok(()) ); // Two pages at the start of the address space. let mut pagetable = LinearMap::new(1, 1, 4096, VaRange::Lower); assert_eq!( - pagetable.map_range(&MemoryRegion::new(0, PAGE_SIZE * 2), Attributes::NORMAL), + pagetable.map_range( + &MemoryRegion::new(0, PAGE_SIZE * 2), + Attributes::NORMAL | Attributes::VALID + ), Ok(()) ); @@ -219,7 +225,7 @@ mod tests { MAX_ADDRESS_FOR_ROOT_LEVEL_1 - 1, MAX_ADDRESS_FOR_ROOT_LEVEL_1 ), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Ok(()) ); @@ -231,7 +237,7 @@ mod tests { assert_eq!( pagetable.map_range( &MemoryRegion::new(0, MAX_ADDRESS_FOR_ROOT_LEVEL_1), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Ok(()) ); @@ -244,7 +250,7 @@ mod tests { assert_eq!( pagetable.map_range( &MemoryRegion::new(PAGE_SIZE, PAGE_SIZE + 1), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Ok(()) ); @@ -254,7 +260,7 @@ mod tests { assert_eq!( pagetable.map_range( &MemoryRegion::new(PAGE_SIZE, PAGE_SIZE * 3), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Ok(()) ); @@ -267,7 +273,7 @@ mod tests { MAX_ADDRESS_FOR_ROOT_LEVEL_1 - 1, MAX_ADDRESS_FOR_ROOT_LEVEL_1 ), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Ok(()) ); @@ -279,7 +285,7 @@ mod tests { assert_eq!( pagetable.map_range( &MemoryRegion::new(LEVEL_2_BLOCK_SIZE, MAX_ADDRESS_FOR_ROOT_LEVEL_1), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Ok(()) ); @@ -296,7 +302,7 @@ mod tests { MAX_ADDRESS_FOR_ROOT_LEVEL_1, MAX_ADDRESS_FOR_ROOT_LEVEL_1 + 1, ), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Err(MapError::AddressRange(VirtualAddress( MAX_ADDRESS_FOR_ROOT_LEVEL_1 + PAGE_SIZE @@ -307,7 +313,7 @@ mod tests { assert_eq!( pagetable.map_range( &MemoryRegion::new(0, MAX_ADDRESS_FOR_ROOT_LEVEL_1 + 1), - Attributes::NORMAL + Attributes::NORMAL | Attributes::VALID ), Err(MapError::AddressRange(VirtualAddress( MAX_ADDRESS_FOR_ROOT_LEVEL_1 + PAGE_SIZE @@ -419,7 +425,10 @@ mod tests { // Test that block mapping is used when the PA is appropriately aligned... let mut pagetable = LinearMap::new(1, 1, 1 << 30, VaRange::Lower); pagetable - .map_range(&MemoryRegion::new(0, 1 << 30), Attributes::NORMAL) + .map_range( + &MemoryRegion::new(0, 1 << 30), + Attributes::NORMAL | Attributes::VALID, + ) .unwrap(); assert_eq!( pagetable.mapping.root.mapping_level(VirtualAddress(0)), @@ -429,7 +438,10 @@ mod tests { // ...but not when it is not. let mut pagetable = LinearMap::new(1, 1, 1 << 29, VaRange::Lower); pagetable - .map_range(&MemoryRegion::new(0, 1 << 30), Attributes::NORMAL) + .map_range( + &MemoryRegion::new(0, 1 << 30), + Attributes::NORMAL | Attributes::VALID, + ) .unwrap(); assert_eq!( pagetable.mapping.root.mapping_level(VirtualAddress(0)), @@ -479,4 +491,33 @@ mod tests { }) .unwrap(); } + + #[test] + fn breakup_invalid_block() { + const BLOCK_RANGE: usize = 0x200000; + + let mut lmap = LinearMap::new(1, 1, 0x1000, VaRange::Lower); + lmap.map_range( + &MemoryRegion::new(0, BLOCK_RANGE), + Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::SWFLAG_0, + ) + .unwrap(); + lmap.map_range( + &MemoryRegion::new(0, PAGE_SIZE), + Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::VALID, + ) + .unwrap(); + lmap.modify_range( + &MemoryRegion::new(0, BLOCK_RANGE), + &|range, entry, level| { + if level == 3 { + let has_swflag = entry.flags().unwrap().contains(Attributes::SWFLAG_0); + let is_first_page = range.start().0 == 0usize; + assert!(has_swflag != is_first_page); + } + Ok(()) + }, + ) + .unwrap(); + } } diff --git a/src/paging.rs b/src/paging.rs index bdda728..f0370f7 100644 --- a/src/paging.rs +++ b/src/paging.rs @@ -838,18 +838,19 @@ mod tests { #[test] fn set_descriptor() { + const PHYSICAL_ADDRESS: usize = 0x12340000; let mut desc = Descriptor(0usize); assert!(!desc.is_valid()); desc.set( - PhysicalAddress(0x12340000), - Attributes::TABLE_OR_PAGE | Attributes::USER | Attributes::SWFLAG_1, + PhysicalAddress(PHYSICAL_ADDRESS), + Attributes::TABLE_OR_PAGE | Attributes::USER | Attributes::SWFLAG_1 | Attributes::VALID, ); assert!(desc.is_valid()); assert_eq!( desc.flags().unwrap(), Attributes::TABLE_OR_PAGE | Attributes::USER | Attributes::SWFLAG_1 | Attributes::VALID ); - assert_eq!(desc.output_address().unwrap(), PhysicalAddress(0x12340000)); + assert_eq!(desc.output_address(), PhysicalAddress(PHYSICAL_ADDRESS)); } #[test]