From 0001229827afcc7d5e168b2711dab3a26ab5df12 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 10 Sep 2016 16:55:33 +0200 Subject: [PATCH] save /restore only MXCSR & the x87 status word - reduce overhead for a "user-level" context switch --- hermit/arch/x86/include/asm/stddef.h | 2 ++ hermit/arch/x86/include/asm/tasks_types.h | 16 ++++++++++++++++ hermit/arch/x86/kernel/entry.asm | 17 ++++++++--------- hermit/include/hermit/syscall.h | 4 +++- hermit/usr/newlib | 2 +- 5 files changed, 30 insertions(+), 11 deletions(-) diff --git a/hermit/arch/x86/include/asm/stddef.h b/hermit/arch/x86/include/asm/stddef.h index c40070bde..9f0eb045d 100644 --- a/hermit/arch/x86/include/asm/stddef.h +++ b/hermit/arch/x86/include/asm/stddef.h @@ -144,6 +144,8 @@ typedef struct mregs { uint64_t rsp; /// RIP uint64_t rip; + /// MSXCSR + uint32_t mxcsr; } mregs_t; /// This defines what the stack looks like after the task context is saved diff --git a/hermit/arch/x86/include/asm/tasks_types.h b/hermit/arch/x86/include/asm/tasks_types.h index 45f44882d..172f08a4a 100644 --- a/hermit/arch/x86/include/asm/tasks_types.h +++ b/hermit/arch/x86/include/asm/tasks_types.h @@ -108,6 +108,22 @@ union fpu_state { xsave_t xsave; }; +typedef struct { + uint16_t control_word; + uint16_t unused1; + uint16_t status_word; + uint16_t unused2; + uint16_t tags; + uint16_t unused3; + uint32_t eip; + uint16_t cs_selector; + uint32_t opcode:11; + uint32_t unused4:5; + uint32_t data_offset; + uint16_t data_selector; + uint16_t unused5; +} fenv_t; + typedef void (*handle_fpu_state)(union fpu_state* state); extern handle_fpu_state save_fpu_state; diff --git a/hermit/arch/x86/kernel/entry.asm b/hermit/arch/x86/kernel/entry.asm index 150f3f81c..9bbffa6b4 100644 --- a/hermit/arch/x86/kernel/entry.asm +++ b/hermit/arch/x86/kernel/entry.asm @@ -493,7 +493,6 @@ isrsyscall: o64 sysret %endif -extern save_fpu_state global getcontext align 64 getcontext: @@ -515,23 +514,23 @@ getcontext: mov QWORD [rdi + 0x60], rax mov rax, QWORD [rsp] mov QWORD [rdi + 0x68], rax - ; restore FPU state - add rdi, 0x80 - call [save_fpu_state] - sub rdi, 0x80 + ; save FPU state + fnstenv [rdi + 0x74] + fldenv [rdi + 0x74] + lea rax, [rdi + 0x70] + stmxcsr [rax] xor rax, rax sti ret -extern restore_fpu_state global setcontext align 64 setcontext: cli ; restore FPU state - add rdi, 0x80 - call [restore_fpu_state] - sub rdi, 0x80 + fldenv [rdi + 0x74] + lea rax, [rdi + 0x70] + ldmxcsr [rax] ; restore general purpose registers mov r15, QWORD [rdi + 0x00] mov r14, QWORD [rdi + 0x08] diff --git a/hermit/include/hermit/syscall.h b/hermit/include/hermit/syscall.h index a7da385fb..5d7da4c50 100644 --- a/hermit/include/hermit/syscall.h +++ b/hermit/include/hermit/syscall.h @@ -95,13 +95,15 @@ int sys_signal(signal_handler_t handler); typedef struct ucontext { mregs_t uc_mregs; - union fpu_state uc_fpu; + fenv_t uc_fenv; struct ucontext *uc_link; stack_t uc_stack; } ucontext_t; void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...); int swapcontext(ucontext_t *oucp, const ucontext_t *ucp); +int getcontext(ucontext_t *ucp); +int setcontext(ucontext_t *ucp); #define __NR_exit 0 #define __NR_write 1 diff --git a/hermit/usr/newlib b/hermit/usr/newlib index ba4dae88b..30a3e67a8 160000 --- a/hermit/usr/newlib +++ b/hermit/usr/newlib @@ -1 +1 @@ -Subproject commit ba4dae88bdc2fda079fc96cf70e7b238282229ca +Subproject commit 30a3e67a8641c3a6884ad3d18e1fc8752652e89c