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

[Minios-devel] [UNIKRAFT PATCH 4/4] plat/common: Introduce thread context


  • To: minios-devel@xxxxxxxxxxxxx
  • From: Costin Lupu <costin.lupu@xxxxxxxxx>
  • Date: Mon, 8 Jul 2019 00:09:27 +0300
  • Cc: felipe.huici@xxxxxxxxx, simon.kuenzer@xxxxxxxxx
  • Delivery-date: Sun, 07 Jul 2019 21:09:59 +0000
  • Ironport-phdr: 9a23:I9ZCXx3PV1HoHS/usmDT+DRfVm0co7zxezQtwd8ZseIRIvad9pjvdHbS+e9qxAeQG9mCsbQf26GP7fiocFdDyK7JiGoFfp1IWk1NouQttCtkPvS4D1bmJuXhdS0wEZcKflZk+3amLRodQ56mNBXdrXKo8DEdBAj0OxZrKeTpAI7SiNm82/yv95HJbAhEmSSxbal8IRi1ogndq8gbjZd/Iast1xXFpWdFdf5Lzm1yP1KTmBj85sa0/JF99ilbpuws+c1dX6jkZqo0VbNXAigoPGAz/83rqALMTRCT6XsGU2UZiQRHDg7Y5xznRJjxsy/6tu1g2CmGOMD9UL45VSi+46ptVRTljjoMOTwk/2HNksF+jLxVrg+vqRJ8xIDbYo+VOeFicq/BZ94WWXBMUtpNWyFHH4iyb5EPD+0EPetAsYT9oEAOrQe/BQmqGejhzCJIhmfr3aYn1OkuDQbG3Bc8H9IPtnTYttH1NLoKUeCo16TH0S7DY+lO2Tfg84fEaAohofaVUL92bMHfylEvGhvYgliftIDpJTCY2+QXv2SF8eZtV/ijhmA/pw1srTWj290gh4rJi44P1FzJ+yt0zJwoKdC3VkJ2Z8OvHoFKuCGALYR2R9svQ2RvuCkn1LILoYW7fC0WyJQ/wB7fduCHf5CI4h39UOaRJi91hGxgeL2lhhay9VKsxfHnVsWuyFZKszFKnsPWtnAKzxDT686HReVh/kq5xDqC2B3f5vtHLE00j6bXNYAtz7wqmpcdqUjDGzX5mETyjK+YbEUk/e2o5vz7bbXhvZ+cK450igfkPqQqh8y/Gfk4PxMSUGiA4+i8zKDj8lbjTLVQif06irPZv4zCJcQHuq65BBdY0oMi6xa5Djem188YkWAaI11bZhKIkYzpNkrKIPD5Fve/n0+snC1kxv/YOL3tGJLNLmLMkL35Z7Zy91ZcyBYvzdBY/59UBK8OIPbyWk/pqtPUFB85MxG1w+n7CdVwzYUeVnyTDa+dKqzdqkWE6fwyI+OUfo8apC79K+Q55/7plXI5gl4dfayu3ZsRcny4HelmLFufYXvtnNgBC3wHvgwgQ+P2jF2NSyVca2ysUKIhtXkHD9ejDIHCQZvojLGf0SOTGpxNensAGl2KV3DyeNaqQfAJPQmVOdNglHQgSKC8A9sq0gqytQm8z6d/M8Lf4WsAqJilzt8jtL6brg076TEhV5fV6GqKVWwhxm4=
  • Ironport-sdr: FcuvEIlFerJFv6z2GgVhCjSFvbiXFuWDKzwm2mh329tx8KeI0fEak/rJiprnPLP9vBHr3rbIY3 8lpe0AlOSJLQ==
  • List-id: Mini-os development list <minios-devel.lists.xenproject.org>

Commits 143f93e7 and 11ac352a introduced extended registers and TLS support,
respectively, breaking the software context abstraction because both concepts
may and should be used with other types of contexts as well.

