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
--sCI69OhZNC5rOBd5
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="fxsr-3.diff"
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();
--sCI69OhZNC5rOBd5--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/