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

Re: [Minios-devel] [UNIKRAFT PATCH v2 8/9] plat/common: Add functionality to save and restore extended (x86) registers



Hi,

see my notes inline

-Yuri.

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  |  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 fae96beb..1b279b25 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.
> +                                      */
You can easily achieve that extregs always pointing to the begining of
extregs area. If extregs is a pointer, you can just assign it the
address of this area. E.g.

        ctx = uk_malloc(allocator, sz);
        ctx.extregs = ALIGN_UP(((uintptr_t)ctx + sizeof(struct sw_ctx)),
                                x86_cpu_features.extregs_align);


>  };
>  
>  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 fbc229d9..f2a8f0d5 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 a477753b..79935776 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);
Maybe a small note why we are saving registers without actual context
switch here? So people like me get less confusion :)

>  
>       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.2
>

-- 
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

 


Rackspace

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