|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH v3 6/8] plat/common: Add functionality to save and restore extended (x86) registers
Reviewed-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx>
Florian Schmidt <florian.schmidt@xxxxxxxxx> writes:
> 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 | 8 +++++--
> plat/common/include/x86/cpu.h | 43 +++++++++++++++++++++++++++++++++++
> plat/common/sw_ctx.c | 18 +++++++++++++--
> 3 files changed, 65 insertions(+), 4 deletions(-)
>
> diff --git a/plat/common/include/sw_ctx.h b/plat/common/include/sw_ctx.h
> index fae96beb..d52fe65b 100644
> --- a/plat/common/include/sw_ctx.h
> +++ b/plat/common/include/sw_ctx.h
> @@ -35,11 +35,15 @@
> #define __PLAT_CMN_SW_CTX_H__
>
> #ifndef __ASSEMBLY__
> +#include <stdint.h>
> #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 */
> + 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 6de62dc0..8acd71e4 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,48 @@ struct _x86_features {
>
> extern struct _x86_features x86_cpu_features;
>
> +static inline void save_extregs(struct sw_ctx *ctx)
> +{
> + 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");
> + break;
> + case X86_SAVE_FXSAVE:
> + asm volatile("fxsave (%0)" :: "r"(ctx->extregs) : "memory");
> + break;
> + case X86_SAVE_XSAVE:
> + asm volatile("xsave (%0)" :: "r"(ctx->extregs),
> + "a"(0xffffffff), "d"(0xffffffff) : "memory");
> + break;
> + case X86_SAVE_XSAVEOPT:
> + asm volatile("xsaveopt (%0)" :: "r"(ctx->extregs),
> + "a"(0xffffffff), "d"(0xffffffff) : "memory");
> + break;
> + }
> +}
> +static inline void restore_extregs(struct sw_ctx *ctx)
> +{
> + switch (x86_cpu_features.save) {
> + case X86_SAVE_NONE:
> + /* nothing to do */
> + break;
> + case X86_SAVE_FSAVE:
> + asm volatile("frstor (%0)" :: "r"(ctx->extregs));
> + break;
> + case X86_SAVE_FXSAVE:
> + asm volatile("fxrstor (%0)" :: "r"(ctx->extregs));
> + break;
> + case X86_SAVE_XSAVE:
> + case X86_SAVE_XSAVEOPT:
> + asm volatile("xrstor (%0)" :: "r"(ctx->extregs),
> + "a"(0xffffffff), "d"(0xffffffff));
> + break;
> + }
> +}
> +
> static inline void _init_cpufeatures(void)
> {
> __u32 eax, ebx, ecx, edx;
> diff --git a/plat/common/sw_ctx.c b/plat/common/sw_ctx.c
> index a477753b..c69f5fde 100644
> --- a/plat/common/sw_ctx.c
> +++ b/plat/common/sw_ctx.c
> @@ -32,12 +32,13 @@
> * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
> */
>
> +#include <stdint.h>
> #include <stdlib.h>
> #include <uk/plat/thread.h>
> #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 +53,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 +68,10 @@ static void *sw_ctx_create(struct uk_alloc *allocator,
> unsigned long sp)
>
> ctx->sp = sp;
> ctx->ip = (unsigned long) asm_thread_starter;
> + ctx->extregs = ALIGN_UP(((uintptr_t)ctx + sizeof(struct sw_ctx)),
> + x86_cpu_features.extregs_align);
> + // Initialize the extregs area by saving a valid register layout to it
> + save_extregs(ctx);
>
> return ctx;
> }
> @@ -85,6 +94,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.20.1
>
--
Yuri Volchkov
Software Specialist
NEC Europe Ltd
Kurfürsten-Anlage 36
D-69115 Heidelberg
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |