]> xenbits.xensource.com Git - rumpuser-xen.git/commitdiff
Add TLS support for x86_64
authorAntti Kantee <pooka@iki.fi>
Tue, 20 Jan 2015 14:56:05 +0000 (15:56 +0100)
committerAntti Kantee <pooka@iki.fi>
Tue, 20 Jan 2015 14:58:08 +0000 (14:58 +0000)
issue #19, with help from @mato

xen/arch/x86/minios-x86_32.lds
xen/arch/x86/minios-x86_64.lds
xen/arch/x86/sched.c
xen/arch/x86/x86_32.S
xen/arch/x86/x86_64.S
xen/include/mini-os/x86/sched.h
xen/sched.c

index f5cabb6a11d9278984ebc2e722cdf38a1a8b4558..a9f4c9e9c7d41ca7536cddb3191917fd64de4d9b 100644 (file)
@@ -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)
index 3da0a9f130db75693144a25ee53ad1c9098aaee4..510f34c44515fa1fccc72bf9553b6f3f53295870 100644 (file)
@@ -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)
index 4e6ae4e5303a68b818d52445a1824cd79727ca6a..4fc48d3f6cca6c670218297f0a14352f969eb0f9 100644 (file)
@@ -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);
+}
index a5ca322162f502d40a1ae65cb61d92e2965614d1..98df1fbcced34b267c8e501a5a2596c5ccffc6fa 100644 (file)
@@ -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
index 4a57241aa1f1ac8e8ad4022f67aac5d6aa755131..c38b93e9339b4c99d415d10eef7ae3895eca9dc1 100644 (file)
@@ -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
index be9b5c4e02d453e56b40293f87156d6b4f0c57d9..4c0f61369432d82f100734997f8bacfd1c746c95 100644 (file)
@@ -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__ */
index 5293ec238d1539f4850362a80e4fa71f184231f8..ce59151420ae554985071669f73d669da0418a17 100644 (file)
@@ -47,6 +47,8 @@
 
 #include <sys/queue.h>
 
+#include <string.h> /* 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;
 }