[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Minios-devel] [UNIKRAFT PATCH v3 7/7] plat: switch thread-local storage area on context switch



On x86, the standard way is writing to an MSR to switch the fs register,
which is used as the pointer to the TLS area. However, this is a
privileged instruction, so for the linuxu platform, use a system call
provided by Linux that does exactly that instead.

Signed-off-by: Florian Schmidt <florian.schmidt@xxxxxxxxx>
Reviewed-by: Costin Lupu <costin.lupu@xxxxxxxxx>
---
 arch/x86/x86_64/include/uk/asm/tls.h        |  5 +++
 include/uk/plat/thread.h                    |  8 ++--
 lib/uksched/thread.c                        |  5 ++-
 plat/common/include/sw_ctx.h                |  1 +
 plat/common/include/tls.h                   | 41 ++++++++++++++++++++
 plat/common/include/x86/cpu_defs.h          |  5 +++
 plat/common/include/x86/tls.h               | 39 +++++++++++++++++++
 plat/common/sw_ctx.c                        | 10 ++++-
 plat/linuxu/include/linuxu/syscall-x86_64.h |  1 +
 plat/linuxu/include/linuxu/syscall.h        |  8 ++++
 plat/linuxu/include/tls.h                   | 42 +++++++++++++++++++++
 11 files changed, 158 insertions(+), 7 deletions(-)
 create mode 100644 plat/common/include/tls.h
 create mode 100644 plat/common/include/x86/tls.h
 create mode 100644 plat/linuxu/include/tls.h

diff --git a/arch/x86/x86_64/include/uk/asm/tls.h 
b/arch/x86/x86_64/include/uk/asm/tls.h
index 70bbc1d1..116d8a1d 100644
--- a/arch/x86/x86_64/include/uk/asm/tls.h
+++ b/arch/x86/x86_64/include/uk/asm/tls.h
@@ -66,3 +66,8 @@ static inline void ukarch_tls_area_copy(void *tls_area)
        /* x86_64 ABI requires that fs:%0 contains the address of itself. */
        *((__uptr *)(tls_area + tls_len)) = (__uptr)(tls_area + tls_len);
 }
