1
0
mirror of https://github.com/rcore-os/rCore.git synced 2025-01-18 17:07:04 +04:00

Fix mipsel page fault handling

This commit is contained in:
Jiajie Chen 2020-07-07 15:49:55 +08:00
parent 4dd72365ca
commit 6a3a85ca5a
19 changed files with 88 additions and 24 deletions

View File

@ -30,6 +30,7 @@
- fn ack(trap: usize):确认中断处理
- fn timer():处理时钟中断
- fn wait_for_interrupt():打开并等待中断
- fn handle_user_page_fault(thread: &Arc\<Thread\>, addr: usize):处理用户态的缺页异常
### interrupt/consts

View File

@ -2,7 +2,9 @@
pub use self::handler::*;
use crate::arch::board::timer::is_pending;
use crate::process::thread::Thread;
use aarch64::regs::*;
use alloc::sync::Arc;
use trapframe::UserContext;
pub mod consts;
@ -68,3 +70,7 @@ pub fn wait_for_interrupt() {
aarch64::asm::wfe();
DAIF.set(daif);
}
pub fn handle_user_page_fault(thread: &Arc<Thread>, addr: usize) -> bool {
thread.vm.lock().handle_page_fault(addr)
}

View File

@ -1,3 +1,5 @@
use mips::registers::cp0;
pub const IrqMin: usize = 0x20;
pub const IrqMax: usize = 0x3f;
pub const Syscall: usize = 0x100;
@ -5,5 +7,12 @@ pub const Syscall: usize = 0x100;
pub const Timer: usize = IrqMin + 0;
pub fn is_page_fault(trap: usize) -> bool {
false
use cp0::cause::Exception as E;
let cause = cp0::cause::Cause { bits: trap as u32 };
match cause.cause() {
E::TLBModification => true,
E::TLBLoadMiss => true,
E::TLBStoreMiss => true,
_ => false,
}
}

View File

@ -1,5 +1,7 @@
use crate::arch::paging::get_root_page_table_ptr;
use crate::drivers::IRQ_MANAGER;
use crate::process::thread::Thread;
use alloc::sync::Arc;
use log::*;
use mips::addr::*;
use mips::interrupts;
@ -235,6 +237,39 @@ fn reserved_inst(tf: &mut TrapFrame) -> bool {
false
}
pub fn handle_user_page_fault(thread: &Arc<Thread>, addr: usize) -> bool {
let virt_addr = VirtAddr::new(addr);
let root_table = unsafe { &mut *(get_root_page_table_ptr() as *mut MIPSPageTable) };
let tlb_result = root_table.lookup(addr);
match tlb_result {
Ok(tlb_entry) => {
trace!(
"PhysAddr = {:x}/{:x}",
tlb_entry.entry_lo0.get_pfn() << 12,
tlb_entry.entry_lo1.get_pfn() << 12
);
let tlb_valid = if virt_addr.page_number() & 1 == 0 {
tlb_entry.entry_lo0.valid()
} else {
tlb_entry.entry_lo1.valid()
};
if !tlb_valid {
if !thread.vm.lock().handle_page_fault(addr) {
return false;
}
}
tlb_entry.write_random();
true
}
Err(()) => {
return thread.vm.lock().handle_page_fault(addr);
}
}
}
fn page_fault(tf: &mut TrapFrame) {
// TODO: set access/dirty bit
let addr = tf.vaddr;

View File

@ -1,6 +1,7 @@
use crate::arch::paging::*;
use crate::consts::{KERNEL_OFFSET, MEMORY_END, MEMORY_OFFSET};
use crate::memory::{init_heap, FRAME_ALLOCATOR};
use mips::registers::cp0;
use rcore_memory::PAGE_SIZE;
/// Initialize the memory management module
@ -9,13 +10,12 @@ pub fn init() {
init_frame_allocator();
init_heap();
// for debugging
set_root_page_table_ptr(0xFFFF_FFFF);
extern "C" {
fn _root_page_table_buffer();
fn _root_page_table_ptr();
}
println!("_root_page_table_ptr {:x}", _root_page_table_ptr as usize);
}
pub fn init_other() {
@ -72,10 +72,11 @@ extern "C" {
}
pub fn set_page_table(vmtoken: usize) {
// TODO
if get_root_page_table_ptr() != vmtoken {
set_root_page_table_ptr(vmtoken);
}
}
pub fn get_page_fault_addr() -> usize {
// TODO
0
cp0::bad_vaddr::read_u32() as usize
}

View File

@ -15,7 +15,7 @@ pub const MEMORY_OFFSET: usize = 0x8000_0000;
// TODO: get memory end from device tree
pub const MEMORY_END: usize = 0x8800_0000;
// FIXME: rv64 `sh` and `ls` will crash if stack top > 0x80000000 ???
// TODO: rv64 `sh` and `ls` will crash if stack top > 0x80000000 ???
pub const USER_STACK_OFFSET: usize = 0x40000000 - USER_STACK_SIZE;
pub const USER_STACK_SIZE: usize = 0x10000;

View File

@ -1,5 +1,7 @@
use crate::arch::interrupt::consts::SupervisorExternal;
use crate::drivers::IRQ_MANAGER;
use crate::process::thread::Thread;
use alloc::sync::Arc;
use log::*;
use riscv::register::*;
use riscv::register::{scause::Scause, sscratch, stvec};
@ -113,3 +115,7 @@ pub fn wait_for_interrupt() {
}
}
}
pub fn handle_user_page_fault(thread: &Arc<Thread>, addr: usize) -> bool {
thread.vm.lock().handle_page_fault(addr)
}

