mirror of
https://github.com/rcore-os/rCore.git
synced 2025-01-18 08:57:05 +04:00
Fix mipsel page fault handling
This commit is contained in:
parent
4dd72365ca
commit
6a3a85ca5a
@ -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
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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)?;
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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> {}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user