diff --git a/src/arch/emulate.rs b/src/arch/emulate.rs index efdde5a80b..331c81fe8e 100644 --- a/src/arch/emulate.rs +++ b/src/arch/emulate.rs @@ -7,8 +7,10 @@ use std::collections::BTreeMap; use crate::{ Arch, - PhysicalAddress, MemoryArea, + PageEntry, + PhysicalAddress, + VirtualAddress, arch::x86_64::X8664Arch, }; @@ -37,45 +39,45 @@ impl Arch for EmulateArch { let pml4 = 0; let pdp = pml4 + Self::PAGE_SIZE; let flags = Self::ENTRY_FLAG_WRITABLE | Self::ENTRY_FLAG_PRESENT; - machine.write_phys::(pml4, pdp | flags); + machine.write_phys::(PhysicalAddress::new(pml4), pdp | flags); // Recursive mapping - machine.write_phys::(pml4 + (Self::PAGE_ENTRIES - 1) * Self::PAGE_ENTRY_SIZE, pml4 | flags); + machine.write_phys::(PhysicalAddress::new(pml4 + (Self::PAGE_ENTRIES - 1) * Self::PAGE_ENTRY_SIZE), pml4 | flags); // PDP link to PD let pd = pdp + Self::PAGE_SIZE; - machine.write_phys::(pdp, pd | flags); + machine.write_phys::(PhysicalAddress::new(pdp), pd | flags); // PD link to PT let pt = pd + Self::PAGE_SIZE; - machine.write_phys::(pd, pt | flags); + machine.write_phys::(PhysicalAddress::new(pd), pt | flags); // PT links to frames for i in 0..Self::PAGE_ENTRIES { let page = i * Self::PAGE_SIZE; - machine.write_phys::(pt + i * Self::PAGE_ENTRY_SIZE, page | flags); + machine.write_phys::(PhysicalAddress::new(pt + i * Self::PAGE_ENTRY_SIZE), page | flags); } MACHINE = Some(machine); // Set table to pml4 - EmulateArch::set_table(pml4); + EmulateArch::set_table(PhysicalAddress::new(pml4)); &MEMORY_AREAS } #[inline(always)] - unsafe fn read(address: usize) -> T { + unsafe fn read(address: VirtualAddress) -> T { MACHINE.as_ref().unwrap().read(address) } #[inline(always)] - unsafe fn write(address: usize, value: T) { + unsafe fn write(address: VirtualAddress, value: T) { MACHINE.as_mut().unwrap().write(address, value) } #[inline(always)] - unsafe fn invalidate(address: usize) { + unsafe fn invalidate(address: VirtualAddress) { MACHINE.as_mut().unwrap().invalidate(address); } @@ -85,12 +87,12 @@ impl Arch for EmulateArch { } #[inline(always)] - unsafe fn table() -> usize { + unsafe fn table() -> PhysicalAddress { MACHINE.as_mut().unwrap().get_table() } #[inline(always)] - unsafe fn set_table(address: usize) { + unsafe fn set_table(address: PhysicalAddress) { MACHINE.as_mut().unwrap().set_table(address); } } @@ -108,8 +110,8 @@ static mut MACHINE: Option> = None; struct Machine { memory: Box<[u8]>, - map: BTreeMap, - table_addr: usize, + map: BTreeMap>, + table_addr: PhysicalAddress, phantom: PhantomData, } @@ -118,12 +120,13 @@ impl Machine { Self { memory: vec![0; memory_size].into_boxed_slice(), map: BTreeMap::new(), - table_addr: 0, + table_addr: PhysicalAddress::new(0), phantom: PhantomData, } } - fn read_phys(&self, phys: usize) -> T { + fn read_phys(&self, phys: PhysicalAddress) -> T { + let phys = phys.data(); let size = mem::size_of::(); if phys + size <= self.memory.len() { unsafe { @@ -134,7 +137,8 @@ impl Machine { } } - fn write_phys(&mut self, phys: usize, value: T) { + fn write_phys(&mut self, phys: PhysicalAddress, value: T) { + let phys = phys.data(); let size = mem::size_of::(); if phys + size <= self.memory.len() { unsafe { @@ -145,104 +149,107 @@ impl Machine { } } - fn translate(&self, virt: usize) -> Option<(usize, usize)> { - let page = virt & A::PAGE_ADDRESS_MASK; - let offset = virt & A::PAGE_OFFSET_MASK; - let phys = self.map.get(&page)?; + fn translate(&self, virt: VirtualAddress) -> Option<(PhysicalAddress, usize)> { + let virt_data = virt.data(); + let page = virt_data & A::PAGE_ADDRESS_MASK; + let offset = virt_data & A::PAGE_OFFSET_MASK; + let entry = self.map.get(&VirtualAddress::new(page))?; Some(( - (phys & A::ENTRY_ADDRESS_MASK) + offset, - phys & A::ENTRY_FLAGS_MASK, + PhysicalAddress::new(entry.address().data() + offset), + entry.flags(), )) } - fn read(&self, virt: usize) -> T { + fn read(&self, virt: VirtualAddress) -> T { //TODO: allow reading past page boundaries + let virt_data = virt.data(); let size = mem::size_of::(); - if (virt & A::PAGE_ADDRESS_MASK) != ((virt + (size - 1)) & A::PAGE_ADDRESS_MASK) { - panic!("read: 0x{:X} size 0x{:X} passes page boundary", virt, size); + if (virt_data & A::PAGE_ADDRESS_MASK) != ((virt_data + (size - 1)) & A::PAGE_ADDRESS_MASK) { + panic!("read: 0x{:X} size 0x{:X} passes page boundary", virt_data, size); } if let Some((phys, _flags)) = self.translate(virt) { self.read_phys(phys) } else { - panic!("read: 0x{:X} size 0x{:X} not present", virt, size); + panic!("read: 0x{:X} size 0x{:X} not present", virt_data, size); } } - fn write(&mut self, virt: usize, value: T) { + fn write(&mut self, virt: VirtualAddress, value: T) { //TODO: allow writing past page boundaries + let virt_data = virt.data(); let size = mem::size_of::(); - if (virt & A::PAGE_ADDRESS_MASK) != ((virt + (size - 1)) & A::PAGE_ADDRESS_MASK) { - panic!("write: 0x{:X} size 0x{:X} passes page boundary", virt, size); + if (virt_data & A::PAGE_ADDRESS_MASK) != ((virt_data + (size - 1)) & A::PAGE_ADDRESS_MASK) { + panic!("write: 0x{:X} size 0x{:X} passes page boundary", virt_data, size); } if let Some((phys, flags)) = self.translate(virt) { if flags & A::ENTRY_FLAG_WRITABLE != 0 { self.write_phys(phys, value); } else { - panic!("write: 0x{:X} size 0x{:X} not writable", virt, size); + panic!("write: 0x{:X} size 0x{:X} not writable", virt_data, size); } } else { - panic!("write: 0x{:X} size 0x{:X} not present", virt, size); + panic!("write: 0x{:X} size 0x{:X} not present", virt_data, size); } } - fn invalidate(&mut self, _address: usize) { + fn invalidate(&mut self, _address: VirtualAddress) { unimplemented!(); } + //TODO: cleanup fn invalidate_all(&mut self) { self.map.clear(); // PML4 - let a4 = self.table_addr; + let a4 = self.table_addr.data(); for i4 in 0..A::PAGE_ENTRIES { - let e3 = self.read_phys::(a4 + i4 * A::PAGE_ENTRY_SIZE); + let e3 = self.read_phys::(PhysicalAddress::new(a4 + i4 * A::PAGE_ENTRY_SIZE)); let f3 = e3 & A::ENTRY_FLAGS_MASK; if f3 & A::ENTRY_FLAG_PRESENT == 0 { continue; } // Page directory pointer let a3 = e3 & A::ENTRY_ADDRESS_MASK; for i3 in 0..A::PAGE_ENTRIES { - let e2 = self.read_phys::(a3 + i3 * A::PAGE_ENTRY_SIZE); + let e2 = self.read_phys::(PhysicalAddress::new(a3 + i3 * A::PAGE_ENTRY_SIZE)); let f2 = e2 & A::ENTRY_FLAGS_MASK; if f2 & A::ENTRY_FLAG_PRESENT == 0 { continue; } // Page directory let a2 = e2 & A::ENTRY_ADDRESS_MASK; for i2 in 0..A::PAGE_ENTRIES { - let e1 = self.read_phys::(a2 + i2 * A::PAGE_ENTRY_SIZE); + let e1 = self.read_phys::(PhysicalAddress::new(a2 + i2 * A::PAGE_ENTRY_SIZE)); let f1 = e1 & A::ENTRY_FLAGS_MASK; if f1 & A::ENTRY_FLAG_PRESENT == 0 { continue; } // Page table let a1 = e1 & A::ENTRY_ADDRESS_MASK; for i1 in 0..A::PAGE_ENTRIES { - let e = self.read_phys::(a1 + i1 * A::PAGE_ENTRY_SIZE); + let e = self.read_phys::(PhysicalAddress::new(a1 + i1 * A::PAGE_ENTRY_SIZE)); let f = e & A::ENTRY_FLAGS_MASK; if f & A::ENTRY_FLAG_PRESENT == 0 { continue; } // Page let a = e & A::ENTRY_ADDRESS_MASK; let page = - if i4 >= 256 { 0xFFFF_0000_0000_0000 } else { 0 } | (i4 << 39) | (i3 << 30) | (i2 << 21) | (i1 << 12); println!("map 0x{:X} to 0x{:X}, 0x{:X}", page, a, f); - self.map.insert(page, e); + self.map.insert(VirtualAddress::new(page), PageEntry::new(e)); } } } } } - fn get_table(&self) -> usize { + fn get_table(&self) -> PhysicalAddress { self.table_addr } - fn set_table(&mut self, address: usize) { + fn set_table(&mut self, address: PhysicalAddress) { self.table_addr = address; self.invalidate_all(); } diff --git a/src/arch/mod.rs b/src/arch/mod.rs index a404f99733..32f6b2a797 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -40,22 +40,22 @@ pub trait Arch { unsafe fn init() -> &'static [MemoryArea]; #[inline(always)] - unsafe fn read(address: usize) -> T { - ptr::read(address as *const T) + unsafe fn read(address: VirtualAddress) -> T { + ptr::read(address.data() as *const T) } #[inline(always)] - unsafe fn write(address: usize, value: T) { - ptr::write(address as *mut T, value) + unsafe fn write(address: VirtualAddress, value: T) { + ptr::write(address.data() as *mut T, value) } - unsafe fn invalidate(address: usize); + unsafe fn invalidate(address: VirtualAddress); unsafe fn invalidate_all(); - unsafe fn table() -> usize; + unsafe fn table() -> PhysicalAddress; - unsafe fn set_table(address: usize); + unsafe fn set_table(address: PhysicalAddress); unsafe fn phys_to_virt(phys: PhysicalAddress) -> VirtualAddress { VirtualAddress::new(phys.data() + Self::PAGE_OFFSET) diff --git a/src/arch/x86_64.rs b/src/arch/x86_64.rs index bfba675a1e..5fbac9f49d 100644 --- a/src/arch/x86_64.rs +++ b/src/arch/x86_64.rs @@ -1,6 +1,8 @@ use crate::{ Arch, - MemoryArea + MemoryArea, + PhysicalAddress, + VirtualAddress, }; pub struct X8664Arch; @@ -24,7 +26,7 @@ impl Arch for X8664Arch { } #[inline(always)] - unsafe fn invalidate(address: usize) { + unsafe fn invalidate(address: VirtualAddress) { //TODO: invlpg address unimplemented!(); } @@ -36,13 +38,13 @@ impl Arch for X8664Arch { } #[inline(always)] - unsafe fn table() -> usize { + unsafe fn table() -> PhysicalAddress { //TODO: return cr3 unimplemented!(); } #[inline(always)] - unsafe fn set_table(address: usize) { + unsafe fn set_table(address: PhysicalAddress) { //TODO: mov cr3, address unimplemented!(); } diff --git a/src/main.rs b/src/main.rs index b43058d287..1fd59273a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,8 @@ use rmm::{ Arch, EmulateArch, - PageTable + PageTable, + VirtualAddress, }; unsafe fn dump_tables(table: PageTable) { @@ -28,16 +29,16 @@ unsafe fn inner() { // Debug table dump_tables(PageTable::::top()); - let megabyte = 0x100000; + let megabyte = VirtualAddress::new(0x100000); // Test read - println!("0x{:X} = 0x{:X}", megabyte, A::read::(megabyte)); + println!("0x{:X} = 0x{:X}", megabyte.data(), A::read::(megabyte)); // Test write A::write::(megabyte, 0x5A); // Test read - println!("0x{:X} = 0x{:X}", megabyte, A::read::(megabyte)); + println!("0x{:X} = 0x{:X}", megabyte.data(), A::read::(megabyte)); } fn main() { diff --git a/src/page/table.rs b/src/page/table.rs index ab77a39c2d..44113a9d26 100644 --- a/src/page/table.rs +++ b/src/page/table.rs @@ -22,7 +22,7 @@ impl PageTable { pub unsafe fn top() -> Self { Self::new( VirtualAddress::new(0), - PhysicalAddress::new(A::table()), + A::table(), A::PAGE_LEVELS - 1 ) } @@ -47,7 +47,7 @@ impl PageTable { addr <<= A::PAGE_ENTRY_SHIFT; addr |= index << A::PAGE_SHIFT; } - VirtualAddress(addr) + VirtualAddress::new(addr) // Identity mapping //VirtualAddress(self.phys.0) @@ -55,8 +55,8 @@ impl PageTable { pub fn entry_base(&self, i: usize) -> Option { if i < A::PAGE_ENTRIES { - Some(VirtualAddress( - self.base.0 + (i << (self.level * A::PAGE_ENTRY_SHIFT + A::PAGE_SHIFT)) + Some(VirtualAddress::new( + self.base.data() + (i << (self.level * A::PAGE_ENTRY_SHIFT + A::PAGE_SHIFT)) )) } else { None @@ -65,8 +65,8 @@ impl PageTable { pub unsafe fn entry_virt(&self, i: usize) -> Option { if i < A::PAGE_ENTRIES { - Some(VirtualAddress( - self.virt().0 + i * A::PAGE_ENTRY_SIZE + Some(VirtualAddress::new( + self.virt().data() + i * A::PAGE_ENTRY_SIZE )) } else { None @@ -75,12 +75,12 @@ impl PageTable { pub unsafe fn entry(&self, i: usize) -> Option> { let addr = self.entry_virt(i)?; - Some(PageEntry::new(A::read::(addr.0))) + Some(PageEntry::new(A::read::(addr))) } pub unsafe fn set_entry(&mut self, i: usize, entry: PageEntry) -> Option<()> { let addr = self.entry_virt(i)?; - A::write::(addr.0, entry.data()); + A::write::(addr, entry.data()); Some(()) }