From: Antti Kantee Date: Tue, 20 Jan 2015 14:56:05 +0000 (+0100) Subject: Add TLS support for x86_64 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=383479d70fcffa06d9c5c2565e6cef785809e8c7;p=rumpuser-xen.git Add TLS support for x86_64 issue #19, with help from @mato --- diff --git a/xen/arch/x86/minios-x86_32.lds b/xen/arch/x86/minios-x86_32.lds index f5cabb6..a9f4c9e 100644 --- a/xen/arch/x86/minios-x86_32.lds +++ b/xen/arch/x86/minios-x86_32.lds @@ -49,6 +49,18 @@ SECTIONS _edata = .; /* End of data section */ + .tdata : { + _tdata_start = . ; + *(.tdata) + _tdata_end = . ; + } + + .tbss : { + _tbss_start = . ; + *(.tbss) + _tbss_end = . ; + } + __bss_start = .; /* BSS */ .bss : { *(.bss) diff --git a/xen/arch/x86/minios-x86_64.lds b/xen/arch/x86/minios-x86_64.lds index 3da0a9f..510f34c 100644 --- a/xen/arch/x86/minios-x86_64.lds +++ b/xen/arch/x86/minios-x86_64.lds @@ -49,6 +49,18 @@ SECTIONS _edata = .; /* End of data section */ + .tdata : { + _tdata_start = . ; + *(.tdata) + _tdata_end = . ; + } + + .tbss : { + _tbss_start = . ; + *(.tbss) + _tbss_end = . ; + } + __bss_start = .; /* BSS */ .bss : { *(.bss) diff --git a/xen/arch/x86/sched.c b/xen/arch/x86/sched.c index 4e6ae4e..4fc48d3 100644 --- a/xen/arch/x86/sched.c +++ b/xen/arch/x86/sched.c @@ -128,3 +128,16 @@ void run_idle_thread(void) :"m" (idle_thread->thr_ip)); #endif } + +void arch__switch(unsigned long *, unsigned long *); +void +arch_switch_threads(struct thread *prev, struct thread *next) +{ + +/* XXX: TLS is available only on x86_64 currently */ +#if defined(__x86_64__) + wrmsrl(0xc0000100, next->thr_tp); +#endif + + arch__switch(&prev->thr_sp, &next->thr_sp); +} diff --git a/xen/arch/x86/x86_32.S b/xen/arch/x86/x86_32.S index a5ca322..98df1fb 100644 --- a/xen/arch/x86/x86_32.S +++ b/xen/arch/x86/x86_32.S @@ -289,7 +289,8 @@ ENTRY(thread_starter) call *%ebx call minios_exit_thread -ENTRY(arch_switch_threads) +.globl arch__switch +arch__switch: movl 4(%esp), %ecx /* prev */ movl 8(%esp), %edx /* next */ pushl %ebp diff --git a/xen/arch/x86/x86_64.S b/xen/arch/x86/x86_64.S index 4a57241..c38b93e 100644 --- a/xen/arch/x86/x86_64.S +++ b/xen/arch/x86/x86_64.S @@ -297,7 +297,8 @@ ENTRY(thread_starter) call minios_exit_thread -ENTRY(arch_switch_threads) +.globl arch__switch +arch__switch: pushq %rbp pushq %rbx pushq %r12 diff --git a/xen/include/mini-os/x86/sched.h b/xen/include/mini-os/x86/sched.h index be9b5c4..4c0f613 100644 --- a/xen/include/mini-os/x86/sched.h +++ b/xen/include/mini-os/x86/sched.h @@ -19,12 +19,16 @@ static inline struct thread* get_current(void) struct thread_md { unsigned long thrmd_sp; unsigned long thrmd_ip; + unsigned long thrmd_tp; + unsigned long thrmd_tl; }; #define thr_sp md.thrmd_sp #define thr_ip md.thrmd_ip +#define thr_tp md.thrmd_tp +#define thr_tl md.thrmd_tl -extern void _minios_entry_arch_switch_threads(unsigned long *prevctx, unsigned long *nextctx); +extern void _minios_entry_arch_switch_threads(struct thread *prevctx, struct thread *nextctx); -#define arch_switch_threads(prev,next) _minios_entry_arch_switch_threads(&(prev)->thr_sp, &(next)->thr_sp) +#define arch_switch_threads(prev,next) _minios_entry_arch_switch_threads(prev, next) #endif /* __ARCH_SCHED_H__ */ diff --git a/xen/sched.c b/xen/sched.c index 5293ec2..ce59151 100644 --- a/xen/sched.c +++ b/xen/sched.c @@ -47,6 +47,8 @@ #include +#include /* XXX: for mem{cpy,set}() */ + TAILQ_HEAD(thread_list, thread); struct thread *idle_thread = NULL; @@ -141,6 +143,42 @@ void minios_schedule(void) } } +/* + * Allocate tls and initialize it. + * + * XXX: this needs to change in the future so that + * we put the tcb in the same space instead of having multiple + * random copies flying around. + */ +extern const char _tdata_start[], _tdata_end[]; +extern const char _tbss_start[], _tbss_end[]; +static int +allocothertls(struct thread *thread) +{ + const size_t tdatasize = _tdata_end - _tdata_start; + const size_t tbsssize = _tbss_end - _tbss_start; + uint8_t *tlsmem; + + tlsmem = memalloc(tdatasize + tbsssize, 0); + + memcpy(tlsmem, _tdata_start, tdatasize); + memset(tlsmem + tdatasize, 0, tbsssize); + + thread->thr_tp = (uintptr_t)(tlsmem + tdatasize + tbsssize); + thread->thr_tl = tdatasize + tbsssize; + + return 0; +} + +static void +freeothertls(struct thread *thread) +{ + void *mem; + + mem = (void *)(thread->thr_tp); + memfree(mem); +} + struct thread * minios_create_thread(const char *name, void *cookie, void (*function)(void *), void *data, void *stack) @@ -155,6 +193,7 @@ minios_create_thread(const char *name, void *cookie, thread->lwp = NULL; thread->cookie = cookie; set_runnable(thread); + allocothertls(thread); local_irq_save(flags); TAILQ_INSERT_TAIL(&thread_list, thread, thread_list); local_irq_restore(flags); @@ -201,6 +240,8 @@ void minios_exit_thread(void) TAILQ_INSERT_HEAD(&exited_threads, thread, thread_list); local_irq_restore(flags); + freeothertls(thread); + /* Schedule will free the resources */ while(1) { @@ -312,6 +353,7 @@ struct thread *minios_init_mainlwp(void *cookie) { current->cookie = cookie; + allocothertls(current); return current; }