refactor: move Mapping<F> to types crate with VirtualAddress/PhysicalAddress newtypes, rename MapFlags to Sv39Flags
This commit is contained in:
@@ -91,7 +91,7 @@ static USER_EXIT_PROGRAM: [u8; 12] = [
|
|||||||
0x6f, 0xf0, 0xdf, 0xff, // j -4
|
0x6f, 0xf0, 0xdf, 0xff, // j -4
|
||||||
];
|
];
|
||||||
|
|
||||||
const USER_VA: usize = 0x10000;
|
const USER_VA_RAW: usize = 0x10000;
|
||||||
|
|
||||||
fn userspace_demo(uart: &Uart, kernel_pt: &mmu::PageTable) {
|
fn userspace_demo(uart: &Uart, kernel_pt: &mmu::PageTable) {
|
||||||
uart.write_str("k-os: --- userspace demo ---\n");
|
uart.write_str("k-os: --- userspace demo ---\n");
|
||||||
@@ -105,7 +105,12 @@ fn userspace_demo(uart: &Uart, kernel_pt: &mmu::PageTable) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let user_pt = mmu::create_user_page_table(kernel_pt, program_page, 1, USER_VA);
|
let user_pt = mmu::create_user_page_table(
|
||||||
|
kernel_pt,
|
||||||
|
types::address::PhysicalAddress::from_raw(program_page),
|
||||||
|
1,
|
||||||
|
types::address::VirtualAddress::from_raw(USER_VA_RAW),
|
||||||
|
);
|
||||||
|
|
||||||
uart.write_str("k-os: user page table created, entering U-mode\n");
|
uart.write_str("k-os: user page table created, entering U-mode\n");
|
||||||
|
|
||||||
@@ -115,7 +120,7 @@ fn userspace_demo(uart: &Uart, kernel_pt: &mmu::PageTable) {
|
|||||||
unsafe { core::arch::asm!("mv {0}, sp", out(reg) kernel_sp) };
|
unsafe { core::arch::asm!("mv {0}, sp", out(reg) kernel_sp) };
|
||||||
trap::set_kernel_stack(kernel_sp);
|
trap::set_kernel_stack(kernel_sp);
|
||||||
|
|
||||||
let user_stack = USER_VA - 8;
|
let user_stack = USER_VA_RAW - 8;
|
||||||
unsafe {
|
unsafe {
|
||||||
core::arch::asm!(
|
core::arch::asm!(
|
||||||
"csrc sstatus, {spp}",
|
"csrc sstatus, {spp}",
|
||||||
@@ -125,7 +130,7 @@ fn userspace_demo(uart: &Uart, kernel_pt: &mmu::PageTable) {
|
|||||||
"sret",
|
"sret",
|
||||||
spp = in(reg) 1usize << 8,
|
spp = in(reg) 1usize << 8,
|
||||||
spie = in(reg) 1usize << 5,
|
spie = in(reg) 1usize << 5,
|
||||||
entry = in(reg) USER_VA,
|
entry = in(reg) USER_VA_RAW,
|
||||||
stack = in(reg) user_stack,
|
stack = in(reg) user_stack,
|
||||||
options(noreturn),
|
options(noreturn),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ pub mod allocator;
|
|||||||
pub mod page_table;
|
pub mod page_table;
|
||||||
|
|
||||||
pub use allocator::init_allocator;
|
pub use allocator::init_allocator;
|
||||||
pub use page_table::{activate, init_kernel_page_table, create_user_page_table, map, MapFlags, Mapping, PageTable, PAGE_SIZE};
|
pub use page_table::{activate, init_kernel_page_table, create_user_page_table, map, Sv39Flags, Mapping, PageTable, PAGE_SIZE};
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use crate::board;
|
use crate::board;
|
||||||
use super::allocator::alloc_page_table;
|
use super::allocator::alloc_page_table;
|
||||||
|
use types::address::{PhysicalAddress, VirtualAddress};
|
||||||
|
|
||||||
|
pub use types::mapping::Mapping;
|
||||||
pub const PAGE_SIZE: usize = 4096;
|
pub const PAGE_SIZE: usize = 4096;
|
||||||
|
|
||||||
const PTE_V: u64 = 1 << 0;
|
const PTE_V: u64 = 1 << 0;
|
||||||
@@ -13,11 +15,11 @@ const PTE_A: u64 = 1 << 6;
|
|||||||
const PTE_D: u64 = 1 << 7;
|
const PTE_D: u64 = 1 << 7;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct MapFlags {
|
pub struct Sv39Flags {
|
||||||
bits: u64,
|
bits: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MapFlags {
|
impl Sv39Flags {
|
||||||
pub fn kernel_rwx() -> Self {
|
pub fn kernel_rwx() -> Self {
|
||||||
Self { bits: PTE_R | PTE_W | PTE_X | PTE_G }
|
Self { bits: PTE_R | PTE_W | PTE_X | PTE_G }
|
||||||
}
|
}
|
||||||
@@ -47,14 +49,6 @@ impl MapFlags {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct Mapping {
|
|
||||||
pub va: usize,
|
|
||||||
pub pa: usize,
|
|
||||||
pub pages: usize,
|
|
||||||
pub flags: MapFlags,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct PageTableEntry(u64);
|
pub struct PageTableEntry(u64);
|
||||||
@@ -64,7 +58,7 @@ impl PageTableEntry {
|
|||||||
Self(0)
|
Self(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_leaf(ppn: u64, flags: MapFlags) -> Self {
|
fn new_leaf(ppn: u64, flags: Sv39Flags) -> Self {
|
||||||
Self(flags.to_pte_flags() | (ppn << 10))
|
Self(flags.to_pte_flags() | (ppn << 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +92,7 @@ fn vpn(va: usize, level: usize) -> usize {
|
|||||||
(va >> (12 + 9 * level)) & 0x1FF
|
(va >> (12 + 9 * level)) & 0x1FF
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_page(root: &mut PageTable, va: usize, pa: usize, flags: MapFlags) {
|
fn map_page(root: &mut PageTable, va: usize, pa: usize, flags: Sv39Flags) {
|
||||||
let vpn2 = vpn(va, 2);
|
let vpn2 = vpn(va, 2);
|
||||||
let vpn1 = vpn(va, 1);
|
let vpn1 = vpn(va, 1);
|
||||||
let vpn0 = vpn(va, 0);
|
let vpn0 = vpn(va, 0);
|
||||||
@@ -125,43 +119,29 @@ fn map_page(root: &mut PageTable, va: usize, pa: usize, flags: MapFlags) {
|
|||||||
l0.entries[vpn0] = PageTableEntry::new_leaf(ppn, flags);
|
l0.entries[vpn0] = PageTableEntry::new_leaf(ppn, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map(root: &mut PageTable, mapping: Mapping) {
|
pub fn map(root: &mut PageTable, mapping: Mapping<Sv39Flags>) {
|
||||||
for i in 0..mapping.pages {
|
for i in 0..mapping.pages {
|
||||||
let offset = i * PAGE_SIZE;
|
let offset = i * PAGE_SIZE;
|
||||||
map_page(root, mapping.va + offset, mapping.pa + offset, mapping.flags);
|
map_page(root, mapping.va.raw() + offset, mapping.pa.raw() + offset, mapping.flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_kernel_page_table() -> &'static mut PageTable {
|
pub fn init_kernel_page_table() -> &'static mut PageTable {
|
||||||
let root = alloc_page_table();
|
let root = alloc_page_table();
|
||||||
|
|
||||||
map(root, Mapping {
|
let identity = |addr: usize| (VirtualAddress::from_raw(addr), PhysicalAddress::from_raw(addr));
|
||||||
va: board::RAM_BASE,
|
|
||||||
pa: board::RAM_BASE,
|
|
||||||
pages: board::RAM_SIZE / PAGE_SIZE,
|
|
||||||
flags: MapFlags::kernel_rwx(),
|
|
||||||
});
|
|
||||||
|
|
||||||
map(root, Mapping {
|
let (va, pa) = identity(board::RAM_BASE);
|
||||||
va: board::UART_BASE,
|
map(root, Mapping { va, pa, pages: board::RAM_SIZE / PAGE_SIZE, flags: Sv39Flags::kernel_rwx() });
|
||||||
pa: board::UART_BASE,
|
|
||||||
pages: 1,
|
|
||||||
flags: MapFlags::kernel_rw(),
|
|
||||||
});
|
|
||||||
|
|
||||||
map(root, Mapping {
|
let (va, pa) = identity(board::UART_BASE);
|
||||||
va: board::PLIC_BASE,
|
map(root, Mapping { va, pa, pages: 1, flags: Sv39Flags::kernel_rw() });
|
||||||
pa: board::PLIC_BASE,
|
|
||||||
pages: 0x400000 / PAGE_SIZE,
|
|
||||||
flags: MapFlags::kernel_rw(),
|
|
||||||
});
|
|
||||||
|
|
||||||
map(root, Mapping {
|
let (va, pa) = identity(board::PLIC_BASE);
|
||||||
va: board::CLINT_BASE,
|
map(root, Mapping { va, pa, pages: 0x400000 / PAGE_SIZE, flags: Sv39Flags::kernel_rw() });
|
||||||
pa: board::CLINT_BASE,
|
|
||||||
pages: 0x10000 / PAGE_SIZE,
|
let (va, pa) = identity(board::CLINT_BASE);
|
||||||
flags: MapFlags::kernel_rw(),
|
map(root, Mapping { va, pa, pages: 0x10000 / PAGE_SIZE, flags: Sv39Flags::kernel_rw() });
|
||||||
});
|
|
||||||
|
|
||||||
root
|
root
|
||||||
}
|
}
|
||||||
@@ -180,9 +160,9 @@ pub fn activate(root: &PageTable) {
|
|||||||
|
|
||||||
pub fn create_user_page_table(
|
pub fn create_user_page_table(
|
||||||
kernel_root: &PageTable,
|
kernel_root: &PageTable,
|
||||||
program_pa: usize,
|
program_pa: PhysicalAddress,
|
||||||
program_pages: usize,
|
program_pages: usize,
|
||||||
user_va: usize,
|
user_va: VirtualAddress,
|
||||||
) -> &'static mut PageTable {
|
) -> &'static mut PageTable {
|
||||||
let root = alloc_page_table();
|
let root = alloc_page_table();
|
||||||
|
|
||||||
@@ -197,16 +177,17 @@ pub fn create_user_page_table(
|
|||||||
va: user_va,
|
va: user_va,
|
||||||
pa: program_pa,
|
pa: program_pa,
|
||||||
pages: program_pages,
|
pages: program_pages,
|
||||||
flags: MapFlags::user_rx(),
|
flags: Sv39Flags::user_rx(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let stack_table = alloc_page_table();
|
let stack_table = alloc_page_table();
|
||||||
let stack_pa = stack_table as *const PageTable as usize;
|
let stack_pa = PhysicalAddress::from_raw(stack_table as *const PageTable as usize);
|
||||||
|
let stack_va = VirtualAddress::from_raw(user_va.raw().wrapping_sub(PAGE_SIZE));
|
||||||
map(root, Mapping {
|
map(root, Mapping {
|
||||||
va: user_va.wrapping_sub(PAGE_SIZE),
|
va: stack_va,
|
||||||
pa: stack_pa,
|
pa: stack_pa,
|
||||||
pages: 1,
|
pages: 1,
|
||||||
flags: MapFlags::user_rw(),
|
flags: Sv39Flags::user_rw(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use domain::memory::MemoryRegion;
|
|||||||
use domain::process::MAX_PROCESSES;
|
use domain::process::MAX_PROCESSES;
|
||||||
use platform::Platform;
|
use platform::Platform;
|
||||||
use types::{
|
use types::{
|
||||||
address::{EntryPoint, PhysicalAddress, StackPointer},
|
address::{EntryPoint, PhysicalAddress, StackPointer, VirtualAddress},
|
||||||
bounded::PageCount,
|
bounded::PageCount,
|
||||||
id::{CoreId, IrqId, ProcessId},
|
id::{CoreId, IrqId, ProcessId},
|
||||||
permission::{Permission, PermissionSet},
|
permission::{Permission, PermissionSet},
|
||||||
@@ -34,7 +34,12 @@ impl RiscVPlatform {
|
|||||||
let idx = pid.raw() as usize;
|
let idx = pid.raw() as usize;
|
||||||
if self.page_tables[idx] == 0 {
|
if self.page_tables[idx] == 0 {
|
||||||
let kernel_pt = unsafe { &*(self.page_tables[0] as *const mmu::PageTable) };
|
let kernel_pt = unsafe { &*(self.page_tables[0] as *const mmu::PageTable) };
|
||||||
let user_pt = mmu::create_user_page_table(kernel_pt, 0, 0, 0x10000);
|
let user_pt = mmu::create_user_page_table(
|
||||||
|
kernel_pt,
|
||||||
|
PhysicalAddress::from_raw(0),
|
||||||
|
0,
|
||||||
|
VirtualAddress::from_raw(0x10000),
|
||||||
|
);
|
||||||
self.page_tables[idx] = user_pt as *const mmu::PageTable as usize;
|
self.page_tables[idx] = user_pt as *const mmu::PageTable as usize;
|
||||||
}
|
}
|
||||||
unsafe { &mut *(self.page_tables[idx] as *mut mmu::PageTable) }
|
unsafe { &mut *(self.page_tables[idx] as *mut mmu::PageTable) }
|
||||||
@@ -46,10 +51,10 @@ impl Platform for RiscVPlatform {
|
|||||||
let pt = self.ensure_page_table(process);
|
let pt = self.ensure_page_table(process);
|
||||||
for region in regions {
|
for region in regions {
|
||||||
mmu::map(pt, mmu::Mapping {
|
mmu::map(pt, mmu::Mapping {
|
||||||
va: region.base().raw(),
|
va: VirtualAddress::from_raw(region.base().raw()),
|
||||||
pa: region.base().raw(),
|
pa: region.base(),
|
||||||
pages: region.size().value() as usize,
|
pages: region.size().value() as usize,
|
||||||
flags: mmu::MapFlags::user(true, true, true),
|
flags: mmu::Sv39Flags::user(true, true, true),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,10 +116,10 @@ impl Platform for RiscVPlatform {
|
|||||||
) {
|
) {
|
||||||
let pt = self.ensure_page_table(process);
|
let pt = self.ensure_page_table(process);
|
||||||
mmu::map(pt, mmu::Mapping {
|
mmu::map(pt, mmu::Mapping {
|
||||||
va: base.raw(),
|
va: VirtualAddress::from_raw(base.raw()),
|
||||||
pa: base.raw(),
|
pa: base,
|
||||||
pages: size.value() as usize,
|
pages: size.value() as usize,
|
||||||
flags: mmu::MapFlags::user(
|
flags: mmu::Sv39Flags::user(
|
||||||
permissions.allows(Permission::Read),
|
permissions.allows(Permission::Read),
|
||||||
permissions.allows(Permission::Write),
|
permissions.allows(Permission::Write),
|
||||||
permissions.allows(Permission::Execute),
|
permissions.allows(Permission::Execute),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ pub mod bounded;
|
|||||||
pub mod generation;
|
pub mod generation;
|
||||||
pub mod id;
|
pub mod id;
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
|
pub mod mapping;
|
||||||
pub mod permission;
|
pub mod permission;
|
||||||
#[cfg(kani)]
|
#[cfg(kani)]
|
||||||
pub mod proofs;
|
pub mod proofs;
|
||||||
|
|||||||
8
crates/types/src/mapping.rs
Normal file
8
crates/types/src/mapping.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use crate::address::{PhysicalAddress, VirtualAddress};
|
||||||
|
|
||||||
|
pub struct Mapping<F> {
|
||||||
|
pub va: VirtualAddress,
|
||||||
|
pub pa: PhysicalAddress,
|
||||||
|
pub pages: usize,
|
||||||
|
pub flags: F,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user