Parlib is no PIC-capable
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 17 Apr 2015 14:46:15 +0000 (10:46 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 17 Apr 2015 14:51:01 +0000 (10:51 -0400)
We needed some minor changes, mostly to uthread, to be able to build
parlib with -fPIC (and as a .so).

Thanks to the lack of TLS-clobbers, anytime we set_tls_desc and then
access TLS variables in the same function, we need to wrap those
accesses with 'begin_safe_access'.  Otherwise, the compiler will cache
the address of TLS variables and not discard and recompute the address
after a TLS change.

The other big change is that leaq needed to do PC-relative addressing.
Otherwise the asm emits a _32S relocation, which fails when we make a
shared library with parlib.  For a nice review of relocations, check
out: http://www.mindfruit.co.uk/2012/06/relocations-relocations.html

user/parlib/include/vcore.h
user/parlib/include/x86/vcore64.h
user/parlib/uthread.c

index daae116..0efaa7f 100644 (file)
@@ -208,12 +208,14 @@ static inline uint64_t vcore_account_uptime_nsec(uint32_t vcoreid)
  * address of TLS variables across loads/stores of the TLS descriptor, in lieu
  * of a "TLS cmb()". */
 #define begin_safe_access_tls_vars()                                           \
+{                                                                              \
        void __attribute__((noinline, optimize("O0")))                             \
        safe_access_tls_var_internal() {                                           \
                asm("");                                                               \
 
 #define end_safe_access_tls_vars()                                             \
        } safe_access_tls_var_internal();                                          \
+}
 
 #else
 
index d746392..6155d8d 100644 (file)
@@ -275,7 +275,7 @@ static inline void save_user_ctx(struct user_context *ctx)
        asm volatile ("fnstcw %0" : "=m"(sw_tf->tf_fpucw));
        /* Pretty simple: save all the regs, IAW the sys-v ABI */
        asm volatile("mov %%rsp, 0x48(%0);   " /* save rsp in its slot*/
-                    "leaq 1f, %%rax;        " /* get future rip */
+                    "leaq 1f(%%rip), %%rax; " /* get future rip */
                     "mov %%rax, 0x40(%0);   " /* save rip in its slot*/
                     "mov %%r15, 0x38(%0);   "
                     "mov %%r14, 0x30(%0);   "
index fcd32bb..135e506 100644 (file)
@@ -62,14 +62,18 @@ static void uthread_manage_thread0(struct uthread *uthread)
         * (right before vcore_entry(), don't try and take the address of any of
         * its TLS vars. */
        set_tls_desc(get_vcpd_tls_desc(0), 0);
+       begin_safe_access_tls_vars();
        /* We might have a basic uthread already installed (from slim_init), so
         * free it before installing the new one. */
        if (current_uthread)
                free(current_uthread);
        current_uthread = uthread;
+       end_safe_access_tls_vars();
        set_tls_desc(uthread->tls_desc, 0);
+       begin_safe_access_tls_vars();
        __vcoreid = 0;  /* setting the uthread's TLS var */
        assert(!in_vcore_context());
+       end_safe_access_tls_vars();
 }
 
 /* The real 2LS calls this, passing in a uthread representing thread0.  When it
@@ -358,8 +362,10 @@ void uthread_yield(bool save_state, void (*yield_func)(struct uthread*, void*),
        /* Change to the transition context (both TLS (if applicable) and stack). */
        if (__uthread_has_tls(uthread)) {
                set_tls_desc(get_vcpd_tls_desc(vcoreid), vcoreid);
+               begin_safe_access_tls_vars();
                assert(current_uthread == uthread);
                assert(in_vcore_context());
+               end_safe_access_tls_vars();
        } else {
                /* Since uthreads and vcores share TLS (it's always the vcore's TLS, the
                 * uthread one just bootstraps from it), we need to change our state at
@@ -475,7 +481,9 @@ void highjack_current_uthread(struct uthread *uthread)
        if (__uthread_has_tls(uthread)) {
                assert(uthread->tls_desc);
                set_tls_desc(uthread->tls_desc, vcoreid);
+               begin_safe_access_tls_vars();
                __vcoreid = vcoreid;    /* setting the uthread's TLS var */
+               end_safe_access_tls_vars();
        }
 }
 
@@ -486,7 +494,9 @@ static void set_uthread_tls(struct uthread *uthread, uint32_t vcoreid)
 {
        if (__uthread_has_tls(uthread)) {
                set_tls_desc(uthread->tls_desc, vcoreid);
+               begin_safe_access_tls_vars();
                __vcoreid = vcoreid;    /* setting the uthread's TLS var */
+               end_safe_access_tls_vars();
        } else {
                __vcore_context = FALSE;
        }