mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-29 23:40:03 +00:00
nova: add exception handlers for all core threads
The commit will improve diagnostics, if a core thread dies (which should never happen) with an hardware exception beside a page fault, e.g. general protection fault or undefined opcode. Without the commit we may not see this circumstance easily. Issue #5443
This commit is contained in:
parent
c6ee9cf86c
commit
44018bf49b
@ -109,30 +109,37 @@ enum { CORE_PAGER_UTCB_ADDR = 0xbff02000 };
|
|||||||
/**
|
/**
|
||||||
* IDC handler for the page-fault portal
|
* IDC handler for the page-fault portal
|
||||||
*/
|
*/
|
||||||
static void page_fault_handler()
|
__attribute__((regparm(1)))
|
||||||
|
static void exception_handler(addr_t const pt_id)
|
||||||
{
|
{
|
||||||
Utcb *utcb = (Utcb *)CORE_PAGER_UTCB_ADDR;
|
Utcb *utcb = (Utcb *)CORE_PAGER_UTCB_ADDR;
|
||||||
|
|
||||||
|
addr_t const ip = utcb->ip;
|
||||||
|
addr_t const sp = utcb->sp;
|
||||||
|
|
||||||
|
if (pt_id == PT_SEL_PAGE_FAULT) {
|
||||||
addr_t const pf_addr = utcb->pf_addr();
|
addr_t const pf_addr = utcb->pf_addr();
|
||||||
addr_t const pf_ip = utcb->ip;
|
|
||||||
addr_t const pf_sp = utcb->sp;
|
|
||||||
uint8_t const pf_type = utcb->pf_type();
|
uint8_t const pf_type = utcb->pf_type();
|
||||||
|
|
||||||
error("\nPAGE-FAULT IN CORE addr=", Hex(pf_addr), " ip=", Hex(pf_ip),
|
error("\nPAGE-FAULT IN CORE addr=", Hex(pf_addr), " ip=", Hex(ip),
|
||||||
" (", (pf_type & Ipc_pager::ERR_W) ? "write" : "read", ")");
|
" (", (pf_type & Ipc_pager::ERR_W) ? "write" : "read", ")");
|
||||||
|
|
||||||
log("\nstack pointer ", Hex(pf_sp), ", qualifiers ", Hex(pf_type), " ",
|
log("\nstack pointer ", Hex(sp), ", qualifiers ", Hex(pf_type), " ",
|
||||||
pf_type & Ipc_pager::ERR_I ? "I" : "i",
|
pf_type & Ipc_pager::ERR_I ? "I" : "i",
|
||||||
pf_type & Ipc_pager::ERR_R ? "R" : "r",
|
pf_type & Ipc_pager::ERR_R ? "R" : "r",
|
||||||
pf_type & Ipc_pager::ERR_U ? "U" : "u",
|
pf_type & Ipc_pager::ERR_U ? "U" : "u",
|
||||||
pf_type & Ipc_pager::ERR_W ? "W" : "w",
|
pf_type & Ipc_pager::ERR_W ? "W" : "w",
|
||||||
pf_type & Ipc_pager::ERR_P ? "P" : "p");
|
pf_type & Ipc_pager::ERR_P ? "P" : "p");
|
||||||
|
} else {
|
||||||
|
error("\nEXCEPTION IN CORE ip=", Hex(ip), " sp=", Hex(sp),
|
||||||
|
" exception=", Hex(pt_id));
|
||||||
|
}
|
||||||
|
|
||||||
if ((stack_area_virtual_base() <= pf_sp) &&
|
if ((stack_area_virtual_base() <= sp) &&
|
||||||
(pf_sp < stack_area_virtual_base() +
|
(sp < stack_area_virtual_base() +
|
||||||
stack_area_virtual_size()))
|
stack_area_virtual_size()))
|
||||||
{
|
{
|
||||||
addr_t utcb_addr_f = pf_sp / stack_virtual_size();
|
addr_t utcb_addr_f = sp / stack_virtual_size();
|
||||||
utcb_addr_f *= stack_virtual_size();
|
utcb_addr_f *= stack_virtual_size();
|
||||||
utcb_addr_f += stack_virtual_size();
|
utcb_addr_f += stack_virtual_size();
|
||||||
utcb_addr_f -= 4096;
|
utcb_addr_f -= 4096;
|
||||||
@ -184,10 +191,10 @@ static void page_fault_handler()
|
|||||||
};
|
};
|
||||||
|
|
||||||
int count = 1;
|
int count = 1;
|
||||||
log(" #", count++, " ", Hex(pf_sp, Hex::PREFIX, Hex::PAD), " ",
|
log(" #", count++, " ", Hex(sp, Hex::PREFIX, Hex::PAD), " ",
|
||||||
Hex(pf_ip, Hex::PREFIX, Hex::PAD));
|
Hex(ip, Hex::PREFIX, Hex::PAD));
|
||||||
|
|
||||||
Core_img dump(pf_sp);
|
Core_img dump(sp);
|
||||||
while (dump.ip_valid()) {
|
while (dump.ip_valid()) {
|
||||||
log(" #", count++, " ", Hex((addr_t)dump.ip(), Hex::PREFIX, Hex::PAD),
|
log(" #", count++, " ", Hex((addr_t)dump.ip(), Hex::PREFIX, Hex::PAD),
|
||||||
" ", Hex(*dump.ip(), Hex::PREFIX, Hex::PAD));
|
" ", Hex(*dump.ip(), Hex::PREFIX, Hex::PAD));
|
||||||
@ -224,7 +231,7 @@ static void startup_handler()
|
|||||||
|
|
||||||
static addr_t init_core_page_fault_handler(addr_t const core_pd_sel)
|
static addr_t init_core_page_fault_handler(addr_t const core_pd_sel)
|
||||||
{
|
{
|
||||||
/* create fault handler EC for core main thread */
|
/* create fault handler EC used by all core threads */
|
||||||
enum {
|
enum {
|
||||||
GLOBAL = false,
|
GLOBAL = false,
|
||||||
EXC_BASE = 0
|
EXC_BASE = 0
|
||||||
@ -232,22 +239,33 @@ static addr_t init_core_page_fault_handler(addr_t const core_pd_sel)
|
|||||||
|
|
||||||
addr_t ec_sel = cap_map().insert(1);
|
addr_t ec_sel = cap_map().insert(1);
|
||||||
|
|
||||||
uint8_t ret = create_ec(ec_sel, core_pd_sel, boot_cpu(),
|
auto ret = create_ec(ec_sel, core_pd_sel, boot_cpu(),
|
||||||
CORE_PAGER_UTCB_ADDR, core_pager_stack_top(),
|
CORE_PAGER_UTCB_ADDR, core_pager_stack_top(),
|
||||||
EXC_BASE, GLOBAL);
|
EXC_BASE, GLOBAL);
|
||||||
if (ret)
|
if (ret != Nova::NOVA_OK)
|
||||||
log(__func__, ": create_ec returned ", ret);
|
log(__func__, ": create_ec returned ", ret);
|
||||||
|
|
||||||
/* set up page-fault portal */
|
for (unsigned i = 0; i < NUM_INITIAL_PT; i++) {
|
||||||
create_pt(PT_SEL_PAGE_FAULT, core_pd_sel, ec_sel,
|
if (i == PT_SEL_PAGE_FAULT || i == PT_SEL_STARTUP || i == SM_SEL_EC)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = create_pt(i, core_pd_sel, ec_sel,
|
||||||
Mtd(Mtd::QUAL | Mtd::ESP | Mtd::EIP),
|
Mtd(Mtd::QUAL | Mtd::ESP | Mtd::EIP),
|
||||||
(addr_t)page_fault_handler);
|
(addr_t)exception_handler);
|
||||||
revoke(Obj_crd(PT_SEL_PAGE_FAULT, 0, Obj_crd::RIGHT_PT_CTRL));
|
if (ret != Nova::NOVA_OK)
|
||||||
|
warning(__func__, " exception handler ", i,
|
||||||
|
" could not be setup, error=", ret);
|
||||||
|
|
||||||
|
revoke(Obj_crd(i, 0, Obj_crd::RIGHT_PT_CTRL));
|
||||||
|
}
|
||||||
|
|
||||||
/* startup portal for global core threads */
|
/* startup portal for global core threads */
|
||||||
create_pt(PT_SEL_STARTUP, core_pd_sel, ec_sel,
|
ret = create_pt(PT_SEL_STARTUP, core_pd_sel, ec_sel,
|
||||||
Mtd(Mtd::EIP | Mtd::ESP),
|
Mtd(Mtd::EIP | Mtd::ESP),
|
||||||
(addr_t)startup_handler);
|
(addr_t)startup_handler);
|
||||||
|
if (ret != Nova::NOVA_OK)
|
||||||
|
warning(__func__, " startup handler ", unsigned(PT_SEL_STARTUP),
|
||||||
|
" could not be setup, error=", ret);
|
||||||
revoke(Obj_crd(PT_SEL_STARTUP, 0, Obj_crd::RIGHT_PT_CTRL));
|
revoke(Obj_crd(PT_SEL_STARTUP, 0, Obj_crd::RIGHT_PT_CTRL));
|
||||||
|
|
||||||
return ec_sel;
|
return ec_sel;
|
||||||
|
@ -105,13 +105,18 @@ Thread::Start_result Thread::start()
|
|||||||
utcb.crd_rcv = Obj_crd();
|
utcb.crd_rcv = Obj_crd();
|
||||||
utcb.crd_xlt = Obj_crd();
|
utcb.crd_xlt = Obj_crd();
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < NUM_INITIAL_PT; i++) {
|
||||||
|
if (i == SM_SEL_EC)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (map_local(platform_specific().core_pd_sel(),
|
if (map_local(platform_specific().core_pd_sel(),
|
||||||
*reinterpret_cast<Nova::Utcb *>(Thread::myself()->utcb()),
|
*reinterpret_cast<Nova::Utcb *>(Thread::myself()->utcb()),
|
||||||
Obj_crd(PT_SEL_PAGE_FAULT, 0),
|
Obj_crd(i, 0),
|
||||||
Obj_crd(native_thread().exc_pt_sel + PT_SEL_PAGE_FAULT, 0))) {
|
Obj_crd(native_thread().exc_pt_sel + i, 0))) {
|
||||||
error("Thread::start: failed to create page-fault portal");
|
error("Thread::start: failed to create page-fault portal");
|
||||||
return Start_result::DENIED;
|
return Start_result::DENIED;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Core_trace_source : public Core::Trace::Source::Info_accessor,
|
struct Core_trace_source : public Core::Trace::Source::Info_accessor,
|
||||||
private Core::Trace::Control,
|
private Core::Trace::Control,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user