sel4: handle non pagefault exceptions

by checking for it in core, submitting a signal (if registered) and not
replying instantly. Before this commit, an exception (a non page fault)
caused and endless "unknown exception" loop between originator and core.

This was handled before commit "core: kernel-agnostic 'Mapping' type" by
throwing an exception, which was with that commit not working anymore.

Fixes #4751
This commit is contained in:
Alexander Boettcher 2023-02-03 12:11:12 +01:00 committed by Christian Helmuth
parent 79d389d812
commit d089e80906
4 changed files with 80 additions and 29 deletions

View File

@ -31,10 +31,10 @@ class Genode::Ipc_pager : public Native_capability
addr_t _reply_sel = 0; /* selector to save reply cap */
addr_t _pf_addr = 0; /* page-fault address */
addr_t _pf_ip = 0; /* instruction pointer of faulter */
addr_t _fault_type = 0; /* type of fault */
bool _pf_write = false; /* true on write fault */
bool _pf_exec = false; /* true on exec fault */
bool _pf_align = false; /* true on unaligned fault */
bool _exception = false; /* true on non page fault */
bool _pf_write = false; /* true on write fault */
bool _pf_exec = false; /* true on exec fault */
bool _pf_align = false; /* true on unaligned fault */
Mapping _reply_mapping { };
@ -99,6 +99,11 @@ class Genode::Ipc_pager : public Native_capability
* Install memory mapping after pager code executed.
*/
bool install_mapping();
/**
* Return true if last fault was an exception
*/
bool exception() const { return _exception; }
};
#endif /* _CORE__INCLUDE__IPC_PAGER_H_ */

View File

@ -87,6 +87,8 @@ void Ipc_pager::reply_and_wait_for_fault()
addr_t const fault_type = seL4_MessageInfo_get_label(page_fault_msg_info);
_exception = fault_type != seL4_Fault_VMFault;
auto fault_name = [] (addr_t type)
{
switch (type) {
@ -203,6 +205,22 @@ void Pager_entrypoint::entry()
if (!obj)
return;
/* on exception (beside page fault) don't reply and submit signal */
if (_pager.exception()) {
warning("exception ", _pager.fault_addr(), " ",
*obj, " ip=", Hex(_pager.fault_ip()));
obj->submit_exception_signal();
return;
}
/* on alignment fault don't reply and submit signal */
if (_pager.align_fault()) {
warning("alignment fault, addr=", Hex(_pager.fault_addr()),
" ip=", Hex(_pager.fault_ip()));
reply_pending = false;
obj->submit_exception_signal();
}
/* send reply if page-fault handling succeeded */
reply_pending = !obj->pager(_pager);
if (!reply_pending) {
@ -213,20 +231,9 @@ void Pager_entrypoint::entry()
return;
}
try {
/* install memory mappings */
if (_pager.install_mapping())
return;
/* on alignment fault don't reply and submit signal */
if (_pager.align_fault()) {
warning("alignment fault, addr=", Hex(_pager.fault_addr()),
" ip=", Hex(_pager.fault_ip()));
throw 1;
}
} catch (...) {
reply_pending = false;
obj->submit_exception_signal();
/* install memory mappings */
if (_pager.install_mapping()) {
return;
}
});
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
* Copyright (C) 2017-2023 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
@ -26,10 +26,29 @@ struct Fault_info
DFSR_WRITE_FAULT = 1UL << 11
};
Fault_info(seL4_MessageInfo_t)
Genode::addr_t _ip_from_message(seL4_MessageInfo_t &info) const
{
auto const fault_type = seL4_MessageInfo_get_label(info);
if (fault_type == seL4_Fault_UserException)
return seL4_Fault_UserException_get_FaultIP(seL4_getFault(info));
else
return seL4_GetMR(0);
}
Genode::addr_t _pf_from_message(seL4_MessageInfo_t &info) const
{
auto const fault_type = seL4_MessageInfo_get_label(info);
if (fault_type == seL4_Fault_UserException)
return seL4_Fault_UserException_get_Number(seL4_getFault(info));
else
return seL4_GetMR(1);
}
Fault_info(seL4_MessageInfo_t info)
:
ip(seL4_GetMR(0)),
pf(seL4_GetMR(1)),
ip(_ip_from_message(info)),
pf(_pf_from_message(info)),
data_abort(seL4_GetMR(2) != IFSR_FAULT),
/* Instruction Fault Status Register (IFSR) resp. Data FSR (DFSR) */
write(data_abort && (seL4_GetMR(3) & DFSR_WRITE_FAULT)),

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
* Copyright (C) 2017-2023 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
@ -13,9 +13,9 @@
struct Fault_info
{
Genode::addr_t ip = 0;
Genode::addr_t pf = 0;
bool write = 0;
Genode::addr_t const ip;
Genode::addr_t const pf;
bool const write;
/*
* Intel manual: 6.15 EXCEPTION AND INTERRUPT REFERENCE
@ -29,10 +29,30 @@ struct Fault_info
ERR_P = 1 << 0,
};
Fault_info(seL4_MessageInfo_t)
Genode::addr_t _ip_from_message(seL4_MessageInfo_t &info) const
{
auto const fault_type = seL4_MessageInfo_get_label(info);
if (fault_type == seL4_Fault_UserException)
return seL4_Fault_UserException_get_FaultIP(seL4_getFault(info));
else
return seL4_GetMR(0);
}
Genode::addr_t _pf_from_message(seL4_MessageInfo_t &info) const
{
auto const fault_type = seL4_MessageInfo_get_label(info);
if (fault_type == seL4_Fault_UserException)
return seL4_Fault_UserException_get_Number(seL4_getFault(info));
else
return seL4_GetMR(1);
}
Fault_info(seL4_MessageInfo_t info)
:
ip(seL4_GetMR(0)),
pf(seL4_GetMR(1)),
ip(_ip_from_message(info)),
pf(_pf_from_message(info)),
write(seL4_GetMR(3) & ERR_W)
{ }