hw: don't communicate main-thread UTCB via SP

When using the initial SP of a main thread for the UTCB
startup-argument, fork_trampoline in libc_noux gets broken.
The function expects the SP to be initialized already in contrast
to the _start function in crt0.s that is called for processes that
are not forked. As the main-thread UTCB is located at the same virtual
address for every PD anyways, we can circumvent this problem by
defining it statically.

ref #964
This commit is contained in:
Martin Stein 2013-11-23 02:30:24 +01:00 committed by Norman Feske
parent 2b8e5d7b19
commit 54610247ad
5 changed files with 36 additions and 27 deletions

View File

@ -277,5 +277,26 @@ class Genode::Native_utcb
void * base() const { return (void *)_data; }
};
namespace Genode
{
enum {
VIRT_ADDR_SPACE_START = 0x1000,
VIRT_ADDR_SPACE_SIZE = 0xfffef000,
};
/**
* Return virtual UTCB location of main threads
*/
inline Native_utcb * main_thread_utcb()
{
enum {
VAS_TOP = VIRT_ADDR_SPACE_START + VIRT_ADDR_SPACE_SIZE,
UTCB = VAS_TOP - sizeof(Native_utcb),
UTCB_ALIGNED = UTCB & ~((1 << MIN_MAPPING_SIZE_LOG2) - 1),
};
return (Native_utcb *)UTCB_ALIGNED;
}
}
#endif /* _BASE__NATIVE_TYPES_H_ */

View File

@ -19,8 +19,6 @@
using namespace Genode;
extern Native_utcb * __initial_sp;
namespace Genode { Rm_session * env_context_area_rm_session(); }
@ -34,7 +32,7 @@ void Thread_base::_init_platform_thread() { }
Native_utcb * Thread_base::utcb()
{
if (this) { return &_context->utcb; }
return __initial_sp;
return main_thread_utcb();
}

View File

@ -41,8 +41,8 @@ namespace Genode {
Phys_allocator _irq_alloc; /* IRQ allocator */
Rom_fs _rom_fs; /* ROM file system */
addr_t _vm_base; /* base of virtual address space */
size_t _vm_size; /* size of virtual address space */
addr_t _vm_start; /* base of virtual address space */
size_t _vm_size; /* size of virtual address space */
/**
* Get one of the consecutively numbered available resource regions
@ -101,7 +101,7 @@ namespace Genode {
inline Range_allocator * irq_alloc() { return &_irq_alloc; }
inline addr_t vm_start() const { return _vm_base; }
inline addr_t vm_start() const { return _vm_start; }
inline size_t vm_size() const { return _vm_size; }

View File

@ -109,10 +109,12 @@ Native_region * Platform::_core_only_ram_regions(unsigned const i)
}
Platform::Platform() :
Platform::Platform()
:
_core_mem_alloc(0),
_io_mem_alloc(core_mem_alloc()), _io_port_alloc(core_mem_alloc()),
_irq_alloc(core_mem_alloc()), _vm_base(0x1000), _vm_size(0xfffef000)
_irq_alloc(core_mem_alloc()),
_vm_start(VIRT_ADDR_SPACE_START), _vm_size(VIRT_ADDR_SPACE_SIZE)
{
/*
* Initialise platform resource allocators.

View File

@ -20,6 +20,8 @@ using namespace Genode;
namespace Kernel { unsigned core_id(); }
void Platform_thread::_init() { }
bool Platform_thread::_attaches_utcb_by_itself()
{
@ -158,23 +160,12 @@ int Platform_thread::join_pd(unsigned const pd_id, bool const main_thread,
}
void Platform_thread::_init()
{
}
int Platform_thread::start(void * const ip, void * const sp,
unsigned int const cpu_id)
{
/* attach UTCB if the thread can't do this by itself */
if (!_attaches_utcb_by_itself())
{
/* declare page aligned virtual UTCB outside the context area */
_utcb_virt = (Native_utcb *)((platform()->vm_start()
+ platform()->vm_size() - sizeof(Native_utcb))
& ~((1<<MIN_MAPPING_SIZE_LOG2)-1));
/* attach UTCB */
/* attach UTCB in case of a main thread */
if (_main_thread) {
_utcb_virt = main_thread_utcb();
if (!_rm_client) {
PERR("invalid RM client");
return -1;
@ -186,16 +177,13 @@ int Platform_thread::start(void * const ip, void * const sp,
return -1;
}
}
/* initialize thread regisers */
/* initialize thread registers */
typedef Kernel::Thread_reg_id Reg_id;
enum { WRITES = 2 };
addr_t * write_regs = (addr_t *)Thread_base::myself()->utcb()->base();
write_regs[0] = Reg_id::IP;
write_regs[1] = Reg_id::SP;
addr_t write_values[] = {
(addr_t)ip,
_main_thread ? (addr_t)_utcb_virt : (addr_t)sp
};
addr_t write_values[] = { (addr_t)ip, (addr_t)sp };
if (Kernel::access_thread_regs(id(), 0, WRITES, 0, write_values)) {
PERR("failed to initialize thread registers");
return -1;