mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 07:22:25 +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()
|
void Thread::_mmu_exception()
|
||||||
{
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
using Genode::log;
|
||||||
|
|
||||||
_become_inactive(AWAITS_RESTART);
|
_become_inactive(AWAITS_RESTART);
|
||||||
_exception_state = MMU_FAULT;
|
_exception_state = MMU_FAULT;
|
||||||
Cpu::mmu_fault(*regs, _fault);
|
Cpu::mmu_fault(*regs, _fault);
|
||||||
_fault.ip = regs->ip;
|
_fault.ip = regs->ip;
|
||||||
|
|
||||||
if (_fault.type == Thread_fault::UNKNOWN) {
|
if (_fault.type == Thread_fault::UNKNOWN) {
|
||||||
Genode::raw(*this, " raised unhandled MMU fault ", _fault);
|
Genode::warning(*this, " raised unhandled MMU fault ", _fault);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_type != USER)
|
if (_type != USER) {
|
||||||
Genode::raw(*this, " raised a fault, which should never happen ",
|
error(*this, " raised a fault, which should never happen ",
|
||||||
_fault);
|
_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)) {
|
if (_pager && _pager->can_submit(1)) {
|
||||||
_pager->submit(1);
|
_pager->submit(1);
|
||||||
|
@ -22,6 +22,32 @@
|
|||||||
using namespace Core;
|
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)
|
Arm_cpu::Context::Context(bool privileged)
|
||||||
{
|
{
|
||||||
using Psr = Arm_cpu::Psr;
|
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
|
struct alignas(8) Context : Cpu_state, Fpu_context
|
||||||
{
|
{
|
||||||
Context(bool privileged);
|
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;
|
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)
|
Cpu::Context::Context(bool privileged)
|
||||||
{
|
{
|
||||||
Spsr::El::set(pstate, privileged ? 1 : 0);
|
Spsr::El::set(pstate, privileged ? 1 : 0);
|
||||||
|
@ -79,6 +79,18 @@ struct Core::Cpu : Hw::Arm_64_cpu
|
|||||||
Fpu_state fpu_state { };
|
Fpu_state fpu_state { };
|
||||||
|
|
||||||
Context(bool privileged);
|
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
|
class Mmu_context
|
||||||
|
@ -25,6 +25,47 @@ using Mmu_context = Core::Cpu::Mmu_context;
|
|||||||
using namespace Core;
|
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)
|
Cpu::Context::Context(bool)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -56,6 +56,11 @@ class Core::Cpu : public Hw::Riscv_cpu
|
|||||||
struct alignas(8) Context : Genode::Cpu_state
|
struct alignas(8) Context : Genode::Cpu_state
|
||||||
{
|
{
|
||||||
Context(bool);
|
Context(bool);
|
||||||
|
|
||||||
|
void print(Output &output) const;
|
||||||
|
|
||||||
|
void for_each_return_address(Const_byte_range_ptr const &,
|
||||||
|
auto const &) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Mmu_context
|
class Mmu_context
|
||||||
|
@ -37,6 +37,27 @@ struct Pseudo_descriptor
|
|||||||
} __attribute__((packed));
|
} __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)
|
Cpu::Context::Context(bool core)
|
||||||
{
|
{
|
||||||
eflags = EFLAGS_IF_SET;
|
eflags = EFLAGS_IF_SET;
|
||||||
|
@ -100,6 +100,18 @@ class Core::Cpu : public Hw::X86_64_cpu
|
|||||||
};
|
};
|
||||||
|
|
||||||
Context(bool privileged);
|
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));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user