diff --git a/src/arch/aarch64/interrupt/exception.rs b/src/arch/aarch64/interrupt/exception.rs index b7c36415a2..90ce963285 100644 --- a/src/arch/aarch64/interrupt/exception.rs +++ b/src/arch/aarch64/interrupt/exception.rs @@ -32,9 +32,10 @@ unsafe fn far_el1() -> usize { ret } -unsafe fn instr_data_abort_inner(stack: &mut InterruptStack, from_user: bool, instr_not_data: bool) -> bool { +unsafe fn instr_data_abort_inner(stack: &mut InterruptStack, from_user: bool, instr_not_data: bool, from: &str) -> bool { let iss = iss(stack.iret.esr_el1); let fsc = iss & 0x3F; + //dbg!(fsc); let was_translation_fault = fsc >= 0b000100 && fsc <= 0b000111; //let was_permission_fault = fsc >= 0b001101 && fsc <= 0b001111; @@ -50,44 +51,45 @@ unsafe fn instr_data_abort_inner(stack: &mut InterruptStack, from_user: bool, in flags.set(GenericPfFlags::USER_NOT_SUPERVISOR, from_user); let faulting_addr = VirtualAddress::new(far_el1()); + //dbg!(faulting_addr, flags, from); crate::memory::page_fault_handler(stack, flags, faulting_addr).is_ok() } exception_stack!(synchronous_exception_at_el1_with_spx, |stack| { - if !pf_inner(stack, exception_code(stack.iret.esr_el1)) { + if !pf_inner(stack, exception_code(stack.iret.esr_el1), "sync_exc_el1_spx") { println!("Synchronous exception at EL1 with SPx"); stack.dump(); stack_trace(); loop {} } }); -unsafe fn pf_inner(stack: &mut InterruptStack, ty: u8) -> bool { +unsafe fn pf_inner(stack: &mut InterruptStack, ty: u8, from: &str) -> bool { match ty { // "Data Abort taken from a lower Exception level" - 0b100100 => instr_data_abort_inner(stack, true, false), + 0b100100 => instr_data_abort_inner(stack, true, false, from), // "Data Abort taken without a change in Exception level" - 0b100101 => instr_data_abort_inner(stack, false, false), + 0b100101 => instr_data_abort_inner(stack, false, false, from), // "Instruction Abort taken from a lower Exception level" - 0b100000 => instr_data_abort_inner(stack, true, true), + 0b100000 => instr_data_abort_inner(stack, true, true, from), // "Instruction Abort taken without a change in Exception level" - 0b100001 => instr_data_abort_inner(stack, false, true), + 0b100001 => instr_data_abort_inner(stack, false, true, from), _ => return false, } } exception_stack!(synchronous_exception_at_el0, |stack| { - match stack.iret.esr_el1 { + match exception_code(stack.iret.esr_el1) { 0b010101 => with_exception_stack!(|stack| { let scratch = &stack.scratch; syscall::syscall(scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, stack) }), - ty => if !pf_inner(stack, ty as u8) { - println!("FATAL: Not an SVC induced synchronous exception"); + ty => if !pf_inner(stack, ty as u8, "sync_exc_el0") { + log::error!("FATAL: Not an SVC induced synchronous exception (ty={:b})", ty); println!("FAR_EL1: {:#0x}", far_el1()); - crate::debugger::debugger(None); + //crate::debugger::debugger(None); stack.dump(); stack_trace(); crate::ksignal(SIGSEGV); diff --git a/src/debugger.rs b/src/debugger.rs index 524810c727..d03aa903fb 100644 --- a/src/debugger.rs +++ b/src/debugger.rs @@ -5,11 +5,19 @@ use crate::paging::{RmmA, RmmArch, TableKind, PAGE_SIZE}; // Super unsafe due to page table switching and raw pointers! #[cfg(target_arch = "aarch64")] pub unsafe fn debugger(target_id: Option) { + use alloc::collections::{BTreeSet, BTreeMap}; + + use crate::memory::{RefCount, get_page_info}; + println!("DEBUGGER START"); println!(); + let mut tree = BTreeMap::new(); + let old_table = RmmA::table(TableKind::User); + let mut spaces = BTreeSet::new(); + for (id, context_lock) in crate::context::contexts().iter() { if target_id.map_or(false, |target_id| *id != target_id) { continue; } let context = context_lock.read(); @@ -22,8 +30,10 @@ pub unsafe fn debugger(target_id: Option) { // Switch to context page table to ensure syscall debug and stack dump will work if let Some(ref space) = context.addr_space { + let new_as = spaces.insert(space.read().table.utable.table().phys().data()); + RmmA::set_table(TableKind::User, space.read().table.utable.table().phys()); - check_consistency(&mut *space.write()); + check_consistency(&mut *space.write(), new_as, &mut tree); if let Some((a, b, c, d, e, f)) = context.syscall { println!("syscall: {}", crate::syscall::debug::format_call(a, b, c, d, e, f)); @@ -36,7 +46,7 @@ pub unsafe fn debugger(target_id: Option) { for (base, grant) in space.grants.iter() { println!( " virt 0x{:016x}:0x{:016x} size 0x{:08x} {:?}", - base.start_address().data(), base.next_by(grant.page_count()).start_address().data(), grant.page_count() * PAGE_SIZE, grant.provider, + base.start_address().data(), base.next_by(grant.page_count() - 1).start_address().data() + 0xFFF, grant.page_count() * PAGE_SIZE, grant.provider, ); } @@ -73,6 +83,18 @@ pub unsafe fn debugger(target_id: Option) { println!(); } + for (frame, count) in tree { + let rc = get_page_info(frame).unwrap().refcount(); + let c = match rc { + RefCount::Zero => 0, + RefCount::One => 1, + RefCount::Cow(c) => c.get(), + RefCount::Shared(s) => s.get(), + }; + if c < count { + println!("undercounted frame {:?} ({} < {})", frame, c, count); + } + } println!("DEBUGGER END"); } @@ -224,10 +246,11 @@ pub unsafe fn debugger(target_id: Option) { println!("DEBUGGER END"); unsafe { x86::bits64::rflags::clac(); } } +#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] +use {alloc::collections::BTreeMap, crate::memory::Frame}; #[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] -pub unsafe fn check_consistency(addr_space: &mut crate::context::memory::AddrSpace) { - use alloc::collections::BTreeMap; +pub unsafe fn check_consistency(addr_space: &mut crate::context::memory::AddrSpace, new_as: bool, tree: &mut BTreeMap) { use crate::context::memory::PageSpan; use crate::memory::{get_page_info, Frame, RefCount}; @@ -235,8 +258,6 @@ pub unsafe fn check_consistency(addr_space: &mut crate::context::memory::AddrSpa let p4 = addr_space.table.utable.table(); - let mut tree = BTreeMap::new(); - for p4i in 0..256 { let p3 = match p4.next(p4i) { Some(p3) => p3, @@ -274,12 +295,14 @@ pub unsafe fn check_consistency(addr_space: &mut crate::context::memory::AddrSpa } }; - const EXCLUDE: usize = (1 << 5) | (1 << 6) | (1 << 1); // accessed+dirty+writable - if grant.flags().data() & !EXCLUDE != flags.data() & !EXCLUDE { + const EXCLUDE: usize = (1 << 5) | (1 << 6); // accessed+dirty+writable + if grant.flags().write(false).data() & !EXCLUDE != flags.write(false).data() & !EXCLUDE { log::error!("FLAG MISMATCH: {:?} != {:?}, address {:p} in grant at {:?}", grant.flags(), flags, address.data() as *const u8, PageSpan::new(base, grant.page_count())); } let frame = Frame::containing_address(physaddr); - *tree.entry(frame).or_insert(0) += 1; + if new_as { + *tree.entry(frame).or_insert(0) += 1; + } if let Some(page) = get_page_info(frame) { match page.refcount() { @@ -297,16 +320,6 @@ pub unsafe fn check_consistency(addr_space: &mut crate::context::memory::AddrSpa } } } - for (frame, count) in tree { - let rc = get_page_info(frame).unwrap().refcount(); - let c = match rc { - RefCount::Zero => 0, - RefCount::One => 1, - RefCount::Cow(c) => c.get(), - RefCount::Shared(s) => s.get(), - }; - assert_eq!(c, count); - } /*for (base, info) in addr_space.grants.iter() { let span = PageSpan::new(base, info.page_count()); diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 614eaaf3cd..7d8883394d 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -183,7 +183,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack let contexts = crate::context::contexts(); if let Some(context_lock) = contexts.current() { let context = context_lock.read(); - if context.name.contains("dash") { + if context.name.contains("getty") { if a == SYS_CLOCK_GETTIME || a == SYS_YIELD { false } else if (a == SYS_WRITE || a == SYS_FSYNC) && (b == 1 || b == 2) {