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 
This commit is contained in:
Martin Stein 2013-06-06 14:18:36 +02:00 committed by Norman Feske
parent 5a3e340699
commit e20b773bef
6 changed files with 149 additions and 62 deletions
base-hw/src

@ -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