Messages in this thread Patch in this message | | | Date | Wed, 3 Feb 1999 19:00:53 +0000 | From | Philipp Rumpf <> | Subject | Re: [patch] Katmai/PIII support for Linux pre-2.2.2-1 |
| |
On Wed, Feb 03, 1999 at 07:11:11PM +0100, MOLNAR Ingo wrote: > nor do we want to do boot-time dynamic linking.
I think it would be better to do this. It would allow for a common kernel that runs on all of Intel CPUs without opening a potential security hole or having a serious performance impact, as not using the KNIs at all would have.
So here is the "concept patch" Ingo mentioned. It is untested, as I do not have a PII (I don't have a PIII either 8).
> reports, comments, suggestions welcome,
same here.
Philipp Rumpf diff -ur /linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- /linux/arch/i386/kernel/traps.c Thu Jan 21 11:50:43 1999 +++ linux/arch/i386/kernel/traps.c Wed Feb 3 18:47:46 1999 @@ -451,8 +451,14 @@ asmlinkage void math_state_restore(struct pt_regs regs) { __asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */ + if(current->used_math) - __asm__("frstor %0": :"m" (current->tss.i387)); + __asm__("0 :nop\n\t" + "frstor %0\n\t" + ".section __lfxrstor\n\t" + ".long 0b\n\t" + ".previous\n\t" + : :"m" (current->tss.i387)); else { /* diff -ur /linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- /linux/arch/i386/mm/init.c Wed Jan 27 18:07:54 1999 +++ linux/arch/i386/mm/init.c Wed Feb 3 18:51:15 1999 @@ -191,6 +191,7 @@ #define X86_CR4_MCE 0x0040 /* Machine check enable */ #define X86_CR4_PGE 0x0080 /* enable global pages */ #define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */ +#define X86_CR4_OSFXSR 0x0200 /* OS uses fxsave / fxrstor instructions */ /* * Save the cr4 feature set we're using (ie @@ -343,6 +344,70 @@ local_flush_tlb(); return free_area_init(start_mem, end_mem); +} + +/* If we use the fxsave / fxrstor instructions, we should ensure we're running + * on a CPU that supports them */ + +int __initdata no_fxsr = 0; +extern char * __start___lfxsave; +extern char * __stop___lfxsave; +extern char * __start___lfxrstor; +extern char * __stop___lfxrstor; + +__initfunc(void disable_fxsr(char *s, int *ints)) +{ + no_fxsr = 1; +} + +__initfunc(void test_fxsr(void)) +{ + char *p, **pp; + + if(!(boot_cpu_data.x86_capability & X86_FEATURE_FXSR)) { + return; + } + + if(no_fxsr) { + printk(KERN_DEBUG "not enabling FXSAVE / FXRSTOR instructions\n"); + return; + } + + printk(KERN_DEBUG "enabling FXSAVE / FXRSTOR instructions\n"); + + /* Note: We are directly modifying assembly instructions here. + This should be no problem as these instructions are used for + process management and no processes are running in the moment */ + + for(pp = &__start___lfxsave; pp <= &__stop___lfxsave; pp++) { + p = *pp; + /* 10010000 11011101 XXX110XX nop fnsave */ + if(p[0] != 0x90 || + p[1] != 0xdd || + (p[2] & 0x1a) != 0x18) + printk(KERN_ERR "test_fxsr: wrong instruction at %p\n", p); + + /* 00001111 10101110 XXX000XX fxsave */ + p[0] = 0x0f; + p[1] = 0xae; + p[2] = (p[2] & 0xe3); + } + + for(pp = &__start___lfxrstor; pp <= &__stop___lfxrstor; pp++) { + p = *pp; + /* 10010000 11011101 XXX100XX nop frstor */ + if(p[0] != 0x90 || + p[1] != 0xdd || + (p[2] & 0x1a) != 0x10) + printk(KERN_ERR "test_fxsr: wrong instruction at %p\n", p); + + /* 00001111 10101110 XXX001XX fxrstor */ + p[0] = 0x0f; + p[1] = 0xae; + p[2] = (p[2] & 0xe3) | 0x4; + } + + set_in_cr4(X86_CR4_OSFXSR); } /* diff -ur /linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h --- /linux/include/asm-i386/processor.h Thu Jan 21 11:50:11 1999 +++ linux/include/asm-i386/processor.h Wed Feb 3 18:47:46 1999 @@ -11,6 +11,7 @@ #include <asm/math_emu.h> #include <asm/segment.h> #include <asm/page.h> +#include <linux/config.h> /* * CPU type and hardware bug flags. Kept separately for each CPU. @@ -164,6 +165,22 @@ */ #define IO_BITMAP_SIZE 32 +struct i387_fast_struct { + char resvd_1[2]; + short cs; + long ip; + short fop; + char resvd_2[1]; + char ftw; + short fsw; + short fcw; + char resvd_3[10]; + short ds; + long dp; + long st_space[32]; + long resvd_4[88]; +}; + struct i387_hard_struct { long cwd; long swd; @@ -193,6 +210,7 @@ union i387_union { struct i387_hard_struct hard; struct i387_soft_struct soft; + struct i387_fast_struct fast; }; typedef struct { @@ -286,8 +304,14 @@ /* * FPU lazy state save handling.. */ + #define save_fpu(tsk) do { \ - asm volatile("fnsave %0\n\tfwait":"=m" (tsk->tss.i387)); \ + asm volatile("0: nop\n\t" \ + "fnsave %0\n\t" \ + ".section __lfxsave\n\t" \ + ".long 0b\n\t" \ + ".previous\n\t" \ + "fwait\n\t":"=m" (tsk->tss.i387)); \ tsk->flags &= ~PF_USEDFPU; \ stts(); \ } while (0) diff -ur /linux/init/main.c linux/init/main.c --- /linux/init/main.c Wed Feb 3 13:47:03 1999 +++ linux/init/main.c Wed Feb 3 18:47:46 1999 @@ -91,6 +91,8 @@ #ifdef __i386__ extern void ioapic_pirq_setup(char *str, int *ints); extern void ioapic_setup(char *str, int *ints); +extern void disable_fxsr(void); +extern void test_fxsr(void); #endif extern void no_scroll(char *str, int *ints); extern void kbd_reset_setup(char *str, int *ints); @@ -545,6 +547,7 @@ #ifdef CONFIG_X86_IO_APIC { "noapic", ioapic_setup }, { "pirq=", ioapic_pirq_setup }, + { "nofxsr", disable_fxsr }, #endif #endif #ifdef CONFIG_BLK_DEV_RAM @@ -1118,6 +1121,9 @@ printk(linux_banner); setup_arch(&command_line, &memory_start, &memory_end); memory_start = paging_init(memory_start,memory_end); +#ifdef __i386__ + test_fxsr(); +#endif trap_init(); init_IRQ(); sched_init(); | |