]> git.neil.brown.name Git - history.git/commitdiff
Sysenter cleanups (originals by Brian Gerst, updated and expanded by me):
authorLinus Torvalds <torvalds@home.transmeta.com>
Sat, 21 Dec 2002 08:02:05 +0000 (00:02 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Sat, 21 Dec 2002 08:02:05 +0000 (00:02 -0800)
 - set up kernel stack pointer for sysenter at each context switch.
 - disable sysenter while in vm86 mode.
 - clean up mtrr number defines and SEP feature testing

arch/i386/kernel/cpu/common.c
arch/i386/kernel/process.c
arch/i386/kernel/sysenter.c
arch/i386/kernel/vm86.c
include/asm-i386/cpufeature.h
include/asm-i386/msr.h
include/asm-i386/processor.h

index a06389c6322d90da2c2b43b181cf0c2c380dd168..b54998f01af4b70b0671145d83401d1a26f4da1c 100644 (file)
@@ -516,7 +516,7 @@ void __init cpu_init (void)
                BUG();
        enter_lazy_tlb(&init_mm, current, cpu);
 
-       t->esp0 = thread->esp0;
+       load_esp0(t, thread->esp0);
        set_tss_desc(cpu,t);
        cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
        load_TR_desc();
index e31d79b11a5b5b9a2747897ce4cb6393446def97..b6a06a1e852c5e585c534a4da54cfac6c821ea5f 100644 (file)
@@ -443,7 +443,7 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        /*
         * Reload esp0, LDT and the page table pointer:
         */
-       tss->esp0 = next->esp0;
+       load_esp0(tss, next->esp0);
 
        /*
         * Load the per-thread Thread-Local Storage descriptor.
index 685bf5154e7db1a5b440c5b0e74b4ef2075d2cf9..796c23d04a387011d850047c5046ce40e89aed39 100644 (file)
@@ -34,40 +34,14 @@ struct fake_sep_struct {
        unsigned char stack[0];
 } __attribute__((aligned(8192)));
        
-static struct fake_sep_struct *alloc_sep_thread(int cpu)
-{
-       struct fake_sep_struct *entry;
-
-       entry = (struct fake_sep_struct *) __get_free_pages(GFP_ATOMIC, 1);
-       if (!entry)
-               return NULL;
-
-       memset(entry, 0, PAGE_SIZE<<1);
-       entry->thread.task = &entry->task;
-       entry->task.thread_info = &entry->thread;
-       entry->thread.preempt_count = 1;
-       entry->thread.cpu = cpu;        
-
-       return entry;
-}
-
 static void __init enable_sep_cpu(void *info)
 {
        int cpu = get_cpu();
-       struct fake_sep_struct *sep = alloc_sep_thread(cpu);
-       unsigned long *esp0_ptr = &(init_tss + cpu)->esp0;
-       unsigned long rel32;
-
-       rel32 = (unsigned long) sysenter_entry - (unsigned long) (sep->trampoline+11);
-       
-       *(short *) (sep->trampoline+0) = 0x258b;                /* movl xxxxx,%esp */
-       *(long **) (sep->trampoline+2) = esp0_ptr;
-       *(char *)  (sep->trampoline+6) = 0xe9;                  /* jmp rl32 */
-       *(long *)  (sep->trampoline+7) = rel32;
+       struct tss_struct *tss = init_tss + cpu;
 
-       wrmsr(0x174, __KERNEL_CS, 0);                           /* SYSENTER_CS_MSR */
-       wrmsr(0x175, PAGE_SIZE*2 + (unsigned long) sep, 0);     /* SYSENTER_ESP_MSR */
-       wrmsr(0x176, (unsigned long) &sep->trampoline, 0);      /* SYSENTER_EIP_MSR */
+       wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
+       wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp0, 0);
+       wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0);
 
        printk("Enabling SEP on CPU %d\n", cpu);
        put_cpu();      
index 8917425babd710a3870df9df313fd6521b2b78c8..8bbef75c7025f17a346ad865ff3a3eebc8565841 100644 (file)
@@ -113,7 +113,8 @@ struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
                do_exit(SIGSEGV);
        }
        tss = init_tss + smp_processor_id();
-       tss->esp0 = current->thread.esp0 = current->thread.saved_esp0;
+       current->thread.esp0 = current->thread.saved_esp0;
+       load_esp0(tss, current->thread.esp0);
        current->thread.saved_esp0 = 0;
        ret = KVM86->regs32;
        return ret;
@@ -284,6 +285,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
        tsk->thread.saved_esp0 = tsk->thread.esp0;
        tss = init_tss + smp_processor_id();
        tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
+       disable_sysenter();
 
        tsk->thread.screen_bitmap = info->screen_bitmap;
        if (info->flags & VM86_SCREEN_BITMAP)
index f0becf88e4a0160c4b84de33fc2a6a34e8585d23..92ff7f79dee4eb5c57fd5d5621f5d694bb409c9f 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef __ASM_I386_CPUFEATURE_H
 #define __ASM_I386_CPUFEATURE_H
 
+#include <linux/bitops.h>
+
 #define NCAPINTS       4       /* Currently we have 4 32-bit words worth of info */
 
 /* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
@@ -74,6 +76,7 @@
 #define cpu_has_pae            boot_cpu_has(X86_FEATURE_PAE)
 #define cpu_has_pge            boot_cpu_has(X86_FEATURE_PGE)
 #define cpu_has_apic           boot_cpu_has(X86_FEATURE_APIC)
+#define cpu_has_sep            boot_cpu_has(X86_FEATURE_SEP)
 #define cpu_has_mtrr           boot_cpu_has(X86_FEATURE_MTRR)
 #define cpu_has_mmx            boot_cpu_has(X86_FEATURE_MMX)
 #define cpu_has_fxsr           boot_cpu_has(X86_FEATURE_FXSR)
index f8819948d6292c060adcc4f1a948452b5cb4219b..6e7572e46d1f010f9d2750b6ba547446daa2b684 100644 (file)
 
 #define MSR_IA32_BBL_CR_CTL            0x119
 
+#define MSR_IA32_SYSENTER_CS           0x174
+#define MSR_IA32_SYSENTER_ESP          0x175
+#define MSR_IA32_SYSENTER_EIP          0x176
+
 #define MSR_IA32_MCG_CAP               0x179
 #define MSR_IA32_MCG_STATUS            0x17a
 #define MSR_IA32_MCG_CTL               0x17b
index ec17e06a6df00d285c426e5719e2526904f6abc6..ac467d123706cc532138ec22aac00fce21caf58d 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/types.h>
 #include <asm/sigcontext.h>
 #include <asm/cpufeature.h>
+#include <asm/msr.h>
 #include <linux/cache.h>
 #include <linux/config.h>
 #include <linux/threads.h>
@@ -416,6 +417,21 @@ struct thread_struct {
        {~0, } /* ioperm */                                     \
 }
 
+static inline void load_esp0(struct tss_struct *tss, unsigned long esp0)
+{
+       tss->esp0 = esp0;
+       if (cpu_has_sep) {
+               wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
+               wrmsr(MSR_IA32_SYSENTER_ESP, esp0, 0);
+       }
+}
+
+static inline void disable_sysenter(void)
+{
+       if (cpu_has_sep)  
+               wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
+}
+
 #define start_thread(regs, new_eip, new_esp) do {              \
        __asm__("movl %0,%%fs ; movl %0,%%gs": :"r" (0));       \
        set_fs(USER_DS);                                        \