Improve aarch64 debugger.
This commit is contained in:
@@ -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);
|
||||
|
||||
+32
-19
@@ -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<crate::context::ContextId>) {
|
||||
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<crate::context::ContextId>) {
|
||||
|
||||
// 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<crate::context::ContextId>) {
|
||||
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<crate::context::ContextId>) {
|
||||
|
||||
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<crate::context::ContextId>) {
|
||||
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<Frame, usize>) {
|
||||
|
||||
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());
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user