The software context was defined as an abstraction needed only for cooperative
scheduling and holding the information specific to this kind of scheduling. The
upcoming preemptive scheduling patches will introduce two new types of contexts,
hardware and paravirtualization contexts, both of which should also be used
together with extended registers and TLS.

Therefore, we introduced the thread context abstraction which will keep the
information common to all types of contexts. For now it will contain the
extended registers area address and the TLS address, besides the address of the
context specialization (software, hardware or paravirtualization).

This patch doesn't completely fix the problem. The thread context still uses
references to x86 specific information which should be fixed when introducing
support for ARM.

Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx>
---
 include/uk/plat/thread.h        | 56 ++++++++++------------------
 lib/uksched/include/uk/thread.h |  2 +-
 plat/common/include/sw_ctx.h    |  4 --
 plat/common/include/x86/cpu.h   | 19 +++++-----
 plat/common/sw_ctx.c            | 49 ++++++-------------------
 plat/common/thread.c            | 81 +++++++++++++++++++++++++++++++++++++++--
 6 files changed, 117 insertions(+), 94 deletions(-)

diff --git a/include/uk/plat/thread.h b/include/uk/plat/thread.h
index 4b349ea7..f2573195 100644
--- a/include/uk/plat/thread.h
+++ b/include/uk/plat/thread.h
@@ -50,17 +50,18 @@ enum ukplat_ctx_type {
 
 struct uk_alloc;
 
-typedef void *(*ukplat_ctx_create_func_t)
-               (struct uk_alloc *allocator, unsigned long sp,
-                unsigned long tlsp);
+typedef void  (*ukplat_ctx_init_func_t)
+               (void *ctx, unsigned long sp);
 typedef void  (*ukplat_ctx_start_func_t)
                (void *ctx);
 typedef void  (*ukplat_ctx_switch_func_t)
                (void *prevctx, void *nextctx);
 
 struct ukplat_ctx_callbacks {
-       /* callback for creating thread context */
-       ukplat_ctx_create_func_t create_cb;
+       /* underlying context size */
+       __sz ctx_size;
+       /* callback for initializing underlying context */
+       ukplat_ctx_init_func_t init_cb;
        /* callback for starting thread context */
        ukplat_ctx_start_func_t start_cb __noreturn;
        /* callback for switching contexts */
@@ -71,42 +72,23 @@ int ukplat_ctx_callbacks_init(struct ukplat_ctx_callbacks 
*ctx_cbs,
                enum ukplat_ctx_type ctx_type);
 
 
-static inline
-void *ukplat_thread_ctx_create(struct ukplat_ctx_callbacks *cbs,
-               struct uk_alloc *allocator, unsigned long sp,
-               unsigned long tlsp)
-{
-       UK_ASSERT(cbs != NULL);
-       UK_ASSERT(allocator != NULL);
-
-       return cbs->create_cb(allocator, sp, tlsp);
-}
-
-void ukplat_thread_ctx_destroy(struct uk_alloc *allocator, void *ctx);
+struct thread_context {
+       void *ctx;          /* Underlying context (sw, hw or pv) */
+       __uptr tlsp;        /* Thread-local storage pointer */
+       __uptr extregs;     /* Extended registers area address */
+};
 
-static inline
-void ukplat_thread_ctx_start(struct ukplat_ctx_callbacks *cbs,
-               void *ctx) __noreturn;
+struct thread_context *
+ukplat_thread_ctx_create(struct ukplat_ctx_callbacks *cbs,
+               struct uk_alloc *allocator, unsigned long sp,
+               unsigned long tlsp);
+void ukplat_thread_ctx_destroy(struct uk_alloc *allocator,
+               struct thread_context *ctx);
 
-static inline
 void ukplat_thread_ctx_start(struct ukplat_ctx_callbacks *cbs,
-               void *ctx)
-{
-       UK_ASSERT(cbs != NULL);
-       UK_ASSERT(ctx != NULL);
+               struct thread_context *ctx) __noreturn;
 
-       cbs->start_cb(ctx);
-}
-
-static inline
 void ukplat_thread_ctx_switch(struct ukplat_ctx_callbacks *cbs,
-               void *prevctx, void *nextctx)
-{
-       UK_ASSERT(cbs != NULL);
-       UK_ASSERT(prevctx != NULL);
-       UK_ASSERT(nextctx != NULL);
-
-       cbs->switch_cb(prevctx, nextctx);
-}
+               struct thread_context *prevctx, struct thread_context *nextctx);
 
 #endif /* __UKPLAT_THREAD_H__ */
