[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH 5/6] plat/common: Add functionality to save and restore extended (x86) registers
On creation of a sw_ctx struct, allocate an area sufficiently large to save all extended registers. On context switch, use the appropriate CPU instruction to save and restore those registers to/from that area. Signed-off-by: Florian Schmidt <florian.schmidt@xxxxxxxxx> --- plat/common/include/sw_ctx.h | 9 +++++-- plat/common/include/x86/cpu.h | 49 +++++++++++++++++++++++++++++++++++ plat/common/sw_ctx.c | 14 ++++++++-- 3 files changed, 68 insertions(+), 4 deletions(-) diff --git a/plat/common/include/sw_ctx.h b/plat/common/include/sw_ctx.h index 34116b1..5cb949a 100644 --- a/plat/common/include/sw_ctx.h +++ b/plat/common/include/sw_ctx.h @@ -38,8 +38,13 @@ #include <uk/plat/thread.h> struct sw_ctx { - unsigned long sp; /* Stack pointer */ - unsigned long ip; /* Instruction pointer */ + unsigned long sp; /* Stack pointer */ + unsigned long ip; /* Instruction pointer */ + unsigned char extregs[]; /* NB, this will typically NOT point to + * the beginning of the extregs area, + * because the extregs area needs to + * be aligned. + */ }; 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 fbc229d..f2a8f0d 100644 --- a/plat/common/include/x86/cpu.h +++ b/plat/common/include/x86/cpu.h @@ -32,6 +32,7 @@ #include <uk/arch/types.h> #include <x86/cpu_defs.h> +#include <sw_ctx.h> #include <stdint.h> void halt(void); @@ -55,6 +56,54 @@ struct _x86_features { extern struct _x86_features x86_cpu_features; +static inline void save_extregs(struct sw_ctx *ctx) +{ + uintptr_t r = ALIGN_UP(((uintptr_t)ctx + sizeof(struct sw_ctx)), + x86_cpu_features.extregs_align); + + switch (x86_cpu_features.save) { + case X86_SAVE_NONE: + /* nothing to do */ + break; + case X86_SAVE_FSAVE: + asm volatile("fsave (%0)" :: "r"(r) : "memory"); + break; + case X86_SAVE_FXSAVE: + asm volatile("fxsave (%0)" :: "r"(r) : "memory"); + break; + case X86_SAVE_XSAVE: + asm volatile("xsave (%0)" :: "r"(r), "a"(0xffffffff), + "d"(0xffffffff) : "memory"); + break; + case X86_SAVE_XSAVEOPT: + asm volatile("xsaveopt (%0)" :: "r"(r), "a"(0xffffffff), + "d"(0xffffffff) : "memory"); + break; + } +} +static inline void restore_extregs(struct sw_ctx *ctx) +{ + uintptr_t r = ALIGN_UP(((uintptr_t)ctx + sizeof(struct sw_ctx)), + x86_cpu_features.extregs_align); + + switch (x86_cpu_features.save) { + case X86_SAVE_NONE: + /* nothing to do */ + break; + case X86_SAVE_FSAVE: + asm volatile("frstor (%0)" :: "r"(r)); + break; + case X86_SAVE_FXSAVE: + asm volatile("fxrstor (%0)" :: "r"(r)); + break; + case X86_SAVE_XSAVE: + case X86_SAVE_XSAVEOPT: + asm volatile("xrstor (%0)" :: "r"(r), "a"(0xffffffff), + "d"(0xffffffff)); + break; + } +} + static inline void _init_cpufeatures(void) { #if LINUXUPLAT diff --git a/plat/common/sw_ctx.c b/plat/common/sw_ctx.c index a477753..7993577 100644 --- a/plat/common/sw_ctx.c +++ b/plat/common/sw_ctx.c @@ -37,7 +37,7 @@ #include <uk/alloc.h> #include <sw_ctx.h> #include <uk/assert.h> - +#include <x86/cpu.h> static void *sw_ctx_create(struct uk_alloc *allocator, unsigned long sp); static void sw_ctx_start(void *ctx) __noreturn; @@ -52,10 +52,14 @@ extern void asm_thread_starter(void); static void *sw_ctx_create(struct uk_alloc *allocator, unsigned long sp) { struct sw_ctx *ctx; + size_t sz; UK_ASSERT(allocator != NULL); - ctx = uk_malloc(allocator, sizeof(struct 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; @@ -63,6 +67,7 @@ static void *sw_ctx_create(struct uk_alloc *allocator, unsigned long sp) ctx->sp = sp; ctx->ip = (unsigned long) asm_thread_starter; + save_extregs(ctx); return ctx; } @@ -85,6 +90,11 @@ 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); asm_sw_ctx_switch(prevctx, nextctx); } -- 2.19.1 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |