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

View File

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

View File

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

View File

@ -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();
}

View File

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

View File

@ -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();
}

View File

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