diff --git a/lib/uksched/include/uk/thread.h b/lib/uksched/include/uk/thread.h
index d8a4ac88..3f1e6cab 100644
--- a/lib/uksched/include/uk/thread.h
+++ b/lib/uksched/include/uk/thread.h
@@ -51,7 +51,7 @@ struct uk_thread {
        const char *name;
        void *stack;
        void *tls;
-       void *ctx;
+       struct thread_context *ctx;
        UK_TAILQ_ENTRY(struct uk_thread) thread_list;
        uint32_t flags;
        __snsec wakeup_time;
diff --git a/plat/common/include/sw_ctx.h b/plat/common/include/sw_ctx.h
index 366c6a8f..05cae4e2 100644
--- a/plat/common/include/sw_ctx.h
+++ b/plat/common/include/sw_ctx.h
@@ -41,10 +41,6 @@
 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.
-                                */
 };
 
 void sw_ctx_callbacks_init(struct ukplat_ctx_callbacks *ctx_cbs);
diff --git a/plat/common/include/x86/cpu.h b/plat/common/include/x86/cpu.h
index 8acd71e4..8003a871 100644
--- a/plat/common/include/x86/cpu.h
+++ b/plat/common/include/x86/cpu.h
@@ -32,7 +32,6 @@
 
 #include <uk/arch/types.h>
 #include <x86/cpu_defs.h>
-#include <sw_ctx.h>
 #include <stdint.h>
 
 void halt(void);
