mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
hw & arm: use sp to hand out main UTCB pointer
Also don't hand out UTCB pointers to cores main thread and to threads other than main threads. Ref #766
This commit is contained in:
parent
5a3e340699
commit
e20b773bef
@ -469,16 +469,6 @@ namespace Arm
|
||||
uint32_t cidr; /* context ID register backup */
|
||||
uint32_t section_table; /* base address of applied section table */
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
void tlb(addr_t const st) { section_table = st; }
|
||||
|
||||
addr_t tlb() const { return section_table; }
|
||||
|
||||
void protection_domain(unsigned const id) { cidr = id; }
|
||||
|
||||
/**
|
||||
* Copy CPU state data to 'c'
|
||||
*/
|
||||
@ -524,6 +514,21 @@ namespace Arm
|
||||
lr = s->lr;
|
||||
ip = s->ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get base of assigned translation lookaside buffer
|
||||
*/
|
||||
addr_t tlb() const { return section_table; }
|
||||
|
||||
/**
|
||||
* Assign translation lookaside buffer
|
||||
*/
|
||||
void tlb(addr_t const st) { section_table = st; }
|
||||
|
||||
/**
|
||||
* Assign protection domain
|
||||
*/
|
||||
void protection_domain(unsigned const id) { cidr = id; }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -557,6 +562,62 @@ namespace Arm
|
||||
unsigned user_arg_6() const { return r6; }
|
||||
unsigned user_arg_7() const { return r7; }
|
||||
|
||||
/**
|
||||
* Part of context init that is common for all types of threads
|
||||
*/
|
||||
void init_thread_common(void * const instr_p,
|
||||
addr_t const tlb,
|
||||
unsigned const pd_id)
|
||||
{
|
||||
ip = (addr_t)instr_p;
|
||||
cidr = pd_id;
|
||||
section_table = tlb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init context of the first thread of core
|
||||
*/
|
||||
void init_core_main_thread(void * const instr_p,
|
||||
void * const stack_p,
|
||||
addr_t const tlb,
|
||||
unsigned const pd_id)
|
||||
{
|
||||
sp = (addr_t)stack_p;
|
||||
init_thread_common(instr_p, tlb, pd_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init context of a thread that isn't first thread of a program
|
||||
*/
|
||||
void init_thread(void * const instr_p,
|
||||
void * const stack_p,
|
||||
addr_t const tlb,
|
||||
unsigned const pd_id)
|
||||
{
|
||||
sp = (addr_t)stack_p;
|
||||
init_thread_common(instr_p, tlb, pd_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init context of the first thread of a program other than core
|
||||
*/
|
||||
void init_main_thread(void * const instr_p,
|
||||
void * const utcb_virt,
|
||||
addr_t const tlb,
|
||||
unsigned const pd_id)
|
||||
{
|
||||
/*
|
||||
* Normally threads receive their UTCB pointer through their
|
||||
* 'Thread_base' but the first thread of a program doesn't
|
||||
* have such object. Thus the kernel hands out the UTCB pointer
|
||||
* through the main threads initial CPU context. 'crt0.s' then
|
||||
* can save the received pointer to local mem before polluting
|
||||
* the CPU context.
|
||||
*/
|
||||
sp = (addr_t)utcb_virt;
|
||||
init_thread_common(instr_p, tlb, pd_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a pagefault has occured due to a translation miss
|
||||
*
|
||||
|
@ -178,7 +178,7 @@ namespace Genode {
|
||||
|
||||
Thread_base * thread_base()
|
||||
{
|
||||
if (!_thread_base) assert(_main_thread);
|
||||
if (!_thread_base) assert(main_thread());
|
||||
return _thread_base;
|
||||
}
|
||||
|
||||
@ -188,6 +188,8 @@ namespace Genode {
|
||||
|
||||
Ram_dataspace_capability utcb() const { return _utcb; }
|
||||
|
||||
bool main_thread() const { return _main_thread; }
|
||||
|
||||
Tlb * tlb() const { return _tlb; }
|
||||
};
|
||||
}
|
||||
|
@ -766,7 +766,15 @@ namespace Kernel
|
||||
/* initialize idle thread */
|
||||
void * sp;
|
||||
sp = (void *)&idle_stack[sizeof(idle_stack)/sizeof(idle_stack[0])];
|
||||
idle.init_context((void *)&idle_main, sp, core_id());
|
||||
|
||||
/*
|
||||
* Idle doesn't use its UTCB pointer, thus
|
||||
* utcb_phys = utcb_virt = 0 is save.
|
||||
* Base-hw doesn't support multiple cores, thus
|
||||
* cpu_no = 0 is ok. We don't use 'start' to avoid
|
||||
* recursive call of'cpu_scheduler'.
|
||||
*/
|
||||
idle.prepare_to_start((void *)&idle_main, sp, 0, core_id(), 0, 0);
|
||||
initial = 0;
|
||||
}
|
||||
/* create scheduler with a permanent idle thread */
|
||||
@ -929,8 +937,7 @@ namespace Kernel
|
||||
assert(t);
|
||||
|
||||
/* start thread */
|
||||
assert(!t->start(ip, sp, cpu, pt->pd_id(),
|
||||
pt->phys_utcb(), pt->virt_utcb()))
|
||||
t->start(ip, sp, cpu, pt->pd_id(), pt->phys_utcb(), pt->virt_utcb());
|
||||
|
||||
/* return software TLB that the thread is assigned to */
|
||||
Pd::Pool * const pp = Pd::pool();
|
||||
@ -1529,42 +1536,49 @@ int Kernel::Thread::resume()
|
||||
}
|
||||
|
||||
|
||||
int Thread::start(void *ip, void *sp, unsigned cpu_no,
|
||||
unsigned const pd_id,
|
||||
Native_utcb * const phys_utcb,
|
||||
Native_utcb * const virt_utcb)
|
||||
void Thread::prepare_to_start(void * const ip,
|
||||
void * const sp,
|
||||
unsigned const cpu_id,
|
||||
unsigned const pd_id,
|
||||
Native_utcb * const utcb_phys,
|
||||
Native_utcb * const utcb_virt)
|
||||
{
|
||||
/* check state and arguments */
|
||||
assert(_state == AWAIT_START)
|
||||
assert(!cpu_no);
|
||||
assert(!cpu_id);
|
||||
|
||||
/* apply thread configuration */
|
||||
init_context(ip, sp, pd_id);
|
||||
_phys_utcb = phys_utcb;
|
||||
_virt_utcb = virt_utcb;
|
||||
/* store thread parameters */
|
||||
_phys_utcb = utcb_phys;
|
||||
_virt_utcb = utcb_virt;
|
||||
_pd_id = pd_id;
|
||||
|
||||
/* offer thread-entry arguments */
|
||||
user_arg_0((unsigned)_virt_utcb);
|
||||
/* join a protection domain */
|
||||
Pd * const pd = Pd::pool()->object(_pd_id);
|
||||
assert(pd)
|
||||
addr_t const tlb = pd->tlb()->base();
|
||||
|
||||
/* start thread */
|
||||
_schedule();
|
||||
return 0;
|
||||
/* initialize CPU context */
|
||||
if (!_platform_thread)
|
||||
/* this is the main thread of core */
|
||||
User_context::init_core_main_thread(ip, sp, tlb, pd_id);
|
||||
else if (!_platform_thread->main_thread())
|
||||
/* this is not a main thread */
|
||||
User_context::init_thread(ip, sp, tlb, pd_id);
|
||||
else
|
||||
/* this is the main thread of a program other than core */
|
||||
User_context::init_main_thread(ip, _virt_utcb, tlb, pd_id);
|
||||
}
|
||||
|
||||
|
||||
void Thread::init_context(void * const instr_p, void * const stack_p,
|
||||
unsigned const pd_id)
|
||||
void Thread::start(void * const ip,
|
||||
void * const sp,
|
||||
unsigned const cpu_id,
|
||||
unsigned const pd_id,
|
||||
Native_utcb * const utcb_phys,
|
||||
Native_utcb * const utcb_virt)
|
||||
{
|
||||
/* basic thread state */
|
||||
sp = (addr_t)stack_p;
|
||||
ip = (addr_t)instr_p;
|
||||
|
||||
/* join a pd */
|
||||
_pd_id = pd_id;
|
||||
Pd * const pd = Pd::pool()->object(_pd_id);
|
||||
assert(pd)
|
||||
protection_domain(pd_id);
|
||||
tlb(pd->tlb()->base());
|
||||
prepare_to_start(ip, sp, cpu_id, pd_id, utcb_phys, utcb_virt);
|
||||
_schedule();
|
||||
}
|
||||
|
||||
|
||||
|
@ -847,19 +847,39 @@ namespace Kernel
|
||||
_phys_utcb(0), _virt_utcb(0), _signal_receiver(0)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Prepare thread to get scheduled the first time
|
||||
*
|
||||
* \param ip initial instruction pointer
|
||||
* \param sp initial stack pointer
|
||||
* \param cpu_id target cpu
|
||||
* \param pd_id target protection-domain
|
||||
* \param utcb_phys physical UTCB pointer
|
||||
* \param utcb_virt virtual UTCB pointer
|
||||
*/
|
||||
void prepare_to_start(void * const ip,
|
||||
void * const sp,
|
||||
unsigned const cpu_id,
|
||||
unsigned const pd_id,
|
||||
Native_utcb * const utcb_phys,
|
||||
Native_utcb * const utcb_virt);
|
||||
|
||||
/**
|
||||
* Start this thread
|
||||
*
|
||||
* \param ip instruction pointer to start at
|
||||
* \param sp stack pointer to use
|
||||
* \param cpu_no target cpu
|
||||
*
|
||||
* \retval 0 successful
|
||||
* \retval -1 thread could not be started
|
||||
* \param ip initial instruction pointer
|
||||
* \param sp initial stack pointer
|
||||
* \param cpu_id target cpu
|
||||
* \param pd_id target protection-domain
|
||||
* \param utcb_phys physical UTCB pointer
|
||||
* \param utcb_virt virtual UTCB pointer
|
||||
*/
|
||||
int start(void *ip, void *sp, unsigned cpu_no,
|
||||
unsigned const pd_id, Native_utcb * const phys_utcb,
|
||||
Native_utcb * const virt_utcb);
|
||||
void start(void * const ip,
|
||||
void * const sp,
|
||||
unsigned const cpu_id,
|
||||
unsigned const pd_id,
|
||||
Native_utcb * const utcb_phys,
|
||||
Native_utcb * const utcb_virt);
|
||||
|
||||
/**
|
||||
* Pause this thread
|
||||
@ -891,16 +911,6 @@ namespace Kernel
|
||||
*/
|
||||
void reply(size_t const size, bool const await_request);
|
||||
|
||||
/**
|
||||
* Initialize our execution context
|
||||
*
|
||||
* \param ip instruction pointer
|
||||
* \param sp stack pointer
|
||||
* \param pd_id identifies protection domain we're assigned to
|
||||
*/
|
||||
void init_context(void * const ip, void * const sp,
|
||||
unsigned const pd_id);
|
||||
|
||||
/**
|
||||
* Handle a pagefault that originates from this thread
|
||||
*
|
||||
|
@ -28,7 +28,7 @@ bool Platform_thread::_attaches_utcb_by_itself()
|
||||
* virtual context area by itself, as it is done for other threads
|
||||
* through a sub RM-session.
|
||||
*/
|
||||
return _pd_id == Kernel::core_id() || !_main_thread;
|
||||
return _pd_id == Kernel::core_id() || !main_thread();
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,8 +19,8 @@
|
||||
_start:
|
||||
|
||||
/* fetch thread-entry arguments to their destinations in BSS */
|
||||
ldr r1, =_main_utcb
|
||||
str r0, [r1]
|
||||
ldr r0, =_main_utcb
|
||||
str sp, [r0]
|
||||
|
||||
/* call _main routine */
|
||||
ldr sp, =_stack_high
|
||||
|
Loading…
Reference in New Issue
Block a user