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

[Minios-devel] [UNIKRAFT PATCH v3 4/7] plat/arm: Support fp/simd save/restore during context switch



Floating point feature is useful for some applications. We should
save/restore fp registers during context switch.

Signed-off-by: Jia He <justin.he@xxxxxxx>
---
 plat/common/arm/thread_start64.S    | 72 +++++++++++++++++++++++++++++
 plat/common/include/arm/arm64/cpu.h | 46 +++++++++++++++++-
 2 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/plat/common/arm/thread_start64.S b/plat/common/arm/thread_start64.S
index 9a80f62..495040c 100644
--- a/plat/common/arm/thread_start64.S
+++ b/plat/common/arm/thread_start64.S
@@ -34,6 +34,7 @@
 #include <uk/plat/common/sw_ctx.h>
 #include <uk/arch/lcpu.h>
 #include <uk/asm.h>
+#include <uk/config.h>
 
 /*
  * Thread stack memory layout:
@@ -121,3 +122,74 @@ restore_point:
        add sp, x2, #__CALLEE_SAVED_SIZE
        ret
 ENDPROC(asm_sw_ctx_switch)
+
+#ifdef CONFIG_FLOAT_POINT
+/*
+ * Save the FP registers.
+ *
+ * x0 - pointer to struct fpsimd_state
+ */
+ENTRY(fpsimd_save_state)
+       stp     q0, q1, [x0, #16 * 0]
+       stp     q2, q3, [x0, #16 * 2]
+       stp     q4, q5, [x0, #16 * 4]
+       stp     q6, q7, [x0, #16 * 6]
+       stp     q8, q9, [x0, #16 * 8]
+       stp     q10, q11, [x0, #16 * 10]
+       stp     q12, q13, [x0, #16 * 12]
+       stp     q14, q15, [x0, #16 * 14]
+       stp     q16, q17, [x0, #16 * 16]
+       stp     q18, q19, [x0, #16 * 18]
+       stp     q20, q21, [x0, #16 * 20]
+       stp     q22, q23, [x0, #16 * 22]
+       stp     q24, q25, [x0, #16 * 24]
+       stp     q26, q27, [x0, #16 * 26]
+       stp     q28, q29, [x0, #16 * 28]
+       stp     q30, q31, [x0, #16 * 30]!
+       mrs     x8, fpsr
+       str     w8, [x0, #16 * 2]
+       mrs     x8, fpcr
+       str     w8, [x0, #16 * 2 + 4]
+
+       ret
+ENDPROC(fpsimd_save_state)
+
+/*
+ * Load the FP registers.
+ *
+ * x0 - pointer to struct fpsimd_state
+ */
+ENTRY(fpsimd_restore_state)
+       ldp     q0, q1, [x0, #16 * 0]
+       ldp     q2, q3, [x0, #16 * 2]
+       ldp     q4, q5, [x0, #16 * 4]
+       ldp     q6, q7, [x0, #16 * 6]
+       ldp     q8, q9, [x0, #16 * 8]
+       ldp     q10, q11, [x0, #16 * 10]
+       ldp     q12, q13, [x0, #16 * 12]
+       ldp     q14, q15, [x0, #16 * 14]
+       ldp     q16, q17, [x0, #16 * 16]
+       ldp     q18, q19, [x0, #16 * 18]
+       ldp     q20, q21, [x0, #16 * 20]
+       ldp     q22, q23, [x0, #16 * 22]
+       ldp     q24, q25, [x0, #16 * 24]
+       ldp     q26, q27, [x0, #16 * 26]
+       ldp     q28, q29, [x0, #16 * 28]
+       ldp     q30, q31, [x0, #16 * 30]!
+       ldr     w8, [x0, #16 * 2]
+       msr     fpsr, x8
+       ldr     w8, [x0, #16 * 2 + 4]
+
+       /*
+        * Writes to fpcr may be self-synchronising, so avoid restoring
+        * the register if it hasn't changed.
+        */
+       mrs     x0, fpcr
+       cmp     x0, x8
+       b.eq    9999f
+       msr     fpcr, x8
+
+9999:
+       ret
+ENDPROC(fpsimd_restore_state)
+#endif /* CONFIG_FLOAT_POINT) */
diff --git a/plat/common/include/arm/arm64/cpu.h 
b/plat/common/include/arm/arm64/cpu.h
index 122727a..71090b2 100644
--- a/plat/common/include/arm/arm64/cpu.h
+++ b/plat/common/include/arm/arm64/cpu.h
@@ -116,6 +116,47 @@ void halt(void);
 void reset(void);
 void system_off(void);
 
+#ifdef CONFIG_FLOAT_POINT
+struct user_fpsimd_state {
+       __u64           vregs[32 * 2];
+       __u32           fpsr;
+       __u32           fpcr;
+       __u32           __reserved[2];
+};
+
+extern void fpsimd_save_state(uintptr_t ptr);
+extern void fpsimd_restore_state(uintptr_t ptr);
+
+static inline void save_extregs(struct sw_ctx *ctx)
+{
+       fpsimd_save_state(ctx->extregs);
+}
+
+static inline void restore_extregs(struct sw_ctx *ctx)
+{
+       fpsimd_restore_state(ctx->extregs);
+}
+
+static inline struct sw_ctx *arch_alloc_sw_ctx(struct uk_alloc *allocator)
+{
+       struct sw_ctx *ctx;
+
+       ctx = (struct sw_ctx *)uk_malloc(allocator, sizeof(struct sw_ctx));
+       if (ctx)
+               ctx->extregs = (uintptr_t)uk_malloc(allocator,
+                                       sizeof(struct user_fpsimd_state));
+
+       uk_pr_debug("Allocating %lu bytes for sw ctx at %p, extregs at %p\n",
+                       sizeof(struct sw_ctx), ctx, (void *)ctx->extregs);
+
+       return ctx;
+}
+
+static inline void arch_init_extregs(struct sw_ctx *ctx __unused)
+{
+}
+
+#else /* !CONFIG_FLOAT_POINT */
 static inline void save_extregs(struct sw_ctx *ctx __unused)
 {
 }
@@ -128,9 +169,9 @@ static inline struct sw_ctx *arch_alloc_sw_ctx(struct 
uk_alloc *allocator)
 {
        struct sw_ctx *ctx;
 
-       ctx = uk_malloc(allocator, sizeof(struct sw_ctx));
+       ctx = (struct sw_ctx *)uk_malloc(allocator, sizeof(struct sw_ctx));
        uk_pr_debug("Allocating %lu bytes for sw ctx at %p\n",
-                  sizeof(struct sw_ctx), ctx);
+               sizeof(struct sw_ctx), ctx);
 
        return ctx;
 }
@@ -140,4 +181,5 @@ static inline void arch_init_extregs(struct sw_ctx *ctx)
        ctx->extregs = (uintptr_t)ctx + sizeof(struct sw_ctx);
 }
 
+#endif /* CONFIG_FLOAT_POINT */
 #endif /* __PLAT_COMMON_ARM64_CPU_H__ */
-- 
2.17.1


_______________________________________________
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®.