@@ -56,43 +55,43 @@ struct _x86_features {
 
 extern struct _x86_features x86_cpu_features;
 
-static inline void save_extregs(struct sw_ctx *ctx)
+static inline void save_extregs(__uptr extregs)
 {
        switch (x86_cpu_features.save) {
        case X86_SAVE_NONE:
                /* nothing to do */
                break;
        case X86_SAVE_FSAVE:
-               asm volatile("fsave (%0)" :: "r"(ctx->extregs) : "memory");
+               asm volatile("fsave (%0)" :: "r"(extregs) : "memory");
                break;
        case X86_SAVE_FXSAVE:
-               asm volatile("fxsave (%0)" :: "r"(ctx->extregs) : "memory");
+               asm volatile("fxsave (%0)" :: "r"(extregs) : "memory");
                break;
        case X86_SAVE_XSAVE:
-               asm volatile("xsave (%0)" :: "r"(ctx->extregs),
+               asm volatile("xsave (%0)" :: "r"(extregs),
                                "a"(0xffffffff), "d"(0xffffffff) : "memory");
                break;
        case X86_SAVE_XSAVEOPT:
-               asm volatile("xsaveopt (%0)" :: "r"(ctx->extregs),
+               asm volatile("xsaveopt (%0)" :: "r"(extregs),
                                "a"(0xffffffff), "d"(0xffffffff) : "memory");
                break;
        }
 }
-static inline void restore_extregs(struct sw_ctx *ctx)
+static inline void restore_extregs(__uptr extregs)
 {
        switch (x86_cpu_features.save) {
        case X86_SAVE_NONE:
                /* nothing to do */
                break;
        case X86_SAVE_FSAVE:
-               asm volatile("frstor (%0)" :: "r"(ctx->extregs));
+               asm volatile("frstor (%0)" :: "r"(extregs));
                break;
        case X86_SAVE_FXSAVE:
-               asm volatile("fxrstor (%0)" :: "r"(ctx->extregs));
+               asm volatile("fxrstor (%0)" :: "r"(extregs));
                break;
        case X86_SAVE_XSAVE:
        case X86_SAVE_XSAVEOPT:
-               asm volatile("xrstor (%0)" :: "r"(ctx->extregs),
+               asm volatile("xrstor (%0)" :: "r"(extregs),
                                "a"(0xffffffff), "d"(0xffffffff));
                break;
        }
diff --git a/plat/common/sw_ctx.c b/plat/common/sw_ctx.c
index 88a377f1..99074398 100644
--- a/plat/common/sw_ctx.c
+++ b/plat/common/sw_ctx.c
@@ -37,49 +37,28 @@
 #include <string.h>
 #include <uk/plat/thread.h>
 #include <uk/alloc.h>
-#include <sw_ctx.h>
 #include <uk/assert.h>
-#include <tls.h>
-#include <x86/cpu.h>
+#include <sw_ctx.h>
 
-static void *sw_ctx_create(struct uk_alloc *allocator, unsigned long sp,
-                               unsigned long tlsp);
+static void  sw_ctx_init(void *ctx, unsigned long sp);
 static void  sw_ctx_start(void *ctx) __noreturn;
 static void  sw_ctx_switch(void *prevctx, void *nextctx);
 
 
 /* Gets run when a new thread is scheduled the first time ever,
- * defined in x86_[32/64].S
+ * defined in thread_start.S
  */
 extern void asm_thread_starter(void);
 
-static void *sw_ctx_create(struct uk_alloc *allocator, unsigned long sp,
-                               unsigned long tlsp)
+static void sw_ctx_init(void *ctx, unsigned long sp)
 {
-       struct sw_ctx *ctx;
-       size_t sz;
-
-       UK_ASSERT(allocator != NULL);
+       struct sw_ctx *sw_ctx;
 
-       sz = ALIGN_UP(sizeof(struct sw_ctx), x86_cpu_features.extregs_align)
-               + x86_cpu_features.extregs_size;
-       ctx = uk_malloc(allocator, sz);
-       uk_pr_debug("Allocating %lu bytes for sw ctx at %p\n", sz, ctx);
-       if (ctx == NULL) {
-               uk_pr_warn("Error allocating software context.");
-               return NULL;
-       }
+       UK_ASSERT(ctx != NULL);
 
-       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);
-       // Initialize extregs area: zero out, then save a valid layout to it.
-       memset((void *)ctx->extregs, 0, x86_cpu_features.extregs_size);
-       save_extregs(ctx);
-
-       return ctx;
+       sw_ctx = ctx;
+       sw_ctx->sp = sp;
+       sw_ctx->ip = (unsigned long) asm_thread_starter;
 }
 
 extern void asm_ctx_start(unsigned long sp, unsigned long ip) __noreturn;
@@ -90,7 +69,6 @@ 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,19 +79,14 @@ extern void asm_sw_ctx_switch(void *prevctx, void 
*nextctx);
 
 static void sw_ctx_switch(void *prevctx, void *nextctx)
 {
-       struct sw_ctx *p = prevctx;
-       struct sw_ctx *n = nextctx;
-
-       save_extregs(p);
-       restore_extregs(n);
-       set_tls_pointer(n->tlsp);
        asm_sw_ctx_switch(prevctx, nextctx);
 }
 
 void sw_ctx_callbacks_init(struct ukplat_ctx_callbacks *ctx_cbs)
 {
        UK_ASSERT(ctx_cbs != NULL);
-       ctx_cbs->create_cb = sw_ctx_create;
+       ctx_cbs->ctx_size = sizeof(struct sw_ctx);
+       ctx_cbs->init_cb = sw_ctx_init;
        ctx_cbs->start_cb = sw_ctx_start;
        ctx_cbs->switch_cb = sw_ctx_switch;
 }
diff --git a/plat/common/thread.c b/plat/common/thread.c
index 702338ec..242da09d 100644
--- a/plat/common/thread.c
+++ b/plat/common/thread.c
@@ -33,17 +33,90 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 #include <uk/plat/thread.h>
 #include <uk/alloc.h>
-#include <sw_ctx.h>
 #include <uk/assert.h>
+#include <x86/cpu.h> /* TODO revisit for ARM */
+#include <tls.h>
+#include <sw_ctx.h>
+
 
-void ukplat_thread_ctx_destroy(struct uk_alloc *allocator, void *ctx)
+struct thread_context *ukplat_thread_ctx_create(
+               struct ukplat_ctx_callbacks *cbs,
+               struct uk_alloc *allocator, unsigned long sp,
+               unsigned long tlsp)
 {
+       struct thread_context *thread_ctx;
+       void *ctx, *extregs;
+       __sz sz;
+
+       UK_ASSERT(cbs != NULL);
        UK_ASSERT(allocator != NULL);
-       UK_ASSERT(ctx != NULL);
 
-       uk_free(allocator, ctx);
+       /*
+        * TODO replace the x86_cpu_features reference with a more generic
+        * abstraction which should support other architectures as well.
+        */
+       sz = ALIGN_UP(cbs->ctx_size, x86_cpu_features.extregs_align)
+               + x86_cpu_features.extregs_size
+               + sizeof(struct thread_context);
+
+       ctx = uk_malloc(allocator, sz);
+       if (ctx == NULL) {
+               uk_pr_warn("Error allocating thread context.");
+               return NULL;
+       }
+       uk_pr_debug("Allocated %lu bytes for thread ctx at %p\n", sz, ctx);
+
+       /* Initialize underlying context */
+       cbs->init_cb(ctx, sp);
+
+       /* Initialize extregs area: zero out, then save a valid layout to it */
+       extregs = (void *) ALIGN_UP(((__uptr) ctx + cbs->ctx_size),
+               x86_cpu_features.extregs_align);
+       memset(extregs, 0, x86_cpu_features.extregs_size);
+       save_extregs((__uptr) extregs);
+
+       /* Initialize thread context */
+       thread_ctx = extregs + x86_cpu_features.extregs_size;
+       thread_ctx->ctx = ctx;
+       thread_ctx->tlsp = tlsp;
+       thread_ctx->extregs = (__uptr) extregs;
+
+       return thread_ctx;
+}
+
+void ukplat_thread_ctx_destroy(struct uk_alloc *allocator,
+               struct thread_context *thread_ctx)
+{
+       UK_ASSERT(allocator != NULL);
+       UK_ASSERT(thread_ctx != NULL);
+
+       uk_free(allocator, thread_ctx->ctx);
+}
+
+void ukplat_thread_ctx_start(struct ukplat_ctx_callbacks *cbs,
+               struct thread_context *thread_ctx)
+{
+       UK_ASSERT(cbs != NULL);
+       UK_ASSERT(thread_ctx != NULL);
+
+       set_tls_pointer(thread_ctx->tlsp);
+       cbs->start_cb(thread_ctx->ctx);
+}
+
+void ukplat_thread_ctx_switch(struct ukplat_ctx_callbacks *cbs,
+               struct thread_context *prevctx, struct thread_context *nextctx)
+{
+       UK_ASSERT(cbs != NULL);
+       UK_ASSERT(prevctx != NULL);
+       UK_ASSERT(nextctx != NULL);
+
+       save_extregs(prevctx->extregs);
+       restore_extregs(nextctx->extregs);
+       set_tls_pointer(nextctx->tlsp);
+       cbs->switch_cb(prevctx->ctx, nextctx->ctx);
 }
 
 int ukplat_ctx_callbacks_init(struct ukplat_ctx_callbacks *ctx_cbs,
-- 
2.11.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®.