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