mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-21 18:06:50 +00:00
parent
ff5d28822c
commit
57949c2bbb
@ -339,6 +339,13 @@ namespace Nova {
|
||||
}
|
||||
|
||||
|
||||
ALWAYS_INLINE
|
||||
inline uint8_t delegate(mword_t pd_snd, mword_t pd_dst, Crd crd_dst)
|
||||
{
|
||||
return syscall_2(NOVA_LOOKUP, 1, pd_snd, crd_dst.value(), pd_dst);
|
||||
}
|
||||
|
||||
|
||||
ALWAYS_INLINE
|
||||
inline uint8_t sm_ctrl(unsigned sm, Sem_op op, unsigned long long timeout = 0)
|
||||
{
|
||||
|
@ -292,6 +292,13 @@ namespace Nova {
|
||||
}
|
||||
|
||||
|
||||
ALWAYS_INLINE
|
||||
inline uint8_t delegate(mword_t pd_snd, mword_t pd_dst, Crd crd_dst)
|
||||
{
|
||||
return syscall_2(NOVA_LOOKUP, 1, pd_snd, crd_dst.value(), pd_dst);
|
||||
}
|
||||
|
||||
|
||||
ALWAYS_INLINE
|
||||
inline uint8_t sm_ctrl(mword_t sm, Sem_op op, unsigned long long timeout = 0)
|
||||
{
|
||||
|
@ -1 +1 @@
|
||||
931c26a24d490daae7df7ebbb03274366088adf0
|
||||
6f91bce10f8f9faa2a0f57b9d135559a1ce499a7
|
||||
|
@ -4,7 +4,7 @@ DOWNLOADS := nova.git
|
||||
|
||||
# r9 branch - use r9_debug for more verbose kernel messages
|
||||
URL(nova) := https://github.com/alex-ab/NOVA.git
|
||||
REV(nova) := 4d6f04dd02d8099a20766025457be0afd0eae534
|
||||
REV(nova) := b493eef81a1313f1cd420b4ed4310ef154c79c04
|
||||
DIR(nova) := src/kernel/nova
|
||||
|
||||
PATCHES := $(wildcard $(REP_DIR)/patches/*.patch)
|
||||
|
@ -37,6 +37,6 @@ build_boot_image "core init test-platform"
|
||||
|
||||
append qemu_args "-nographic -m 128 -smp 2"
|
||||
|
||||
run_genode_until {Test finished} 150
|
||||
run_genode_until {Test finished} 200
|
||||
|
||||
puts "\nTest succeeded"
|
||||
|
@ -12,8 +12,8 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Core includes */
|
||||
#include <platform_pd.h>
|
||||
/* core-local includes */
|
||||
#include <platform.h>
|
||||
|
||||
/* local includes */
|
||||
#include <echo.h>
|
||||
@ -69,9 +69,12 @@ Echo::Echo(Genode::addr_t utcb_addr)
|
||||
{
|
||||
using namespace Nova;
|
||||
|
||||
extern Genode::addr_t __initial_sp;
|
||||
Hip const * const hip = reinterpret_cast<Hip *>(__initial_sp);
|
||||
|
||||
/* create echo EC */
|
||||
Genode::addr_t pd_sel = Genode::Platform_pd::pd_core_sel();
|
||||
uint8_t res = create_ec(_ec_sel, pd_sel, boot_cpu(), utcb_addr,
|
||||
Genode::addr_t const core_pd_sel = hip->sel_exc;
|
||||
uint8_t res = create_ec(_ec_sel, core_pd_sel, boot_cpu(), utcb_addr,
|
||||
reinterpret_cast<mword_t>(echo_stack_top()),
|
||||
ECHO_EXC_BASE, ECHO_GLOBAL);
|
||||
|
||||
@ -79,7 +82,7 @@ Echo::Echo(Genode::addr_t utcb_addr)
|
||||
if (res != Nova::NOVA_OK) { *reinterpret_cast<unsigned *>(0) = 0xdead; }
|
||||
|
||||
/* set up echo portal to ourself */
|
||||
res = create_pt(_pt_sel, pd_sel, _ec_sel, Mtd(0), (mword_t)echo_reply);
|
||||
res = create_pt(_pt_sel, core_pd_sel, _ec_sel, Mtd(0), (mword_t)echo_reply);
|
||||
if (res != Nova::NOVA_OK) { *reinterpret_cast<unsigned *>(0) = 0xdead; }
|
||||
revoke(Obj_crd(_pt_sel, 0, Obj_crd::RIGHT_PT_CTRL));
|
||||
|
||||
|
@ -75,12 +75,19 @@ namespace Genode {
|
||||
{
|
||||
private:
|
||||
|
||||
addr_t _pd_dst;
|
||||
addr_t _pd_core;
|
||||
addr_t _fault_ip;
|
||||
addr_t _fault_addr;
|
||||
addr_t _sp;
|
||||
uint8_t _fault_type;
|
||||
uint8_t _syscall_res;
|
||||
uint8_t _normal_ipc;
|
||||
|
||||
public:
|
||||
|
||||
Ipc_pager (Nova::Utcb *, addr_t pd_dst, addr_t pd_core);
|
||||
|
||||
/*
|
||||
* Intel manual: 6.15 EXCEPTION AND INTERRUPT REFERENCE
|
||||
* Interrupt 14—Page-Fault Exception (#PF)
|
||||
@ -93,18 +100,10 @@ namespace Genode {
|
||||
ERR_P = 1 << 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* Wait for page-fault info
|
||||
*
|
||||
* After returning from this call, 'fault_ip' and 'fault_addr'
|
||||
* have a defined state.
|
||||
*/
|
||||
void wait_for_fault();
|
||||
|
||||
/**
|
||||
* Answer current page fault
|
||||
*/
|
||||
void reply_and_wait_for_fault(unsigned sm = 0);
|
||||
void reply_and_wait_for_fault(addr_t sm = 0UL);
|
||||
|
||||
/**
|
||||
* Request instruction pointer of current fault
|
||||
@ -136,6 +135,23 @@ namespace Genode {
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return result of delegate syscall
|
||||
*/
|
||||
uint8_t syscall_result() const { return _syscall_res; }
|
||||
|
||||
/**
|
||||
* Return low level fault type info
|
||||
* Intel manual: 6.15 EXCEPTION AND INTERRUPT REFERENCE
|
||||
* Interrupt 14—Page-Fault Exception (#PF)
|
||||
*/
|
||||
addr_t fault_type() { return _fault_type; }
|
||||
|
||||
/**
|
||||
* Return stack pointer address valid during page-fault
|
||||
*/
|
||||
addr_t sp() { return _sp; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,8 @@ namespace Genode {
|
||||
Phys_allocator _io_port_alloc; /* I/O port allocator */
|
||||
Phys_allocator _irq_alloc; /* IRQ allocator */
|
||||
Rom_fs _rom_fs; /* ROM file system */
|
||||
int _gsi_base_sel; /* cap selector of 1st IRQ */
|
||||
unsigned _gsi_base_sel; /* cap selector of 1st IRQ */
|
||||
unsigned _core_pd_sel; /* cap selector of root PD */
|
||||
|
||||
/**
|
||||
* Virtual address range usable by non-core processes
|
||||
@ -100,6 +101,11 @@ namespace Genode {
|
||||
* Return kernel CPU ID for given Genode CPU
|
||||
*/
|
||||
unsigned kernel_cpu_id(unsigned genode_cpu_id);
|
||||
|
||||
/**
|
||||
* PD kernel capability selector of core
|
||||
*/
|
||||
unsigned core_pd_sel() const { return _core_pd_sel; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -18,11 +18,6 @@
|
||||
#include <platform_thread.h>
|
||||
#include <address_space.h>
|
||||
|
||||
/*
|
||||
* Must be initialized by the startup code,
|
||||
* only valid in core
|
||||
*/
|
||||
extern Genode::addr_t __core_pd_sel;
|
||||
|
||||
namespace Genode {
|
||||
|
||||
@ -83,14 +78,6 @@ namespace Genode {
|
||||
*/
|
||||
addr_t pd_sel() const { return _pd_sel; }
|
||||
|
||||
/**
|
||||
* Capability selector of core protection domain
|
||||
*
|
||||
* \return PD selector
|
||||
*/
|
||||
static addr_t pd_core_sel() { return __core_pd_sel; }
|
||||
|
||||
|
||||
/**
|
||||
* Label of this protection domain
|
||||
*
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <nova/capability_space.h>
|
||||
|
||||
/* core-local includes */
|
||||
#include <platform.h>
|
||||
#include <signal_source_component.h>
|
||||
#include <signal_source/capability.h>
|
||||
|
||||
@ -91,8 +92,9 @@ class Genode::Signal_broker
|
||||
Native_capability si = Capability_space::import(cap_map()->insert());
|
||||
Signal_context_capability cap = reinterpret_cap_cast<Signal_context>(si);
|
||||
|
||||
uint8_t res = Nova::create_si(cap.local_name(), __core_pd_sel, imprint,
|
||||
sm.local_name());
|
||||
uint8_t res = Nova::create_si(cap.local_name(),
|
||||
platform_specific()->core_pd_sel(),
|
||||
imprint, sm.local_name());
|
||||
if (res != Nova::NOVA_OK) {
|
||||
warning("creating signal failed - error ", res);
|
||||
return Signal_context_capability();
|
||||
|
@ -23,17 +23,24 @@
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
void Ipc_pager::wait_for_fault()
|
||||
Ipc_pager::Ipc_pager(Nova::Utcb * utcb, addr_t pd_dst, addr_t pd_core)
|
||||
:
|
||||
_pd_dst(pd_dst),
|
||||
_pd_core(pd_core),
|
||||
_fault_ip(utcb->ip),
|
||||
_fault_addr(utcb->qual[1]),
|
||||
_sp(utcb->sp),
|
||||
_fault_type(utcb->qual[0]),
|
||||
_syscall_res(Nova::NOVA_OK),
|
||||
_normal_ipc((((addr_t)&utcb->qual[2] - (addr_t)utcb->msg) / sizeof(addr_t))
|
||||
== utcb->msg_words())
|
||||
{
|
||||
|
||||
/*
|
||||
* When this function is called from the page-fault handler EC, a page
|
||||
* fault already occurred. So we never wait but immediately read the
|
||||
* page-fault information from our UTCB.
|
||||
*/
|
||||
Nova::Utcb *utcb = (Nova::Utcb *)Thread::myself()->utcb();
|
||||
_fault_type = utcb->qual[0];
|
||||
_fault_addr = utcb->qual[1];
|
||||
_fault_ip = utcb->ip;
|
||||
}
|
||||
|
||||
|
||||
@ -41,14 +48,31 @@ void Ipc_pager::set_reply_mapping(Mapping m)
|
||||
{
|
||||
Nova::Utcb *utcb = (Nova::Utcb *)Thread::myself()->utcb();
|
||||
utcb->set_msg_word(0);
|
||||
bool res = utcb->append_item(m.mem_crd(), m.dst_addr(), true, false,
|
||||
bool res = utcb->append_item(m.mem_crd(), 0, true, false,
|
||||
false, m.dma(), m.write_combined());
|
||||
/* one item ever fits on the UTCB */
|
||||
(void)res;
|
||||
|
||||
/* receive window in destination pd */
|
||||
Nova::Mem_crd crd_mem(m.dst_addr() >> 12, m.mem_crd().order(),
|
||||
Nova::Rights(true, true, true));
|
||||
/* asynchronously map memory */
|
||||
_syscall_res = Nova::delegate(_pd_core, _pd_dst, crd_mem);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_pager::reply_and_wait_for_fault(unsigned sm)
|
||||
void Ipc_pager::reply_and_wait_for_fault(addr_t sm)
|
||||
{
|
||||
Nova::reply(Thread::myself()->stack_top(), sm);
|
||||
Thread * myself = Thread::myself();
|
||||
Nova::Utcb * utcb = reinterpret_cast<Nova::Utcb *>(myself->utcb());
|
||||
|
||||
utcb->mtd = 0;
|
||||
|
||||
/*
|
||||
* If it was a normal IPC and the mapping failed, caller may re-try.
|
||||
* Otherwise nothing left to be delegated - done asynchronously beforehand.
|
||||
*/
|
||||
utcb->set_msg_word((_normal_ipc && _syscall_res != Nova::NOVA_OK) ? 1 : 0);
|
||||
|
||||
Nova::reply(myself->stack_top(), sm);
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ static bool verbose_oom = false;
|
||||
using namespace Genode;
|
||||
using namespace Nova;
|
||||
|
||||
extern Genode::addr_t __core_pd_sel;
|
||||
|
||||
static Nova::Hip * kernel_hip()
|
||||
{
|
||||
@ -79,11 +78,13 @@ struct Page_fault_info
|
||||
char const * const pd;
|
||||
char const * const thread;
|
||||
unsigned const cpu;
|
||||
addr_t const ip, addr;
|
||||
addr_t const ip, addr, sp;
|
||||
uint8_t const pf_type;
|
||||
|
||||
Page_fault_info(char const *pd, char const *thread, unsigned cpu,
|
||||
addr_t ip, addr_t addr)
|
||||
: pd(pd), thread(thread), cpu(cpu), ip(ip), addr(addr) { }
|
||||
addr_t ip, addr_t addr, addr_t sp, unsigned type)
|
||||
: pd(pd), thread(thread), cpu(cpu), ip(ip), addr(addr),
|
||||
sp(sp), pf_type(type) { }
|
||||
|
||||
void print(Genode::Output &out) const
|
||||
{
|
||||
@ -91,32 +92,57 @@ struct Page_fault_info
|
||||
"thread='", thread, "' "
|
||||
"cpu=", cpu, " "
|
||||
"ip=", Hex(ip), " "
|
||||
"address=", Hex(addr));
|
||||
"address=", Hex(addr), " "
|
||||
"stack pointer=", Hex(sp), " "
|
||||
"qualifiers=", Hex(pf_type), " ",
|
||||
pf_type & Ipc_pager::ERR_I ? "I" : "i",
|
||||
pf_type & Ipc_pager::ERR_R ? "R" : "r",
|
||||
pf_type & Ipc_pager::ERR_U ? "U" : "u",
|
||||
pf_type & Ipc_pager::ERR_W ? "W" : "w",
|
||||
pf_type & Ipc_pager::ERR_P ? "P" : "p");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Pager_object::_page_fault_handler(addr_t pager_obj)
|
||||
{
|
||||
Ipc_pager ipc_pager;
|
||||
ipc_pager.wait_for_fault();
|
||||
|
||||
Thread * myself = Thread::myself();
|
||||
Pager_object * obj = reinterpret_cast<Pager_object *>(pager_obj);
|
||||
Utcb * utcb = reinterpret_cast<Utcb *>(myself->utcb());
|
||||
|
||||
Ipc_pager ipc_pager(reinterpret_cast<Nova::Utcb *>(utcb), obj->pd_sel(),
|
||||
platform_specific()->core_pd_sel());
|
||||
|
||||
Pager_activation_base * pager_thread = static_cast<Pager_activation_base *>(myself);
|
||||
|
||||
/* lookup fault address and decide what to do */
|
||||
int ret = obj->pager(ipc_pager);
|
||||
int error = obj->pager(ipc_pager);
|
||||
|
||||
/* don't open receive window for pager threads */
|
||||
if (utcb->crd_rcv.value())
|
||||
nova_die();
|
||||
|
||||
if (!error && ipc_pager.syscall_result() != Nova::NOVA_OK) {
|
||||
/* something went wrong - by default don't answer the page fault */
|
||||
error = 4;
|
||||
|
||||
/* dst pd has not enough kernel quota ? - try to recover */
|
||||
if (ipc_pager.syscall_result() == Nova::NOVA_PD_OOM) {
|
||||
uint8_t res = obj->handle_oom();
|
||||
if (res == Nova::NOVA_PD_OOM)
|
||||
/* block until revoke is due */
|
||||
ipc_pager.reply_and_wait_for_fault(obj->sel_sm_block_oom());
|
||||
else if (res == Nova::NOVA_OK)
|
||||
/* succeeded to recover - continue normally */
|
||||
error = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* good case - found a valid region which is mappable */
|
||||
if (!ret)
|
||||
if (!error)
|
||||
ipc_pager.reply_and_wait_for_fault();
|
||||
|
||||
|
||||
obj->_state_lock.lock();
|
||||
|
||||
obj->_state.thread.ip = ipc_pager.fault_ip();
|
||||
@ -132,33 +158,16 @@ void Pager_object::_page_fault_handler(addr_t pager_obj)
|
||||
|
||||
Page_fault_info const fault_info(client_pd, client_thread,
|
||||
which_cpu(pager_thread),
|
||||
ipc_pager.fault_ip(), ipc_pager.fault_addr());
|
||||
ipc_pager.fault_ip(),
|
||||
ipc_pager.fault_addr(),
|
||||
ipc_pager.sp(),
|
||||
ipc_pager.fault_type());
|
||||
|
||||
/* region manager fault - to be handled */
|
||||
if (ret == 1) {
|
||||
log("page fault, ", fault_info);
|
||||
log("page fault, ", fault_info, " reason=", error);
|
||||
|
||||
utcb->set_msg_word(0);
|
||||
utcb->mtd = 0;
|
||||
|
||||
/* block the faulting thread until region manager is done */
|
||||
ipc_pager.reply_and_wait_for_fault(obj->sel_sm_block_pause());
|
||||
}
|
||||
|
||||
/* unhandled case */
|
||||
obj->_state.mark_dead();
|
||||
|
||||
warning("unresolvable page fault, ", fault_info, " ret=", ret);
|
||||
|
||||
Native_capability pager_cap = obj->Object_pool<Pager_object>::Entry::cap();
|
||||
|
||||
revoke(Capability_space::crd(pager_cap).base());
|
||||
|
||||
revoke(Obj_crd(obj->exc_pt_sel_client(), NUM_INITIAL_PT_LOG2));
|
||||
|
||||
utcb->set_msg_word(0);
|
||||
utcb->mtd = 0;
|
||||
ipc_pager.reply_and_wait_for_fault();
|
||||
/* block the faulting thread until region manager is done */
|
||||
ipc_pager.reply_and_wait_for_fault(obj->sel_sm_block_pause());
|
||||
}
|
||||
|
||||
|
||||
@ -364,7 +373,7 @@ void Pager_object::_invoke_handler(addr_t pager_obj)
|
||||
revoke(Obj_crd(obj->exc_pt_sel_client() + PT_SEL_STARTUP, 0));
|
||||
|
||||
bool res = Nova::create_sm(obj->exc_pt_sel_client() + PT_SEL_STARTUP,
|
||||
__core_pd_sel, 0);
|
||||
platform_specific()->core_pd_sel(), 0);
|
||||
if (res != Nova::NOVA_OK)
|
||||
reply(myself->stack_top());
|
||||
|
||||
@ -524,7 +533,7 @@ void Exception_handlers::register_handler(Pager_object *obj, Mtd mtd,
|
||||
/* compiler generates instance of exception entry if not specified */
|
||||
addr_t entry = func ? (addr_t)func : (addr_t)(&_handler<EV>);
|
||||
uint8_t res = create_portal(obj->exc_pt_sel_client() + EV,
|
||||
__core_pd_sel, ec_sel, mtd, entry, obj);
|
||||
platform_specific()->core_pd_sel(), ec_sel, mtd, entry, obj);
|
||||
if (res != Nova::NOVA_OK)
|
||||
throw Region_map::Invalid_thread();
|
||||
}
|
||||
@ -589,7 +598,7 @@ Pager_object::Pager_object(Cpu_session_capability cpu_session_cap,
|
||||
{
|
||||
uint8_t res;
|
||||
|
||||
addr_t pd_sel = __core_pd_sel;
|
||||
addr_t const pd_sel = platform_specific()->core_pd_sel();
|
||||
_state._status = 0;
|
||||
_state.modified = false;
|
||||
_state.sel_client_ec = Native_thread::INVALID_INDEX;
|
||||
@ -685,13 +694,14 @@ uint8_t Pager_object::handle_oom(addr_t transfer_from,
|
||||
char const * src_pd, char const * src_thread,
|
||||
enum Pager_object::Policy policy)
|
||||
{
|
||||
const char * dst_pd = client_pd();
|
||||
const char * dst_thread = client_thread();
|
||||
char const * dst_pd = client_pd();
|
||||
char const * dst_thread = client_thread();
|
||||
addr_t const core_pd_sel = platform_specific()->core_pd_sel();
|
||||
|
||||
enum { QUOTA_TRANSFER_PAGES = 2 };
|
||||
|
||||
if (transfer_from == SRC_CORE_PD)
|
||||
transfer_from = __core_pd_sel;
|
||||
transfer_from = core_pd_sel;
|
||||
|
||||
/* request current kernel quota usage of target pd */
|
||||
addr_t limit_before = 0, usage_before = 0;
|
||||
@ -721,8 +731,8 @@ uint8_t Pager_object::handle_oom(addr_t transfer_from,
|
||||
|
||||
/* retry upgrade using core quota if policy permits */
|
||||
if (policy == UPGRADE_PREFER_SRC_TO_DST) {
|
||||
if (transfer_from != __core_pd_sel) {
|
||||
res = Nova::pd_ctrl(__core_pd_sel, Pd_op::TRANSFER_QUOTA,
|
||||
if (transfer_from != core_pd_sel) {
|
||||
res = Nova::pd_ctrl(core_pd_sel, Pd_op::TRANSFER_QUOTA,
|
||||
pd_sel(), QUOTA_TRANSFER_PAGES);
|
||||
if (res == Nova::NOVA_OK)
|
||||
return res;
|
||||
@ -836,14 +846,14 @@ void Pager_object::_oom_handler(addr_t pager_dst, addr_t pager_src,
|
||||
utcb->set_msg_word(0);
|
||||
}
|
||||
|
||||
transfer_from = __core_pd_sel;
|
||||
transfer_from = platform_specific()->core_pd_sel();
|
||||
break;
|
||||
default:
|
||||
/* non core PD -> non core PD */
|
||||
utcb->set_msg_word(0);
|
||||
|
||||
if (pager_src == pager_dst || policy == UPGRADE_CORE_TO_DST)
|
||||
transfer_from = __core_pd_sel;
|
||||
transfer_from = platform_specific()->core_pd_sel();
|
||||
else {
|
||||
/* delegation of items between different PDs */
|
||||
src_pd = obj_src->client_pd();
|
||||
@ -877,12 +887,13 @@ addr_t Pager_object::get_oom_portal()
|
||||
addr_t const pt_oom = sel_oom_portal();
|
||||
unsigned const genode_cpu_id = _location.xpos();
|
||||
unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(genode_cpu_id);
|
||||
addr_t const core_pd_sel = platform_specific()->core_pd_sel();
|
||||
|
||||
if (kernel_hip()->is_cpu_enabled(kernel_cpu_id) &&
|
||||
pager_threads[genode_cpu_id]) {
|
||||
|
||||
addr_t const ec_sel = pager_threads[genode_cpu_id]->native_thread().ec_sel;
|
||||
uint8_t res = create_portal(pt_oom, __core_pd_sel, ec_sel, Mtd(0),
|
||||
uint8_t res = create_portal(pt_oom, core_pd_sel, ec_sel, Mtd(0),
|
||||
reinterpret_cast<addr_t>(_oom_handler),
|
||||
this);
|
||||
if (res == Nova::NOVA_OK)
|
||||
|
@ -63,11 +63,6 @@ Utcb *__main_thread_utcb;
|
||||
*/
|
||||
extern unsigned _prog_img_beg, _prog_img_end;
|
||||
|
||||
/**
|
||||
* Capability selector of root PD
|
||||
*/
|
||||
addr_t __core_pd_sel;
|
||||
|
||||
|
||||
/**
|
||||
* Map preserved physical pages core-exclusive
|
||||
@ -218,7 +213,7 @@ static void startup_handler()
|
||||
}
|
||||
|
||||
|
||||
static void init_core_page_fault_handler()
|
||||
static void init_core_page_fault_handler(addr_t const core_pd_sel)
|
||||
{
|
||||
/* create echo EC */
|
||||
enum {
|
||||
@ -228,20 +223,20 @@ static void init_core_page_fault_handler()
|
||||
|
||||
addr_t ec_sel = cap_map()->insert(1);
|
||||
|
||||
uint8_t ret = create_ec(ec_sel, __core_pd_sel, boot_cpu(),
|
||||
uint8_t ret = create_ec(ec_sel, core_pd_sel, boot_cpu(),
|
||||
CORE_PAGER_UTCB_ADDR, core_pager_stack_top(),
|
||||
EXC_BASE, GLOBAL);
|
||||
if (ret)
|
||||
log(__func__, ": create_ec returned ", ret);
|
||||
|
||||
/* set up page-fault portal */
|
||||
create_pt(PT_SEL_PAGE_FAULT, __core_pd_sel, ec_sel,
|
||||
create_pt(PT_SEL_PAGE_FAULT, core_pd_sel, ec_sel,
|
||||
Mtd(Mtd::QUAL | Mtd::ESP | Mtd::EIP),
|
||||
(addr_t)page_fault_handler);
|
||||
revoke(Obj_crd(PT_SEL_PAGE_FAULT, 0, Obj_crd::RIGHT_PT_CTRL));
|
||||
|
||||
/* startup portal for global core threads */
|
||||
create_pt(PT_SEL_STARTUP, __core_pd_sel, ec_sel,
|
||||
create_pt(PT_SEL_STARTUP, core_pd_sel, ec_sel,
|
||||
Mtd(Mtd::EIP | Mtd::ESP),
|
||||
(addr_t)startup_handler);
|
||||
revoke(Obj_crd(PT_SEL_STARTUP, 0, Obj_crd::RIGHT_PT_CTRL));
|
||||
@ -291,10 +286,10 @@ Platform::Platform() :
|
||||
__main_thread_utcb = (Utcb *)(__initial_sp - get_page_size());
|
||||
|
||||
/* set core pd selector */
|
||||
__core_pd_sel = hip->sel_exc;
|
||||
_core_pd_sel = hip->sel_exc;
|
||||
|
||||
/* create lock used by capability allocator */
|
||||
Nova::create_sm(Nova::SM_SEL_EC, __core_pd_sel, 0);
|
||||
Nova::create_sm(Nova::SM_SEL_EC, core_pd_sel(), 0);
|
||||
|
||||
/* locally map the whole I/O port range */
|
||||
enum { ORDER_64K = 16 };
|
||||
@ -380,7 +375,7 @@ Platform::Platform() :
|
||||
#endif
|
||||
|
||||
/* set up page fault handler for core - for debugging */
|
||||
init_core_page_fault_handler();
|
||||
init_core_page_fault_handler(core_pd_sel());
|
||||
|
||||
if (verbose_boot_info) {
|
||||
if (hip->has_feature_vmx())
|
||||
|
@ -109,9 +109,8 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
return -5;
|
||||
}
|
||||
|
||||
addr_t pd_core_sel = Platform_pd::pd_core_sel();
|
||||
addr_t pd_utcb = 0;
|
||||
_sel_exc_base = vcpu() ? _pager->exc_pt_vcpu() : _pager->exc_pt_sel_client();
|
||||
addr_t pd_utcb = 0;
|
||||
_sel_exc_base = vcpu() ? _pager->exc_pt_vcpu() : _pager->exc_pt_sel_client();
|
||||
|
||||
if (!vcpu()) {
|
||||
pd_utcb = stack_area_virtual_base() + stack_virtual_size() - get_page_size();
|
||||
@ -138,7 +137,8 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
|
||||
enum { KEEP_FREE_PAGES_NOT_AVAILABLE_FOR_UPGRADE = 2, UPPER_LIMIT_PAGES = 32 };
|
||||
Obj_crd initial_pts(_sel_exc_base, pts, rights);
|
||||
uint8_t res = create_pd(pd_sel, pd_core_sel, initial_pts,
|
||||
uint8_t res = create_pd(pd_sel, platform_specific()->core_pd_sel(),
|
||||
initial_pts,
|
||||
KEEP_FREE_PAGES_NOT_AVAILABLE_FOR_UPGRADE, UPPER_LIMIT_PAGES);
|
||||
if (res != NOVA_OK) {
|
||||
error("create_pd returned ", res);
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
/* core-local includes */
|
||||
#include <rpc_cap_factory.h>
|
||||
#include <platform_pd.h>
|
||||
#include <platform.h>
|
||||
|
||||
/* NOVA includes */
|
||||
#include <nova/capability_space.h>
|
||||
@ -23,9 +23,9 @@ using namespace Genode;
|
||||
|
||||
Native_capability Rpc_cap_factory::alloc(Native_capability ep, addr_t entry, addr_t mtd)
|
||||
{
|
||||
addr_t pt_sel = cap_map()->insert();
|
||||
addr_t pd_sel = Platform_pd::pd_core_sel();
|
||||
addr_t ec_sel = ep.local_name();
|
||||
addr_t const pt_sel = cap_map()->insert();
|
||||
addr_t const pd_sel = platform_specific()->core_pd_sel();
|
||||
addr_t const ec_sel = ep.local_name();
|
||||
|
||||
using namespace Nova;
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
/* core includes */
|
||||
#include <nova_util.h>
|
||||
#include <platform.h>
|
||||
#include <platform_pd.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
@ -43,7 +42,7 @@ void Thread::_init_platform_thread(size_t, Type type)
|
||||
if (type == MAIN)
|
||||
{
|
||||
/* set EC selector according to NOVA spec */
|
||||
native_thread().ec_sel = Platform_pd::pd_core_sel() + 1;
|
||||
native_thread().ec_sel = platform_specific()->core_pd_sel() + 1;
|
||||
|
||||
/*
|
||||
* Exception base of first thread in core is 0. We have to set
|
||||
@ -56,11 +55,10 @@ void Thread::_init_platform_thread(size_t, Type type)
|
||||
}
|
||||
native_thread().ec_sel = cap_map()->insert(1);
|
||||
native_thread().exc_pt_sel = cap_map()->insert(NUM_INITIAL_PT_LOG2);
|
||||
addr_t pd_sel = Platform_pd::pd_core_sel();
|
||||
|
||||
/* create running semaphore required for locking */
|
||||
addr_t rs_sel =native_thread().exc_pt_sel + SM_SEL_EC;
|
||||
uint8_t res = create_sm(rs_sel, pd_sel, 0);
|
||||
uint8_t res = create_sm(rs_sel, platform_specific()->core_pd_sel(), 0);
|
||||
if (res != NOVA_OK) {
|
||||
error("create_sm returned ", res);
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
@ -94,7 +92,6 @@ void Thread::start()
|
||||
addr_t sp = _stack->top();
|
||||
addr_t utcb = reinterpret_cast<addr_t>(&_stack->utcb());
|
||||
Utcb * utcb_obj = reinterpret_cast<Utcb *>(&_stack->utcb());
|
||||
addr_t pd_sel = Platform_pd::pd_core_sel();
|
||||
|
||||
Affinity::Location location = _affinity;
|
||||
|
||||
@ -104,7 +101,8 @@ void Thread::start()
|
||||
/* create local EC */
|
||||
enum { LOCAL_THREAD = false };
|
||||
unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(location.xpos());
|
||||
uint8_t res = create_ec(native_thread().ec_sel, pd_sel, kernel_cpu_id,
|
||||
uint8_t res = create_ec(native_thread().ec_sel,
|
||||
platform_specific()->core_pd_sel(), kernel_cpu_id,
|
||||
utcb, sp, native_thread().exc_pt_sel, LOCAL_THREAD);
|
||||
if (res != NOVA_OK) {
|
||||
error("create_ec returned ", res, " cpu=", location.xpos());
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <base/snprintf.h>
|
||||
|
||||
#include <util/touch.h>
|
||||
#include <util/retry.h>
|
||||
#include <rm_session/connection.h>
|
||||
#include <region_map/client.h>
|
||||
|
||||
@ -580,42 +581,27 @@ class Greedy : public Genode::Thread {
|
||||
{
|
||||
log("starting");
|
||||
|
||||
enum { SUB_RM_SIZE = 2UL * 1024 * 1024 * 1024 };
|
||||
enum { SUB_RM_SIZE = 1280 * 1024 * 1024 };
|
||||
|
||||
Genode::Rm_connection rm(_env);
|
||||
Genode::Region_map_client sub_rm(rm.create(SUB_RM_SIZE));
|
||||
addr_t const mem = _env.rm().attach(sub_rm.dataspace());
|
||||
Genode::Ram_dataspace_capability ds = _env.ram().alloc(4096);
|
||||
|
||||
Nova::Utcb * nova_utcb = reinterpret_cast<Nova::Utcb *>(utcb());
|
||||
Nova::Rights const mapping_rwx(true, true, true);
|
||||
|
||||
addr_t const page_fault_portal = native_thread().exc_pt_sel + 14;
|
||||
log("cause mappings");
|
||||
|
||||
log("cause mappings in range ",
|
||||
Hex_range<addr_t>(mem, SUB_RM_SIZE), " ", &mem);
|
||||
for (unsigned i = 0; i < SUB_RM_SIZE / 4096; i++) {
|
||||
|
||||
for (addr_t map_to = mem; map_to < mem + SUB_RM_SIZE; map_to += 4096) {
|
||||
|
||||
/* setup faked page fault information */
|
||||
nova_utcb->items = ((addr_t)&nova_utcb->qual[2] - (addr_t)nova_utcb->msg) / sizeof(addr_t);
|
||||
nova_utcb->ip = 0xbadaffe;
|
||||
nova_utcb->qual[1] = (addr_t)&mem;
|
||||
nova_utcb->crd_rcv = Nova::Mem_crd(map_to >> 12, 0, mapping_rwx);
|
||||
|
||||
/* trigger faked page fault */
|
||||
Genode::uint8_t res = Nova::call(page_fault_portal);
|
||||
if (res != Nova::NOVA_OK) {
|
||||
log("call result=", res);
|
||||
failed++;
|
||||
return;
|
||||
}
|
||||
addr_t map_to = _env.rm().attach(ds);
|
||||
|
||||
/* check that we really got the mapping */
|
||||
touch_read(reinterpret_cast<unsigned char *>(map_to));
|
||||
|
||||
/* print status information in interval of 32M */
|
||||
if (!(map_to & (32UL * 1024 * 1024 - 1))) {
|
||||
log(Hex(map_to));
|
||||
if (i % 8192 == 0) {
|
||||
/* transfer some quota to avoid tons of upgrade messages */
|
||||
char const * const buf = "ram_quota=1280K";
|
||||
_env.parent().upgrade(_env.pd_session_cap(), buf);
|
||||
log(Hex(i * 4096));
|
||||
/* trigger some work to see quota in kernel decreasing */
|
||||
// Nova::Rights rwx(true, true, true);
|
||||
// Nova::revoke(Nova::Mem_crd((map_to - 32 * 1024 * 1024) >> 12, 12, rwx));
|
||||
|
@ -83,15 +83,21 @@ static bool map_eager(Genode::addr_t const page, unsigned log2_order)
|
||||
|
||||
addr_t const page_fault_portal = myself->native_thread().exc_pt_sel + 14;
|
||||
|
||||
/* setup faked page fault information */
|
||||
utcb->set_msg_word(((addr_t)&utcb->qual[2] - (addr_t)utcb->msg) / sizeof(addr_t));
|
||||
utcb->ip = reinterpret_cast<addr_t>(map_eager);
|
||||
utcb->qual[1] = page;
|
||||
utcb->crd_rcv = Nova::Mem_crd(page >> 12, log2_order - 12, mapping_rw);
|
||||
while (true) {
|
||||
/* setup faked page fault information */
|
||||
utcb->set_msg_word(((addr_t)&utcb->qual[2] - (addr_t)utcb->msg) /
|
||||
sizeof(addr_t));
|
||||
utcb->ip = reinterpret_cast<addr_t>(map_eager);
|
||||
utcb->qual[1] = page;
|
||||
utcb->crd_rcv = Nova::Mem_crd(page >> 12, log2_order - 12, mapping_rw);
|
||||
|
||||
/* trigger faked page fault */
|
||||
Genode::uint8_t res = Nova::call(page_fault_portal);
|
||||
return res == Nova::NOVA_OK;
|
||||
/* trigger faked page fault */
|
||||
Genode::uint8_t res = Nova::call(page_fault_portal);
|
||||
|
||||
bool const retry = utcb->msg_words();
|
||||
if (res != Nova::NOVA_OK || !retry)
|
||||
return res == Nova::NOVA_OK;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -174,7 +180,7 @@ void Platform::Device_pd_component::assign_pci(Genode::Io_mem_dataspace_capabili
|
||||
"phys=", Genode::Hex(ds_client.phys_addr()), " "
|
||||
"virt=", Genode::Hex(page));
|
||||
else
|
||||
Genode::log("assignment of ", rid, " succeeded");
|
||||
Genode::log("assignment of PCI device ", Rid(rid), " succeeded");
|
||||
|
||||
/* we don't need the mapping anymore */
|
||||
_address_space.detach(page);
|
||||
|
Loading…
x
Reference in New Issue
Block a user