diff --git a/repos/base-hw/src/core/kernel/cpu.cc b/repos/base-hw/src/core/kernel/cpu.cc index 5f1f33ac2c..bf2d320cfe 100644 --- a/repos/base-hw/src/core/kernel/cpu.cc +++ b/repos/base-hw/src/core/kernel/cpu.cc @@ -159,11 +159,16 @@ Cpu::Context & Cpu::schedule_next_context(Context &last) } +addr_t Cpu::stack_base() +{ + return Hw::Mm::cpu_local_memory().base + + Hw::Mm::CPU_LOCAL_MEMORY_SLOT_SIZE*_id; +} + + addr_t Cpu::stack_start() { - return Abi::stack_align(Hw::Mm::cpu_local_memory().base + - (Hw::Mm::CPU_LOCAL_MEMORY_SLOT_SIZE*_id) - + Hw::Mm::KERNEL_STACK_SIZE); + return Abi::stack_align(stack_base() + Hw::Mm::KERNEL_STACK_SIZE); } diff --git a/repos/base-hw/src/core/kernel/cpu.h b/repos/base-hw/src/core/kernel/cpu.h index 24d213c248..2314322dd8 100644 --- a/repos/base-hw/src/core/kernel/cpu.h +++ b/repos/base-hw/src/core/kernel/cpu.h @@ -155,6 +155,7 @@ class Kernel::Cpu : public Core::Cpu, private Irq::Pool, Board::Pic & pic() { return _pic; } Timer & timer() { return _timer; } + addr_t stack_base(); addr_t stack_start(); /** @@ -181,6 +182,8 @@ class Kernel::Cpu : public Core::Cpu, private Irq::Pool, _arch_init(); _state = RUN; } + + [[noreturn]] void panic(Genode::Cpu_state &state); }; diff --git a/repos/base-hw/src/core/kernel/main.cc b/repos/base-hw/src/core/kernel/main.cc index b1925cad2e..a88e15ce6b 100644 --- a/repos/base-hw/src/core/kernel/main.cc +++ b/repos/base-hw/src/core/kernel/main.cc @@ -72,9 +72,7 @@ void Kernel::Main::_handle_kernel_entry(Genode::Cpu_state *state) if (state) recent.exception(*state); context = &cpu.schedule_next_context(recent); }, - [&] () { - Genode::error("Cpu ", Cpu::executing_id(), " re-entered lock. ", - "Kernel exception?!"); }); + [&] () { _cpu_pool.cpu(Cpu::executing_id()).panic(*state); }); context->proceed(); } diff --git a/repos/base-hw/src/core/spec/arm/kernel/cpu.cc b/repos/base-hw/src/core/spec/arm/kernel/cpu.cc index da9c280536..654530188f 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/cpu.cc @@ -15,6 +15,7 @@ /* core includes */ #include #include +#include void Kernel::Cpu::_arch_init() @@ -24,3 +25,55 @@ void Kernel::Cpu::_arch_init() /* enable timer interrupt */ _pic.unmask(_timer.interrupt_id(), id()); } + + +[[noreturn]] void Kernel::Cpu::panic(Genode::Cpu_state &state) +{ + using namespace Genode; + using Cs = Genode::Cpu_state; + + const char *reason = "unknown"; + + switch (state.cpu_exception) { + case Cs::PREFETCH_ABORT: [[fallthrough]]; + case Cs::DATA_ABORT: reason = "page-fault"; break; + case Cs::UNDEFINED_INSTRUCTION: reason = "undefined instruction"; break; + case Cs::SUPERVISOR_CALL: reason = "system-call"; break; + case Cs::FAST_INTERRUPT_REQUEST: [[fallthrough]]; + case Cs::INTERRUPT_REQUEST: reason = "interrupt "; break; + case Cs::RESET : reason = "reset "; break; + default: ; + }; + + log(""); + log("Kernel panic on CPU ", Cpu::executing_id()); + log("Exception reason is ", reason); + log(""); + log("Register dump:"); + log("r0 = ", Hex(state.r0)); + log("r1 = ", Hex(state.r1)); + log("r2 = ", Hex(state.r2)); + log("r3 = ", Hex(state.r3)); + log("r4 = ", Hex(state.r4)); + log("r5 = ", Hex(state.r5)); + log("r6 = ", Hex(state.r6)); + log("r7 = ", Hex(state.r7)); + log("r8 = ", Hex(state.r8)); + log("r9 = ", Hex(state.r9)); + log("r10 = ", Hex(state.r10)); + log("r11 = ", Hex(state.r11)); + log("r12 = ", Hex(state.r12)); + log("sp = ", Hex(state.sp)); + log("lr = ", Hex(state.lr)); + log("ip = ", Hex(state.ip)); + log("cpsr = ", Hex(state.cpsr)); + log(""); + log("Backtrace:"); + + Core::Cpu::Context &context = static_cast(state); + Const_byte_range_ptr const stack { + (char const*)stack_base(), Hw::Mm::KERNEL_STACK_SIZE }; + context.for_each_return_address(stack, [&] (void **p) { log(*p); }); + + while (true) asm volatile("wfi"); +} diff --git a/repos/base-hw/src/core/spec/arm_v8/kernel/cpu.cc b/repos/base-hw/src/core/spec/arm_v8/kernel/cpu.cc index c9751ade8f..645bd6f1f3 100644 --- a/repos/base-hw/src/core/spec/arm_v8/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/arm_v8/kernel/cpu.cc @@ -13,6 +13,7 @@ /* core includes */ #include +#include void Kernel::Cpu::_arch_init() @@ -20,3 +21,55 @@ void Kernel::Cpu::_arch_init() /* enable timer interrupt */ _pic.unmask(_timer.interrupt_id(), id()); } + + +[[noreturn]] void Kernel::Cpu::panic(Genode::Cpu_state &state) +{ + using namespace Genode; + + Core::Cpu::Context &context = static_cast(state); + + const char *reason = "unknown"; + + switch (context.exception_type) { + case Cpu::SYNC_LEVEL_EL0: [[fallthrough]]; + case Cpu::SYNC_LEVEL_EL1: + using Ec = Cpu::Esr::Ec; + switch (Ec::get(state.esr_el1)) { + case Ec::INST_ABORT_SAME_LEVEL: [[fallthrough]]; + case Ec::DATA_ABORT_SAME_LEVEL: [[fallthrough]]; + case Ec::INST_ABORT_LOW_LEVEL: [[fallthrough]]; + case Ec::DATA_ABORT_LOW_LEVEL: reason = "page-fault"; break; + case Ec::SVC: reason = "system-call"; break; + case Ec::SOFTWARE_STEP_LOW_LEVEL: [[fallthrough]]; + case Ec::BRK: reason = "debug"; break; + default: ; + } + break; + case Cpu::IRQ_LEVEL_EL0: [[fallthrough]]; + case Cpu::IRQ_LEVEL_EL1: [[fallthrough]]; + case Cpu::FIQ_LEVEL_EL0: [[fallthrough]]; + case Cpu::FIQ_LEVEL_EL1: reason = "interrupt "; break; + case Cpu::RESET: reason = "reset "; break; + default: ; + }; + + log(""); + log("Kernel panic on CPU ", Cpu::executing_id()); + log("Exception reason is ", reason); + log(""); + log("Register dump:"); + for (unsigned i = 0; i < 31; i++) + log("r", i, i<10 ? " " : "", " = ", Hex(state.r[i])); + log("sp = ", Hex(state.sp)); + log("ip = ", Hex(state.ip)); + log("esr_el1 = ", Hex(state.esr_el1)); + log(""); + log("Backtrace:"); + + Const_byte_range_ptr const stack { + (char const*)stack_base(), Hw::Mm::KERNEL_STACK_SIZE }; + context.for_each_return_address(stack, [&] (void **p) { log(*p); }); + + while (true) asm volatile("wfi"); +} diff --git a/repos/base-hw/src/core/spec/riscv/kernel/cpu.cc b/repos/base-hw/src/core/spec/riscv/kernel/cpu.cc index e22f18f3e3..db0bf5daff 100644 --- a/repos/base-hw/src/core/spec/riscv/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/riscv/kernel/cpu.cc @@ -14,7 +14,82 @@ /* core includes */ #include #include +#include void Kernel::Cpu::_arch_init() { Stvec::write(Hw::Mm::supervisor_exception_vector().base); } + + +[[noreturn]] void Kernel::Cpu::panic(Genode::Cpu_state &state) +{ + using namespace Genode; + using Cs = Genode::Cpu_state; + + Core::Cpu::Context &context = static_cast(state); + + const char *reason = "unknown"; + + if (context.is_irq()) reason = "interrupt"; + + switch(state.cpu_exception) { + case Cs::ECALL_FROM_SUPERVISOR: [[fallthrough]]; + case Cs::ECALL_FROM_USER: reason = "system-call"; break; + case Cs::INSTRUCTION_PAGE_FAULT: [[fallthrough]]; + case Cs::STORE_PAGE_FAULT: [[fallthrough]]; + case Cs::LOAD_PAGE_FAULT: [[fallthrough]]; + case Cs::INSTRUCTION_ACCESS_FAULT: [[fallthrough]]; + case Cs::LOAD_ACCESS_FAULT: [[fallthrough]]; + case Cs::STORE_ACCESS_FAULT: reason = "page-fault"; break; + case Cs::INSTRUCTION_ILLEGAL: reason = "undefined-instruction"; break; + case Cs::BREAKPOINT: reason = "debug"; break; + case Cs::RESET: reason = "reset"; break; + default: ; + } + + log(""); + log("Kernel panic on CPU ", Cpu::executing_id()); + log("Exception reason is ", reason); + log(""); + log("Register dump:"); + log("ip = ", Hex(state.ip)); + log("ra = ", Hex(state.ra)); + log("sp = ", Hex(state.sp)); + log("gp = ", Hex(state.gp)); + log("tp = ", Hex(state.tp)); + log("t0 = ", Hex(state.t0)); + log("t1 = ", Hex(state.t1)); + log("t2 = ", Hex(state.t2)); + log("s0 = ", Hex(state.s0)); + log("s1 = ", Hex(state.s1)); + log("a0 = ", Hex(state.a0)); + log("a1 = ", Hex(state.a1)); + log("a2 = ", Hex(state.a2)); + log("a3 = ", Hex(state.a3)); + log("a4 = ", Hex(state.a4)); + log("a5 = ", Hex(state.a5)); + log("a6 = ", Hex(state.a6)); + log("a7 = ", Hex(state.a7)); + log("s2 = ", Hex(state.s2)); + log("s3 = ", Hex(state.s3)); + log("s4 = ", Hex(state.s4)); + log("s5 = ", Hex(state.s5)); + log("s6 = ", Hex(state.s6)); + log("s7 = ", Hex(state.s7)); + log("s8 = ", Hex(state.s8)); + log("s9 = ", Hex(state.s9)); + log("s10 = ", Hex(state.s10)); + log("s11 = ", Hex(state.s11)); + log("t3 = ", Hex(state.t3)); + log("t4 = ", Hex(state.t4)); + log("t5 = ", Hex(state.t5)); + log("t6 = ", Hex(state.t6)); + log(""); + log("Backtrace:"); + + Const_byte_range_ptr const stack { + (char const*)stack_base(), Hw::Mm::KERNEL_STACK_SIZE }; + context.for_each_return_address(stack, [&] (void **p) { log(*p); }); + + while (true) asm volatile("wfi"); +} diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc b/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc index d41bf8232e..0a93aaf7c1 100644 --- a/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc @@ -14,6 +14,7 @@ /* core includes */ #include +#include void Kernel::Cpu::_arch_init() @@ -32,3 +33,44 @@ void Kernel::Cpu::_arch_init() /* enable timer interrupt */ _pic.unmask(_timer.interrupt_id(), id()); } + + +[[noreturn]] void Kernel::Cpu::panic(Genode::Cpu_state &state) +{ + using namespace Genode; + using Cs = Genode::Cpu_state; + + const char *reason = "unknown"; + + switch (state.trapno) { + case Cs::PAGE_FAULT: reason = "page-fault"; break; + case Cs::UNDEFINED_INSTRUCTION: reason = "undefined instruction"; break; + case Cs::SUPERVISOR_CALL: reason = "system-call"; break; + default: + if (state.trapno >= Cs::INTERRUPTS_START && + state.trapno <= Cs::INTERRUPTS_END) + reason = "interrupt"; + }; + + log(""); + log("Kernel panic on CPU ", Cpu::executing_id()); + log("Exception reason is ", reason, " (trapno=", state.trapno, ")"); + log(""); + log("Register dump:"); + log("ip = ", Hex(state.ip)); + log("sp = ", Hex(state.sp)); + log("cs = ", Hex(state.cs)); + log("ss = ", Hex(state.ss)); + log("eflags = ", Hex(state.eflags)); + log("rax = ", Hex(state.rax)); + log("rbx = ", Hex(state.rbx)); + log("rcx = ", Hex(state.rcx)); + log("rdx = ", Hex(state.rdx)); + log("rdi = ", Hex(state.rdi)); + log("rsi = ", Hex(state.rsi)); + log("rbp = ", Hex(state.rbp)); + log("CR2 = ", Hex(Cpu::Cr2::read())); + log("CR3 = ", Hex(Cpu::Cr3::read())); + + while (true) asm volatile("hlt"); +}