diff --git a/src/acpi/dmar/mod.rs b/src/acpi/dmar/mod.rs index 710357d..8b107e2 100644 --- a/src/acpi/dmar/mod.rs +++ b/src/acpi/dmar/mod.rs @@ -3,8 +3,7 @@ use core::mem; use super::sdt::Sdt; use self::drhd::Drhd; use crate::memory::Frame; -use crate::paging::{ActivePageTable, PhysicalAddress}; -use crate::paging::entry::EntryFlags; +use crate::paging::{ActivePageTable, PageFlags, PhysicalAddress}; use super::{find_sdt, load_table, get_sdt_signature}; @@ -92,7 +91,7 @@ pub struct DmarDrhd { impl DmarDrhd { pub fn get(&self, active_table: &mut ActivePageTable) -> &'static mut Drhd { - let result = active_table.identity_map(Frame::containing_address(PhysicalAddress::new(self.base as usize)), EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE); + let result = active_table.identity_map(Frame::containing_address(PhysicalAddress::new(self.base as usize)), PageFlags::new().write(true)); result.flush(); unsafe { &mut *(self.base as *mut Drhd) } } diff --git a/src/acpi/hpet.rs b/src/acpi/hpet.rs index 56272f5..269fa60 100644 --- a/src/acpi/hpet.rs +++ b/src/acpi/hpet.rs @@ -3,8 +3,7 @@ use core::{mem, ptr}; use core::intrinsics::{volatile_load, volatile_store}; use crate::memory::Frame; -use crate::paging::{ActivePageTable, PhysicalAddress, Page, VirtualAddress}; -use crate::paging::entry::EntryFlags; +use crate::paging::{ActivePageTable, PhysicalAddress, Page, PageFlags, VirtualAddress}; use super::sdt::Sdt; use super::{ACPI_TABLE, find_sdt, load_table, get_sdt_signature}; @@ -69,7 +68,7 @@ impl GenericAddressStructure { pub unsafe fn init(&self, active_table: &mut ActivePageTable) { let page = Page::containing_address(VirtualAddress::new(self.address as usize)); let frame = Frame::containing_address(PhysicalAddress::new(self.address as usize)); - let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE); + let result = active_table.map_to(page, frame, PageFlags::new().write(true)); result.flush(); } diff --git a/src/acpi/madt.rs b/src/acpi/madt.rs index 2d95410..031598c 100644 --- a/src/acpi/madt.rs +++ b/src/acpi/madt.rs @@ -1,8 +1,7 @@ use core::mem; use crate::memory::{allocate_frames, Frame}; -use crate::paging::{ActivePageTable, Page, PhysicalAddress, VirtualAddress}; -use crate::paging::entry::EntryFlags; +use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress}; use super::sdt::Sdt; use super::{find_sdt, load_table, get_sdt_signature}; @@ -58,7 +57,7 @@ impl Madt { // Map trampoline let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)); let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); - let result = active_table.map_to(trampoline_page, trampoline_frame, EntryFlags::PRESENT | EntryFlags::WRITABLE); + let result = active_table.map_to(trampoline_page, trampoline_frame, PageFlags::new().execute(true).write(true)); //TODO: do not have writable and executable! result.flush(); // Write trampoline, make sure TRAMPOLINE page is free for use diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index 2212050..13b6743 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -14,8 +14,7 @@ use crate::stop::kstop; use crate::log::info; use crate::memory::Frame; -use crate::paging::{ActivePageTable, Page, PhysicalAddress, VirtualAddress}; -use crate::paging::entry::EntryFlags; +use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress}; use self::dmar::Dmar; use self::fadt::Fadt; @@ -45,7 +44,7 @@ pub fn get_sdt(sdt_address: usize, active_table: &mut ActivePageTable) -> &'stat let page = Page::containing_address(VirtualAddress::new(sdt_address)); if active_table.translate_page(page).is_none() { let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().data())); - let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::NO_EXECUTE); + let result = active_table.map_to(page, frame, PageFlags::new()); result.flush(); } } @@ -59,7 +58,7 @@ pub fn get_sdt(sdt_address: usize, active_table: &mut ActivePageTable) -> &'stat for page in Page::range_inclusive(start_page, end_page) { if active_table.translate_page(page).is_none() { let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().data())); - let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::NO_EXECUTE); + let result = active_table.map_to(page, frame, PageFlags::new()); result.flush(); } } diff --git a/src/acpi/rsdp.rs b/src/acpi/rsdp.rs index e64b388..d96214b 100644 --- a/src/acpi/rsdp.rs +++ b/src/acpi/rsdp.rs @@ -2,8 +2,7 @@ use core::convert::TryFrom; use core::mem; use crate::memory::Frame; -use crate::paging::{ActivePageTable, Page, PhysicalAddress, VirtualAddress}; -use crate::paging::entry::EntryFlags; +use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress}; /// RSDP #[derive(Copy, Clone, Debug)] @@ -91,7 +90,7 @@ impl RSDP { let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr)); for frame in Frame::range_inclusive(start_frame, end_frame) { let page = Page::containing_address(VirtualAddress::new(frame.start_address().data())); - let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::NO_EXECUTE); + let result = active_table.map_to(page, frame, PageFlags::new()); result.flush(); } } diff --git a/src/allocator/mod.rs b/src/allocator/mod.rs index be3ffff..0d7c939 100644 --- a/src/allocator/mod.rs +++ b/src/allocator/mod.rs @@ -1,5 +1,4 @@ -use crate::paging::{ActivePageTable, Page, VirtualAddress}; -use crate::paging::entry::EntryFlags; +use crate::paging::{ActivePageTable, Page, PageFlags, VirtualAddress}; use crate::paging::mapper::PageFlushAll; #[cfg(not(feature="slab"))] @@ -20,7 +19,7 @@ unsafe fn map_heap(active_table: &mut ActivePageTable, offset: usize, size: usiz let heap_start_page = Page::containing_address(VirtualAddress::new(offset)); let heap_end_page = Page::containing_address(VirtualAddress::new(offset + size-1)); for page in Page::range_inclusive(heap_start_page, heap_end_page) { - let result = active_table.map(page, EntryFlags::PRESENT | EntryFlags::GLOBAL | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE); + let result = active_table.map(page, PageFlags::new().write(true)); flush_all.consume(result); } diff --git a/src/arch/x86_64/device/ioapic.rs b/src/arch/x86_64/device/ioapic.rs index d980e35..54ea18a 100644 --- a/src/arch/x86_64/device/ioapic.rs +++ b/src/arch/x86_64/device/ioapic.rs @@ -8,7 +8,8 @@ use crate::acpi::madt::{self, Madt, MadtEntry, MadtIoApic, MadtIntSrcOverride}; use crate::arch::interrupt::irq; use crate::memory::Frame; -use crate::paging::{ActivePageTable, entry::EntryFlags, Page, PhysicalAddress, VirtualAddress}; +use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress}; +use crate::paging::entry::EntryFlags; use super::pic; @@ -239,7 +240,7 @@ pub unsafe fn handle_ioapic(active_table: &mut ActivePageTable, madt_ioapic: &'s assert_eq!(active_table.translate_page(page), None); - let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::GLOBAL | EntryFlags::WRITABLE | EntryFlags::NO_CACHE); + let result = active_table.map_to(page, frame, PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true)); result.flush(); let ioapic_registers = page.start_address().data() as *const u32; diff --git a/src/arch/x86_64/device/local_apic.rs b/src/arch/x86_64/device/local_apic.rs index 3c48349..4f7c515 100644 --- a/src/arch/x86_64/device/local_apic.rs +++ b/src/arch/x86_64/device/local_apic.rs @@ -4,8 +4,7 @@ use x86::cpuid::CpuId; use x86::msr::*; use crate::memory::Frame; -use crate::paging::{ActivePageTable, PhysicalAddress, Page, VirtualAddress}; -use crate::paging::entry::EntryFlags; +use crate::paging::{ActivePageTable, PhysicalAddress, Page, PageFlags, VirtualAddress}; pub static mut LOCAL_APIC: LocalApic = LocalApic { address: 0, @@ -49,7 +48,7 @@ impl LocalApic { if ! self.x2 { let page = Page::containing_address(VirtualAddress::new(self.address)); let frame = Frame::containing_address(PhysicalAddress::new(self.address - crate::PHYS_OFFSET)); - let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE); + let result = active_table.map_to(page, frame, PageFlags::new().write(true)); result.flush(); } diff --git a/src/arch/x86_64/idt.rs b/src/arch/x86_64/idt.rs index 2830444..2c50c0f 100644 --- a/src/arch/x86_64/idt.rs +++ b/src/arch/x86_64/idt.rs @@ -10,6 +10,7 @@ use x86::dtables::{self, DescriptorTablePointer}; use crate::interrupt::*; use crate::ipi::IpiKind; +use crate::paging::PageFlags; use spin::RwLock; @@ -175,7 +176,6 @@ pub unsafe fn init_generic(is_bsp: bool, idt: &mut Idt) { let base_address = { use crate::memory::{Frame, PhysicalAddress}; use crate::paging::{ActivePageTable, Page, VirtualAddress}; - use crate::paging::entry::EntryFlags; let mut active_table = ActivePageTable::new(); let base_virtual_address = VirtualAddress::new(frames.start_address().data() + crate::PHYS_OFFSET); @@ -185,7 +185,7 @@ pub unsafe fn init_generic(is_bsp: bool, idt: &mut Idt) { let physical_address = PhysicalAddress::new(frames.start_address().data() + i * crate::memory::PAGE_SIZE); let page = Page::containing_address(virtual_address); - let flags = EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE; + let flags = PageFlags::new().write(true); let flusher = if let Some(already_mapped) = active_table.translate_page(page) { assert_eq!(already_mapped.start_address(), physical_address, "address already mapped, but non-linearly"); diff --git a/src/arch/x86_64/paging/entry.rs b/src/arch/x86_64/paging/entry.rs index c3e6810..9cd85f2 100644 --- a/src/arch/x86_64/paging/entry.rs +++ b/src/arch/x86_64/paging/entry.rs @@ -3,25 +3,23 @@ use crate::memory::Frame; -use super::{PhysicalAddress, RmmA, RmmArch}; +use super::{PageFlags, PhysicalAddress, RmmA, RmmArch}; /// A page table entry #[repr(packed(8))] pub struct Entry(u64); bitflags! { - pub struct EntryFlags: u64 { - const PRESENT = RmmA::ENTRY_FLAG_PRESENT as u64; - const WRITABLE = RmmA::ENTRY_FLAG_READWRITE as u64; - const USER_ACCESSIBLE = RmmA::ENTRY_FLAG_USER as u64; + pub struct EntryFlags: usize { + const PRESENT = RmmA::ENTRY_FLAG_PRESENT; + const WRITABLE = RmmA::ENTRY_FLAG_READWRITE; + const USER_ACCESSIBLE = RmmA::ENTRY_FLAG_USER; const NO_CACHE = 1 << 4; const HUGE_PAGE = 1 << 7; - const GLOBAL = 1 << 8; - const NO_EXECUTE = RmmA::ENTRY_FLAG_NO_EXEC as u64; + const NO_EXECUTE = RmmA::ENTRY_FLAG_NO_EXEC; } } -pub const ADDRESS_MASK: usize = 0x000f_ffff_ffff_f000; pub const COUNTER_MASK: u64 = 0x3ff0_0000_0000_0000; impl Entry { @@ -42,26 +40,26 @@ impl Entry { /// Get the address this page references pub fn address(&self) -> PhysicalAddress { - PhysicalAddress::new(self.0 as usize & ADDRESS_MASK) + PhysicalAddress::new(self.0 as usize & RmmA::PAGE_ADDRESS_MASK) } /// Get the current entry flags - pub fn flags(&self) -> EntryFlags { - EntryFlags::from_bits_truncate(self.0) + pub fn flags(&self) -> PageFlags { + unsafe { PageFlags::from_data((self.0 as usize & RmmA::ENTRY_FLAGS_MASK) & !(COUNTER_MASK as usize)) } } /// Get the associated frame, if available pub fn pointed_frame(&self) -> Option { - if self.flags().contains(EntryFlags::PRESENT) { + if self.flags().has_present() { Some(Frame::containing_address(self.address())) } else { None } } - pub fn set(&mut self, frame: Frame, flags: EntryFlags) { - debug_assert!(frame.start_address().data() & !ADDRESS_MASK == 0); - self.0 = (frame.start_address().data() as u64) | flags.bits() | (self.0 & COUNTER_MASK); + pub fn set(&mut self, frame: Frame, flags: PageFlags) { + debug_assert!(frame.start_address().data() & !RmmA::PAGE_ADDRESS_MASK == 0); + self.0 = (frame.start_address().data() as u64) | (flags.data() as u64) | (self.0 & COUNTER_MASK); } /// Get bits 52-61 in entry, used as counter for page table diff --git a/src/arch/x86_64/paging/mapper.rs b/src/arch/x86_64/paging/mapper.rs index fd0a550..c2308e4 100644 --- a/src/arch/x86_64/paging/mapper.rs +++ b/src/arch/x86_64/paging/mapper.rs @@ -2,8 +2,7 @@ use core::ptr::Unique; use crate::memory::{allocate_frames, deallocate_frames, Frame}; -use super::{Page, PAGE_SIZE, PhysicalAddress, VirtualAddress}; -use super::entry::EntryFlags; +use super::{Page, PAGE_SIZE, PageFlags, PhysicalAddress, VirtualAddress}; use super::table::{self, Table, Level4}; use super::RmmA; @@ -31,7 +30,7 @@ impl Mapper { } /// Map a page to a frame - pub fn map_to(&mut self, page: Page, frame: Frame, flags: EntryFlags) -> PageFlush { + pub fn map_to(&mut self, page: Page, frame: Frame, flags: PageFlags) -> PageFlush { let p3 = self.p4_mut().next_table_create(page.p4_index()); let p2 = p3.next_table_create(page.p3_index()); let p1 = p2.next_table_create(page.p2_index()); @@ -42,28 +41,28 @@ impl Mapper { p1[page.p1_index()].address().data(), p1[page.p1_index()].flags(), frame.start_address().data(), flags); p1.increment_entry_count(); - p1[page.p1_index()].set(frame, flags | EntryFlags::PRESENT); + p1[page.p1_index()].set(frame, flags); PageFlush::new(page.start_address()) } /// Map a page to the next free frame - pub fn map(&mut self, page: Page, flags: EntryFlags) -> PageFlush { + pub fn map(&mut self, page: Page, flags: PageFlags) -> PageFlush { let frame = allocate_frames(1).expect("out of frames"); self.map_to(page, frame, flags) } /// Update flags for a page - pub fn remap(&mut self, page: Page, flags: EntryFlags) -> PageFlush { + pub fn remap(&mut self, page: Page, flags: PageFlags) -> PageFlush { let p3 = self.p4_mut().next_table_mut(page.p4_index()).expect("failed to remap: no p3"); let p2 = p3.next_table_mut(page.p3_index()).expect("failed to remap: no p2"); let p1 = p2.next_table_mut(page.p2_index()).expect("failed to remap: no p1"); let frame = p1[page.p1_index()].pointed_frame().expect("failed to remap: not mapped"); - p1[page.p1_index()].set(frame, flags | EntryFlags::PRESENT); + p1[page.p1_index()].set(frame, flags); PageFlush::new(page.start_address()) } /// Identity map a frame - pub fn identity_map(&mut self, frame: Frame, flags: EntryFlags) -> PageFlush { + pub fn identity_map(&mut self, frame: Frame, flags: PageFlags) -> PageFlush { let page = Page::containing_address(VirtualAddress::new(frame.start_address().data())); self.map_to(page, frame, flags) } @@ -155,7 +154,7 @@ impl Mapper { .and_then(|p1| p1[page.p1_index()].pointed_frame()) } - pub fn translate_page_flags(&self, page: Page) -> Option { + pub fn translate_page_flags(&self, page: Page) -> Option> { self.p4().next_table(page.p4_index()) .and_then(|p3| p3.next_table(page.p3_index())) .and_then(|p2| p2.next_table(page.p2_index())) diff --git a/src/arch/x86_64/paging/mod.rs b/src/arch/x86_64/paging/mod.rs index dd1a8de..d3f77ff 100644 --- a/src/arch/x86_64/paging/mod.rs +++ b/src/arch/x86_64/paging/mod.rs @@ -8,12 +8,12 @@ use x86::msr; use crate::memory::Frame; -use self::entry::EntryFlags; use self::mapper::{Mapper, PageFlushAll}; use self::temporary_page::TemporaryPage; pub use rmm::{ Arch as RmmArch, + PageFlags, PhysicalAddress, VirtualAddress, X8664Arch as RmmA, @@ -114,13 +114,7 @@ unsafe fn map_tss(cpu_id: usize, mapper: &mut Mapper) -> PageFlushAll { let start_page = Page::containing_address(VirtualAddress::new(start)); let end_page = Page::containing_address(VirtualAddress::new(end - 1)); for page in Page::range_inclusive(start_page, end_page) { - let result = mapper.map( - page, - EntryFlags::PRESENT - | EntryFlags::GLOBAL - | EntryFlags::NO_EXECUTE - | EntryFlags::WRITABLE, - ); + let result = mapper.map(page, PageFlags::new().write(true)); flush_all.consume(result); } flush_all @@ -302,14 +296,14 @@ impl ActivePageTable { // map temporary_page to current p4 table let p4_table = temporary_page.map_table_frame( backup.clone(), - EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE, + PageFlags::new_table().write(true), //TODO: RISC-V will not like this self, ); // overwrite recursive mapping self.p4_mut()[crate::RECURSIVE_PAGE_PML4].set( table.frame.clone(), - EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE, + PageFlags::new_table().write(true), //TODO: RISC-V will not like this ); self.flush_all(); @@ -319,7 +313,7 @@ impl ActivePageTable { // restore recursive mapping to original p4 table p4_table[crate::RECURSIVE_PAGE_PML4].set( backup, - EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE, + PageFlags::new_table().write(true), //TODO: RISC-V will not like this ); self.flush_all(); } @@ -354,7 +348,7 @@ impl InactivePageTable { { let table = temporary_page.map_table_frame( frame.clone(), - EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE, + PageFlags::new_table().write(true), //TODO: RISC-V will not like this active_table, ); // now we are able to zero the table @@ -362,7 +356,7 @@ impl InactivePageTable { // set up recursive mapping for the table table[crate::RECURSIVE_PAGE_PML4].set( frame.clone(), - EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE, + PageFlags::new_table().write(true), //TODO: RISC-V will not like this ); } temporary_page.unmap(active_table); diff --git a/src/arch/x86_64/paging/table.rs b/src/arch/x86_64/paging/table.rs index a6f45c5..7023b11 100644 --- a/src/arch/x86_64/paging/table.rs +++ b/src/arch/x86_64/paging/table.rs @@ -6,8 +6,8 @@ use core::ops::{Index, IndexMut}; use crate::memory::allocate_frames; -use super::entry::{EntryFlags, Entry}; -use super::ENTRY_COUNT; +use super::{ENTRY_COUNT, PageFlags}; +use super::entry::{Entry, EntryFlags}; pub const P4: *mut Table = (crate::RECURSIVE_PAGE_OFFSET | 0x7f_ffff_f000) as *mut _; @@ -93,11 +93,12 @@ impl Table where L: HierarchicalLevel { pub fn next_table_create(&mut self, index: usize) -> &mut Table { if self.next_table(index).is_none() { - assert!(!self[index].flags().contains(EntryFlags::HUGE_PAGE), + assert!(!self[index].flags().has_flag(EntryFlags::HUGE_PAGE.bits()), "next_table_create does not support huge pages"); let frame = allocate_frames(1).expect("no frames available"); self.increment_entry_count(); - self[index].set(frame, EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE /* Allow users to go down the page table, implement permissions at the page level */); + //TODO: RISC-V will not like this + self[index].set(frame, PageFlags::new_table().execute(true).write(true).user(true) /* Allow users to go down the page table, implement permissions at the page level */); self.next_table_mut(index).unwrap().zero(); } self.next_table_mut(index).unwrap() @@ -105,7 +106,7 @@ impl Table where L: HierarchicalLevel { fn next_table_address(&self, index: usize) -> Option { let entry_flags = self[index].flags(); - if entry_flags.contains(EntryFlags::PRESENT) && !entry_flags.contains(EntryFlags::HUGE_PAGE) { + if entry_flags.has_present() && !entry_flags.has_flag(EntryFlags::HUGE_PAGE.bits()) { let table_address = self as *const _ as usize; Some((table_address << 9) | (index << 12)) } else { diff --git a/src/arch/x86_64/paging/temporary_page.rs b/src/arch/x86_64/paging/temporary_page.rs index a599dcb..c8427cc 100644 --- a/src/arch/x86_64/paging/temporary_page.rs +++ b/src/arch/x86_64/paging/temporary_page.rs @@ -3,8 +3,7 @@ use crate::memory::Frame; -use super::{ActivePageTable, Page, VirtualAddress}; -use super::entry::EntryFlags; +use super::{ActivePageTable, Page, PageFlags, RmmA, VirtualAddress}; use super::table::{Table, Level1}; pub struct TemporaryPage { @@ -22,7 +21,7 @@ impl TemporaryPage { /// Maps the temporary page to the given frame in the active table. /// Returns the start address of the temporary page. - pub fn map(&mut self, frame: Frame, flags: EntryFlags, active_table: &mut ActivePageTable) -> VirtualAddress { + pub fn map(&mut self, frame: Frame, flags: PageFlags, active_table: &mut ActivePageTable) -> VirtualAddress { assert!(active_table.translate_page(self.page).is_none(), "temporary page is already mapped"); let result = active_table.map_to(self.page, frame, flags); result.flush(); @@ -31,7 +30,7 @@ impl TemporaryPage { /// Maps the temporary page to the given page table frame in the active /// table. Returns a reference to the now mapped table. - pub fn map_table_frame(&mut self, frame: Frame, flags: EntryFlags, active_table: &mut ActivePageTable) -> &mut Table { + pub fn map_table_frame(&mut self, frame: Frame, flags: PageFlags, active_table: &mut ActivePageTable) -> &mut Table { unsafe { &mut *(self.map(frame, flags, active_table).data() as *mut Table) } } diff --git a/src/arch/x86_64/rmm.rs b/src/arch/x86_64/rmm.rs index b87ba74..640f60c 100644 --- a/src/arch/x86_64/rmm.rs +++ b/src/arch/x86_64/rmm.rs @@ -12,7 +12,7 @@ use rmm::{ PageMapper, PhysicalAddress, VirtualAddress, - X8664Arch, + X8664Arch as RmmA, }; use spin::Mutex; @@ -41,13 +41,13 @@ unsafe fn page_flags(virt: VirtualAddress) -> PageFlags { if in_section!(text) { // Remap text read-only, execute - PageFlags::new().write(false).execute(true) + PageFlags::new().execute(true) } else if in_section!(rodata) { // Remap rodata read-only, no execute - PageFlags::new().write(false).execute(false) + PageFlags::new() } else { // Remap everything else writable, no execute - PageFlags::new().write(true).execute(false) + PageFlags::new().write(true) } } @@ -126,7 +126,7 @@ unsafe fn inner(areas: &'static [MemoryArea], kernel_base: usize, kerne } pub struct LockedAllocator { - inner: Mutex>>, + inner: Mutex>>, } impl LockedAllocator { @@ -168,21 +168,21 @@ static mut AREAS: [MemoryArea; 512] = [MemoryArea { pub static mut FRAME_ALLOCATOR: LockedAllocator = LockedAllocator::new(); -pub unsafe fn mapper_new(table_addr: PhysicalAddress) -> PageMapper<'static, X8664Arch, LockedAllocator> { +pub unsafe fn mapper_new(table_addr: PhysicalAddress) -> PageMapper<'static, RmmA, LockedAllocator> { PageMapper::new(table_addr, &mut FRAME_ALLOCATOR) } //TODO: global paging lock? -pub unsafe fn mapper_create() -> Option> { +pub unsafe fn mapper_create() -> Option> { PageMapper::create(&mut FRAME_ALLOCATOR) } -pub unsafe fn mapper_current() -> PageMapper<'static, X8664Arch, LockedAllocator> { +pub unsafe fn mapper_current() -> PageMapper<'static, RmmA, LockedAllocator> { PageMapper::current(&mut FRAME_ALLOCATOR) } pub unsafe fn init(kernel_base: usize, kernel_size: usize) { - type A = X8664Arch; + type A = RmmA; let kernel_size_aligned = ((kernel_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE; let kernel_end = kernel_base + kernel_size_aligned; diff --git a/src/context/memory.rs b/src/context/memory.rs index c3b9ad9..1b8b6dd 100644 --- a/src/context/memory.rs +++ b/src/context/memory.rs @@ -15,8 +15,7 @@ use crate::arch::paging::PAGE_SIZE; use crate::context::file::FileDescriptor; use crate::ipi::{ipi, IpiKind, IpiTarget}; use crate::memory::Frame; -use crate::paging::{ActivePageTable, InactivePageTable, Page, PageIter, PhysicalAddress, VirtualAddress}; -use crate::paging::entry::EntryFlags; +use crate::paging::{ActivePageTable, InactivePageTable, Page, PageFlags, PageIter, PhysicalAddress, RmmA, VirtualAddress}; use crate::paging::mapper::PageFlushAll; use crate::paging::temporary_page::TemporaryPage; @@ -29,20 +28,12 @@ pub fn round_up_pages(number: usize) -> usize { round_down_pages(number + PAGE_SIZE - 1) } -pub fn entry_flags(flags: MapFlags) -> EntryFlags { - let mut entry_flags = EntryFlags::PRESENT | EntryFlags::USER_ACCESSIBLE; - - if !flags.contains(MapFlags::PROT_EXEC) { - entry_flags |= EntryFlags::NO_EXECUTE; - } - if flags.contains(MapFlags::PROT_READ) { +pub fn page_flags(flags: MapFlags) -> PageFlags { + PageFlags::new() + .user(true) + .execute(flags.contains(MapFlags::PROT_EXEC)) + .write(flags.contains(MapFlags::PROT_WRITE)) //TODO: PROT_READ - } - if flags.contains(MapFlags::PROT_WRITE) { - entry_flags |= EntryFlags::WRITABLE; - } - - entry_flags } #[derive(Debug, Default)] @@ -293,7 +284,7 @@ impl<'a> From<&'a Grant> for Region { #[derive(Debug)] pub struct Grant { region: Region, - flags: EntryFlags, + flags: PageFlags, mapped: bool, owned: bool, //TODO: This is probably a very heavy way to keep track of fmap'd files, perhaps move to the context? @@ -311,7 +302,7 @@ impl Grant { &mut self.region } - pub fn physmap(from: PhysicalAddress, to: VirtualAddress, size: usize, flags: EntryFlags) -> Grant { + pub fn physmap(from: PhysicalAddress, to: VirtualAddress, size: usize, flags: PageFlags) -> Grant { let mut active_table = unsafe { ActivePageTable::new() }; let flush_all = PageFlushAll::new(); @@ -338,7 +329,7 @@ impl Grant { } } - pub fn map(to: VirtualAddress, size: usize, flags: EntryFlags) -> Grant { + pub fn map(to: VirtualAddress, size: usize, flags: PageFlags) -> Grant { let mut active_table = unsafe { ActivePageTable::new() }; let flush_all = PageFlushAll::new(); @@ -364,7 +355,7 @@ impl Grant { } } - pub fn map_inactive(from: VirtualAddress, to: VirtualAddress, size: usize, flags: EntryFlags, desc_opt: Option, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage) -> Grant { + pub fn map_inactive(from: VirtualAddress, to: VirtualAddress, size: usize, flags: PageFlags, desc_opt: Option, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage) -> Grant { let mut active_table = unsafe { ActivePageTable::new() }; //TODO: Do not allocate @@ -419,7 +410,7 @@ impl Grant { let new_page = Page::containing_address(VirtualAddress::new(page.start_address().data() - self.region.start.data() + new_start.data())); if self.owned { - let result = active_table.map(new_page, EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE); + let result = active_table.map(new_page, PageFlags::new().write(true)); flush_all.consume(result); } else { let result = active_table.map_to(new_page, frame, flags); @@ -488,7 +479,7 @@ impl Grant { self.region.start = new_start; } - pub fn flags(&self) -> EntryFlags { + pub fn flags(&self) -> PageFlags { self.flags } @@ -664,11 +655,11 @@ impl SharedMemory { pub struct Memory { start: VirtualAddress, size: usize, - flags: EntryFlags + flags: PageFlags, } impl Memory { - pub fn new(start: VirtualAddress, size: usize, flags: EntryFlags, clear: bool) -> Self { + pub fn new(start: VirtualAddress, size: usize, flags: PageFlags, clear: bool) -> Self { let mut memory = Memory { start, size, @@ -692,7 +683,7 @@ impl Memory { self.size } - pub fn flags(&self) -> EntryFlags { + pub fn flags(&self) -> PageFlags { self.flags } @@ -715,7 +706,7 @@ impl Memory { flush_all.flush(); if clear { - assert!(self.flags.contains(EntryFlags::WRITABLE)); + assert!(self.flags.has_write()); unsafe { intrinsics::write_bytes(self.start_address().data() as *mut u8, 0, self.size); } @@ -759,7 +750,7 @@ impl Memory { self.start = new_start; } - pub fn remap(&mut self, new_flags: EntryFlags) { + pub fn remap(&mut self, new_flags: PageFlags) { let mut active_table = unsafe { ActivePageTable::new() }; let flush_all = PageFlushAll::new(); diff --git a/src/ptrace.rs b/src/ptrace.rs index 6f9ab01..2528cd8 100644 --- a/src/ptrace.rs +++ b/src/ptrace.rs @@ -6,7 +6,6 @@ use crate::{ arch::{ interrupt::InterruptStack, paging::{ - entry::EntryFlags, mapper::PageFlushAll, temporary_page::TemporaryPage, ActivePageTable, InactivePageTable, Page, PAGE_SIZE, VirtualAddress @@ -488,7 +487,7 @@ where F: FnOnce(*mut u8) -> Result<()> let mut page = start; let flush_all = PageFlushAll::new(); for (frame, mut flags) in frames { - flags |= EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE; + flags = flags.execute(false).write(true); flush_all.consume(active_page_table.map_to(page, frame, flags)); page = page.next(); diff --git a/src/scheme/memory.rs b/src/scheme/memory.rs index 0fd0247..5a812e6 100644 --- a/src/scheme/memory.rs +++ b/src/scheme/memory.rs @@ -1,5 +1,5 @@ use crate::context; -use crate::context::memory::{entry_flags, Grant}; +use crate::context::memory::{page_flags, Grant}; use crate::memory::{free_frames, used_frames, PAGE_SIZE}; use crate::paging::{ActivePageTable, VirtualAddress}; use crate::syscall::data::{Map, OldMap, StatVfs}; @@ -58,7 +58,7 @@ impl Scheme for MemoryScheme { } } - grants.insert(Grant::map(region.start_address(), region.size(), entry_flags(map.flags))); + grants.insert(Grant::map(region.start_address(), region.size(), page_flags(map.flags))); Ok(region.start_address().data()) } diff --git a/src/scheme/user.rs b/src/scheme/user.rs index b62e581..7959413 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -8,7 +8,7 @@ use spin::{Mutex, RwLock}; use crate::context::{self, Context}; use crate::context::file::FileDescriptor; -use crate::context::memory::{entry_flags, round_down_pages, Grant, Region}; +use crate::context::memory::{page_flags, round_down_pages, Grant, Region}; use crate::event; use crate::paging::{PAGE_SIZE, InactivePageTable, Page, VirtualAddress}; use crate::paging::temporary_page::TemporaryPage; @@ -163,7 +163,7 @@ impl UserInner { from_region.start_address(), to_region.start_address(), from_region.size(), - entry_flags(flags), + page_flags(flags), desc_opt, &mut new_table, &mut temporary_page diff --git a/src/syscall/driver.rs b/src/syscall/driver.rs index eb64f36..9d73f1b 100644 --- a/src/syscall/driver.rs +++ b/src/syscall/driver.rs @@ -1,6 +1,6 @@ use crate::interrupt::InterruptStack; use crate::memory::{allocate_frames_complex, deallocate_frames, Frame}; -use crate::paging::{ActivePageTable, PhysicalAddress, VirtualAddress}; +use crate::paging::{ActivePageTable, PageFlags, PhysicalAddress, VirtualAddress}; use crate::paging::entry::EntryFlags; use crate::context; use crate::context::memory::{Grant, Region}; @@ -81,15 +81,15 @@ pub fn inner_physmap(physical_address: usize, size: usize, flags: PhysmapFlags) let full_size = ((offset + size + 4095)/4096) * 4096; let mut to_address = crate::USER_GRANT_OFFSET; - let mut entry_flags = EntryFlags::PRESENT | EntryFlags::NO_EXECUTE | EntryFlags::USER_ACCESSIBLE; + let mut page_flags = PageFlags::new().user(true); if flags.contains(PHYSMAP_WRITE) { - entry_flags |= EntryFlags::WRITABLE; + page_flags = page_flags.write(true); } if flags.contains(PHYSMAP_WRITE_COMBINE) { - entry_flags |= EntryFlags::HUGE_PAGE; + page_flags = page_flags.custom_flag(EntryFlags::HUGE_PAGE.bits(), true); } if flags.contains(PHYSMAP_NO_CACHE) { - entry_flags |= EntryFlags::NO_CACHE; + page_flags = page_flags.custom_flag(EntryFlags::NO_CACHE.bits(), true); } // TODO: Make this faster than Sonic himself by using le superpowers of BTreeSet @@ -109,7 +109,7 @@ pub fn inner_physmap(physical_address: usize, size: usize, flags: PhysmapFlags) PhysicalAddress::new(from_address), VirtualAddress::new(to_address), full_size, - entry_flags + page_flags )); Ok(to_address + offset) diff --git a/src/syscall/process.rs b/src/syscall/process.rs index cd40508..588b4ca 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -19,10 +19,9 @@ use crate::elf::{self, program_header}; use crate::interrupt; use crate::ipi::{ipi, IpiKind, IpiTarget}; use crate::memory::allocate_frames; -use crate::paging::entry::EntryFlags; use crate::paging::mapper::PageFlushAll; use crate::paging::temporary_page::TemporaryPage; -use crate::paging::{ActivePageTable, InactivePageTable, Page, VirtualAddress, PAGE_SIZE}; +use crate::paging::{ActivePageTable, InactivePageTable, Page, PageFlags, VirtualAddress, PAGE_SIZE}; use crate::{ptrace, syscall}; use crate::scheme::FileHandle; use crate::start::usermode; @@ -132,7 +131,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result { let mut new_memory = context::memory::Memory::new( VirtualAddress::new(memory.start_address().data() + crate::USER_TMP_OFFSET), memory.size(), - EntryFlags::PRESENT | EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE, + PageFlags::new().write(true), false ); @@ -156,7 +155,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result { let mut new_stack = context::memory::Memory::new( VirtualAddress::new(crate::USER_TMP_STACK_OFFSET), stack.size(), - EntryFlags::PRESENT | EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE, + PageFlags::new().write(true), false ); @@ -176,7 +175,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result { let mut new_sigstack = context::memory::Memory::new( VirtualAddress::new(crate::USER_TMP_SIGSTACK_OFFSET), sigstack.size(), - EntryFlags::PRESENT | EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE, + PageFlags::new().write(true), false ); @@ -197,7 +196,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result { mem: context::memory::Memory::new( VirtualAddress::new(crate::USER_TMP_TLS_OFFSET), tls.mem.size(), - EntryFlags::PRESENT | EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE, + PageFlags::new().write(true), true ), offset: tls.offset, @@ -432,7 +431,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result { for page in Page::range_inclusive(start_page, end_page) { let frame = active_table.translate_page(page).expect("kernel percpu not mapped"); active_table.with(&mut new_table, &mut temporary_page, |mapper| { - let result = mapper.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE); + let result = mapper.map_to(page, frame, PageFlags::new().write(true)); // Ignore result due to operating on inactive table unsafe { result.ignore(); } }); @@ -489,7 +488,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result { let mut tcb = context::memory::Memory::new( VirtualAddress::new(tcb_addr), PAGE_SIZE, - EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE, + PageFlags::new().write(true).user(true), true ); @@ -656,7 +655,7 @@ fn fexec_noreturn( let tcb_mem = context::memory::Memory::new( VirtualAddress::new(tcb_addr), PAGE_SIZE, - EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE, + PageFlags::new().write(true).user(true), true ); @@ -669,7 +668,7 @@ fn fexec_noreturn( let mut memory = context::memory::Memory::new( VirtualAddress::new(vaddr), segment.p_memsz as usize + voff, - EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE, + PageFlags::new().write(true), true ); @@ -680,17 +679,13 @@ fn fexec_noreturn( segment.p_filesz as usize); } - let mut flags = EntryFlags::NO_EXECUTE | EntryFlags::USER_ACCESSIBLE; - - if segment.p_flags & program_header::PF_R == program_header::PF_R { - flags.insert(EntryFlags::PRESENT); - } + let mut flags = PageFlags::new().user(true); // W ^ X. If it is executable, do not allow it to be writable, even if requested if segment.p_flags & program_header::PF_X == program_header::PF_X { - flags.remove(EntryFlags::NO_EXECUTE); + flags = flags.execute(true); } else if segment.p_flags & program_header::PF_W == program_header::PF_W { - flags.insert(EntryFlags::WRITABLE); + flags = flags.write(true); } memory.remap(flags); @@ -714,7 +709,7 @@ fn fexec_noreturn( mem: context::memory::Memory::new( VirtualAddress::new(tls_addr), rounded_size as usize, - EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE, + PageFlags::new().write(true).user(true), true ), offset: rounded_offset as usize, @@ -740,7 +735,7 @@ fn fexec_noreturn( context.stack = Some(context::memory::Memory::new( VirtualAddress::new(crate::USER_STACK_OFFSET), crate::USER_STACK_SIZE, - EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE, + PageFlags::new().write(true).user(true), true ).to_shared()); @@ -748,7 +743,7 @@ fn fexec_noreturn( context.sigstack = Some(context::memory::Memory::new( VirtualAddress::new(crate::USER_SIGSTACK_OFFSET), crate::USER_SIGSTACK_SIZE, - EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE, + PageFlags::new().write(true).user(true), true )); @@ -799,7 +794,7 @@ fn fexec_noreturn( let mut memory = context::memory::Memory::new( VirtualAddress::new(crate::USER_ARG_OFFSET), arg_size, - EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE, + PageFlags::new().write(true), true ); @@ -818,7 +813,7 @@ fn fexec_noreturn( arg_offset += 1; } - memory.remap(EntryFlags::NO_EXECUTE | EntryFlags::USER_ACCESSIBLE); + memory.remap(PageFlags::new().user(true)); context.image.push(memory.to_shared()); } @@ -1329,21 +1324,21 @@ pub fn mprotect(address: usize, size: usize, flags: MapFlags) -> Result { flush_all.flush(); return Err(Error::new(EFAULT)); }; - if !page_flags.contains(EntryFlags::PRESENT) { + if !page_flags.has_present() { flush_all.flush(); return Err(Error::new(EFAULT)); } if flags.contains(PROT_EXEC) { - page_flags.remove(EntryFlags::NO_EXECUTE); + page_flags = page_flags.execute(true); } else { - page_flags.insert(EntryFlags::NO_EXECUTE); + page_flags = page_flags.execute(false); } if flags.contains(PROT_WRITE) { //TODO: Not allowing gain of write privileges } else { - page_flags.remove(EntryFlags::WRITABLE); + page_flags = page_flags.write(false); } if flags.contains(PROT_READ) { diff --git a/src/syscall/validate.rs b/src/syscall/validate.rs index 0f2633f..6ae3502 100644 --- a/src/syscall/validate.rs +++ b/src/syscall/validate.rs @@ -1,10 +1,9 @@ use core::{mem, slice, str}; use crate::paging::{ActivePageTable, Page, VirtualAddress}; -use crate::paging::entry::EntryFlags; use crate::syscall::error::*; -fn validate(address: usize, size: usize, flags: EntryFlags) -> Result<()> { +fn validate(address: usize, size: usize, writable: bool) -> Result<()> { let end_offset = size.checked_sub(1).ok_or(Error::new(EFAULT))?; let end_address = address.checked_add(end_offset).ok_or(Error::new(EFAULT))?; @@ -14,12 +13,17 @@ fn validate(address: usize, size: usize, flags: EntryFlags) -> Result<()> { let end_page = Page::containing_address(VirtualAddress::new(end_address)); for page in Page::range_inclusive(start_page, end_page) { if let Some(page_flags) = active_table.translate_page_flags(page) { - if ! page_flags.contains(flags) { - //println!("{:X}: Not {:?}", page.start_address().data(), flags); + if ! page_flags.has_user() { + // println!("{:X}: Not usermode", page.start_address().data()); + return Err(Error::new(EFAULT)); + } + + if writable && ! page_flags.has_write() { + // println!("{:X}: Not writable {}", page.start_address().data(), writable); return Err(Error::new(EFAULT)); } } else { - //println!("{:X}: Not found", page.start_address().data()); + // println!("{:X}: Not found", page.start_address().data()); return Err(Error::new(EFAULT)); } } @@ -33,7 +37,7 @@ pub fn validate_slice(ptr: *const T, len: usize) -> Result<&'static [T]> { if len == 0 { Ok(&[]) } else { - validate(ptr as usize, len * mem::size_of::(), EntryFlags::PRESENT | EntryFlags::USER_ACCESSIBLE)?; + validate(ptr as usize, len * mem::size_of::(), false)?; Ok(unsafe { slice::from_raw_parts(ptr, len) }) } } @@ -44,7 +48,7 @@ pub fn validate_slice_mut(ptr: *mut T, len: usize) -> Result<&'static mut [T] if len == 0 { Ok(&mut []) } else { - validate(ptr as usize, len * mem::size_of::(), EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE)?; + validate(ptr as usize, len * mem::size_of::(), true)?; Ok(unsafe { slice::from_raw_parts_mut(ptr, len) }) } }