Merge aarch64 and x86/x86_64 debugger implementations

And make the debugger partially work on riscv64.
This commit is contained in:
bjorn3
2025-09-11 13:03:37 +02:00
parent e131bf219d
commit 9a2203076a
+21 -104
View File
@@ -1,118 +1,17 @@
use crate::{
context::Context,
memory::Frame,
memory::{get_page_info, the_zeroed_frame, Frame, RefCount},
paging::{RmmA, RmmArch, TableKind, PAGE_SIZE},
};
use alloc::sync::Arc;
use hashbrown::{HashMap, HashSet};
use spinning_top::RwSpinlock;
//TODO: combine arches into one function (aarch64 one is newest)
/// Super unsafe due to page table switching and raw pointers!
pub unsafe fn debugger(target_id: Option<*const RwSpinlock<Context>>) {
println!("DEBUGGER START");
println!();
unsafe { debugger_arch(target_id) };
println!("DEBUGGER END");
}
#[cfg(target_arch = "aarch64")]
pub unsafe fn debugger_arch(target_id: Option<*const RwSpinlock<Context>>) {
use crate::memory::{get_page_info, RefCount};
let mut tree = HashMap::new();
let mut spaces = HashSet::new();
let old_table = unsafe { RmmA::table(TableKind::User) };
for context_lock in crate::context::contexts().iter() {
if target_id.map_or(false, |target_id| Arc::as_ptr(&context_lock.0) != target_id) {
continue;
}
let context = context_lock.0.read();
println!("{:p}: {}", Arc::as_ptr(&context_lock.0), context.name);
println!("status: {:?}", context.status);
if !context.status_reason.is_empty() {
println!("reason: {}", context.status_reason);
}
// 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.acquire_read().table.utable.table().phys().data());
unsafe {
RmmA::set_table(
TableKind::User,
space.acquire_read().table.utable.table().phys(),
);
check_page_table_consistency(&mut *space.acquire_write(), new_as, &mut tree);
}
if let Some([a, b, c, d, e, f]) = context.current_syscall() {
println!(
"syscall: {}",
crate::syscall::debug::format_call(a, b, c, d, e, f)
);
}
{
let space = space.acquire_read();
if !space.grants.is_empty() {
println!("grants:");
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() - 1).start_address().data() + 0xFFF,
grant.page_count() * PAGE_SIZE,
grant.provider,
);
}
}
}
if let Some(regs) = context.regs() {
println!("regs:");
regs.dump();
dump_stack(&*context, regs.iret.sp_el0);
}
// Switch to original page table
unsafe { RmmA::set_table(TableKind::User, old_table) };
}
println!();
}
for (frame, (count, p)) in tree {
let Some(info) = get_page_info(frame) else {
assert!(p);
continue;
};
let rc = info.refcount();
let (c, s) = match rc {
None => (0, false),
Some(RefCount::One) => (1, false),
Some(RefCount::Cow(c)) => (c.get(), false),
Some(RefCount::Shared(s)) => (s.get(), true),
};
if c != count {
println!(
"frame refcount mismatch for {:?} ({} != {} s {})",
frame, c, count, s
);
}
}
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub unsafe fn debugger_arch(target_id: Option<*const RwSpinlock<Context>>) {
use crate::memory::{get_page_info, the_zeroed_frame, RefCount};
let mut tree = HashMap::new();
let mut spaces = HashSet::new();
@@ -148,7 +47,7 @@ pub unsafe fn debugger_arch(target_id: Option<*const RwSpinlock<Context>>) {
TableKind::User,
space.acquire_read().table.utable.table().phys(),
);
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
check_page_table_consistency(&mut space.acquire_write(), was_new, &mut tree);
}
}
@@ -170,6 +69,17 @@ pub unsafe fn debugger_arch(target_id: Option<*const RwSpinlock<Context>>) {
for (base, info) in addr_space.grants.iter() {
let size = info.page_count() * PAGE_SIZE;
#[cfg(target_arch = "aarch64")]
println!(
" virt 0x{:016x}:0x{:016x} size 0x{:08x} {:?}",
base.start_address().data(),
base.next_by(info.page_count() - 1).start_address().data() + 0xFFF,
size,
info.provider,
);
// FIXME riscv64 implementation
#[cfg(target_arch = "x86")]
println!(
" virt 0x{:08x}:0x{:08x} size 0x{:08x} {:?}",
@@ -194,6 +104,11 @@ pub unsafe fn debugger_arch(target_id: Option<*const RwSpinlock<Context>>) {
println!("regs:");
regs.dump();
#[cfg(target_arch = "aarch64")]
dump_stack(&*context, regs.iret.sp_el0);
// FIXME riscv64 implementation
#[cfg(target_arch = "x86")]
dump_stack(&*context, regs.iret.esp);
@@ -214,7 +129,7 @@ pub unsafe fn debugger_arch(target_id: Option<*const RwSpinlock<Context>>) {
println!();
}
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
crate::scheme::proc::foreach_addrsp(|addrsp| {
let was_new = spaces.insert(addrsp.acquire_read().table.utable.table().phys().data());
unsafe { check_page_table_consistency(&mut *addrsp.acquire_write(), was_new, &mut tree) };
@@ -242,6 +157,8 @@ pub unsafe fn debugger_arch(target_id: Option<*const RwSpinlock<Context>>) {
"({} kernel-owned references were not counted)",
temporarily_taken_htbufs
);
println!("DEBUGGER END");
}
fn dump_stack(context: &Context, mut sp: usize) {