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 cidr; /* context ID register backup */
uint32_t section_table; /* base address of applied section table */ 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' * Copy CPU state data to 'c'
*/ */
@ -524,6 +514,21 @@ namespace Arm
lr = s->lr; lr = s->lr;
ip = s->ip; 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_6() const { return r6; }
unsigned user_arg_7() const { return r7; } 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 * Check if a pagefault has occured due to a translation miss
* *

View File

@ -178,7 +178,7 @@ namespace Genode {
Thread_base * thread_base() Thread_base * thread_base()
{ {
if (!_thread_base) assert(_main_thread); if (!_thread_base) assert(main_thread());
return _thread_base; return _thread_base;
} }
@ -188,6 +188,8 @@ namespace Genode {
Ram_dataspace_capability utcb() const { return _utcb; } Ram_dataspace_capability utcb() const { return _utcb; }
bool main_thread() const { return _main_thread; }
Tlb * tlb() const { return _tlb; } Tlb * tlb() const { return _tlb; }
}; };
} }

View File

@ -766,7 +766,15 @@ namespace Kernel
/* initialize idle thread */ /* initialize idle thread */
void * sp; void * sp;
sp = (void *)&idle_stack[sizeof(idle_stack)/sizeof(idle_stack[0])]; 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; initial = 0;
} }
/* create scheduler with a permanent idle thread */ /* create scheduler with a permanent idle thread */
@ -929,8 +937,7 @@ namespace Kernel
assert(t); assert(t);
/* start thread */ /* start thread */
assert(!t->start(ip, sp, cpu, pt->pd_id(), t->start(ip, sp, cpu, pt->pd_id(), pt->phys_utcb(), pt->virt_utcb());
pt->phys_utcb(), pt->virt_utcb()))
/* return software TLB that the thread is assigned to */ /* return software TLB that the thread is assigned to */
Pd::Pool * const pp = Pd::pool(); Pd::Pool * const pp = Pd::pool();
@ -1529,42 +1536,49 @@ int Kernel::Thread::resume()
} }
int Thread::start(void *ip, void *sp, unsigned cpu_no, void Thread::prepare_to_start(void * const ip,
unsigned const pd_id, void * const sp,
Native_utcb * const phys_utcb, unsigned const cpu_id,
Native_utcb * const virt_utcb) unsigned const pd_id,
Native_utcb * const utcb_phys,
Native_utcb * const utcb_virt)
{ {
/* check state and arguments */ /* check state and arguments */
assert(_state == AWAIT_START) assert(_state == AWAIT_START)
assert(!cpu_no); assert(!cpu_id);
/* apply thread configuration */ /* store thread parameters */
init_context(ip, sp, pd_id); _phys_utcb = utcb_phys;
_phys_utcb = phys_utcb; _virt_utcb = utcb_virt;
_virt_utcb = virt_utcb; _pd_id = pd_id;
/* offer thread-entry arguments */ /* join a protection domain */
user_arg_0((unsigned)_virt_utcb); Pd * const pd = Pd::pool()->object(_pd_id);
assert(pd)
addr_t const tlb = pd->tlb()->base();
/* start thread */ /* initialize CPU context */
_schedule(); if (!_platform_thread)
return 0; /* 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, void Thread::start(void * const ip,
unsigned const pd_id) void * const sp,
unsigned const cpu_id,
unsigned const pd_id,
Native_utcb * const utcb_phys,
Native_utcb * const utcb_virt)
{ {
/* basic thread state */ prepare_to_start(ip, sp, cpu_id, pd_id, utcb_phys, utcb_virt);
sp = (addr_t)stack_p; _schedule();
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());
} }

View File

@ -847,19 +847,39 @@ namespace Kernel
_phys_utcb(0), _virt_utcb(0), _signal_receiver(0) _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 * Start this thread
* *
* \param ip instruction pointer to start at * \param ip initial instruction pointer
* \param sp stack pointer to use * \param sp initial stack pointer
* \param cpu_no target cpu * \param cpu_id target cpu
* * \param pd_id target protection-domain
* \retval 0 successful * \param utcb_phys physical UTCB pointer
* \retval -1 thread could not be started * \param utcb_virt virtual UTCB pointer
*/ */
int start(void *ip, void *sp, unsigned cpu_no, void start(void * const ip,
unsigned const pd_id, Native_utcb * const phys_utcb, void * const sp,
Native_utcb * const virt_utcb); unsigned const cpu_id,
unsigned const pd_id,
Native_utcb * const utcb_phys,
Native_utcb * const utcb_virt);
/** /**
* Pause this thread * Pause this thread
@ -891,16 +911,6 @@ namespace Kernel
*/ */
void reply(size_t const size, bool const await_request); 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 * 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 * virtual context area by itself, as it is done for other threads
* through a sub RM-session. * 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: _start:
/* fetch thread-entry arguments to their destinations in BSS */ /* fetch thread-entry arguments to their destinations in BSS */
ldr r1, =_main_utcb ldr r0, =_main_utcb
str r0, [r1] str sp, [r0]
/* call _main routine */ /* call _main routine */
ldr sp, =_stack_high ldr sp, =_stack_high