View File

@ -53,7 +53,7 @@ pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! {
}
memory::init(device_tree_vaddr);
timer::init();
// FIXME: init driver on u540
// TODO: init driver on u540
#[cfg(not(any(feature = "board_u540")))]
board::init(device_tree_vaddr);
unsafe {

View File

@ -39,7 +39,7 @@ pub const SYS_MKDIRAT: usize = 34;
pub const SYS_UNLINKAT: usize = 35;
pub const SYS_SYMLINKAT: usize = 36;
pub const SYS_LINKAT: usize = 37;
pub const SYS_RENAMEAT: usize = 38; // FIXME
pub const SYS_RENAMEAT: usize = 38;
pub const SYS_UMOUNT2: usize = 39;
pub const SYS_MOUNT: usize = 40;
pub const SYS_PIVOT_ROOT: usize = 41;

View File

@ -3,6 +3,8 @@ mod handler;
pub use self::handler::*;
use crate::memory::phys_to_virt;
use crate::process::thread::Thread;
use alloc::sync::Arc;
use apic::*;
use trapframe::{TrapFrame, UserContext};
@ -60,3 +62,7 @@ pub fn wait_for_interrupt() {
x86_64::instructions::interrupts::enable_interrupts_and_hlt();
x86_64::instructions::interrupts::disable();
}
pub fn handle_user_page_fault(thread: &Arc<Thread>, addr: usize) -> bool {
thread.vm.lock().handle_page_fault(addr)
}

View File

@ -284,7 +284,7 @@ impl FrameDeallocator<Size4KiB> for FrameAllocatorForX86 {
/// Flush TLB for `vaddr` on all CPU
fn flush_tlb_all(_vaddr: usize) {
// FIXME: too slow, disable now.
// TODO: too slow, disable now.
return;
// if !super::AP_CAN_INIT.load(Ordering::Relaxed) {
// return;

View File

@ -13,7 +13,7 @@ pub static CONSOLE: Mutex<Option<RCoreConsole>> = Mutex::new(None);
pub fn init() {
if cfg!(feature = "consolegraphic") {
if let Some(fb) = FRAME_BUFFER.write().take() {
// FIXME: now take FrameBuffer out of global variable, then move into Console
// TODO: now take FrameBuffer out of global variable, then move into Console
let console = Console::on_frame_buffer(fb.fb_info.xres, fb.fb_info.yres, fb);
*CONSOLE.lock() = Some(console);
info!("console: init end");

View File

@ -113,7 +113,7 @@ impl FileHandle {
pub async fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
// let options = &self.description.read().options;
if !self.description.read().options.read {
return Err(FsError::InvalidParam); // FIXME: => EBADF
return Err(FsError::InvalidParam); // TODO: => EBADF
}
if !self.description.read().options.nonblock {
// block
@ -150,7 +150,7 @@ impl FileHandle {
pub fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
if !self.description.read().options.write {
return Err(FsError::InvalidParam); // FIXME: => EBADF
return Err(FsError::InvalidParam); // TODO: => EBADF
}
let len = self.inode.write_at(offset, buf)?;
TimeSpec::update(&self.inode);
@ -169,7 +169,7 @@ impl FileHandle {
pub fn set_len(&mut self, len: u64) -> Result<()> {
if !self.description.read().options.write {
return Err(FsError::InvalidParam); // FIXME: => EBADF
return Err(FsError::InvalidParam); // TODO: => EBADF
}
self.inode.resize(len as usize)?;
Ok(())
@ -194,7 +194,7 @@ impl FileHandle {
pub fn read_entry(&mut self) -> Result<String> {
let mut description = self.description.write();
if !description.options.read {
return Err(FsError::InvalidParam); // FIXME: => EBADF
return Err(FsError::InvalidParam); // TODO: => EBADF
}
let mut offset = &mut description.offset;
let name = self.inode.get_entry(*offset as usize)?;
@ -205,7 +205,7 @@ impl FileHandle {
pub fn read_entry_with_metadata(&mut self) -> Result<(Metadata, String)> {
let mut description = self.description.write();
if !description.options.read {
return Err(FsError::InvalidParam); // FIXME: => EBADF
return Err(FsError::InvalidParam); // TODO: => EBADF
}
let mut offset = &mut description.offset;
let ret = self.inode.get_entry_with_metadata(*offset as usize)?;

View File

@ -527,7 +527,7 @@ impl Socket for UdpSocketState {
match request {
// SIOCGARP
0x8954 => {
// FIXME: check addr
// TODO: check addr
let req = unsafe { &mut *(arg1 as *mut ArpReq) };
if let AddressFamily::Internet = AddressFamily::from(req.arp_pa.family) {
let name = req.arp_dev.as_ptr();

View File

@ -3,7 +3,7 @@ use super::{
add_to_process_table, Pid, Process, PROCESSORS,
};
use crate::arch::interrupt::consts::{is_page_fault, IrqMax, IrqMin, Syscall, Timer};
use crate::arch::interrupt::get_trap_num;
use crate::arch::interrupt::{get_trap_num, handle_user_page_fault};
use crate::arch::{
cpu,
fp::FpState,
@ -511,7 +511,7 @@ pub fn spawn(thread: Arc<Thread>) {
let addr = get_page_fault_addr();
debug!("page fault from user @ {:#x}", addr);
if !thread.vm.lock().handle_page_fault(addr as usize) {
if !handle_user_page_fault(&thread, addr) {
// TODO: SIGSEGV
panic!("page fault handle failed");
}

View File

@ -172,7 +172,7 @@ pub fn handle_signal(thread: &Arc<Thread>, tf: &mut UserContext) -> bool {
match signal {
SIGALRM | SIGHUP | SIGINT => {
info!("default action: Term");
// FIXME: exit code ref please?
// TODO: exit code ref please?
process.exit(info.signo as usize + 128);
return true;
}

View File

@ -81,7 +81,7 @@ impl Syscall<'_> {
);
let _attr = prot.to_attr();
// FIXME: properly set the attribute of the area
// TODO: properly set the attribute of the area
// now some mut ptr check is fault
let vm = self.vm();
let memory_area = vm
@ -147,7 +147,7 @@ impl MmapProt {
if self.contains(MmapProt::EXEC) {
attr = attr.execute();
}
// FIXME: see sys_mprotect
// TODO: see sys_mprotect
// if !self.contains(MmapProt::WRITE) { attr = attr.readonly(); }
attr
}

View File

@ -350,7 +350,7 @@ impl Syscall<'_> {
// perform futex wake 1
// ref: http://man7.org/linux/man-pages/man2/set_tid_address.2.html
// FIXME: do it in all possible ways a thread can exit
// TODO: do it in all possible ways a thread can exit
// it has memory access so we can't move it to Thread::drop?
let clear_child_tid = self.thread.inner.lock().clear_child_tid as *mut u32;
if !clear_child_tid.is_null() {

View File

@ -38,7 +38,7 @@ impl<T, P: Policy> Debug for UserPtr<T, P> {
}
}
// FIXME: this is a workaround for `clear_child_tid`.
// TODO: this is a workaround for `clear_child_tid`.
unsafe impl<T, P: Policy> Send for UserPtr<T, P> {}
unsafe impl<T, P: Policy> Sync for UserPtr<T, P> {}