Switch to using RMM PageFlags

This commit is contained in:
Jeremy Soller
2021-05-03 17:28:08 -06:00
parent 826180659c
commit b9448274fc
22 changed files with 126 additions and 152 deletions

View File

@@ -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) }
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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");

View File

@@ -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<RmmA> {
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<Frame> {
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<RmmA>) {
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

View File

@@ -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<RmmA> {
pub fn map_to(&mut self, page: Page, frame: Frame, flags: PageFlags<RmmA>) -> PageFlush<RmmA> {
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<RmmA> {
pub fn map(&mut self, page: Page, flags: PageFlags<RmmA>) -> PageFlush<RmmA> {
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<RmmA> {
pub fn remap(&mut self, page: Page, flags: PageFlags<RmmA>) -> PageFlush<RmmA> {
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<RmmA> {
pub fn identity_map(&mut self, frame: Frame, flags: PageFlags<RmmA>) -> PageFlush<RmmA> {
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<EntryFlags> {
pub fn translate_page_flags(&self, page: Page) -> Option<PageFlags<RmmA>> {
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()))

View File

@@ -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<RmmA> {
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);

View File

@@ -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<Level4> = (crate::RECURSIVE_PAGE_OFFSET | 0x7f_ffff_f000) as *mut _;
@@ -93,11 +93,12 @@ impl<L> Table<L> where L: HierarchicalLevel {
pub fn next_table_create(&mut self, index: usize) -> &mut Table<L::NextLevel> {
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<L> Table<L> where L: HierarchicalLevel {
fn next_table_address(&self, index: usize) -> Option<usize> {
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 {

View File

@@ -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<RmmA>, 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<Level1> {
pub fn map_table_frame(&mut self, frame: Frame, flags: PageFlags<RmmA>, active_table: &mut ActivePageTable) -> &mut Table<Level1> {
unsafe { &mut *(self.map(frame, flags, active_table).data() as *mut Table<Level1>) }
}

View File

@@ -12,7 +12,7 @@ use rmm::{
PageMapper,
PhysicalAddress,
VirtualAddress,
X8664Arch,
X8664Arch as RmmA,
};
use spin::Mutex;
@@ -41,13 +41,13 @@ unsafe fn page_flags<A: Arch>(virt: VirtualAddress) -> PageFlags<A> {
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<A: Arch>(areas: &'static [MemoryArea], kernel_base: usize, kerne
}
pub struct LockedAllocator {
inner: Mutex<Option<BuddyAllocator<X8664Arch>>>,
inner: Mutex<Option<BuddyAllocator<RmmA>>>,
}
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<PageMapper<'static, X8664Arch, LockedAllocator>> {
pub unsafe fn mapper_create() -> Option<PageMapper<'static, RmmA, LockedAllocator>> {
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;

View File

@@ -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<RmmA> {
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<RmmA>,
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<RmmA>) -> 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<RmmA>) -> 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<FileDescriptor>, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage) -> Grant {
pub fn map_inactive(from: VirtualAddress, to: VirtualAddress, size: usize, flags: PageFlags<RmmA>, desc_opt: Option<FileDescriptor>, 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<RmmA> {
self.flags
}
@@ -664,11 +655,11 @@ impl SharedMemory {
pub struct Memory {
start: VirtualAddress,
size: usize,
flags: EntryFlags
flags: PageFlags<RmmA>,
}
impl Memory {
pub fn new(start: VirtualAddress, size: usize, flags: EntryFlags, clear: bool) -> Self {
pub fn new(start: VirtualAddress, size: usize, flags: PageFlags<RmmA>, 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<RmmA> {
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<RmmA>) {
let mut active_table = unsafe { ActivePageTable::new() };
let flush_all = PageFlushAll::new();

View File

@@ -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();

View File

@@ -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())
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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<ContextId> {
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<ContextId> {
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<ContextId> {
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<ContextId> {
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<ContextId> {
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<ContextId> {
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<usize> {
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) {

View File

@@ -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<T>(ptr: *const T, len: usize) -> Result<&'static [T]> {
if len == 0 {
Ok(&[])
} else {
validate(ptr as usize, len * mem::size_of::<T>(), EntryFlags::PRESENT | EntryFlags::USER_ACCESSIBLE)?;
validate(ptr as usize, len * mem::size_of::<T>(), false)?;
Ok(unsafe { slice::from_raw_parts(ptr, len) })
}
}
@@ -44,7 +48,7 @@ pub fn validate_slice_mut<T>(ptr: *mut T, len: usize) -> Result<&'static mut [T]
if len == 0 {
Ok(&mut [])
} else {
validate(ptr as usize, len * mem::size_of::<T>(), EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE)?;
validate(ptr as usize, len * mem::size_of::<T>(), true)?;
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
}
}