mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 13:26:27 +00:00
hw: register state and backtrace when core faults
If one of core's threads is causing an MMU fault, dump the register state and stack backtrace of the faulting stack to aid debugging. Fix genodelabs/genode#5387
This commit is contained in:
parent
cc2bcee417
commit
4730312c1e
@ -935,19 +935,31 @@ void Thread::_call()
|
||||
|
||||
void Thread::_mmu_exception()
|
||||
{
|
||||
using namespace Genode;
|
||||
using Genode::log;
|
||||
|
||||
_become_inactive(AWAITS_RESTART);
|
||||
_exception_state = MMU_FAULT;
|
||||
Cpu::mmu_fault(*regs, _fault);
|
||||
_fault.ip = regs->ip;
|
||||
|
||||
if (_fault.type == Thread_fault::UNKNOWN) {
|
||||
Genode::raw(*this, " raised unhandled MMU fault ", _fault);
|
||||
Genode::warning(*this, " raised unhandled MMU fault ", _fault);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_type != USER)
|
||||
Genode::raw(*this, " raised a fault, which should never happen ",
|
||||
_fault);
|
||||
if (_type != USER) {
|
||||
error(*this, " raised a fault, which should never happen ",
|
||||
_fault);
|
||||
log("Register dump: ", *regs);
|
||||
log("Backtrace:");
|
||||
|
||||
Const_byte_range_ptr const stack {
|
||||
(char const*)Hw::Mm::core_stack_area().base,
|
||||
Hw::Mm::core_stack_area().size };
|
||||
regs->for_each_return_address(stack, [&] (void **p) {
|
||||
log(*p); });
|
||||
}
|
||||
|
||||
if (_pager && _pager->can_submit(1)) {
|
||||
_pager->submit(1);
|
||||
|
@ -22,6 +22,32 @@
|
||||
using namespace Core;
|
||||
|
||||
|
||||
void Arm_cpu::Context::print(Output &output) const
|
||||
{
|
||||
using namespace Genode;
|
||||
using Genode::print;
|
||||
|
||||
print(output, "\n");
|
||||
print(output, " r0 = ", Hex(r0), "\n");
|
||||
print(output, " r1 = ", Hex(r1), "\n");
|
||||
print(output, " r2 = ", Hex(r2), "\n");
|
||||
print(output, " r3 = ", Hex(r3), "\n");
|
||||
print(output, " r4 = ", Hex(r4), "\n");
|
||||
print(output, " r5 = ", Hex(r5), "\n");
|
||||
print(output, " r6 = ", Hex(r6), "\n");
|
||||
print(output, " r7 = ", Hex(r7), "\n");
|
||||
print(output, " r8 = ", Hex(r8), "\n");
|
||||
print(output, " r9 = ", Hex(r9), "\n");
|
||||
print(output, " r10 = ", Hex(r10), "\n");
|
||||
print(output, " r11 = ", Hex(r11), "\n");
|
||||
print(output, " r12 = ", Hex(r12), "\n");
|
||||
print(output, " ip = ", Hex(ip), "\n");
|
||||
print(output, " sp = ", Hex(sp), "\n");
|
||||
print(output, " lr = ", Hex(lr), "\n");
|
||||
print(output, " cpsr = ", Hex(cpsr));
|
||||
}
|
||||
|
||||
|
||||
Arm_cpu::Context::Context(bool privileged)
|
||||
{
|
||||
using Psr = Arm_cpu::Psr;
|
||||
|
@ -49,6 +49,18 @@ struct Core::Arm_cpu : public Hw::Arm_cpu
|
||||
struct alignas(8) Context : Cpu_state, Fpu_context
|
||||
{
|
||||
Context(bool privileged);
|
||||
|
||||
void print(Output &output) const;
|
||||
|
||||
void for_each_return_address(Const_byte_range_ptr const &stack,
|
||||
auto const &fn)
|
||||
{
|
||||
void **fp = (void**)r11;
|
||||
while (stack.contains(fp-1) && stack.contains(fp) && fp[0]) {
|
||||
fn(fp);
|
||||
fp = (void **) fp[-1];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -22,6 +22,22 @@
|
||||
using namespace Core;
|
||||
|
||||
|
||||
void Cpu::Context::print(Output &output) const
|
||||
{
|
||||
using namespace Genode;
|
||||
using Genode::print;
|
||||
|
||||
print(output, "\n");
|
||||
for (unsigned i = 0; i < 31; i++)
|
||||
print(output, " x", i, " = ", Hex(r[i]), "\n");
|
||||
print(output, " ip = ", Hex(ip), "\n");
|
||||
print(output, " sp = ", Hex(sp), "\n");
|
||||
print(output, " esr = ", Hex(esr_el1), "\n");
|
||||
print(output, " pstate = ", Hex(pstate), "\n");
|
||||
print(output, " mdscr = ", Hex(mdscr_el1));
|
||||
}
|
||||
|
||||
|
||||
Cpu::Context::Context(bool privileged)
|
||||
{
|
||||
Spsr::El::set(pstate, privileged ? 1 : 0);
|
||||
|
@ -79,6 +79,18 @@ struct Core::Cpu : Hw::Arm_64_cpu
|
||||
Fpu_state fpu_state { };
|
||||
|
||||
Context(bool privileged);
|
||||
|
||||
void print(Output &output) const;
|
||||
|
||||
void for_each_return_address(Const_byte_range_ptr const &stack,
|
||||
auto const &fn)
|
||||
{
|
||||
void **fp = (void**)r[29];
|
||||
while (stack.contains(fp) && stack.contains(fp + 1) && fp[1]) {
|
||||
fn(fp + 1);
|
||||
fp = (void **) fp[0];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Mmu_context
|
||||
|
@ -25,6 +25,47 @@ using Mmu_context = Core::Cpu::Mmu_context;
|
||||
using namespace Core;
|
||||
|
||||
|
||||
void Cpu::Context::print(Output &output) const
|
||||
{
|
||||
using namespace Genode;
|
||||
using Genode::print;
|
||||
|
||||
print(output, "\n");
|
||||
print(output, " ip = ", Hex(ip), "\n");
|
||||
print(output, " ra = ", Hex(ra), "\n");
|
||||
print(output, " sp = ", Hex(sp), "\n");
|
||||
print(output, " gp = ", Hex(gp), "\n");
|
||||
print(output, " tp = ", Hex(tp), "\n");
|
||||
print(output, " t0 = ", Hex(t0), "\n");
|
||||
print(output, " t1 = ", Hex(t1), "\n");
|
||||
print(output, " t2 = ", Hex(t2), "\n");
|
||||
print(output, " s0 = ", Hex(s0), "\n");
|
||||
print(output, " s1 = ", Hex(s1), "\n");
|
||||
print(output, " a0 = ", Hex(a0), "\n");
|
||||
print(output, " a1 = ", Hex(a1), "\n");
|
||||
print(output, " a2 = ", Hex(a2), "\n");
|
||||
print(output, " a3 = ", Hex(a3), "\n");
|
||||
print(output, " a4 = ", Hex(a4), "\n");
|
||||
print(output, " a5 = ", Hex(a5), "\n");
|
||||
print(output, " a6 = ", Hex(a6), "\n");
|
||||
print(output, " a7 = ", Hex(a7), "\n");
|
||||
print(output, " s2 = ", Hex(s2), "\n");
|
||||
print(output, " s3 = ", Hex(s3), "\n");
|
||||
print(output, " s4 = ", Hex(s4), "\n");
|
||||
print(output, " s5 = ", Hex(s5), "\n");
|
||||
print(output, " s6 = ", Hex(s6), "\n");
|
||||
print(output, " s7 = ", Hex(s7), "\n");
|
||||
print(output, " s8 = ", Hex(s8), "\n");
|
||||
print(output, " s9 = ", Hex(s9), "\n");
|
||||
print(output, " s10 = ", Hex(s10), "\n");
|
||||
print(output, " s11 = ", Hex(s11), "\n");
|
||||
print(output, " t3 = ", Hex(t3), "\n");
|
||||
print(output, " t4 = ", Hex(t4), "\n");
|
||||
print(output, " t5 = ", Hex(t5), "\n");
|
||||
print(output, " t6 = ", Hex(t6));
|
||||
}
|
||||
|
||||
|
||||
Cpu::Context::Context(bool)
|
||||
{
|
||||
/*
|
||||
|
@ -56,6 +56,11 @@ class Core::Cpu : public Hw::Riscv_cpu
|
||||
struct alignas(8) Context : Genode::Cpu_state
|
||||
{
|
||||
Context(bool);
|
||||
|
||||
void print(Output &output) const;
|
||||
|
||||
void for_each_return_address(Const_byte_range_ptr const &,
|
||||
auto const &) { }
|
||||
};
|
||||
|
||||
class Mmu_context
|
||||
|
@ -37,6 +37,27 @@ struct Pseudo_descriptor
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
void Cpu::Context::print(Output &output) const
|
||||
{
|
||||
using namespace Genode;
|
||||
using Genode::print;
|
||||
|
||||
print(output, "\n");
|
||||
print(output, " ip = ", Hex(ip), "\n");
|
||||
print(output, " sp = ", Hex(sp), "\n");
|
||||
print(output, " cs = ", Hex(cs), "\n");
|
||||
print(output, " ss = ", Hex(ss), "\n");
|
||||
print(output, " eflags = ", Hex(eflags), "\n");
|
||||
print(output, " rax = ", Hex(rax), "\n");
|
||||
print(output, " rbx = ", Hex(rbx), "\n");
|
||||
print(output, " rcx = ", Hex(rcx), "\n");
|
||||
print(output, " rdx = ", Hex(rdx), "\n");
|
||||
print(output, " rdi = ", Hex(rdi), "\n");
|
||||
print(output, " rsi = ", Hex(rsi), "\n");
|
||||
print(output, " rbp = ", Hex(rbp));
|
||||
}
|
||||
|
||||
|
||||
Cpu::Context::Context(bool core)
|
||||
{
|
||||
eflags = EFLAGS_IF_SET;
|
||||
|
@ -100,6 +100,18 @@ class Core::Cpu : public Hw::X86_64_cpu
|
||||
};
|
||||
|
||||
Context(bool privileged);
|
||||
|
||||
void print(Output &output) const;
|
||||
|
||||
void for_each_return_address(Const_byte_range_ptr const &stack,
|
||||
auto const &fn)
|
||||
{
|
||||
void **fp = (void**)rbp;
|
||||
while (stack.contains(fp) && stack.contains(fp + 1) && fp[1]) {
|
||||
fn(fp + 1);
|
||||
fp = (void **) fp[0];
|
||||
}
|
||||
}
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user