Merge branch 'riscv' into 'master'

Fixes and changes to make RISC-V paging work

See merge request redox-os/rmm!14
This commit is contained in:
Jeremy Soller
2024-09-24 12:51:39 +00:00
11 changed files with 122 additions and 84 deletions
+6 -4
View File
@@ -11,26 +11,28 @@ impl Arch for AArch64Arch {
const PAGE_LEVELS: usize = 4; // L0, L1, L2, L3
//TODO
const ENTRY_ADDRESS_SHIFT: usize = 52;
const ENTRY_ADDRESS_WIDTH: usize = 40;
const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT
| 1 << 1 // Page flag
| 1 << 10 // Access flag
| Self::ENTRY_FLAG_NO_GLOBAL;
const ENTRY_FLAG_DEFAULT_TABLE: usize
= Self::ENTRY_FLAG_PRESENT
| Self::ENTRY_FLAG_READWRITE
| 1 << 1 // Table flag
| 1 << 10 // Access flag
;
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
const ENTRY_FLAG_READONLY: usize = 1 << 7;
const ENTRY_FLAG_READWRITE: usize = 0;
const ENTRY_FLAG_USER: usize = 1 << 6;
const ENTRY_FLAG_PAGE_USER: usize = 1 << 6;
// This sets both userspace and privileged execute never
//TODO: Separate the two?
const ENTRY_FLAG_NO_EXEC: usize = 0b11 << 53;
const ENTRY_FLAG_EXEC: usize = 0;
const ENTRY_FLAG_GLOBAL: usize = 0;
const ENTRY_FLAG_NO_GLOBAL: usize = 1 << 11;
const ENTRY_FLAG_WRITE_COMBINING: usize = 0;
const PHYS_OFFSET: usize = 0xFFFF_8000_0000_0000;
@@ -110,8 +112,8 @@ mod tests {
assert_eq!(AArch64Arch::PAGE_ENTRY_MASK, 0x1FF);
assert_eq!(AArch64Arch::PAGE_NEGATIVE_MASK, 0xFFFF_0000_0000_0000);
assert_eq!(AArch64Arch::ENTRY_ADDRESS_SIZE, 0x0010_0000_0000_0000);
assert_eq!(AArch64Arch::ENTRY_ADDRESS_MASK, 0x000F_FFFF_FFFF_F000);
assert_eq!(AArch64Arch::ENTRY_ADDRESS_SIZE, 0x0000_0100_0000_0000);
assert_eq!(AArch64Arch::ENTRY_ADDRESS_MASK, 0x0000_00FF_FFFF_FFFF);
assert_eq!(AArch64Arch::ENTRY_FLAGS_MASK, 0xFFF0_0000_0000_0FFF);
assert_eq!(AArch64Arch::PHYS_OFFSET, 0xFFFF_8000_0000_0000);
+10 -5
View File
@@ -20,7 +20,7 @@ impl Arch for EmulateArch {
const ENTRY_FLAG_PRESENT: usize = X8664Arch::ENTRY_FLAG_PRESENT;
const ENTRY_FLAG_READONLY: usize = X8664Arch::ENTRY_FLAG_READONLY;
const ENTRY_FLAG_READWRITE: usize = X8664Arch::ENTRY_FLAG_READWRITE;
const ENTRY_FLAG_USER: usize = X8664Arch::ENTRY_FLAG_USER;
const ENTRY_FLAG_PAGE_USER: usize = X8664Arch::ENTRY_FLAG_PAGE_USER;
const ENTRY_FLAG_NO_EXEC: usize = X8664Arch::ENTRY_FLAG_NO_EXEC;
const ENTRY_FLAG_EXEC: usize = X8664Arch::ENTRY_FLAG_EXEC;
@@ -29,6 +29,10 @@ impl Arch for EmulateArch {
const ENTRY_FLAG_GLOBAL: usize = X8664Arch::ENTRY_FLAG_GLOBAL;
const ENTRY_FLAG_NO_GLOBAL: usize = X8664Arch::ENTRY_FLAG_NO_GLOBAL;
const ENTRY_ADDRESS_WIDTH: usize = X8664Arch::ENTRY_ADDRESS_WIDTH;
const ENTRY_FLAG_WRITE_COMBINING: usize = X8664Arch::ENTRY_FLAG_WRITE_COMBINING;
unsafe fn init() -> &'static [MemoryArea] {
// Create machine with PAGE_ENTRIES pages offset mapped (2 MiB on x86_64)
let mut machine = Machine::new(MEMORY_SIZE);
@@ -275,7 +279,7 @@ impl<A: Arch> Machine<A> {
}
// Page directory pointer
let a3 = e3 & A::ENTRY_ADDRESS_MASK;
let a3 = ((e3 >> A::ENTRY_ADDRESS_SHIFT) & A::ENTRY_ADDRESS_MASK) << A::PAGE_SHIFT;
for i3 in 0..A::PAGE_ENTRIES {
let e2 =
self.read_phys::<usize>(PhysicalAddress::new(a3 + i3 * A::PAGE_ENTRY_SIZE));
@@ -285,7 +289,7 @@ impl<A: Arch> Machine<A> {
}
// Page directory
let a2 = e2 & A::ENTRY_ADDRESS_MASK;
let a2 = ((e2 >> A::ENTRY_ADDRESS_SHIFT) & A::ENTRY_ADDRESS_MASK) << A::PAGE_SHIFT;
for i2 in 0..A::PAGE_ENTRIES {
let e1 =
self.read_phys::<usize>(PhysicalAddress::new(a2 + i2 * A::PAGE_ENTRY_SIZE));
@@ -295,7 +299,8 @@ impl<A: Arch> Machine<A> {
}
// Page table
let a1 = e1 & A::ENTRY_ADDRESS_MASK;
let a1 =
((e1 >> A::ENTRY_ADDRESS_SHIFT) & A::ENTRY_ADDRESS_MASK) << A::PAGE_SHIFT;
for i1 in 0..A::PAGE_ENTRIES {
let e = self
.read_phys::<usize>(PhysicalAddress::new(a1 + i1 * A::PAGE_ENTRY_SIZE));
@@ -308,7 +313,7 @@ impl<A: Arch> Machine<A> {
let page = (i4 << 39) | (i3 << 30) | (i2 << 21) | (i1 << 12);
//println!("map 0x{:X} to 0x{:X}, 0x{:X}", page, a, f);
self.map
.insert(VirtualAddress::new(page), PageEntry::new(e));
.insert(VirtualAddress::new(page), PageEntry::from_data(e));
}
}
}
+8 -6
View File
@@ -30,17 +30,20 @@ pub trait Arch: Clone + Copy {
const PAGE_ENTRY_SHIFT: usize;
const PAGE_LEVELS: usize;
const ENTRY_ADDRESS_SHIFT: usize;
const ENTRY_ADDRESS_WIDTH: usize; // Number of bits of physical address in PTE
const ENTRY_ADDRESS_SHIFT: usize = Self::PAGE_SHIFT; // Offset of physical address in PTE
const ENTRY_FLAG_DEFAULT_PAGE: usize;
const ENTRY_FLAG_DEFAULT_TABLE: usize;
const ENTRY_FLAG_PRESENT: usize;
const ENTRY_FLAG_READONLY: usize;
const ENTRY_FLAG_READWRITE: usize;
const ENTRY_FLAG_USER: usize;
const ENTRY_FLAG_PAGE_USER: usize; // Leaf table user page flag
const ENTRY_FLAG_TABLE_USER: usize = Self::ENTRY_FLAG_PAGE_USER; // Directory user page table flag
const ENTRY_FLAG_NO_EXEC: usize;
const ENTRY_FLAG_EXEC: usize;
const ENTRY_FLAG_GLOBAL: usize;
const ENTRY_FLAG_NO_GLOBAL: usize;
const ENTRY_FLAG_WRITE_COMBINING: usize;
const PHYS_OFFSET: usize;
@@ -54,10 +57,9 @@ pub trait Arch: Clone + Copy {
const PAGE_ENTRY_MASK: usize = Self::PAGE_ENTRIES - 1;
const PAGE_NEGATIVE_MASK: usize = !(Self::PAGE_ADDRESS_SIZE - 1) as usize;
const ENTRY_ADDRESS_SIZE: u64 = 1 << Self::ENTRY_ADDRESS_SHIFT;
const ENTRY_ADDRESS_MASK: usize =
(Self::ENTRY_ADDRESS_SIZE - (Self::PAGE_SIZE as u64)) as usize;
const ENTRY_FLAGS_MASK: usize = !Self::ENTRY_ADDRESS_MASK;
const ENTRY_ADDRESS_SIZE: usize = 1 << Self::ENTRY_ADDRESS_WIDTH; // size of addressable physical memory, in pages
const ENTRY_ADDRESS_MASK: usize = Self::ENTRY_ADDRESS_SIZE - 1; // Mask of physical address, starting at 0th bit
const ENTRY_FLAGS_MASK: usize = !(Self::ENTRY_ADDRESS_MASK << Self::ENTRY_ADDRESS_SHIFT);
unsafe fn init() -> &'static [MemoryArea];
+26 -21
View File
@@ -10,32 +10,36 @@ impl Arch for RiscV64Sv39Arch {
const PAGE_ENTRY_SHIFT: usize = 9; // 512 entries, 8 bytes each
const PAGE_LEVELS: usize = 3; // L0, L1, L2
//TODO
const ENTRY_ADDRESS_SHIFT: usize = 52;
const ENTRY_FLAG_DEFAULT_PAGE: usize
= Self::ENTRY_FLAG_PRESENT
| 1 << 1 // Read flag
;
const ENTRY_ADDRESS_WIDTH: usize = 44;
const ENTRY_ADDRESS_SHIFT: usize = 10;
const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_READONLY;
const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT;
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
const ENTRY_FLAG_READONLY: usize = 0;
const ENTRY_FLAG_READWRITE: usize = 1 << 2;
const ENTRY_FLAG_USER: usize = 1 << 4;
const ENTRY_FLAG_READONLY: usize = 1 << 1;
const ENTRY_FLAG_READWRITE: usize = 3 << 1;
const ENTRY_FLAG_PAGE_USER: usize = 1 << 4;
const ENTRY_FLAG_TABLE_USER: usize = 0;
const ENTRY_FLAG_NO_EXEC: usize = 0;
const ENTRY_FLAG_EXEC: usize = 1 << 3;
const ENTRY_FLAG_GLOBAL: usize = 1 << 5;
const ENTRY_FLAG_NO_GLOBAL: usize = 0;
const ENTRY_FLAG_WRITE_COMBINING: usize = 0;
const PHYS_OFFSET: usize = 0xFFFF_8000_0000_0000;
const PHYS_OFFSET: usize = 0xFFFF_FFC0_0000_0000;
unsafe fn init() -> &'static [MemoryArea] {
unimplemented!("RiscV64Sv39Arch::init unimplemented");
}
#[inline(always)]
unsafe fn invalidate(_address: VirtualAddress) {
//TODO: can one address be invalidated?
Self::invalidate_all();
unsafe fn invalidate(address: VirtualAddress) {
asm!("sfence.vma {}", in(reg) address.data());
}
#[inline(always)]
unsafe fn invalidate_all() {
asm!("sfence.vma");
}
#[inline(always)]
@@ -43,7 +47,7 @@ impl Arch for RiscV64Sv39Arch {
let satp: usize;
asm!("csrr {0}, satp", out(reg) satp);
PhysicalAddress::new(
(satp & 0x0000_0FFF_FFFF_FFFF) << Self::PAGE_SHIFT, // Convert from PPN
(satp & Self::ENTRY_ADDRESS_MASK) << Self::PAGE_SHIFT, // Convert from PPN
)
}
@@ -52,13 +56,14 @@ impl Arch for RiscV64Sv39Arch {
let satp = (8 << 60) | // Sv39 MODE
(address.data() >> Self::PAGE_SHIFT); // Convert to PPN (TODO: ensure alignment)
asm!("csrw satp, {0}", in(reg) satp);
Self::invalidate_all();
}
fn virt_is_valid(address: VirtualAddress) -> bool {
const MASK: usize = 0xFFFF_FFC0_0000_0000;
let masked = address.data() & MASK;
let mask = !((Self::PAGE_ADDRESS_SIZE as usize - 1) >> 1);
let masked = address.data() & mask;
masked == MASK || masked == 0
masked == mask || masked == 0
}
}
@@ -79,11 +84,11 @@ mod tests {
assert_eq!(RiscV64Sv39Arch::PAGE_ENTRY_MASK, 0x1FF);
assert_eq!(RiscV64Sv39Arch::PAGE_NEGATIVE_MASK, 0xFFFF_FF80_0000_0000);
assert_eq!(RiscV64Sv39Arch::ENTRY_ADDRESS_SIZE, 0x0010_0000_0000_0000);
assert_eq!(RiscV64Sv39Arch::ENTRY_ADDRESS_MASK, 0x000F_FFFF_FFFF_F000);
assert_eq!(RiscV64Sv39Arch::ENTRY_FLAGS_MASK, 0xFFF0_0000_0000_0FFF);
assert_eq!(RiscV64Sv39Arch::ENTRY_ADDRESS_SIZE, 0x0000_1000_0000_0000);
assert_eq!(RiscV64Sv39Arch::ENTRY_ADDRESS_MASK, 0x0000_0FFF_FFFF_FFFF);
assert_eq!(RiscV64Sv39Arch::ENTRY_FLAGS_MASK, 0xFFC0_0000_0000_03FF);
assert_eq!(RiscV64Sv39Arch::PHYS_OFFSET, 0xFFFF_8000_0000_0000);
assert_eq!(RiscV64Sv39Arch::PHYS_OFFSET, 0xFFFF_FFC0_0000_0000);
}
#[test]
fn is_canonical() {
+23 -17
View File
@@ -10,21 +10,21 @@ impl Arch for RiscV64Sv48Arch {
const PAGE_ENTRY_SHIFT: usize = 9; // 512 entries, 8 bytes each
const PAGE_LEVELS: usize = 4; // L0, L1, L2, L3
//TODO
const ENTRY_ADDRESS_SHIFT: usize = 52;
const ENTRY_FLAG_DEFAULT_PAGE: usize
= Self::ENTRY_FLAG_PRESENT
| 1 << 1 // Read flag
;
const ENTRY_ADDRESS_WIDTH: usize = 44;
const ENTRY_ADDRESS_SHIFT: usize = 10;
const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_READONLY;
const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT;
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
const ENTRY_FLAG_READONLY: usize = 0;
const ENTRY_FLAG_READWRITE: usize = 1 << 2;
const ENTRY_FLAG_USER: usize = 1 << 4;
const ENTRY_FLAG_READONLY: usize = 1 << 1;
const ENTRY_FLAG_READWRITE: usize = 3 << 1;
const ENTRY_FLAG_PAGE_USER: usize = 1 << 4;
const ENTRY_FLAG_TABLE_USER: usize = 0;
const ENTRY_FLAG_NO_EXEC: usize = 0;
const ENTRY_FLAG_EXEC: usize = 1 << 3;
const ENTRY_FLAG_GLOBAL: usize = 1 << 5;
const ENTRY_FLAG_NO_GLOBAL: usize = 0;
const ENTRY_FLAG_WRITE_COMBINING: usize = 0;
const PHYS_OFFSET: usize = 0xFFFF_8000_0000_0000;
@@ -33,9 +33,13 @@ impl Arch for RiscV64Sv48Arch {
}
#[inline(always)]
unsafe fn invalidate(_address: VirtualAddress) {
//TODO: can one address be invalidated?
Self::invalidate_all();
unsafe fn invalidate(address: VirtualAddress) {
asm!("sfence.vma {}", in(reg) address.data());
}
#[inline(always)]
unsafe fn invalidate_all() {
asm!("sfence.vma");
}
#[inline(always)]
@@ -43,7 +47,7 @@ impl Arch for RiscV64Sv48Arch {
let satp: usize;
asm!("csrr {0}, satp", out(reg) satp);
PhysicalAddress::new(
(satp & 0x0000_0FFF_FFFF_FFFF) << Self::PAGE_SHIFT, // Convert from PPN
(satp & Self::ENTRY_ADDRESS_MASK) << Self::PAGE_SHIFT, // Convert from PPN
)
}
@@ -52,10 +56,12 @@ impl Arch for RiscV64Sv48Arch {
let satp = (9 << 60) | // Sv48 MODE
(address.data() >> Self::PAGE_SHIFT); // Convert to PPN (TODO: ensure alignment)
asm!("csrw satp, {0}", in(reg) satp);
Self::invalidate_all();
}
fn virt_is_valid(address: VirtualAddress) -> bool {
// RISC-V SV48 uses 48-bit sign-extended addresses, identical to 4-level paging on x86_64.
let mask = 0xFFFF_8000_0000_0000;
let mask = !((Self::PAGE_ADDRESS_SIZE as usize - 1) >> 1);
let masked = address.data() & mask;
masked == mask || masked == 0
@@ -79,9 +85,9 @@ mod tests {
assert_eq!(RiscV64Sv48Arch::PAGE_ENTRY_MASK, 0x1FF);
assert_eq!(RiscV64Sv48Arch::PAGE_NEGATIVE_MASK, 0xFFFF_0000_0000_0000);
assert_eq!(RiscV64Sv48Arch::ENTRY_ADDRESS_SIZE, 0x0010_0000_0000_0000);
assert_eq!(RiscV64Sv48Arch::ENTRY_ADDRESS_MASK, 0x000F_FFFF_FFFF_F000);
assert_eq!(RiscV64Sv48Arch::ENTRY_FLAGS_MASK, 0xFFF0_0000_0000_0FFF);
assert_eq!(RiscV64Sv48Arch::ENTRY_ADDRESS_SIZE, 0x0000_1000_0000_0000);
assert_eq!(RiscV64Sv48Arch::ENTRY_ADDRESS_MASK, 0x0000_0FFF_FFFF_FFFF);
assert_eq!(RiscV64Sv48Arch::ENTRY_FLAGS_MASK, 0xFFC0_0000_0000_03FF);
assert_eq!(RiscV64Sv48Arch::PHYS_OFFSET, 0xFFFF_8000_0000_0000);
}
+6 -5
View File
@@ -11,18 +11,19 @@ impl Arch for X86Arch {
const PAGE_ENTRY_SHIFT: usize = 10; // 1024 entries, 4 bytes each
const PAGE_LEVELS: usize = 2; // PD, PT
const ENTRY_ADDRESS_SHIFT: usize = 32;
const ENTRY_ADDRESS_WIDTH: usize = 20;
const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT;
const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT;
const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_READWRITE;
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
const ENTRY_FLAG_READONLY: usize = 0;
const ENTRY_FLAG_READWRITE: usize = 1 << 1;
const ENTRY_FLAG_USER: usize = 1 << 2;
const ENTRY_FLAG_PAGE_USER: usize = 1 << 2;
// Not used: const ENTRY_FLAG_HUGE: usize = 1 << 7;
const ENTRY_FLAG_GLOBAL: usize = 1 << 8;
const ENTRY_FLAG_NO_GLOBAL: usize = 0;
const ENTRY_FLAG_NO_EXEC: usize = 0; // NOT AVAILABLE UNLESS PAE IS USED!
const ENTRY_FLAG_EXEC: usize = 0;
const ENTRY_FLAG_WRITE_COMBINING: usize = 1 << 7;
const PHYS_OFFSET: usize = 0x8000_0000;
@@ -70,8 +71,8 @@ mod tests {
assert_eq!(X86Arch::PAGE_ENTRY_MASK, 0x3FF);
assert_eq!(X86Arch::PAGE_NEGATIVE_MASK, 0x0000_0000_0000);
assert_eq!(X86Arch::ENTRY_ADDRESS_SIZE, 0x0000_0001_0000_0000);
assert_eq!(X86Arch::ENTRY_ADDRESS_MASK, 0xFFFF_F000);
assert_eq!(X86Arch::ENTRY_ADDRESS_SIZE, 0x0000_0000_0010_0000);
assert_eq!(X86Arch::ENTRY_ADDRESS_MASK, 0x000F_FFFF);
assert_eq!(X86Arch::ENTRY_FLAGS_MASK, 0x0000_0FFF);
assert_eq!(X86Arch::PHYS_OFFSET, 0x8000_0000);
+6 -5
View File
@@ -10,18 +10,19 @@ impl Arch for X8664Arch {
const PAGE_ENTRY_SHIFT: usize = 9; // 512 entries, 8 bytes each
const PAGE_LEVELS: usize = 4; // PML4, PDP, PD, PT
const ENTRY_ADDRESS_SHIFT: usize = 52;
const ENTRY_ADDRESS_WIDTH: usize = 40;
const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT;
const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT;
const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_READWRITE;
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
const ENTRY_FLAG_READONLY: usize = 0;
const ENTRY_FLAG_READWRITE: usize = 1 << 1;
const ENTRY_FLAG_USER: usize = 1 << 2;
const ENTRY_FLAG_PAGE_USER: usize = 1 << 2;
// Not used: const ENTRY_FLAG_HUGE: usize = 1 << 7;
const ENTRY_FLAG_GLOBAL: usize = 1 << 8;
const ENTRY_FLAG_NO_GLOBAL: usize = 0;
const ENTRY_FLAG_NO_EXEC: usize = 1 << 63;
const ENTRY_FLAG_EXEC: usize = 0;
const ENTRY_FLAG_WRITE_COMBINING: usize = 1 << 7;
const PHYS_OFFSET: usize = Self::PAGE_NEGATIVE_MASK + (Self::PAGE_ADDRESS_SIZE >> 1) as usize; // PML4 slot 256 and onwards
@@ -80,8 +81,8 @@ mod tests {
assert_eq!(X8664Arch::PAGE_ENTRY_MASK, 0x1FF);
assert_eq!(X8664Arch::PAGE_NEGATIVE_MASK, 0xFFFF_0000_0000_0000);
assert_eq!(X8664Arch::ENTRY_ADDRESS_SIZE, 0x0010_0000_0000_0000);
assert_eq!(X8664Arch::ENTRY_ADDRESS_MASK, 0x000F_FFFF_FFFF_F000);
assert_eq!(X8664Arch::ENTRY_ADDRESS_SIZE, 0x0000_0100_0000_0000);
assert_eq!(X8664Arch::ENTRY_ADDRESS_MASK, 0x0000_00FF_FFFF_FFFF);
assert_eq!(X8664Arch::ENTRY_FLAGS_MASK, 0xFFF0_0000_0000_0FFF);
assert_eq!(X8664Arch::PHYS_OFFSET, 0xFFFF_8000_0000_0000);
+11 -2
View File
@@ -10,7 +10,14 @@ pub struct PageEntry<A> {
impl<A: Arch> PageEntry<A> {
#[inline(always)]
pub fn new(data: usize) -> Self {
pub fn new(address: usize, flags: usize) -> Self {
let data = (((address >> A::PAGE_SHIFT) & A::ENTRY_ADDRESS_MASK) << A::ENTRY_ADDRESS_SHIFT)
| flags;
Self::from_data(data)
}
#[inline(always)]
pub fn from_data(data: usize) -> Self {
Self {
data,
phantom: PhantomData,
@@ -24,7 +31,9 @@ impl<A: Arch> PageEntry<A> {
#[inline(always)]
pub fn address(&self) -> Result<PhysicalAddress, PhysicalAddress> {
let addr = PhysicalAddress(self.data & A::ENTRY_ADDRESS_MASK);
let addr = PhysicalAddress(
((self.data >> A::ENTRY_ADDRESS_SHIFT) & A::ENTRY_ADDRESS_MASK) << A::PAGE_SHIFT,
);
if self.present() {
Ok(addr)
+18 -10
View File
@@ -27,10 +27,7 @@ impl<A: Arch> PageFlags<A> {
unsafe {
Self::from_data(
// Flags set to present, kernel space, read-only, no-execute by default
A::ENTRY_FLAG_DEFAULT_TABLE
| A::ENTRY_FLAG_READONLY
| A::ENTRY_FLAG_NO_EXEC
| A::ENTRY_FLAG_NO_GLOBAL,
A::ENTRY_FLAG_DEFAULT_TABLE | A::ENTRY_FLAG_NO_EXEC | A::ENTRY_FLAG_NO_GLOBAL,
)
}
}
@@ -59,6 +56,12 @@ impl<A: Arch> PageFlags<A> {
self
}
#[must_use]
#[inline(always)]
pub fn write_combining(self, value: bool) -> Self {
self.custom_flag(A::ENTRY_FLAG_WRITE_COMBINING, value)
}
#[inline(always)]
pub fn has_flag(&self, flag: usize) -> bool {
self.data & flag == flag
@@ -72,25 +75,30 @@ impl<A: Arch> PageFlags<A> {
#[must_use]
#[inline(always)]
pub fn user(self, value: bool) -> Self {
self.custom_flag(A::ENTRY_FLAG_USER, value)
self.custom_flag(A::ENTRY_FLAG_PAGE_USER, value)
}
#[inline(always)]
pub fn has_user(&self) -> bool {
self.has_flag(A::ENTRY_FLAG_USER)
self.has_flag(A::ENTRY_FLAG_PAGE_USER)
}
#[must_use]
#[inline(always)]
pub fn write(self, value: bool) -> Self {
// Architecture may use readonly or readwrite, support either
self.custom_flag(A::ENTRY_FLAG_READONLY, !value)
.custom_flag(A::ENTRY_FLAG_READWRITE, value)
// Architecture may use readonly or readwrite, or both, support either
if value {
self.custom_flag(A::ENTRY_FLAG_READONLY | A::ENTRY_FLAG_READWRITE, false)
.custom_flag(A::ENTRY_FLAG_READWRITE, true)
} else {
self.custom_flag(A::ENTRY_FLAG_READONLY | A::ENTRY_FLAG_READWRITE, false)
.custom_flag(A::ENTRY_FLAG_READONLY, true)
}
}
#[inline(always)]
pub fn has_write(&self) -> bool {
// Architecture may use readonly or readwrite, support either
// Architecture may use readonly or readwrite, or both, support either
self.data & (A::ENTRY_FLAG_READONLY | A::ENTRY_FLAG_READWRITE) == A::ENTRY_FLAG_READWRITE
}
+7 -8
View File
@@ -65,7 +65,7 @@ impl<A: Arch, F: FrameAllocator> PageMapper<A, F> {
let old_flags = old_entry.flags();
let (new_phys, new_flags) = f(old_phys, old_flags);
// TODO: Higher-level PageEntry::new interface?
let new_entry = PageEntry::new(new_phys.data() | new_flags.data());
let new_entry = PageEntry::new(new_phys.data(), new_flags.data());
p1.set_entry(i, new_entry);
Some((old_flags, old_phys, PageFlush::new(virt)))
})
@@ -105,7 +105,7 @@ impl<A: Arch, F: FrameAllocator> PageMapper<A, F> {
) -> Option<PageFlush<A>> {
//TODO: verify virt and phys are aligned
//TODO: verify flags have correct bits
let entry = PageEntry::new(phys.data() | flags.data());
let entry = PageEntry::new(phys.data(), flags.data());
let mut table = self.table();
loop {
let i = table.index_of(virt)?;
@@ -120,14 +120,13 @@ impl<A: Arch, F: FrameAllocator> PageMapper<A, F> {
None => {
let next_phys = self.allocator.allocate_one()?;
//TODO: correct flags?
let flags = A::ENTRY_FLAG_READWRITE
| A::ENTRY_FLAG_DEFAULT_TABLE
let flags = A::ENTRY_FLAG_DEFAULT_TABLE
| if virt.kind() == TableKind::User {
A::ENTRY_FLAG_USER
A::ENTRY_FLAG_TABLE_USER
} else {
0
};
table.set_entry(i, PageEntry::new(next_phys.data() | flags));
table.set_entry(i, PageEntry::new(next_phys.data(), flags));
table.next(i)?
}
};
@@ -198,7 +197,7 @@ unsafe fn unmap_phys_inner<A: Arch>(
if table.level() == 0 {
let entry_opt = table.entry(i);
table.set_entry(i, PageEntry::new(0));
table.set_entry(i, PageEntry::new(0, 0));
let entry = entry_opt?;
Some((entry.address().ok()?, entry.flags()))
@@ -218,7 +217,7 @@ unsafe fn unmap_phys_inner<A: Arch>(
if !is_still_populated {
allocator.free_one(subtable.phys());
table.set_entry(i, PageEntry::new(0));
table.set_entry(i, PageEntry::new(0, 0));
}
}
+1 -1
View File
@@ -72,7 +72,7 @@ impl<A: Arch> PageTable<A> {
pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<A>> {
let addr = self.entry_virt(i)?;
Some(PageEntry::new(A::read::<usize>(addr)))
Some(PageEntry::from_data(A::read::<usize>(addr)))
}
pub unsafe fn set_entry(&mut self, i: usize, entry: PageEntry<A>) -> Option<()> {