nova: support asynchronous delegate

Issue #2173
This commit is contained in:
Alexander Boettcher 2016-11-10 11:46:30 +01:00 committed by Christian Helmuth
parent ff5d28822c
commit 57949c2bbb
18 changed files with 194 additions and 146 deletions

View File

@ -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 ALWAYS_INLINE
inline uint8_t sm_ctrl(unsigned sm, Sem_op op, unsigned long long timeout = 0) inline uint8_t sm_ctrl(unsigned sm, Sem_op op, unsigned long long timeout = 0)
{ {

View File

@ -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 ALWAYS_INLINE
inline uint8_t sm_ctrl(mword_t sm, Sem_op op, unsigned long long timeout = 0) inline uint8_t sm_ctrl(mword_t sm, Sem_op op, unsigned long long timeout = 0)
{ {

View File

@ -1 +1 @@
931c26a24d490daae7df7ebbb03274366088adf0 6f91bce10f8f9faa2a0f57b9d135559a1ce499a7

View File

@ -4,7 +4,7 @@ DOWNLOADS := nova.git
# r9 branch - use r9_debug for more verbose kernel messages # r9 branch - use r9_debug for more verbose kernel messages
URL(nova) := https://github.com/alex-ab/NOVA.git URL(nova) := https://github.com/alex-ab/NOVA.git
REV(nova) := 4d6f04dd02d8099a20766025457be0afd0eae534 REV(nova) := b493eef81a1313f1cd420b4ed4310ef154c79c04
DIR(nova) := src/kernel/nova DIR(nova) := src/kernel/nova
PATCHES := $(wildcard $(REP_DIR)/patches/*.patch) PATCHES := $(wildcard $(REP_DIR)/patches/*.patch)

View File

@ -37,6 +37,6 @@ build_boot_image "core init test-platform"
append qemu_args "-nographic -m 128 -smp 2" append qemu_args "-nographic -m 128 -smp 2"
run_genode_until {Test finished} 150 run_genode_until {Test finished} 200
puts "\nTest succeeded" puts "\nTest succeeded"

View File

@ -12,8 +12,8 @@
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
/* Core includes */ /* core-local includes */
#include <platform_pd.h> #include <platform.h>
/* local includes */ /* local includes */
#include <echo.h> #include <echo.h>
@ -69,9 +69,12 @@ Echo::Echo(Genode::addr_t utcb_addr)
{ {
using namespace Nova; using namespace Nova;
extern Genode::addr_t __initial_sp;
Hip const * const hip = reinterpret_cast<Hip *>(__initial_sp);
/* create echo EC */ /* create echo EC */
Genode::addr_t pd_sel = Genode::Platform_pd::pd_core_sel(); Genode::addr_t const core_pd_sel = hip->sel_exc;
uint8_t res = create_ec(_ec_sel, pd_sel, boot_cpu(), utcb_addr, uint8_t res = create_ec(_ec_sel, core_pd_sel, boot_cpu(), utcb_addr,
reinterpret_cast<mword_t>(echo_stack_top()), reinterpret_cast<mword_t>(echo_stack_top()),
ECHO_EXC_BASE, ECHO_GLOBAL); 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; } if (res != Nova::NOVA_OK) { *reinterpret_cast<unsigned *>(0) = 0xdead; }
/* set up echo portal to ourself */ /* 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; } if (res != Nova::NOVA_OK) { *reinterpret_cast<unsigned *>(0) = 0xdead; }
revoke(Obj_crd(_pt_sel, 0, Obj_crd::RIGHT_PT_CTRL)); revoke(Obj_crd(_pt_sel, 0, Obj_crd::RIGHT_PT_CTRL));

View File

@ -75,12 +75,19 @@ namespace Genode {
{ {
private: private:
addr_t _pd_dst;
addr_t _pd_core;
addr_t _fault_ip; addr_t _fault_ip;
addr_t _fault_addr; addr_t _fault_addr;
addr_t _sp;
uint8_t _fault_type; uint8_t _fault_type;
uint8_t _syscall_res;
uint8_t _normal_ipc;
public: public:
Ipc_pager (Nova::Utcb *, addr_t pd_dst, addr_t pd_core);
/* /*
* Intel manual: 6.15 EXCEPTION AND INTERRUPT REFERENCE * Intel manual: 6.15 EXCEPTION AND INTERRUPT REFERENCE
* Interrupt 14Page-Fault Exception (#PF) * Interrupt 14Page-Fault Exception (#PF)
@ -93,18 +100,10 @@ namespace Genode {
ERR_P = 1 << 0, 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 * 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 * Request instruction pointer of current fault
@ -136,6 +135,23 @@ namespace Genode {
*/ */
return false; 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 14Page-Fault Exception (#PF)
*/
addr_t fault_type() { return _fault_type; }
/**
* Return stack pointer address valid during page-fault
*/
addr_t sp() { return _sp; }
}; };
} }

View File

@ -34,7 +34,8 @@ namespace Genode {
Phys_allocator _io_port_alloc; /* I/O port allocator */ Phys_allocator _io_port_alloc; /* I/O port allocator */
Phys_allocator _irq_alloc; /* IRQ allocator */ Phys_allocator _irq_alloc; /* IRQ allocator */
Rom_fs _rom_fs; /* ROM file system */ 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 * Virtual address range usable by non-core processes
@ -100,6 +101,11 @@ namespace Genode {
* Return kernel CPU ID for given Genode CPU * Return kernel CPU ID for given Genode CPU
*/ */
unsigned kernel_cpu_id(unsigned genode_cpu_id); unsigned kernel_cpu_id(unsigned genode_cpu_id);
/**
* PD kernel capability selector of core
*/
unsigned core_pd_sel() const { return _core_pd_sel; }
}; };
} }

View File

@ -18,11 +18,6 @@
#include <platform_thread.h> #include <platform_thread.h>
#include <address_space.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 { namespace Genode {
@ -83,14 +78,6 @@ namespace Genode {
*/ */
addr_t pd_sel() const { return _pd_sel; } 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 * Label of this protection domain
* *

View File

@ -21,6 +21,7 @@
#include <nova/capability_space.h> #include <nova/capability_space.h>
/* core-local includes */ /* core-local includes */
#include <platform.h>
#include <signal_source_component.h> #include <signal_source_component.h>
#include <signal_source/capability.h> #include <signal_source/capability.h>
@ -91,8 +92,9 @@ class Genode::Signal_broker
Native_capability si = Capability_space::import(cap_map()->insert()); Native_capability si = Capability_space::import(cap_map()->insert());
Signal_context_capability cap = reinterpret_cap_cast<Signal_context>(si); Signal_context_capability cap = reinterpret_cap_cast<Signal_context>(si);
uint8_t res = Nova::create_si(cap.local_name(), __core_pd_sel, imprint, uint8_t res = Nova::create_si(cap.local_name(),
sm.local_name()); platform_specific()->core_pd_sel(),
imprint, sm.local_name());
if (res != Nova::NOVA_OK) { if (res != Nova::NOVA_OK) {
warning("creating signal failed - error ", res); warning("creating signal failed - error ", res);
return Signal_context_capability(); return Signal_context_capability();

View File

@ -23,17 +23,24 @@
using namespace Genode; 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 * When this function is called from the page-fault handler EC, a page
* fault already occurred. So we never wait but immediately read the * fault already occurred. So we never wait but immediately read the
* page-fault information from our UTCB. * 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(); Nova::Utcb *utcb = (Nova::Utcb *)Thread::myself()->utcb();
utcb->set_msg_word(0); 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()); false, m.dma(), m.write_combined());
/* one item ever fits on the UTCB */ /* one item ever fits on the UTCB */
(void)res; (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);
} }

View File

@ -36,7 +36,6 @@ static bool verbose_oom = false;
using namespace Genode; using namespace Genode;
using namespace Nova; using namespace Nova;
extern Genode::addr_t __core_pd_sel;
static Nova::Hip * kernel_hip() static Nova::Hip * kernel_hip()
{ {
@ -79,11 +78,13 @@ struct Page_fault_info
char const * const pd; char const * const pd;
char const * const thread; char const * const thread;
unsigned const cpu; 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, Page_fault_info(char const *pd, char const *thread, unsigned cpu,
addr_t ip, addr_t addr) addr_t ip, addr_t addr, addr_t sp, unsigned type)
: pd(pd), thread(thread), cpu(cpu), ip(ip), addr(addr) { } : pd(pd), thread(thread), cpu(cpu), ip(ip), addr(addr),
sp(sp), pf_type(type) { }
void print(Genode::Output &out) const void print(Genode::Output &out) const
{ {
@ -91,32 +92,57 @@ struct Page_fault_info
"thread='", thread, "' " "thread='", thread, "' "
"cpu=", cpu, " " "cpu=", cpu, " "
"ip=", Hex(ip), " " "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) void Pager_object::_page_fault_handler(addr_t pager_obj)
{ {
Ipc_pager ipc_pager;
ipc_pager.wait_for_fault();
Thread * myself = Thread::myself(); Thread * myself = Thread::myself();
Pager_object * obj = reinterpret_cast<Pager_object *>(pager_obj); Pager_object * obj = reinterpret_cast<Pager_object *>(pager_obj);
Utcb * utcb = reinterpret_cast<Utcb *>(myself->utcb()); 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); Pager_activation_base * pager_thread = static_cast<Pager_activation_base *>(myself);
/* lookup fault address and decide what to do */ /* 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 */ /* don't open receive window for pager threads */
if (utcb->crd_rcv.value()) if (utcb->crd_rcv.value())
nova_die(); 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 */ /* good case - found a valid region which is mappable */
if (!ret) if (!error)
ipc_pager.reply_and_wait_for_fault(); ipc_pager.reply_and_wait_for_fault();
obj->_state_lock.lock(); obj->_state_lock.lock();
obj->_state.thread.ip = ipc_pager.fault_ip(); obj->_state.thread.ip = ipc_pager.fault_ip();
@ -132,35 +158,18 @@ void Pager_object::_page_fault_handler(addr_t pager_obj)
Page_fault_info const fault_info(client_pd, client_thread, Page_fault_info const fault_info(client_pd, client_thread,
which_cpu(pager_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 */ /* region manager fault - to be handled */
if (ret == 1) { log("page fault, ", fault_info, " reason=", error);
log("page fault, ", fault_info);
utcb->set_msg_word(0);
utcb->mtd = 0;
/* block the faulting thread until region manager is done */ /* block the faulting thread until region manager is done */
ipc_pager.reply_and_wait_for_fault(obj->sel_sm_block_pause()); 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();
}
void Pager_object::exception(uint8_t exit_id) void Pager_object::exception(uint8_t exit_id)
{ {
@ -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)); 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, 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) if (res != Nova::NOVA_OK)
reply(myself->stack_top()); 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 */ /* compiler generates instance of exception entry if not specified */
addr_t entry = func ? (addr_t)func : (addr_t)(&_handler<EV>); addr_t entry = func ? (addr_t)func : (addr_t)(&_handler<EV>);
uint8_t res = create_portal(obj->exc_pt_sel_client() + 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) if (res != Nova::NOVA_OK)
throw Region_map::Invalid_thread(); throw Region_map::Invalid_thread();
} }
@ -589,7 +598,7 @@ Pager_object::Pager_object(Cpu_session_capability cpu_session_cap,
{ {
uint8_t res; uint8_t res;
addr_t pd_sel = __core_pd_sel; addr_t const pd_sel = platform_specific()->core_pd_sel();
_state._status = 0; _state._status = 0;
_state.modified = false; _state.modified = false;
_state.sel_client_ec = Native_thread::INVALID_INDEX; _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, char const * src_pd, char const * src_thread,
enum Pager_object::Policy policy) enum Pager_object::Policy policy)
{ {
const char * dst_pd = client_pd(); char const * dst_pd = client_pd();
const char * dst_thread = client_thread(); char const * dst_thread = client_thread();
addr_t const core_pd_sel = platform_specific()->core_pd_sel();
enum { QUOTA_TRANSFER_PAGES = 2 }; enum { QUOTA_TRANSFER_PAGES = 2 };
if (transfer_from == SRC_CORE_PD) if (transfer_from == SRC_CORE_PD)
transfer_from = __core_pd_sel; transfer_from = core_pd_sel;
/* request current kernel quota usage of target pd */ /* request current kernel quota usage of target pd */
addr_t limit_before = 0, usage_before = 0; 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 */ /* retry upgrade using core quota if policy permits */
if (policy == UPGRADE_PREFER_SRC_TO_DST) { if (policy == UPGRADE_PREFER_SRC_TO_DST) {
if (transfer_from != __core_pd_sel) { if (transfer_from != core_pd_sel) {
res = Nova::pd_ctrl(__core_pd_sel, Pd_op::TRANSFER_QUOTA, res = Nova::pd_ctrl(core_pd_sel, Pd_op::TRANSFER_QUOTA,
pd_sel(), QUOTA_TRANSFER_PAGES); pd_sel(), QUOTA_TRANSFER_PAGES);
if (res == Nova::NOVA_OK) if (res == Nova::NOVA_OK)
return res; return res;
@ -836,14 +846,14 @@ void Pager_object::_oom_handler(addr_t pager_dst, addr_t pager_src,
utcb->set_msg_word(0); utcb->set_msg_word(0);
} }
transfer_from = __core_pd_sel; transfer_from = platform_specific()->core_pd_sel();
break; break;
default: default:
/* non core PD -> non core PD */ /* non core PD -> non core PD */
utcb->set_msg_word(0); utcb->set_msg_word(0);
if (pager_src == pager_dst || policy == UPGRADE_CORE_TO_DST) if (pager_src == pager_dst || policy == UPGRADE_CORE_TO_DST)
transfer_from = __core_pd_sel; transfer_from = platform_specific()->core_pd_sel();
else { else {
/* delegation of items between different PDs */ /* delegation of items between different PDs */
src_pd = obj_src->client_pd(); 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(); addr_t const pt_oom = sel_oom_portal();
unsigned const genode_cpu_id = _location.xpos(); unsigned const genode_cpu_id = _location.xpos();
unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(genode_cpu_id); 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) && if (kernel_hip()->is_cpu_enabled(kernel_cpu_id) &&
pager_threads[genode_cpu_id]) { pager_threads[genode_cpu_id]) {
addr_t const ec_sel = pager_threads[genode_cpu_id]->native_thread().ec_sel; 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), reinterpret_cast<addr_t>(_oom_handler),
this); this);
if (res == Nova::NOVA_OK) if (res == Nova::NOVA_OK)

View File

@ -63,11 +63,6 @@ Utcb *__main_thread_utcb;
*/ */
extern unsigned _prog_img_beg, _prog_img_end; extern unsigned _prog_img_beg, _prog_img_end;
/**
* Capability selector of root PD
*/
addr_t __core_pd_sel;
/** /**
* Map preserved physical pages core-exclusive * 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 */ /* create echo EC */
enum { enum {
@ -228,20 +223,20 @@ static void init_core_page_fault_handler()
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(), uint8_t 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)
log(__func__, ": create_ec returned ", ret); log(__func__, ": create_ec returned ", ret);
/* set up page-fault portal */ /* 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), Mtd(Mtd::QUAL | Mtd::ESP | Mtd::EIP),
(addr_t)page_fault_handler); (addr_t)page_fault_handler);
revoke(Obj_crd(PT_SEL_PAGE_FAULT, 0, Obj_crd::RIGHT_PT_CTRL)); revoke(Obj_crd(PT_SEL_PAGE_FAULT, 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, 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);
revoke(Obj_crd(PT_SEL_STARTUP, 0, Obj_crd::RIGHT_PT_CTRL)); 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()); __main_thread_utcb = (Utcb *)(__initial_sp - get_page_size());
/* set core pd selector */ /* set core pd selector */
__core_pd_sel = hip->sel_exc; _core_pd_sel = hip->sel_exc;
/* create lock used by capability allocator */ /* 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 */ /* locally map the whole I/O port range */
enum { ORDER_64K = 16 }; enum { ORDER_64K = 16 };
@ -380,7 +375,7 @@ Platform::Platform() :
#endif #endif
/* set up page fault handler for core - for debugging */ /* 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 (verbose_boot_info) {
if (hip->has_feature_vmx()) if (hip->has_feature_vmx())

View File

@ -109,7 +109,6 @@ int Platform_thread::start(void *ip, void *sp)
return -5; return -5;
} }
addr_t pd_core_sel = Platform_pd::pd_core_sel();
addr_t pd_utcb = 0; addr_t pd_utcb = 0;
_sel_exc_base = vcpu() ? _pager->exc_pt_vcpu() : _pager->exc_pt_sel_client(); _sel_exc_base = vcpu() ? _pager->exc_pt_vcpu() : _pager->exc_pt_sel_client();
@ -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 }; enum { KEEP_FREE_PAGES_NOT_AVAILABLE_FOR_UPGRADE = 2, UPPER_LIMIT_PAGES = 32 };
Obj_crd initial_pts(_sel_exc_base, pts, rights); 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); KEEP_FREE_PAGES_NOT_AVAILABLE_FOR_UPGRADE, UPPER_LIMIT_PAGES);
if (res != NOVA_OK) { if (res != NOVA_OK) {
error("create_pd returned ", res); error("create_pd returned ", res);

View File

@ -13,7 +13,7 @@
/* core-local includes */ /* core-local includes */
#include <rpc_cap_factory.h> #include <rpc_cap_factory.h>
#include <platform_pd.h> #include <platform.h>
/* NOVA includes */ /* NOVA includes */
#include <nova/capability_space.h> #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) Native_capability Rpc_cap_factory::alloc(Native_capability ep, addr_t entry, addr_t mtd)
{ {
addr_t pt_sel = cap_map()->insert(); addr_t const pt_sel = cap_map()->insert();
addr_t pd_sel = Platform_pd::pd_core_sel(); addr_t const pd_sel = platform_specific()->core_pd_sel();
addr_t ec_sel = ep.local_name(); addr_t const ec_sel = ep.local_name();
using namespace Nova; using namespace Nova;

View File

@ -26,7 +26,6 @@
/* core includes */ /* core includes */
#include <nova_util.h> #include <nova_util.h>
#include <platform.h> #include <platform.h>
#include <platform_pd.h>
using namespace Genode; using namespace Genode;
@ -43,7 +42,7 @@ void Thread::_init_platform_thread(size_t, Type type)
if (type == MAIN) if (type == MAIN)
{ {
/* set EC selector according to NOVA spec */ /* 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 * 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().ec_sel = cap_map()->insert(1);
native_thread().exc_pt_sel = cap_map()->insert(NUM_INITIAL_PT_LOG2); 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 */ /* create running semaphore required for locking */
addr_t rs_sel =native_thread().exc_pt_sel + SM_SEL_EC; 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) { if (res != NOVA_OK) {
error("create_sm returned ", res); error("create_sm returned ", res);
throw Cpu_session::Thread_creation_failed(); throw Cpu_session::Thread_creation_failed();
@ -94,7 +92,6 @@ void Thread::start()
addr_t sp = _stack->top(); addr_t sp = _stack->top();
addr_t utcb = reinterpret_cast<addr_t>(&_stack->utcb()); addr_t utcb = reinterpret_cast<addr_t>(&_stack->utcb());
Utcb * utcb_obj = reinterpret_cast<Utcb *>(&_stack->utcb()); Utcb * utcb_obj = reinterpret_cast<Utcb *>(&_stack->utcb());
addr_t pd_sel = Platform_pd::pd_core_sel();
Affinity::Location location = _affinity; Affinity::Location location = _affinity;
@ -104,7 +101,8 @@ void Thread::start()
/* create local EC */ /* create local EC */
enum { LOCAL_THREAD = false }; enum { LOCAL_THREAD = false };
unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(location.xpos()); 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); utcb, sp, native_thread().exc_pt_sel, LOCAL_THREAD);
if (res != NOVA_OK) { if (res != NOVA_OK) {
error("create_ec returned ", res, " cpu=", location.xpos()); error("create_ec returned ", res, " cpu=", location.xpos());

View File

@ -18,6 +18,7 @@
#include <base/snprintf.h> #include <base/snprintf.h>
#include <util/touch.h> #include <util/touch.h>
#include <util/retry.h>
#include <rm_session/connection.h> #include <rm_session/connection.h>
#include <region_map/client.h> #include <region_map/client.h>
@ -580,42 +581,27 @@ class Greedy : public Genode::Thread {
{ {
log("starting"); log("starting");
enum { SUB_RM_SIZE = 2UL * 1024 * 1024 * 1024 }; enum { SUB_RM_SIZE = 1280 * 1024 * 1024 };
Genode::Rm_connection rm(_env); Genode::Ram_dataspace_capability ds = _env.ram().alloc(4096);
Genode::Region_map_client sub_rm(rm.create(SUB_RM_SIZE));
addr_t const mem = _env.rm().attach(sub_rm.dataspace());
Nova::Utcb * nova_utcb = reinterpret_cast<Nova::Utcb *>(utcb());
Nova::Rights const mapping_rwx(true, true, true); 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 ", for (unsigned i = 0; i < SUB_RM_SIZE / 4096; i++) {
Hex_range<addr_t>(mem, SUB_RM_SIZE), " ", &mem);
for (addr_t map_to = mem; map_to < mem + SUB_RM_SIZE; map_to += 4096) { addr_t map_to = _env.rm().attach(ds);
/* 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;
}
/* check that we really got the mapping */ /* check that we really got the mapping */
touch_read(reinterpret_cast<unsigned char *>(map_to)); touch_read(reinterpret_cast<unsigned char *>(map_to));
/* print status information in interval of 32M */ /* print status information in interval of 32M */
if (!(map_to & (32UL * 1024 * 1024 - 1))) { if (i % 8192 == 0) {
log(Hex(map_to)); /* 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 */ /* trigger some work to see quota in kernel decreasing */
// Nova::Rights rwx(true, true, true); // Nova::Rights rwx(true, true, true);
// Nova::revoke(Nova::Mem_crd((map_to - 32 * 1024 * 1024) >> 12, 12, rwx)); // Nova::revoke(Nova::Mem_crd((map_to - 32 * 1024 * 1024) >> 12, 12, rwx));

View File

@ -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; addr_t const page_fault_portal = myself->native_thread().exc_pt_sel + 14;
while (true) {
/* setup faked page fault information */ /* setup faked page fault information */
utcb->set_msg_word(((addr_t)&utcb->qual[2] - (addr_t)utcb->msg) / sizeof(addr_t)); 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->ip = reinterpret_cast<addr_t>(map_eager);
utcb->qual[1] = page; utcb->qual[1] = page;
utcb->crd_rcv = Nova::Mem_crd(page >> 12, log2_order - 12, mapping_rw); utcb->crd_rcv = Nova::Mem_crd(page >> 12, log2_order - 12, mapping_rw);
/* trigger faked page fault */ /* trigger faked page fault */
Genode::uint8_t res = Nova::call(page_fault_portal); 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; 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()), " " "phys=", Genode::Hex(ds_client.phys_addr()), " "
"virt=", Genode::Hex(page)); "virt=", Genode::Hex(page));
else else
Genode::log("assignment of ", rid, " succeeded"); Genode::log("assignment of PCI device ", Rid(rid), " succeeded");
/* we don't need the mapping anymore */ /* we don't need the mapping anymore */
_address_space.detach(page); _address_space.detach(page);