mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-19 03:06:39 +00:00
NOVA: implement pause using recall kernel feature
This commit is contained in:
parent
841a1fd579
commit
197a48a26c
@ -44,14 +44,31 @@ namespace Genode {
|
||||
*/
|
||||
Signal_context_capability _exception_sigh;
|
||||
|
||||
addr_t _pt_cleanup; /* portal selector for object cleanup/destruction */
|
||||
/**
|
||||
* Portal selector for object cleanup/destruction
|
||||
*/
|
||||
addr_t _pt_cleanup;
|
||||
|
||||
/**
|
||||
* Semaphore selector to synchronize pause/state/resume operations
|
||||
*/
|
||||
addr_t _sm_state_notify;
|
||||
|
||||
addr_t _initial_esp;
|
||||
addr_t _initial_eip;
|
||||
|
||||
struct {
|
||||
struct Thread_state thread;
|
||||
bool valid;
|
||||
bool dead;
|
||||
} _state;
|
||||
|
||||
void _copy_state(Nova::Utcb * utcb);
|
||||
|
||||
static void _page_fault_handler();
|
||||
static void _startup_handler();
|
||||
static void _invoke_handler();
|
||||
static void _recall_handler();
|
||||
|
||||
public:
|
||||
|
||||
@ -99,12 +116,14 @@ namespace Genode {
|
||||
/**
|
||||
* Notify exception handler about the occurrence of an exception
|
||||
*/
|
||||
void submit_exception_signal()
|
||||
bool submit_exception_signal()
|
||||
{
|
||||
if (!_exception_sigh.valid()) return;
|
||||
if (!_exception_sigh.valid()) return false;
|
||||
|
||||
Signal_transmitter transmitter(_exception_sigh);
|
||||
transmitter.submit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,8 +131,40 @@ namespace Genode {
|
||||
*/
|
||||
addr_t handler_address()
|
||||
{
|
||||
return reinterpret_cast<addr_t>(_invoke_handler);
|
||||
return reinterpret_cast<addr_t>(_invoke_handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return semaphore to block on until state of a recall is
|
||||
* available.
|
||||
*/
|
||||
Native_capability notify_sm()
|
||||
{
|
||||
if (_state.valid)
|
||||
return Native_capability::invalid_cap();
|
||||
if (_state.dead)
|
||||
return Native_capability::invalid_cap();
|
||||
|
||||
return Native_capability(_sm_state_notify);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy thread state of recalled thread.
|
||||
*/
|
||||
int copy_thread_state(Thread_state * state_dst)
|
||||
{
|
||||
if (!state_dst || !_state.valid) return -1;
|
||||
|
||||
*state_dst = _state.thread;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel blocking in a lock so that recall exception can take
|
||||
* place.
|
||||
*/
|
||||
void cancel_blocking_client();
|
||||
};
|
||||
|
||||
|
||||
|
@ -172,9 +172,12 @@ namespace Nova {
|
||||
|
||||
enum {
|
||||
ACDB = 1 << 0, /* eax, ecx, edx, ebx */
|
||||
EBSD = 1 << 1, /* ebp, esi, edi */
|
||||
ESP = 1 << 2,
|
||||
EIP = 1 << 3,
|
||||
EFL = 1 << 4, /* eflags */
|
||||
FSGS = 1 << 6,
|
||||
CSSS = 1 << 7,
|
||||
QUAL = 1 << 15, /* exit qualification */
|
||||
CTRL = 1 << 16, /* execution controls */
|
||||
INJ = 1 << 17, /* injection info */
|
||||
@ -384,9 +387,13 @@ namespace Nova {
|
||||
*/
|
||||
struct Utcb
|
||||
{
|
||||
mword_t items; /* number of untyped items uses lowest 16 bit, number of typed items uses bit 16-31, bit 32+ are ignored on 64bit */
|
||||
Crd crd_xlt; /* receive capability-range descriptor for translation */
|
||||
Crd crd_rcv; /* receive capability-range descriptor for delegation */
|
||||
/**
|
||||
* Number of untyped items uses lowest 16 bit, number of typed items
|
||||
* uses bit 16-31, bit 32+ are ignored on 64bit
|
||||
*/
|
||||
mword_t items;
|
||||
Crd crd_xlt; /* receive capability-range descriptor for translation */
|
||||
Crd crd_rcv; /* receive capability-range descriptor for delegation */
|
||||
mword_t tls;
|
||||
|
||||
/**
|
||||
@ -402,19 +409,39 @@ namespace Nova {
|
||||
|
||||
/* exception state */
|
||||
struct {
|
||||
mword_t mtd, instr_len, eip, eflags;
|
||||
unsigned misc[4];
|
||||
mword_t eax, ecx, edx, ebx;
|
||||
mword_t esp, ebp, esi, edi;
|
||||
mword_t mtd, instr_len, ip, flags;
|
||||
unsigned intr_state, actv_state, inj_info, inj_error;
|
||||
mword_t ax, cx, dx, bx;
|
||||
mword_t sp, bp, si, di;
|
||||
#ifdef __x86_64__
|
||||
mword_t rxx[8];
|
||||
mword_t r8, r9, r10, r11, r12, r13, r14, r15;
|
||||
#endif
|
||||
unsigned long long qual[2]; /* exit qualification */
|
||||
unsigned ctrl[2];
|
||||
unsigned long long tsc;
|
||||
mword_t cr0, cr2, cr3, cr4;
|
||||
// unsigned misc3[44];
|
||||
};
|
||||
#ifdef __x86_64__
|
||||
mword_t cr8, reserved;
|
||||
#endif
|
||||
mword_t dr7, sysenter_cs, sysenter_sp, sysenter_ip;
|
||||
|
||||
struct {
|
||||
unsigned short sel, ar;
|
||||
unsigned limit;
|
||||
mword_t base;
|
||||
#ifdef __x86_32__
|
||||
mword_t reserved;
|
||||
#endif
|
||||
} es, cs, ss, ds, fs, gs, ldtr, tr;
|
||||
struct {
|
||||
unsigned reserved0;
|
||||
unsigned limit;
|
||||
mword_t base;
|
||||
#ifdef __x86_32__
|
||||
mword_t reserved1;
|
||||
#endif
|
||||
} gdtr, idtr;
|
||||
} __attribute__((packed));
|
||||
};
|
||||
|
||||
struct Item {
|
||||
@ -499,9 +526,10 @@ namespace Nova {
|
||||
PT_SEL_PAGE_FAULT = 0xe,
|
||||
PT_SEL_PARENT = 0x1a, /* convention on Genode */
|
||||
PT_SEL_STARTUP = 0x1e,
|
||||
PT_SEL_RECALL = 0x1f,
|
||||
PD_SEL = 0x1b,
|
||||
PD_SEL_CAP_LOCK = 0x1c, /* convention on Genode */
|
||||
SM_SEL_EC_MAIN = 0x1c, /* convention on Genode */
|
||||
SM_SEL_EC_CLIENT = 0x1c, /* convention on Genode */
|
||||
SM_SEL_EC = 0x1d, /* convention on Genode */
|
||||
};
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
SRC_CC = pager.cc
|
||||
|
||||
vpath pager.cc $(REP_DIR)/src/base/pager
|
3
base-nova/lib/mk/x86_32/pager.mk
Normal file
3
base-nova/lib/mk/x86_32/pager.mk
Normal file
@ -0,0 +1,3 @@
|
||||
SRC_CC = pager.cc x86_32/pager.cc
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/base/pager
|
3
base-nova/lib/mk/x86_64/pager.mk
Normal file
3
base-nova/lib/mk/x86_64/pager.mk
Normal file
@ -0,0 +1,3 @@
|
||||
SRC_CC = pager.cc x86_64/pager.cc
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/base/pager
|
@ -46,7 +46,7 @@ void Ipc_pager::wait_for_fault()
|
||||
Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
|
||||
_fault_type = (Pf_type)utcb->qual[0];
|
||||
_fault_addr = utcb->qual[1];
|
||||
_fault_ip = utcb->eip;
|
||||
_fault_ip = utcb->ip;
|
||||
|
||||
if (verbose_page_fault)
|
||||
print_page_fault(_fault_type, _fault_addr, _fault_ip);
|
||||
|
@ -47,9 +47,13 @@ void Pager_object::_page_fault_handler()
|
||||
PWRN("unresolvable page-fault at address 0x%lx, ip=0x%lx",
|
||||
ipc_pager.fault_addr(), ipc_pager.fault_ip());
|
||||
|
||||
/* revoke paging capability, let thread die in kernel */
|
||||
Nova::revoke(Obj_crd(obj->exc_pt_sel() + PT_SEL_PAGE_FAULT, 0),
|
||||
true);
|
||||
if (!obj->submit_exception_signal()) {
|
||||
/* revoke paging capability, let thread die in kernel */
|
||||
Nova::revoke(Obj_crd(obj->exc_pt_sel() + PT_SEL_PAGE_FAULT, 0),
|
||||
true);
|
||||
obj->_state.dead = true;
|
||||
}
|
||||
|
||||
Utcb *utcb = (Utcb *)Thread_base::myself()->utcb();
|
||||
utcb->set_msg_word(0);
|
||||
}
|
||||
@ -57,14 +61,41 @@ void Pager_object::_page_fault_handler()
|
||||
ipc_pager.reply_and_wait_for_fault();
|
||||
}
|
||||
|
||||
void Pager_object::_recall_handler()
|
||||
{
|
||||
Pager_object *obj = static_cast<Pager_object *>(Thread_base::myself());
|
||||
Utcb *utcb = (Utcb *)Thread_base::myself()->utcb();
|
||||
|
||||
obj->_copy_state(utcb);
|
||||
|
||||
obj->_state.thread.ip = utcb->ip;
|
||||
obj->_state.thread.sp = utcb->sp;
|
||||
|
||||
obj->_state.thread.eflags = utcb->flags;
|
||||
obj->_state.thread.trapno = PT_SEL_RECALL;
|
||||
|
||||
obj->_state.valid = true;
|
||||
|
||||
if (sm_ctrl(obj->_sm_state_notify, SEMAPHORE_UP) != NOVA_OK)
|
||||
PWRN("notify failed");
|
||||
|
||||
if (sm_ctrl(obj->exc_pt_sel() + SM_SEL_EC, SEMAPHORE_DOWNZERO) != NOVA_OK)
|
||||
PWRN("blocking recall handler failed");
|
||||
|
||||
obj->_state.valid = false;
|
||||
|
||||
utcb->set_msg_word(0);
|
||||
utcb->mtd = 0;
|
||||
reply(Thread_base::myself()->stack_top());
|
||||
}
|
||||
|
||||
void Pager_object::_startup_handler()
|
||||
{
|
||||
Pager_object *obj = static_cast<Pager_object *>(Thread_base::myself());
|
||||
Utcb *utcb = (Utcb *)Thread_base::myself()->utcb();
|
||||
|
||||
utcb->eip = obj->_initial_eip;
|
||||
utcb->esp = obj->_initial_esp;
|
||||
utcb->ip = obj->_initial_eip;
|
||||
utcb->sp = obj->_initial_esp;
|
||||
utcb->mtd = Mtd::EIP | Mtd::ESP;
|
||||
utcb->set_msg_word(0);
|
||||
reply(Thread_base::myself()->stack_top());
|
||||
@ -82,12 +113,13 @@ void Pager_object::_invoke_handler()
|
||||
utcb->set_msg_word(0);
|
||||
|
||||
if (event == PT_SEL_STARTUP || event == PT_SEL_PAGE_FAULT ||
|
||||
event == SM_SEL_EC) {
|
||||
event == SM_SEL_EC || event == PT_SEL_RECALL) {
|
||||
|
||||
/**
|
||||
* Caller is requesting the SM cap of main thread
|
||||
* this object is paging - it is stored at SM_SEL_EC_MAIN
|
||||
* Caller is requesting the SM cap of thread
|
||||
* this object is paging - it is stored at SM_SEL_EC_CLIENT
|
||||
*/
|
||||
if (event == SM_SEL_EC) event = SM_SEL_EC_MAIN;
|
||||
if (event == SM_SEL_EC) event = SM_SEL_EC_CLIENT;
|
||||
|
||||
bool res = utcb->append_item(Obj_crd(obj->exc_pt_sel() + event,
|
||||
0), 0);
|
||||
@ -99,13 +131,21 @@ void Pager_object::_invoke_handler()
|
||||
}
|
||||
|
||||
|
||||
void Pager_object::wake_up() { PDBG("not yet implemented"); }
|
||||
void Pager_object::wake_up() { cancel_blocking(); }
|
||||
|
||||
void Pager_object::cancel_blocking_client() {
|
||||
uint8_t res = sm_ctrl(exc_pt_sel() + SM_SEL_EC_CLIENT, SEMAPHORE_UP);
|
||||
if (res != NOVA_OK)
|
||||
PWRN("cancel blocking failed");
|
||||
}
|
||||
|
||||
Pager_object::Pager_object(unsigned long badge)
|
||||
: Thread_base("pager", PF_HANDLER_STACK_SIZE), _badge(badge)
|
||||
{
|
||||
_pt_cleanup = cap_selector_allocator()->alloc();
|
||||
_pt_cleanup = cap_selector_allocator()->alloc();
|
||||
_sm_state_notify = cap_selector_allocator()->alloc();
|
||||
_state.valid = false;
|
||||
_state.dead = false;
|
||||
|
||||
/* create portal for page-fault handler */
|
||||
addr_t pd_sel = __core_pd_sel;
|
||||
@ -129,19 +169,46 @@ Pager_object::Pager_object(unsigned long badge)
|
||||
throw Create_startup_pt_failed();
|
||||
}
|
||||
|
||||
/* Create portal for recall handler */
|
||||
Mtd mtd(Mtd::ESP | Mtd::EIP | Mtd::ACDB | Mtd::EFL | Mtd::EBSD | Mtd::FSGS);
|
||||
res = create_pt(exc_pt_sel() + PT_SEL_RECALL, pd_sel, _tid.ec_sel,
|
||||
mtd, (addr_t)_recall_handler);
|
||||
if (res) {
|
||||
PERR("could not create recall portal, error = %u\n", res);
|
||||
class Create_recall_pt_failed { };
|
||||
throw Create_recall_pt_failed();
|
||||
}
|
||||
|
||||
/* Create portal for final cleanup call used during destruction */
|
||||
res = create_pt(_pt_cleanup, pd_sel, _tid.ec_sel, Mtd(0),
|
||||
reinterpret_cast<addr_t>(_invoke_handler));
|
||||
if (res)
|
||||
PERR("could not create pager cleanup portal, error = %u\n",
|
||||
res);
|
||||
if (res) {
|
||||
PERR("could not create pager cleanup portal, error = %u\n", res);
|
||||
class Create_cleanup_pt_failed { };
|
||||
throw Create_cleanup_pt_failed();
|
||||
}
|
||||
|
||||
res = Nova::create_sm(_sm_state_notify, pd_sel, 0);
|
||||
if (res != Nova::NOVA_OK) {
|
||||
class Create_state_notifiy_sm_failed { };
|
||||
throw Create_state_notifiy_sm_failed();
|
||||
}
|
||||
}
|
||||
|
||||
Pager_object::~Pager_object()
|
||||
{
|
||||
/* Revoke portals of Pager_object */
|
||||
revoke(Obj_crd(exc_pt_sel() + PT_SEL_STARTUP, 0), true);
|
||||
revoke(Obj_crd(exc_pt_sel() + PT_SEL_RECALL, 0), true);
|
||||
revoke(Obj_crd(exc_pt_sel() + PT_SEL_PAGE_FAULT, 0), true);
|
||||
|
||||
/* Revoke semaphore cap to signal valid state after recall */
|
||||
addr_t sm_cap = _sm_state_notify;
|
||||
_sm_state_notify = Native_thread::INVALID_INDEX;
|
||||
/* If pager is blocked wake him up */
|
||||
sm_ctrl(sm_cap, SEMAPHORE_UP);
|
||||
revoke(Obj_crd(sm_cap, 0), true);
|
||||
|
||||
/* Make sure nobody is in the handler anymore by doing an IPC to a
|
||||
* local cap pointing to same serving thread (if not running in the
|
||||
* context of the serving thread). When the call returns
|
||||
@ -158,7 +225,7 @@ Pager_object::~Pager_object()
|
||||
/* Revoke portal used for the cleanup call */
|
||||
revoke(Obj_crd(_pt_cleanup, 0), true);
|
||||
cap_selector_allocator()->free(_pt_cleanup, 0);
|
||||
|
||||
cap_selector_allocator()->free(sm_cap, 0);
|
||||
}
|
||||
|
||||
|
||||
|
34
base-nova/src/base/pager/x86_32/pager.cc
Normal file
34
base-nova/src/base/pager/x86_32/pager.cc
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* \brief Copy thread state - x86_32
|
||||
* \author Alexander Boettcher
|
||||
* \date 2012-08-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/pager.h>
|
||||
|
||||
/* NOVA includes */
|
||||
#include <nova/syscalls.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
void Pager_object::_copy_state(Nova::Utcb * utcb)
|
||||
{
|
||||
_state.thread.ebp = utcb->bp;
|
||||
_state.thread.eax = utcb->ax;
|
||||
_state.thread.ebx = utcb->bx;
|
||||
_state.thread.ecx = utcb->cx;
|
||||
_state.thread.edx = utcb->dx;
|
||||
_state.thread.esi = utcb->si;
|
||||
_state.thread.edi = utcb->di;
|
||||
|
||||
_state.thread.gs = utcb->gs.sel;
|
||||
_state.thread.fs = utcb->fs.sel;
|
||||
}
|
42
base-nova/src/base/pager/x86_64/pager.cc
Normal file
42
base-nova/src/base/pager/x86_64/pager.cc
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* \brief Copy thread state - x86_64
|
||||
* \author Alexander Boettcher
|
||||
* \date 2012-08-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/pager.h>
|
||||
|
||||
/* NOVA includes */
|
||||
#include <nova/syscalls.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
void Pager_object::_copy_state(Nova::Utcb * utcb)
|
||||
{
|
||||
_state.thread.rbp = utcb->bp;
|
||||
_state.thread.rax = utcb->ax;
|
||||
_state.thread.rbx = utcb->bx;
|
||||
_state.thread.rcx = utcb->cx;
|
||||
_state.thread.rdx = utcb->dx;
|
||||
_state.thread.rsi = utcb->si;
|
||||
_state.thread.rdi = utcb->di;
|
||||
|
||||
_state.thread.r8 = utcb->r8;
|
||||
_state.thread.r9 = utcb->r9;
|
||||
_state.thread.r10 = utcb->r10;
|
||||
_state.thread.r11 = utcb->r11;
|
||||
_state.thread.r12 = utcb->r12;
|
||||
_state.thread.r13 = utcb->r13;
|
||||
_state.thread.r14 = utcb->r14;
|
||||
_state.thread.r15 = utcb->r15;
|
||||
|
||||
_state.thread.ss = utcb->ss.sel;
|
||||
}
|
@ -224,6 +224,8 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size,
|
||||
Nova::PT_SEL_PAGE_FAULT);
|
||||
request_event_portal(pager_cap, _tid.exc_pt_sel,
|
||||
Nova::SM_SEL_EC);
|
||||
request_event_portal(pager_cap, _tid.exc_pt_sel,
|
||||
Nova::PT_SEL_RECALL);
|
||||
|
||||
/**
|
||||
* Request native thread cap, _thread_cap only a token.
|
||||
|
@ -132,6 +132,7 @@ void Thread_base::start()
|
||||
request_event_portal(pager_cap, _tid.exc_pt_sel, PT_SEL_STARTUP);
|
||||
request_event_portal(pager_cap, _tid.exc_pt_sel, PT_SEL_PAGE_FAULT);
|
||||
request_event_portal(pager_cap, _tid.exc_pt_sel, SM_SEL_EC);
|
||||
request_event_portal(pager_cap, _tid.exc_pt_sel, PT_SEL_RECALL);
|
||||
}
|
||||
|
||||
/* request creation of SC to let thread run*/
|
||||
|
@ -98,11 +98,11 @@ static void page_fault_handler()
|
||||
Utcb *utcb = (Utcb *)CORE_PAGER_UTCB_ADDR;
|
||||
|
||||
addr_t pf_addr = utcb->qual[1];
|
||||
addr_t pf_eip = utcb->eip;
|
||||
addr_t pf_esp = utcb->esp;
|
||||
addr_t pf_ip = utcb->ip;
|
||||
addr_t pf_sp = utcb->sp;
|
||||
|
||||
printf("\nPAGE-FAULT IN CORE: ADDR %lx IP %lx SP %lx stack trace follows...\n",
|
||||
pf_addr, pf_eip, pf_esp);
|
||||
pf_addr, pf_ip, pf_sp);
|
||||
|
||||
/* dump stack trace */
|
||||
struct Core_img
|
||||
@ -127,9 +127,9 @@ static void page_fault_handler()
|
||||
};
|
||||
|
||||
int count = 1;
|
||||
printf(" #%d %08lx %08lx\n", count++, pf_esp, pf_eip);
|
||||
printf(" #%d %08lx %08lx\n", count++, pf_sp, pf_ip);
|
||||
|
||||
Core_img dump(pf_esp);
|
||||
Core_img dump(pf_sp);
|
||||
while (dump.ip_valid()) {
|
||||
printf(" #%d %p %08lx\n", count++, dump.ip(), *dump.ip());
|
||||
dump.next_ip();
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
/* NOVA includes */
|
||||
#include <nova/syscalls.h>
|
||||
#include <nova/util.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
@ -69,11 +70,11 @@ int Platform_thread::start(void *ip, void *sp, addr_t exc_base, bool vcpu)
|
||||
/**
|
||||
* Create semaphore required for Genode locking.
|
||||
* It is created at the root pager exception base +
|
||||
* SM_SEL_EC_MAIN and can be later on requested by the thread
|
||||
* SM_SEL_EC_CLIENT and can be later on requested by the thread
|
||||
* the same way as STARTUP and PAGEFAULT portal.
|
||||
*/
|
||||
uint8_t res = Nova::create_sm(_pager->exc_pt_sel() +
|
||||
SM_SEL_EC_MAIN,
|
||||
SM_SEL_EC_CLIENT,
|
||||
_pd->pd_sel(), 0);
|
||||
if (res != Nova::NOVA_OK) {
|
||||
PERR("creation of semaphore for new thread failed %u",
|
||||
@ -107,20 +108,32 @@ int Platform_thread::start(void *ip, void *sp, addr_t exc_base, bool vcpu)
|
||||
|
||||
addr_t pd_core_sel = Platform_pd::pd_core_sel();
|
||||
addr_t sm_alloc_sel = _sel_exc_base + PD_SEL_CAP_LOCK;
|
||||
addr_t sm_ec_sel = _sel_exc_base + SM_SEL_EC;
|
||||
addr_t sm_ec_sel = _pager->exc_pt_sel() + SM_SEL_EC_CLIENT;
|
||||
|
||||
addr_t remap_src[] = { _pager->exc_pt_sel() + PT_SEL_PAGE_FAULT,
|
||||
_pd->parent_pt_sel(),
|
||||
_pager->exc_pt_sel() + PT_SEL_STARTUP };
|
||||
_pager->exc_pt_sel() + PT_SEL_STARTUP,
|
||||
_pager->exc_pt_sel() + PT_SEL_RECALL,
|
||||
sm_ec_sel };
|
||||
addr_t remap_dst[] = { PT_SEL_PAGE_FAULT,
|
||||
PT_SEL_PARENT,
|
||||
PT_SEL_STARTUP };
|
||||
PT_SEL_STARTUP,
|
||||
PT_SEL_RECALL,
|
||||
SM_SEL_EC };
|
||||
addr_t pd_sel;
|
||||
|
||||
Obj_crd initial_pts(_sel_exc_base, NUM_INITIAL_PT_LOG2);
|
||||
|
||||
uint8_t res;
|
||||
|
||||
/* Create lock for EC used by lock_helper */
|
||||
res = create_sm(sm_ec_sel, pd_core_sel, 0);
|
||||
if (res != NOVA_OK) {
|
||||
PERR("could not create semaphore for new thread");
|
||||
goto cleanup_base;
|
||||
}
|
||||
|
||||
/* Remap portals to exception base window of first thread */
|
||||
for (unsigned i = 0; i < sizeof(remap_dst)/sizeof(remap_dst[0]); i++) {
|
||||
/* locally map portals to initial portal window */
|
||||
if (map_local((Utcb *)Thread_base::myself()->utcb(),
|
||||
@ -139,13 +152,6 @@ int Platform_thread::start(void *ip, void *sp, addr_t exc_base, bool vcpu)
|
||||
goto cleanup_base;
|
||||
}
|
||||
|
||||
/* Create lock for EC used by lock_helper */
|
||||
res = create_sm(sm_ec_sel, pd_core_sel, 0);
|
||||
if (res != NOVA_OK) {
|
||||
PERR("could not create semaphore for new thread");
|
||||
goto cleanup_base;
|
||||
}
|
||||
|
||||
pd_sel = cap_selector_allocator()->alloc();
|
||||
|
||||
/* create task */
|
||||
@ -192,6 +198,7 @@ int Platform_thread::start(void *ip, void *sp, addr_t exc_base, bool vcpu)
|
||||
cap_selector_allocator()->free(pd_sel, 0);
|
||||
|
||||
cleanup_base:
|
||||
revoke(Obj_crd(sm_ec_sel, 0));
|
||||
revoke(Obj_crd(_sel_exc_base, NUM_INITIAL_PT_LOG2));
|
||||
cap_selector_allocator()->free(_sel_exc_base, NUM_INITIAL_PT_LOG2);
|
||||
_sel_exc_base = ~0UL;
|
||||
@ -202,28 +209,51 @@ int Platform_thread::start(void *ip, void *sp, addr_t exc_base, bool vcpu)
|
||||
|
||||
Native_capability Platform_thread::pause()
|
||||
{
|
||||
PDBG("not implemented");
|
||||
return Native_capability::invalid_cap();
|
||||
if (!_pager)
|
||||
return Native_capability::invalid_cap();
|
||||
|
||||
Native_capability notify_sm = _pager->notify_sm();
|
||||
if (!notify_sm.valid()) return notify_sm;
|
||||
|
||||
if (Nova::ec_ctrl(_sel_ec()) != Nova::NOVA_OK)
|
||||
return Native_capability::invalid_cap();
|
||||
|
||||
/* If the thread is blocked in the its own SM, get him out */
|
||||
cancel_blocking();
|
||||
|
||||
return notify_sm;
|
||||
}
|
||||
|
||||
|
||||
void Platform_thread::resume()
|
||||
{
|
||||
uint8_t res = Nova::create_sc(_sel_sc(), _pd->pd_sel(), _sel_ec(),
|
||||
Nova::Qpd());
|
||||
if (res)
|
||||
PDBG("create_sc returned %u", res);
|
||||
using namespace Nova;
|
||||
|
||||
uint8_t res = create_sc(_sel_sc(), _pd->pd_sel(), _sel_ec(), Qpd());
|
||||
if (res == NOVA_OK) return;
|
||||
|
||||
if (!_pager) return;
|
||||
/* Thread was paused beforehand and blocked in pager - wake up pager */
|
||||
_pager->wake_up();
|
||||
}
|
||||
|
||||
|
||||
int Platform_thread::state(Thread_state *state_dst)
|
||||
{
|
||||
PWRN("not implemented");
|
||||
return -1;
|
||||
if (!state_dst || !_pager) return -1;
|
||||
|
||||
int res = _pager->copy_thread_state(state_dst);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void Platform_thread::cancel_blocking() { PWRN("not implemented"); }
|
||||
void Platform_thread::cancel_blocking()
|
||||
{
|
||||
if (!_pager) return;
|
||||
|
||||
_pager->cancel_blocking_client();
|
||||
}
|
||||
|
||||
|
||||
unsigned long Platform_thread::pager_object_badge() const { return ~0UL; }
|
||||
|
Loading…
Reference in New Issue
Block a user