+
+static inline void *ukarch_tls_pointer(void *tls_area)
+{
+       return tls_area + (_tls_end - _tls_start);
+}
diff --git a/include/uk/plat/thread.h b/include/uk/plat/thread.h
index 69fc5e28..4b349ea7 100644
--- a/include/uk/plat/thread.h
+++ b/include/uk/plat/thread.h
@@ -51,7 +51,8 @@ enum ukplat_ctx_type {
 struct uk_alloc;
 
 typedef void *(*ukplat_ctx_create_func_t)
-               (struct uk_alloc *allocator, unsigned long sp);
+               (struct uk_alloc *allocator, unsigned long sp,
+                unsigned long tlsp);
 typedef void  (*ukplat_ctx_start_func_t)
                (void *ctx);
 typedef void  (*ukplat_ctx_switch_func_t)
@@ -72,12 +73,13 @@ int ukplat_ctx_callbacks_init(struct ukplat_ctx_callbacks 
*ctx_cbs,
 
 static inline
 void *ukplat_thread_ctx_create(struct ukplat_ctx_callbacks *cbs,
-               struct uk_alloc *allocator, unsigned long sp)
+               struct uk_alloc *allocator, unsigned long sp,
+               unsigned long tlsp)
 {
        UK_ASSERT(cbs != NULL);
        UK_ASSERT(allocator != NULL);
 
-       return cbs->create_cb(allocator, sp);
+       return cbs->create_cb(allocator, sp, tlsp);
 }
 
 void ukplat_thread_ctx_destroy(struct uk_alloc *allocator, void *ctx);
diff --git a/lib/uksched/thread.c b/lib/uksched/thread.c
index 7d7ee016..64b6a2fd 100644
--- a/lib/uksched/thread.c
+++ b/lib/uksched/thread.c
@@ -39,7 +39,7 @@
 #include <uk/wait.h>
 #include <uk/print.h>
 #include <uk/assert.h>
-
+#include <uk/arch/tls.h>
 
 /* Pushes the specified value onto the stack of the specified thread */
 static void stack_push(unsigned long *sp, unsigned long value)
@@ -103,7 +103,8 @@ int uk_thread_init(struct uk_thread *thread,
        init_sp(&sp, stack, function, arg);
 
        /* Call platform specific setup. */
-       thread->ctx = ukplat_thread_ctx_create(cbs, allocator, sp);
+       thread->ctx = ukplat_thread_ctx_create(cbs, allocator, sp,
+                       (uintptr_t)ukarch_tls_pointer(tls));
        if (thread->ctx == NULL)
                return -1;
 
diff --git a/plat/common/include/sw_ctx.h b/plat/common/include/sw_ctx.h
index d52fe65b..366c6a8f 100644
--- a/plat/common/include/sw_ctx.h
+++ b/plat/common/include/sw_ctx.h
@@ -41,6 +41,7 @@
 struct sw_ctx {
        unsigned long sp;       /* Stack pointer */
        unsigned long ip;       /* Instruction pointer */
+       unsigned long tlsp;     /* thread-local storage pointer */
        uintptr_t extregs;      /* Pointer to an area to which extended
                                 * registers are saved on context switch.
                                 */
diff --git a/plat/common/include/tls.h b/plat/common/include/tls.h
new file mode 100644
index 00000000..b9176f95
--- /dev/null
+++ b/plat/common/include/tls.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2019, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+#ifndef __PLAT_CMN_TLS_H__
+#define __PLAT_CMN_TLS_H__
+
+#if defined(__X86_64__)
+#include <x86/tls.h>
+#else
+#error "For thread-local storage support, add tls.h for current architecture."
+#endif
+
+#endif /* __PLAT_CMN_TLS_H__ */
diff --git a/plat/common/include/x86/cpu_defs.h 
b/plat/common/include/x86/cpu_defs.h
index e968a832..48baf558 100644
--- a/plat/common/include/x86/cpu_defs.h
+++ b/plat/common/include/x86/cpu_defs.h
@@ -95,4 +95,9 @@
 #define X86_XCR0_SSE            (1 << 1)
 #define X86_XCR0_AVX            (1 << 2)
 
+/*
+ * Model-specific register addresses
+ */
+#define X86_MSR_FS_BASE         0xc0000100
+
 #endif /* __PLAT_CMN_X86_CPU_DEFS_H__ */
diff --git a/plat/common/include/x86/tls.h b/plat/common/include/x86/tls.h
new file mode 100644
index 00000000..5811bcd7
--- /dev/null
+++ b/plat/common/include/x86/tls.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2019, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+#ifndef __PLAT_CMN_X86_TLS_H__
+#define __PLAT_CMN_X86_TLS_H__
+
+#include <x86/cpu_defs.h>
+
+#define set_tls_pointer(ptr) wrmsrl(X86_MSR_FS_BASE, ptr)
+
+#endif /* __PLAT_CMN_X86_TLS_H__ */
diff --git a/plat/common/sw_ctx.c b/plat/common/sw_ctx.c
index 06795244..88a377f1 100644
--- a/plat/common/sw_ctx.c
+++ b/plat/common/sw_ctx.c
@@ -39,9 +39,11 @@
 #include <uk/alloc.h>
 #include <sw_ctx.h>
 #include <uk/assert.h>
+#include <tls.h>
 #include <x86/cpu.h>
 
-static void *sw_ctx_create(struct uk_alloc *allocator, unsigned long sp);
+static void *sw_ctx_create(struct uk_alloc *allocator, unsigned long sp,
+                               unsigned long tlsp);
 static void  sw_ctx_start(void *ctx) __noreturn;
 static void  sw_ctx_switch(void *prevctx, void *nextctx);
 
@@ -51,7 +53,8 @@ static void  sw_ctx_switch(void *prevctx, void *nextctx);
  */
 extern void asm_thread_starter(void);
 
-static void *sw_ctx_create(struct uk_alloc *allocator, unsigned long sp)
+static void *sw_ctx_create(struct uk_alloc *allocator, unsigned long sp,
+                               unsigned long tlsp)
 {
        struct sw_ctx *ctx;
        size_t sz;
@@ -68,6 +71,7 @@ static void *sw_ctx_create(struct uk_alloc *allocator, 
unsigned long sp)
        }
 
        ctx->sp = sp;
+       ctx->tlsp = tlsp;
        ctx->ip = (unsigned long) asm_thread_starter;
        ctx->extregs = ALIGN_UP(((uintptr_t)ctx + sizeof(struct sw_ctx)),
                                x86_cpu_features.extregs_align);
@@ -86,6 +90,7 @@ static void sw_ctx_start(void *ctx)
 
        UK_ASSERT(sw_ctx != NULL);
 
+       set_tls_pointer(sw_ctx->tlsp);
        /* Switch stacks and run the thread */
        asm_ctx_start(sw_ctx->sp, sw_ctx->ip);
 
@@ -101,6 +106,7 @@ static void sw_ctx_switch(void *prevctx, void *nextctx)
 
        save_extregs(p);
        restore_extregs(n);
+       set_tls_pointer(n->tlsp);
        asm_sw_ctx_switch(prevctx, nextctx);
 }
 
diff --git a/plat/linuxu/include/linuxu/syscall-x86_64.h 
b/plat/linuxu/include/linuxu/syscall-x86_64.h
index 26820dcd..553f0ba4 100644
--- a/plat/linuxu/include/linuxu/syscall-x86_64.h
+++ b/plat/linuxu/include/linuxu/syscall-x86_64.h
@@ -48,6 +48,7 @@
 #define __SC_RT_SIGPROCMASK 14
 #define __SC_IOCTL  16
 #define __SC_EXIT   60
+#define __SC_ARCH_PRCTL       158
 #define __SC_TIMER_CREATE     222
 #define __SC_TIMER_SETTIME    223
 #define __SC_TIMER_GETTIME    224
diff --git a/plat/linuxu/include/linuxu/syscall.h 
b/plat/linuxu/include/linuxu/syscall.h
index d378d265..0dca7c5c 100644
--- a/plat/linuxu/include/linuxu/syscall.h
+++ b/plat/linuxu/include/linuxu/syscall.h
@@ -123,6 +123,14 @@ static inline int sys_sigprocmask(int how,
                              sizeof(k_sigset_t));
 }
 
+#define ARCH_SET_FS 0x1002
+static inline int sys_arch_prctl(int code, unsigned long addr)
+{
+       return (int) syscall2(__SC_ARCH_PRCTL,
+                             (long) code,
+                             (long) addr);
+}
+
 static inline int sys_pselect6(int nfds,
                k_fd_set *readfds, k_fd_set *writefds, k_fd_set *exceptfds,
                const struct k_timespec *timeout, const void *sigmask)
diff --git a/plat/linuxu/include/tls.h b/plat/linuxu/include/tls.h
new file mode 100644
index 00000000..97474104
--- /dev/null
+++ b/plat/linuxu/include/tls.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2019, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+#ifndef __PLAT_LINUXU_TLS_H__
+#define __PLAT_LINUXU_TLS_H__
+
+#include <linuxu/syscall.h>
+
+static inline void set_tls_pointer(unsigned long arg)
+{
+       sys_arch_prctl(ARCH_SET_FS, arg);
+}
+
+#endif /* __PLAT_LINUXU_TLS_H__ */
-- 
2.21.0


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.