[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
- [PATCH] add xfloat thread state interface,
Luca Dariz <=
[PATCH v2 gnumach 1/3] add xfloat thread state interface, Luca Dariz, 2024/08/21