mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-23 08:26:17 +04:00
Update mips paging.rs.
This commit is contained in:
parent
2d5b6948b5
commit
05f9327272
@ -1,5 +1,5 @@
|
|||||||
use mips::interrupts::*;
|
use mips::interrupts;
|
||||||
use mips::registers::*;
|
use mips::registers::cp0;
|
||||||
use crate::drivers::DRIVERS;
|
use crate::drivers::DRIVERS;
|
||||||
pub use self::context::*;
|
pub use self::context::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
|
@ -10,7 +10,7 @@ pub mod syscall;
|
|||||||
pub mod rand;
|
pub mod rand;
|
||||||
|
|
||||||
use log::*;
|
use log::*;
|
||||||
use mips::registers;
|
use mips::registers::cp0;
|
||||||
use mips::instructions;
|
use mips::instructions;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -1,19 +1,15 @@
|
|||||||
use crate::consts::RECURSIVE_INDEX;
|
|
||||||
// Depends on kernel
|
// Depends on kernel
|
||||||
use crate::memory::{active_table, alloc_frame, dealloc_frame};
|
use crate::memory::{active_table, alloc_frame, dealloc_frame};
|
||||||
use riscv::addr::*;
|
use mips::addr::*;
|
||||||
use riscv::asm::{sfence_vma, sfence_vma_all};
|
use mips::tlb::*;
|
||||||
use riscv::paging::{Mapper, PageTable as RvPageTable, PageTableEntry, PageTableFlags as EF, RecursivePageTable, PageTableType};
|
use mips::paging::{Mapper, PageTable as MIPSPageTable, PageTableEntry, PageTableFlags as EF, TwoLevelPageTable};
|
||||||
use riscv::paging::{FrameAllocator, FrameDeallocator};
|
use mips::paging::{FrameAllocator, FrameDeallocator};
|
||||||
use riscv::register::satp;
|
|
||||||
use rcore_memory::paging::*;
|
use rcore_memory::paging::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
#[cfg(target_arch = "riscv32")]
|
#[cfg(target_arch = "riscv32")]
|
||||||
use crate::consts::KERNEL_P2_INDEX;
|
use crate::consts::KERNEL_P2_INDEX;
|
||||||
#[cfg(target_arch = "riscv64")]
|
|
||||||
use crate::consts::KERNEL_P4_INDEX;
|
|
||||||
|
|
||||||
pub struct ActivePageTable(RecursivePageTable<'static>, PageEntry);
|
pub struct ActivePageTable(TwoLevelPageTable<'static>, PageEntry);
|
||||||
|
|
||||||
/// PageTableEntry: the contents of this entry.
|
/// PageTableEntry: the contents of this entry.
|
||||||
/// Page: this entry is the pte of page `Page`.
|
/// Page: this entry is the pte of page `Page`.
|
||||||
@ -22,9 +18,8 @@ pub struct PageEntry(&'static mut PageTableEntry, Page);
|
|||||||
impl PageTable for ActivePageTable {
|
impl PageTable for ActivePageTable {
|
||||||
|
|
||||||
fn map(&mut self, addr: usize, target: usize) -> &mut Entry {
|
fn map(&mut self, addr: usize, target: usize) -> &mut Entry {
|
||||||
// use riscv::paging:Mapper::map_to,
|
|
||||||
// map the 4K `page` to the 4K `frame` with `flags`
|
// map the 4K `page` to the 4K `frame` with `flags`
|
||||||
let flags = EF::VALID | EF::READABLE | EF::WRITABLE;
|
let flags = EF::VALID | EF::WRITABLE | EF::CACHEABLE;
|
||||||
let page = Page::of_addr(VirtAddr::new(addr));
|
let page = Page::of_addr(VirtAddr::new(addr));
|
||||||
let frame = Frame::of_addr(PhysAddr::new(target));
|
let frame = Frame::of_addr(PhysAddr::new(target));
|
||||||
// map the page to the frame using FrameAllocatorForRiscv
|
// map the page to the frame using FrameAllocatorForRiscv
|
||||||
@ -54,41 +49,14 @@ impl PageTable for ActivePageTable {
|
|||||||
impl PageTableExt for ActivePageTable {}
|
impl PageTableExt for ActivePageTable {}
|
||||||
|
|
||||||
/// The virtual address of root page table
|
/// The virtual address of root page table
|
||||||
#[cfg(target_arch = "riscv32")]
|
static ROOT_PAGE_TABLE_BUFFER: MIPSPageTable = ::core::mem::uninitialized();
|
||||||
const ROOT_PAGE_TABLE: *mut RvPageTable =
|
static mut root_page_table_ptr: usize =
|
||||||
((RECURSIVE_INDEX << 12 << 10) |
|
&ROOT_PAGE_TABLE_BUFFER as *const MIPSPageTable as usize;
|
||||||
((RECURSIVE_INDEX+1) << 12)) as *mut RvPageTable;
|
|
||||||
#[cfg(all(target_arch = "riscv64", feature = "sv39"))]
|
|
||||||
const ROOT_PAGE_TABLE: *mut RvPageTable =
|
|
||||||
((0xFFFF_0000_0000_0000) |
|
|
||||||
(0o777 << 12 << 9 << 9 << 9) |
|
|
||||||
(RECURSIVE_INDEX << 12 << 9 << 9) |
|
|
||||||
(RECURSIVE_INDEX << 12 << 9) |
|
|
||||||
((RECURSIVE_INDEX+1) << 12)) as *mut RvPageTable;
|
|
||||||
#[cfg(all(target_arch = "riscv64", not(feature = "sv39")))]
|
|
||||||
const ROOT_PAGE_TABLE: *mut RvPageTable =
|
|
||||||
((0xFFFF_0000_0000_0000) |
|
|
||||||
(RECURSIVE_INDEX << 12 << 9 << 9 << 9) |
|
|
||||||
(RECURSIVE_INDEX << 12 << 9 << 9) |
|
|
||||||
(RECURSIVE_INDEX << 12 << 9) |
|
|
||||||
((RECURSIVE_INDEX+1) << 12)) as *mut RvPageTable;
|
|
||||||
|
|
||||||
impl ActivePageTable {
|
impl ActivePageTable {
|
||||||
#[cfg(target_arch = "riscv32")]
|
|
||||||
pub unsafe fn new() -> Self {
|
pub unsafe fn new() -> Self {
|
||||||
ActivePageTable(
|
ActivePageTable(
|
||||||
RecursivePageTable::new(&mut *ROOT_PAGE_TABLE).unwrap(),
|
TwoLevelPageTable::new(&mut ROOT_PAGE_TABLE_BUFFER),
|
||||||
::core::mem::uninitialized()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
#[cfg(target_arch = "riscv64")]
|
|
||||||
pub unsafe fn new() -> Self {
|
|
||||||
#[cfg(feature = "sv39")]
|
|
||||||
let type_ = PageTableType::Sv39;
|
|
||||||
#[cfg(not(feature = "sv39"))]
|
|
||||||
let type_ = PageTableType::Sv48;
|
|
||||||
ActivePageTable(
|
|
||||||
RecursivePageTable::new(&mut *ROOT_PAGE_TABLE, type_).unwrap(),
|
|
||||||
::core::mem::uninitialized()
|
::core::mem::uninitialized()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -97,36 +65,32 @@ impl ActivePageTable {
|
|||||||
/// implementation for the Entry trait in /crate/memory/src/paging/mod.rs
|
/// implementation for the Entry trait in /crate/memory/src/paging/mod.rs
|
||||||
impl Entry for PageEntry {
|
impl Entry for PageEntry {
|
||||||
fn update(&mut self) {
|
fn update(&mut self) {
|
||||||
unsafe { sfence_vma(0, self.1.start_address().as_usize()); }
|
unsafe { clear_all_tlb(); }
|
||||||
}
|
}
|
||||||
fn accessed(&self) -> bool { self.0.flags().contains(EF::ACCESSED) }
|
fn accessed(&self) -> bool { self.0.flags().contains(EF::ACCESSED) }
|
||||||
fn dirty(&self) -> bool { self.0.flags().contains(EF::DIRTY) }
|
fn dirty(&self) -> bool { self.0.flags().contains(EF::DIRTY) }
|
||||||
fn writable(&self) -> bool { self.0.flags().contains(EF::WRITABLE) }
|
fn writable(&self) -> bool { self.0.flags().contains(EF::WRITABLE) }
|
||||||
fn present(&self) -> bool { self.0.flags().contains(EF::VALID | EF::READABLE) }
|
fn present(&self) -> bool { self.0.flags().contains(EF::VALID) }
|
||||||
fn clear_accessed(&mut self) { self.0.flags_mut().remove(EF::ACCESSED); }
|
fn clear_accessed(&mut self) { self.0.flags_mut().remove(EF::ACCESSED); }
|
||||||
fn clear_dirty(&mut self) { self.0.flags_mut().remove(EF::DIRTY); }
|
fn clear_dirty(&mut self) { self.0.flags_mut().remove(EF::DIRTY); }
|
||||||
fn set_writable(&mut self, value: bool) { self.0.flags_mut().set(EF::WRITABLE, value); }
|
fn set_writable(&mut self, value: bool) { self.0.flags_mut().set(EF::WRITABLE, value); }
|
||||||
fn set_present(&mut self, value: bool) { self.0.flags_mut().set(EF::VALID | EF::READABLE, value); }
|
fn set_present(&mut self, value: bool) { self.0.flags_mut().set(EF::VALID, value); }
|
||||||
fn target(&self) -> usize { self.0.addr().as_usize() }
|
fn target(&self) -> usize { self.0.addr().as_usize() }
|
||||||
fn set_target(&mut self, target: usize) {
|
fn set_target(&mut self, target: usize) {
|
||||||
let flags = self.0.flags();
|
let flags = self.0.flags();
|
||||||
let frame = Frame::of_addr(PhysAddr::new(target));
|
let frame = Frame::of_addr(PhysAddr::new(target));
|
||||||
self.0.set(frame, flags);
|
self.0.set(frame, flags);
|
||||||
}
|
}
|
||||||
fn writable_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED1) }
|
fn writable_shared(&self) -> bool { false }
|
||||||
fn readonly_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED2) }
|
fn readonly_shared(&self) -> bool { false }
|
||||||
fn set_shared(&mut self, writable: bool) {
|
fn set_shared(&mut self, writable: bool) { }
|
||||||
let flags = self.0.flags_mut();
|
fn clear_shared(&mut self) { }
|
||||||
flags.set(EF::RESERVED1, writable);
|
|
||||||
flags.set(EF::RESERVED2, !writable);
|
|
||||||
}
|
|
||||||
fn clear_shared(&mut self) { self.0.flags_mut().remove(EF::RESERVED1 | EF::RESERVED2); }
|
|
||||||
fn swapped(&self) -> bool { self.0.flags().contains(EF::RESERVED1) }
|
fn swapped(&self) -> bool { self.0.flags().contains(EF::RESERVED1) }
|
||||||
fn set_swapped(&mut self, value: bool) { self.0.flags_mut().set(EF::RESERVED1, value); }
|
fn set_swapped(&mut self, value: bool) { self.0.flags_mut().set(EF::RESERVED1, value); }
|
||||||
fn user(&self) -> bool { self.0.flags().contains(EF::USER) }
|
fn user(&self) -> bool { true }
|
||||||
fn set_user(&mut self, value: bool) { self.0.flags_mut().set(EF::USER, value); }
|
fn set_user(&mut self, value: bool) { }
|
||||||
fn execute(&self) -> bool { self.0.flags().contains(EF::EXECUTABLE) }
|
fn execute(&self) -> bool { true }
|
||||||
fn set_execute(&mut self, value: bool) { self.0.flags_mut().set(EF::EXECUTABLE, value); }
|
fn set_execute(&mut self, value: bool) { }
|
||||||
fn mmio(&self) -> u8 { 0 }
|
fn mmio(&self) -> u8 { 0 }
|
||||||
fn set_mmio(&mut self, _value: u8) { }
|
fn set_mmio(&mut self, _value: u8) { }
|
||||||
}
|
}
|
||||||
@ -142,93 +106,37 @@ impl InactivePageTable for InactivePageTable0 {
|
|||||||
fn new_bare() -> Self {
|
fn new_bare() -> Self {
|
||||||
let target = alloc_frame().expect("failed to allocate frame");
|
let target = alloc_frame().expect("failed to allocate frame");
|
||||||
let frame = Frame::of_addr(PhysAddr::new(target));
|
let frame = Frame::of_addr(PhysAddr::new(target));
|
||||||
active_table().with_temporary_map(target, |_, table: &mut RvPageTable| {
|
active_table().with_temporary_map(target, |_, table: &mut MIPSPageTable| {
|
||||||
table.zero();
|
table.zero();
|
||||||
table.set_recursive(RECURSIVE_INDEX, frame.clone());
|
|
||||||
});
|
});
|
||||||
InactivePageTable0 { root_frame: frame }
|
InactivePageTable0 { root_frame: frame }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "riscv32")]
|
fn map_kernel(&mut self) { /* nothing to do */ }
|
||||||
fn map_kernel(&mut self) {
|
|
||||||
let table = unsafe { &mut *ROOT_PAGE_TABLE };
|
|
||||||
extern {
|
|
||||||
fn start();
|
|
||||||
fn end();
|
|
||||||
}
|
|
||||||
let mut entrys: [PageTableEntry; 16] = unsafe { core::mem::uninitialized() };
|
|
||||||
let entry_start = start as usize >> 22;
|
|
||||||
let entry_end = (end as usize >> 22) + 1;
|
|
||||||
let entry_count = entry_end - entry_start;
|
|
||||||
for i in 0..entry_count {
|
|
||||||
entrys[i] = table[entry_start + i];
|
|
||||||
}
|
|
||||||
|
|
||||||
self.edit(|_| {
|
|
||||||
// NOTE: 'table' now refers to new page table
|
|
||||||
for i in 0..entry_count {
|
|
||||||
table[entry_start + i] = entrys[i];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "riscv64")]
|
|
||||||
fn map_kernel(&mut self) {
|
|
||||||
let table = unsafe { &mut *ROOT_PAGE_TABLE };
|
|
||||||
let e1 = table[KERNEL_P4_INDEX];
|
|
||||||
assert!(!e1.is_unused());
|
|
||||||
|
|
||||||
self.edit(|_| {
|
|
||||||
table[KERNEL_P4_INDEX] = e1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "riscv32")]
|
|
||||||
fn token(&self) -> usize {
|
fn token(&self) -> usize {
|
||||||
self.root_frame.number() | (1 << 31) // as satp
|
self.root_frame.to_kernel_unmapped().as_usize()
|
||||||
}
|
|
||||||
#[cfg(target_arch = "riscv64")]
|
|
||||||
fn token(&self) -> usize {
|
|
||||||
use bit_field::BitField;
|
|
||||||
let mut satp = self.root_frame.number();
|
|
||||||
satp.set_bits(44..60, 0); // AS is 0
|
|
||||||
#[cfg(feature = "sv39")]
|
|
||||||
satp.set_bits(60..64, satp::Mode::Sv39 as usize);
|
|
||||||
#[cfg(not(feature = "sv39"))]
|
|
||||||
satp.set_bits(60..64, satp::Mode::Sv48 as usize);
|
|
||||||
satp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn set_token(token: usize) {
|
unsafe fn set_token(token: usize) {
|
||||||
asm!("csrw satp, $0" :: "r"(token) :: "volatile");
|
root_page_table_ptr = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn active_token() -> usize {
|
fn active_token() -> usize {
|
||||||
satp::read().bits()
|
root_page_table_ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush_tlb() {
|
fn flush_tlb() {
|
||||||
unsafe { sfence_vma_all(); }
|
unsafe { clear_all_tlb(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn edit<T>(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T {
|
fn edit<T>(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T {
|
||||||
let target = satp::read().frame().start_address().as_usize();
|
let pt: *MIPSPageTable = self.token() as *MIPSPageTable;
|
||||||
active_table().with_temporary_map(target, |active_table, root_table: &mut RvPageTable| {
|
let active = ActivePageTable(
|
||||||
let backup = root_table[RECURSIVE_INDEX].clone();
|
TwoLevelPageTable::new(&mut *pt),
|
||||||
|
::core::mem::uninitialized()
|
||||||
// overwrite recursive mapping
|
);
|
||||||
root_table[RECURSIVE_INDEX].set(self.root_frame.clone(), EF::VALID);
|
f(&mut active)
|
||||||
unsafe { sfence_vma_all(); }
|
|
||||||
|
|
||||||
// execute f in the new context
|
|
||||||
let ret = f(active_table);
|
|
||||||
|
|
||||||
// restore recursive mapping to original p2 table
|
|
||||||
root_table[RECURSIVE_INDEX] = backup;
|
|
||||||
unsafe { sfence_vma_all(); }
|
|
||||||
|
|
||||||
ret
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user