bug-hurd
[Top][All Lists]
Advanced

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

[PATCH] add xfloat thread state interface


From: Luca Dariz
Subject: [PATCH] add xfloat thread state interface
Date: Fri, 2 Aug 2024 17:32:34 +0200

* 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.
* 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.
* i386/include/mach/i386/thread_status.h: add interface definition for
  I386_XFLOAT_STATE and the corresponding data structure.
---
 i386/i386/fpu.c                        | 115 ++++++++++++++++++-------
 i386/i386/fpu.h                        |   8 +-
 i386/i386/pcb.c                        |  23 ++++-
 i386/include/mach/i386/thread_status.h |  12 +++
 4 files changed, 115 insertions(+), 43 deletions(-)

diff --git a/i386/i386/fpu.c b/i386/i386/fpu.c
index 316e3b41..4f783293 100644
--- a/i386/i386/fpu.c
+++ b/i386/i386/fpu.c
@@ -385,10 +385,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 +411,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 +430,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);
@@ -455,9 +450,41 @@ ASSERT_IPL(SPL0);
             */
            memset(ifps, 0, fp_xsave_size);
 
-           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) {
+               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 +494,11 @@ 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]));
+
+               /* TODO: handle header and extended state */
            }
 
            simple_unlock(&pcb->lock);
@@ -495,10 +516,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 +534,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, sizeof(struct i386_xfloat_state));
            return KERN_SUCCESS;
        }
 
@@ -529,18 +554,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 +595,31 @@ 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;
+
+            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]));
+
+           /* TODO: handle header and extended state */
        }
        simple_unlock(&pcb->lock);
 
diff --git a/i386/i386/fpu.h b/i386/i386/fpu.h
index 51e0f31d..527d6a99 100644
--- a/i386/i386/fpu.h
+++ b/i386/i386/fpu.h
@@ -233,12 +233,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..e0358fb7 100644
--- a/i386/i386/pcb.c
+++ b/i386/i386/pcb.c
@@ -613,8 +613,15 @@ 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: {
+
+               if (count < i386_XFLOAT_STATE_COUNT)
+                       return(KERN_INVALID_ARGUMENT);
+
+               return fpu_set_state(thread, tstate, flavor);
            }
 
            /*
@@ -831,8 +838,16 @@ 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: {
+
+               if (*count < i386_XFLOAT_STATE_COUNT)
+                       return(KERN_INVALID_ARGUMENT);
+
+               *count = i386_XFLOAT_STATE_COUNT;
+               return fpu_get_state(thread, tstate, flavor);
            }
 
            /*
diff --git a/i386/include/mach/i386/thread_status.h 
b/i386/include/mach/i386/thread_status.h
index 94596a74..39c0acfa 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))
 
+#define XFP_STATE_BYTES (sizeof (struct i386_xfp_save))
+
+struct i386_xfloat_state {
+       int             fpkind;                 /* FP_NO..FP_387X (readonly) */
+       int             initialized;
+       int             exc_status;             /* exception status (readonly) 
*/
+       unsigned char   hw_state[XFP_STATE_BYTES]; /* actual "hardware" state */
+       /* don't add anything here, the last field of i386_xfp_save is
+        * dynamically sized */
+};
+#define i386_XFLOAT_STATE_COUNT (sizeof(struct 
i386_xfloat_state)/sizeof(unsigned int))
 
 #define PORT_MAP_BITS 0x400
 struct i386_isa_port_map_state {
-- 
2.39.2




reply via email to

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