bug-hurd
[Top][All Lists]
Advanced

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]