- 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
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();
/*
* 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.
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();
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;
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)
#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 */
#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)
#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
#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>
{~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); \