diff options
| -rw-r--r-- | debian/patches/20_mmx_support.patch | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/debian/patches/20_mmx_support.patch b/debian/patches/20_mmx_support.patch new file mode 100644 index 0000000..d7c7dfc --- /dev/null +++ b/debian/patches/20_mmx_support.patch @@ -0,0 +1,276 @@ +2007-01-05 Samuel Thibault <samuel.thibault@ens-lyon.org> + + Add MMX FPU registers save/restore support. This needs 16-byte-aligned + structures. + * i386/include/mach/i386/fp_reg.h (struct i386_fp_regs): Invert array + indices. + (struct i386_xfp_save): New structure. + (FP_387X): New macro. + * i386/i386/thread.h (struct i386_fpsave_state): Add xfp_save_state + member, keep existing fp_save_state and fp_regs members in an unnamed + union member. Move fp_valid member to the end of the structure. + * i386/i386/fpu.h (fxsave, fxrstor): New macros. + (fpu_save_context): Use fxsave() when FPU is FXSR-capable. + * i386/i386/fpu.c: Include <i386/locore.h> + (fp_save, fp_load): Add declaration. + (init_fpu): Add FXSR-capable FPU detection. + (fpu_module_init): Request 16-byte alignment to zinit() for + i386_fpsave_state structures. + (fpu_set_state): Abort when FPU is FXSR-capable (not implemented yet). + (fpu_get_state): Convert FPU state when FPU is FXSR-capable. + (fp_save): Use fxsave() when FPU is FXSR-capable. + (fp_load): Use fxrstor() when FPU is FXSR-capable. + (fp_state_alloc): Add FXSR-aware initialization. + +Index: i386/include/mach/i386/fp_reg.h +=================================================================== +RCS file: /cvsroot/hurd/gnumach/i386/include/mach/i386/fp_reg.h,v +retrieving revision 1.1.1.1 +diff -u -p -r1.1.1.1 fp_reg.h +--- i386/include/mach/i386/fp_reg.h 25 Feb 1997 21:27:00 -0000 1.1.1.1 ++++ i386/include/mach/i386/fp_reg.h 4 Jan 2007 23:55:56 -0000 +@@ -46,10 +46,30 @@ struct i386_fp_save { + }; + + struct i386_fp_regs { +- unsigned short fp_reg_word[5][8]; ++ unsigned short fp_reg_word[8][5]; + /* space for 8 80-bit FP registers */ + }; + ++struct i386_xfp_save { ++ unsigned short fp_control; /* control */ ++ unsigned short fp_status; /* status */ ++ unsigned short fp_tag; /* register tags */ ++ unsigned short fp_opcode; /* opcode of failed instruction */ ++ unsigned int fp_eip; /* eip at failed instruction */ ++ unsigned short fp_cs; /* cs at failed instruction */ ++ unsigned short fp_unused_1; ++ unsigned int fp_dp; /* data address */ ++ unsigned short fp_ds; /* data segment */ ++ unsigned short fp_unused_2; ++ unsigned int fp_mxcsr; /* MXCSR */ ++ unsigned int fp_mxcsr_mask; /* MXCSR_MASK */ ++ unsigned char fp_reg_word[8][16]; ++ /* space for 8 128-bit FP registers */ ++ unsigned char fp_xreg_word[8][16]; ++ /* space for 8 128-bit XMM registers */ ++ unsigned int padding[56]; ++} __attribute__((aligned(16))); ++ + /* + * Control register + */ +@@ -104,5 +124,6 @@ struct i386_fp_regs { + #define FP_SOFT 1 /* software FP emulator */ + #define FP_287 2 /* 80287 */ + #define FP_387 3 /* 80387 or 80486 */ ++#define FP_387X 4 /* FXSAVE/RSTOR-capable */ + + #endif /* _MACH_I386_FP_REG_H_ */ +Index: i386/i386/thread.h +=================================================================== +RCS file: /cvsroot/hurd/gnumach/i386/i386/thread.h,v +retrieving revision 1.3.2.1 +diff -u -p -r1.3.2.1 thread.h +--- i386/i386/thread.h 5 Nov 2006 20:39:24 -0000 1.3.2.1 ++++ i386/i386/thread.h 4 Jan 2007 23:55:56 -0000 +@@ -112,9 +112,14 @@ struct i386_kernel_state { + */ + + struct i386_fpsave_state { ++ union { ++ struct { ++ struct i386_fp_save fp_save_state; ++ struct i386_fp_regs fp_regs; ++ }; ++ struct i386_xfp_save xfp_save_state; ++ }; + boolean_t fp_valid; +- struct i386_fp_save fp_save_state; +- struct i386_fp_regs fp_regs; + }; + + /* +Index: i386/i386/fpu.h +=================================================================== +RCS file: /cvsroot/hurd/gnumach/i386/i386/fpu.h,v +retrieving revision 1.1.1.1.4.3 +diff -u -p -r1.1.1.1.4.3 fpu.h +--- i386/i386/fpu.h 12 Dec 2006 23:30:49 -0000 1.1.1.1.4.3 ++++ i386/i386/fpu.h 4 Jan 2007 23:55:56 -0000 +@@ -66,6 +66,12 @@ + #define frstor(state) \ + asm volatile("frstor %0" : : "m" (state)) + ++#define fxsave(state) \ ++ asm volatile("fxsave %0" : "=m" (*state)) ++ ++#define fxrstor(state) \ ++ asm volatile("fxrstor %0" : : "m" (state)) ++ + #define fwait() \ + asm("fwait"); + +@@ -85,7 +91,10 @@ + if (ifps != 0 && !ifps->fp_valid) { \ + /* registers are in FPU - save to memory */ \ + ifps->fp_valid = TRUE; \ +- fnsave(&ifps->fp_save_state); \ ++ if (fp_kind == FP_387X) \ ++ fxsave(&ifps->fp_save_state.xfp_state); \ ++ else \ ++ fnsave(&ifps->fp_save_state.fp_state); \ + set_ts(); \ + } \ + } +Index: i386/i386/fpu.c +=================================================================== +RCS file: /cvsroot/hurd/gnumach/i386/i386/fpu.c,v +retrieving revision 1.2.4.10 +diff -u -p -r1.2.4.10 fpu.c +--- i386/i386/fpu.c 4 Jan 2007 23:51:02 -0000 1.2.4.10 ++++ i386/i386/fpu.c 4 Jan 2007 23:55:56 -0000 +@@ -43,6 +43,7 @@ + #include <i386/thread.h> + #include <i386/fpu.h> + #include <i386/pio.h> ++#include <i386/locore.h> + #include "cpu_number.h" + + #if 0 +@@ -64,6 +65,9 @@ extern void i386_exception(); + int fp_kind = FP_387; /* 80387 present */ + zone_t ifps_zone; /* zone for FPU save area */ + ++void fp_save(thread_t thread); ++void fp_load(thread_t thread); ++ + #if NCPUS == 1 + volatile thread_t fp_thread = THREAD_NULL; + /* thread whose state is in FPU */ +@@ -130,7 +134,12 @@ init_fpu() + /* + * We have a 387. + */ +- fp_kind = FP_387; ++ if (CPU_HAS_FEATURE(CPU_FEATURE_FXSR)) { ++ fp_kind = FP_387X; ++ printf("Enabling FXSR\n"); ++ set_cr4(get_cr4() | CR4_OSFXSR); ++ } else ++ fp_kind = FP_387; + } + /* + * Trap wait instructions. Turn off FPU for now. +@@ -152,7 +161,7 @@ init_fpu() + void + fpu_module_init() + { +- ifps_zone = zinit(sizeof(struct i386_fpsave_state), 0, ++ ifps_zone = zinit(sizeof(struct i386_fpsave_state), 16, + THREAD_MAX * sizeof(struct i386_fpsave_state), + THREAD_CHUNK * sizeof(struct i386_fpsave_state), + 0, "i386 fpsave state"); +@@ -202,6 +211,10 @@ ASSERT_IPL(SPL0); + if (fp_kind == FP_NO) + return KERN_FAILURE; + ++ if (fp_kind == FP_387X) ++ /* TODO */ ++ return KERN_FAILURE; ++ + #if NCPUS == 1 + + /* +@@ -339,15 +352,29 @@ ASSERT_IPL(SPL0); + */ + memset(user_fp_state, 0, sizeof(struct i386_fp_save)); + +- user_fp_state->fp_control = ifps->fp_save_state.fp_control; +- user_fp_state->fp_status = ifps->fp_save_state.fp_status; +- user_fp_state->fp_tag = ifps->fp_save_state.fp_tag; +- user_fp_state->fp_eip = ifps->fp_save_state.fp_eip; +- user_fp_state->fp_cs = ifps->fp_save_state.fp_cs; +- user_fp_state->fp_opcode = ifps->fp_save_state.fp_opcode; +- user_fp_state->fp_dp = ifps->fp_save_state.fp_dp; +- user_fp_state->fp_ds = ifps->fp_save_state.fp_ds; +- *user_fp_regs = ifps->fp_regs; ++ if (fp_kind == FP_387X) { ++ int i; ++ 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 = ifps->xfp_save_state.fp_tag; /* TODO: convert */ ++ 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_regs[i], &ifps->xfp_save_state.fp_reg_word[i], sizeof(user_fp_regs[i])); ++ } else { ++ user_fp_state->fp_control = ifps->fp_save_state.fp_control; ++ user_fp_state->fp_status = ifps->fp_save_state.fp_status; ++ user_fp_state->fp_tag = ifps->fp_save_state.fp_tag; ++ user_fp_state->fp_eip = ifps->fp_save_state.fp_eip; ++ user_fp_state->fp_cs = ifps->fp_save_state.fp_cs; ++ user_fp_state->fp_opcode = ifps->fp_save_state.fp_opcode; ++ user_fp_state->fp_dp = ifps->fp_save_state.fp_dp; ++ user_fp_state->fp_ds = ifps->fp_save_state.fp_ds; ++ *user_fp_regs = ifps->fp_regs; ++ } + } + simple_unlock(&pcb->lock); + +@@ -553,7 +580,10 @@ fp_save(thread) + if (ifps != 0 && !ifps->fp_valid) { + /* registers are in FPU */ + ifps->fp_valid = TRUE; +- fnsave(&ifps->fp_save_state); ++ if (fp_kind == FP_387X) ++ fxsave(&ifps->xfp_save_state); ++ else ++ fnsave(&ifps->fp_save_state); + } + } + +@@ -601,7 +631,10 @@ ASSERT_IPL(SPL0); + printf("fp_load: invalid FPU state!\n"); + fninit (); + } else { +- frstor(ifps->fp_save_state); ++ if (fp_kind == FP_387X) ++ fxrstor(ifps->xfp_save_state); ++ else ++ frstor(ifps->fp_save_state); + } + ifps->fp_valid = FALSE; /* in FPU */ + } +@@ -623,11 +656,22 @@ fp_state_alloc() + pcb->ims.ifps = ifps; + + ifps->fp_valid = TRUE; +- ifps->fp_save_state.fp_control = (0x037f +- & ~(FPC_IM|FPC_ZM|FPC_OM|FPC_PC)) +- | (FPC_PC_53|FPC_IC_AFF); +- ifps->fp_save_state.fp_status = 0; +- ifps->fp_save_state.fp_tag = 0xffff; /* all empty */ ++ ++ if (fp_kind == FP_387X) { ++ ifps->xfp_save_state.fp_control = (0x037f ++ & ~(FPC_IM|FPC_ZM|FPC_OM|FPC_PC)) ++ | (FPC_PC_53|FPC_IC_AFF); ++ ifps->xfp_save_state.fp_status = 0; ++ ifps->xfp_save_state.fp_tag = 0xffff; /* all empty */ ++ if (CPU_HAS_FEATURE(CPU_FEATURE_SSE)) ++ ifps->xfp_save_state.fp_mxcsr = 0x1f80; ++ } else { ++ ifps->fp_save_state.fp_control = (0x037f ++ & ~(FPC_IM|FPC_ZM|FPC_OM|FPC_PC)) ++ | (FPC_PC_53|FPC_IC_AFF); ++ ifps->fp_save_state.fp_status = 0; ++ ifps->fp_save_state.fp_tag = 0xffff; /* all empty */ ++ } + } + + #if AT386 |
