[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH gnumach v3 1/3] add xfloat thread state interface
From: |
Samuel Thibault |
Subject: |
Re: [PATCH gnumach v3 1/3] add xfloat thread state interface |
Date: |
Sun, 8 Sep 2024 01:08:01 +0200 |
Applied, thanks!
Luca Dariz, le mer. 04 sept. 2024 22:18:04 +0200, a ecrit:
> * i386/i386/fpu.c: extend current getter and setter to support the
> extended state; move the struct casting here to reuse the locking
> and allocation logic for the thread state; make sure the new state
> is set as valid, otherwise it won't be applied; add
> i386_get_xstate_size() to dynamically retrieve the FPU state size.
> * i386/i386/fpu.h: update prototypes to accept generic thread state
> * i386/i386/pcb.c: forward raw thread state to getter and setter, only
> checking for minimum size and use the new i386_get_xstate_size()
> helper.
> * i386/include/mach/i386/mach_i386.defs: expose the new helper
> i386_get_xstate_size().
> * i386/include/mach/i386/thread_status.h: add interface definition for
> I386_XFLOAT_STATE and the corresponding data structure.
> ---
> i386/i386/fpu.c | 139 +++++++++++++++++++------
> i386/i386/fpu.h | 9 +-
> i386/i386/pcb.c | 37 ++++++-
> i386/include/mach/i386/mach_i386.defs | 7 ++
> i386/include/mach/i386/thread_status.h | 12 +++
> 5 files changed, 161 insertions(+), 43 deletions(-)
>
> diff --git a/i386/i386/fpu.c b/i386/i386/fpu.c
> index 316e3b41..43771e7f 100644
> --- a/i386/i386/fpu.c
> +++ b/i386/i386/fpu.c
> @@ -250,6 +250,17 @@ init_fpu(void)
> }
> }
>
> +kern_return_t
> +i386_get_xstate_size(host_t host, vm_size_t *size)
> +{
> + if (host == HOST_NULL)
> + return KERN_INVALID_ARGUMENT;
> +
> + *size = sizeof(struct i386_xfloat_state) + fp_xsave_size;
> +
> + return KERN_SUCCESS;
> +}
> +
> /*
> * Initialize FP handling.
> */
> @@ -385,10 +396,11 @@ twd_fxsr_to_i387 (struct i386_xfp_save *fxsave)
> * concurrent fpu_set_state or fpu_get_state.
> */
> kern_return_t
> -fpu_set_state(const thread_t thread,
> - struct i386_float_state *state)
> +fpu_set_state(const thread_t thread, void *state, int flavor)
> {
> pcb_t pcb = thread->pcb;
> + struct i386_float_state *fstate = (struct i386_float_state*)state;
> + struct i386_xfloat_state *xfstate = (struct i386_xfloat_state*)state;
> struct i386_fpsave_state *ifps;
> struct i386_fpsave_state *new_ifps;
>
> @@ -410,7 +422,8 @@ ASSERT_IPL(SPL0);
> }
> #endif
>
> - if (state->initialized == 0) {
> + if ((flavor == i386_FLOAT_STATE && fstate->initialized == 0) ||
> + (flavor == i386_XFLOAT_STATE && xfstate->initialized == 0)) {
> /*
> * new FPU state is 'invalid'.
> * Deallocate the fp state if it exists.
> @@ -428,13 +441,6 @@ ASSERT_IPL(SPL0);
> /*
> * Valid state. Allocate the fp state if there is none.
> */
> - struct i386_fp_save *user_fp_state;
> - struct i386_fp_regs *user_fp_regs;
> -
> - user_fp_state = (struct i386_fp_save *) &state->hw_state[0];
> - user_fp_regs = (struct i386_fp_regs *)
> - &state->hw_state[sizeof(struct i386_fp_save)];
> -
> new_ifps = 0;
> Retry:
> simple_lock(&pcb->lock);
> @@ -454,10 +460,43 @@ ASSERT_IPL(SPL0);
> * Ensure that reserved parts of the environment are 0.
> */
> memset(ifps, 0, fp_xsave_size);
> + ifps->fp_valid = TRUE;
>
> - if (fp_save_kind != FP_FNSAVE) {
> - int i;
> + if (flavor == i386_FLOAT_STATE) {
> + struct i386_fp_save *user_fp_state;
> + struct i386_fp_regs *user_fp_regs;
> +
> + user_fp_state = (struct i386_fp_save *) &fstate->hw_state[0];
> + user_fp_regs = (struct i386_fp_regs *)
> + &fstate->hw_state[sizeof(struct i386_fp_save)];
>
> + if (fp_save_kind != FP_FNSAVE) {
> + int i;
> +
> + ifps->xfp_save_state.fp_control = user_fp_state->fp_control;
> + ifps->xfp_save_state.fp_status = user_fp_state->fp_status;
> + ifps->xfp_save_state.fp_tag =
> twd_i387_to_fxsr(user_fp_state->fp_tag);
> + ifps->xfp_save_state.fp_eip = user_fp_state->fp_eip;
> + ifps->xfp_save_state.fp_cs = user_fp_state->fp_cs;
> + ifps->xfp_save_state.fp_opcode = user_fp_state->fp_opcode;
> + ifps->xfp_save_state.fp_dp = user_fp_state->fp_dp;
> + ifps->xfp_save_state.fp_ds = user_fp_state->fp_ds;
> + for (i=0; i<8; i++)
> + memcpy(&ifps->xfp_save_state.fp_reg_word[i],
> &user_fp_regs->fp_reg_word[i], sizeof(user_fp_regs->fp_reg_word[i]));
> + } else {
> + ifps->fp_save_state.fp_control = user_fp_state->fp_control;
> + ifps->fp_save_state.fp_status = user_fp_state->fp_status;
> + ifps->fp_save_state.fp_tag = user_fp_state->fp_tag;
> + ifps->fp_save_state.fp_eip = user_fp_state->fp_eip;
> + ifps->fp_save_state.fp_cs = user_fp_state->fp_cs;
> + ifps->fp_save_state.fp_opcode = user_fp_state->fp_opcode;
> + ifps->fp_save_state.fp_dp = user_fp_state->fp_dp;
> + ifps->fp_save_state.fp_ds = user_fp_state->fp_ds;
> + ifps->fp_regs = *user_fp_regs;
> + }
> + } else if ((flavor == i386_XFLOAT_STATE) && (xfstate->fp_save_kind
> == fp_save_kind)) {
> + int i;
> + struct i386_xfp_save *user_fp_state = (struct i386_xfp_save *)
> &xfstate->hw_state[0];
> ifps->xfp_save_state.fp_control = user_fp_state->fp_control;
> ifps->xfp_save_state.fp_status = user_fp_state->fp_status;
> ifps->xfp_save_state.fp_tag =
> twd_i387_to_fxsr(user_fp_state->fp_tag);
> @@ -467,17 +506,17 @@ ASSERT_IPL(SPL0);
> ifps->xfp_save_state.fp_dp = user_fp_state->fp_dp;
> ifps->xfp_save_state.fp_ds = user_fp_state->fp_ds;
> for (i=0; i<8; i++)
> - memcpy(&ifps->xfp_save_state.fp_reg_word[i],
> &user_fp_regs->fp_reg_word[i], sizeof(user_fp_regs->fp_reg_word[i]));
> - } else {
> - ifps->fp_save_state.fp_control = user_fp_state->fp_control;
> - ifps->fp_save_state.fp_status = user_fp_state->fp_status;
> - ifps->fp_save_state.fp_tag = user_fp_state->fp_tag;
> - ifps->fp_save_state.fp_eip = user_fp_state->fp_eip;
> - ifps->fp_save_state.fp_cs = user_fp_state->fp_cs;
> - ifps->fp_save_state.fp_opcode = user_fp_state->fp_opcode;
> - ifps->fp_save_state.fp_dp = user_fp_state->fp_dp;
> - ifps->fp_save_state.fp_ds = user_fp_state->fp_ds;
> - ifps->fp_regs = *user_fp_regs;
> + memcpy(&ifps->xfp_save_state.fp_reg_word[i],
> &user_fp_state->fp_reg_word[i], sizeof(user_fp_state->fp_reg_word[i]));
> + for (i=0; i<16; i++)
> + memcpy(&ifps->xfp_save_state.fp_xreg_word[i],
> &user_fp_state->fp_xreg_word[i], sizeof(user_fp_state->fp_xreg_word[i]));
> +
> + memcpy(&ifps->xfp_save_state.header, &user_fp_state->header,
> + sizeof(ifps->xfp_save_state.header));
> + if (fp_xsave_size > sizeof(struct i386_xfp_save)) {
> + memcpy(&ifps->xfp_save_state.extended,
> &user_fp_state->extended,
> + fp_xsave_size - sizeof(struct i386_xfp_save));
> + }
> +
> }
>
> simple_unlock(&pcb->lock);
> @@ -495,10 +534,11 @@ ASSERT_IPL(SPL0);
> * concurrent fpu_set_state or fpu_get_state.
> */
> kern_return_t
> -fpu_get_state(const thread_t thread,
> - struct i386_float_state *state)
> +fpu_get_state(const thread_t thread, void *state, int flavor)
> {
> pcb_t pcb = thread->pcb;
> + struct i386_float_state *fstate = (struct i386_float_state*)state;
> + struct i386_xfloat_state *xfstate = (struct i386_xfloat_state*)state;
> struct i386_fpsave_state *ifps;
>
> ASSERT_IPL(SPL0);
> @@ -512,7 +552,10 @@ ASSERT_IPL(SPL0);
> * No valid floating-point state.
> */
> simple_unlock(&pcb->lock);
> - memset(state, 0, sizeof(struct i386_float_state));
> + if (flavor == i386_FLOAT_STATE)
> + memset(state, 0, sizeof(struct i386_float_state));
> + else if (flavor == i386_XFLOAT_STATE)
> + memset(state, 0, fp_xsave_size);
> return KERN_SUCCESS;
> }
>
> @@ -529,18 +572,17 @@ ASSERT_IPL(SPL0);
> clear_fpu();
> }
>
> - state->fpkind = fp_kind;
> - state->exc_status = 0;
> -
> - {
> + if (flavor == i386_FLOAT_STATE) {
> struct i386_fp_save *user_fp_state;
> struct i386_fp_regs *user_fp_regs;
>
> - state->initialized = ifps->fp_valid;
> + fstate->fpkind = fp_kind;
> + fstate->exc_status = 0;
> + fstate->initialized = ifps->fp_valid;
>
> - user_fp_state = (struct i386_fp_save *) &state->hw_state[0];
> + user_fp_state = (struct i386_fp_save *) &fstate->hw_state[0];
> user_fp_regs = (struct i386_fp_regs *)
> - &state->hw_state[sizeof(struct i386_fp_save)];
> + &fstate->hw_state[sizeof(struct i386_fp_save)];
>
> /*
> * Ensure that reserved parts of the environment are 0.
> @@ -571,6 +613,37 @@ ASSERT_IPL(SPL0);
> user_fp_state->fp_ds = ifps->fp_save_state.fp_ds;
> *user_fp_regs = ifps->fp_regs;
> }
> + } else if (flavor == i386_XFLOAT_STATE) {
> + int i;
> + struct i386_xfp_save *user_fp_state;
> +
> + xfstate->fpkind = fp_kind;
> + xfstate->exc_status = 0;
> + xfstate->initialized = ifps->fp_valid;
> + xfstate->fp_save_kind = fp_save_kind;
> +
> + user_fp_state = (struct i386_xfp_save *) &xfstate->hw_state[0];
> + memset(user_fp_state, 0, sizeof(struct i386_xfp_save));
> +
> + user_fp_state->fp_control = ifps->xfp_save_state.fp_control;
> + user_fp_state->fp_status = ifps->xfp_save_state.fp_status;
> + user_fp_state->fp_tag = twd_fxsr_to_i387(&ifps->xfp_save_state);
> + user_fp_state->fp_eip = ifps->xfp_save_state.fp_eip;
> + user_fp_state->fp_cs = ifps->xfp_save_state.fp_cs;
> + user_fp_state->fp_opcode = ifps->xfp_save_state.fp_opcode;
> + user_fp_state->fp_dp = ifps->xfp_save_state.fp_dp;
> + user_fp_state->fp_ds = ifps->xfp_save_state.fp_ds;
> + for (i=0; i<8; i++)
> + memcpy(&user_fp_state->fp_reg_word[i],
> &ifps->xfp_save_state.fp_reg_word[i], sizeof(user_fp_state->fp_reg_word[i]));
> + for (i=0; i<16; i++)
> + memcpy(&user_fp_state->fp_xreg_word[i],
> &ifps->xfp_save_state.fp_xreg_word[i],
> sizeof(user_fp_state->fp_xreg_word[i]));
> +
> + memcpy(&user_fp_state->header, &ifps->xfp_save_state.header,
> + sizeof(ifps->xfp_save_state.header));
> + if (fp_xsave_size > sizeof(struct i386_xfp_save)) {
> + memcpy(&user_fp_state->extended,
> &ifps->xfp_save_state.extended,
> + fp_xsave_size - sizeof(struct i386_xfp_save));
> + }
> }
> simple_unlock(&pcb->lock);
>
> diff --git a/i386/i386/fpu.h b/i386/i386/fpu.h
> index 51e0f31d..83a8f2d6 100644
> --- a/i386/i386/fpu.h
> +++ b/i386/i386/fpu.h
> @@ -35,6 +35,7 @@
> #include <sys/types.h>
> #include <i386/proc_reg.h>
> #include <kern/thread.h>
> +#include "i386/i386/mach_i386.server.h"
>
> /*
> * FPU instructions.
> @@ -233,12 +234,8 @@ extern void fp_save(thread_t thread);
> extern void fp_load(thread_t thread);
> extern void fp_free(struct i386_fpsave_state *fps);
> extern void fpu_module_init(void);
> -extern kern_return_t fpu_set_state(
> - thread_t thread,
> - struct i386_float_state *state);
> -extern kern_return_t fpu_get_state(
> - thread_t thread,
> - struct i386_float_state *state);
> +extern kern_return_t fpu_set_state(thread_t thread, void *state, int flavor);
> +extern kern_return_t fpu_get_state(thread_t thread, void *state, int flavor);
> extern void fpnoextflt(void);
> extern void fpextovrflt(void);
> extern void fpexterrflt(void);
> diff --git a/i386/i386/pcb.c b/i386/i386/pcb.c
> index e8901550..5ca6f124 100644
> --- a/i386/i386/pcb.c
> +++ b/i386/i386/pcb.c
> @@ -613,8 +613,22 @@ kern_return_t thread_setstatus(
> if (count < i386_FLOAT_STATE_COUNT)
> return(KERN_INVALID_ARGUMENT);
>
> - return fpu_set_state(thread,
> - (struct i386_float_state *) tstate);
> + return fpu_set_state(thread, tstate, flavor);
> + }
> +
> + case i386_XFLOAT_STATE: {
> +
> + vm_size_t xfp_size;
> + kern_return_t kr;
> + kr = i386_get_xstate_size(&realhost, &xfp_size);
> + if (kr != KERN_SUCCESS)
> + return kr;
> +
> + xfp_size /= sizeof(integer_t);
> + if (count < xfp_size)
> + return(KERN_INVALID_ARGUMENT);
> +
> + return fpu_set_state(thread, tstate, flavor);
> }
>
> /*
> @@ -831,8 +845,23 @@ kern_return_t thread_getstatus(
> return(KERN_INVALID_ARGUMENT);
>
> *count = i386_FLOAT_STATE_COUNT;
> - return fpu_get_state(thread,
> - (struct i386_float_state *)tstate);
> + return fpu_get_state(thread, tstate, flavor);
> + }
> +
> + case i386_XFLOAT_STATE: {
> +
> + vm_size_t xfp_size;
> + kern_return_t kr;
> + kr = i386_get_xstate_size(&realhost, &xfp_size);
> + if (kr != KERN_SUCCESS)
> + return kr;
> +
> + xfp_size /= sizeof(integer_t);
> + if (*count < xfp_size)
> + return(KERN_INVALID_ARGUMENT);
> +
> + *count = xfp_size;
> + return fpu_get_state(thread, tstate, flavor);
> }
>
> /*
> diff --git a/i386/include/mach/i386/mach_i386.defs
> b/i386/include/mach/i386/mach_i386.defs
> index 965d5c3b..78bbc2ed 100644
> --- a/i386/include/mach/i386/mach_i386.defs
> +++ b/i386/include/mach/i386/mach_i386.defs
> @@ -111,3 +111,10 @@ routine i386_get_gdt(
> target_thread : thread_t;
> selector : int;
> out desc : descriptor_t);
> +
> +/* Returns the size in bytes of the FPU extended state, to be used
> + with i386_XFLOAT_STATE instead of i386_XFLOAT_STATE_COUNT.
> + */
> +routine i386_get_xstate_size(
> + host : host_t;
> + out size : vm_size_t);
> diff --git a/i386/include/mach/i386/thread_status.h
> b/i386/include/mach/i386/thread_status.h
> index 94596a74..2f472247 100644
> --- a/i386/include/mach/i386/thread_status.h
> +++ b/i386/include/mach/i386/thread_status.h
> @@ -58,6 +58,7 @@
> #define i386_REGS_SEGS_STATE 5
> #define i386_DEBUG_STATE 6
> #define i386_FSGS_BASE_STATE 7
> +#define i386_XFLOAT_STATE 8
>
> /*
> * This structure is used for both
> @@ -148,6 +149,17 @@ struct i386_float_state {
> };
> #define i386_FLOAT_STATE_COUNT (sizeof(struct
> i386_float_state)/sizeof(unsigned int))
>
> +struct i386_xfloat_state {
> + int fpkind; /* FP_NO..FP_387X (readonly) */
> + int initialized;
> + int exc_status; /* exception status (readonly)
> */
> + int fp_save_kind; /* format of hardware state */
> + unsigned char hw_state[]; /* actual "hardware" state */
> + /* don't add anything here, as hw_state is dynamically sized */
> +};
> +/* NOTE: i386_XFLOAT_STATE_COUNT is not defined as i386_xfloat_state is
> + * dynamically sized. Use i386_get_xstate_size(host) to get the current
> + * size. */
>
> #define PORT_MAP_BITS 0x400
> struct i386_isa_port_map_state {
> --
> 2.39.2
>
>
--
Samuel
<D> m'enfin, le 5 juillet, le mec vient visiter le labo...
* D a marque d'une croix rouge le 5 juillet sur son agenda
<y> niarc niarc niarc
<D> cet homme va souffrir
<B> c'est donc le 5 juillet qu'il meurt d'un accident de la route écrasé par un
truck muni d'un pare buffle
-+- #ens-mim - repaire de terroristes -+-