mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 16:35:28 +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 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
|
||||||
*
|
*
|
||||||
|
@ -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; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
void * const sp,
|
||||||
|
unsigned const cpu_id,
|
||||||
unsigned const pd_id,
|
unsigned const pd_id,
|
||||||
Native_utcb * const phys_utcb,
|
Native_utcb * const utcb_phys,
|
||||||
Native_utcb * const virt_utcb)
|
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
*
|
*
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user