Commit 783faefa authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Fix sysenter disabling in vm86 mode

From: Brian Gerst <bgerst@didntduck.org>

The current code disables sysenter when first entering vm86 mode, but does
not disable it again when coming back to a vm86 task after a task switch.
parent ffd0cf49
...@@ -510,7 +510,7 @@ void __init cpu_init (void) ...@@ -510,7 +510,7 @@ void __init cpu_init (void)
BUG(); BUG();
enter_lazy_tlb(&init_mm, current); enter_lazy_tlb(&init_mm, current);
load_esp0(t, thread->esp0); load_esp0(t, thread);
set_tss_desc(cpu,t); set_tss_desc(cpu,t);
cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff; cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
load_TR_desc(); load_TR_desc();
......
...@@ -507,7 +507,7 @@ struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct ...@@ -507,7 +507,7 @@ struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct
/* /*
* Reload esp0, LDT and the page table pointer: * Reload esp0, LDT and the page table pointer:
*/ */
load_esp0(tss, next->esp0); load_esp0(tss, next);
/* /*
* Load the per-thread Thread-Local Storage descriptor. * Load the per-thread Thread-Local Storage descriptor.
......
...@@ -124,7 +124,8 @@ struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs) ...@@ -124,7 +124,8 @@ struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
tss = init_tss + get_cpu(); tss = init_tss + get_cpu();
current->thread.esp0 = current->thread.saved_esp0; current->thread.esp0 = current->thread.saved_esp0;
load_esp0(tss, current->thread.esp0); current->thread.sysenter_cs = __KERNEL_CS;
load_esp0(tss, &current->thread);
current->thread.saved_esp0 = 0; current->thread.saved_esp0 = 0;
put_cpu(); put_cpu();
...@@ -301,8 +302,10 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk ...@@ -301,8 +302,10 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs)); asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs));
tss = init_tss + get_cpu(); tss = init_tss + get_cpu();
tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
disable_sysenter(tss); if (cpu_has_sep)
tsk->thread.sysenter_cs = 0;
load_esp0(tss, &tsk->thread);
put_cpu(); put_cpu();
tsk->thread.screen_bitmap = info->screen_bitmap; tsk->thread.screen_bitmap = info->screen_bitmap;
......
...@@ -407,6 +407,7 @@ struct thread_struct { ...@@ -407,6 +407,7 @@ struct thread_struct {
/* cached TLS descriptors. */ /* cached TLS descriptors. */
struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES]; struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
unsigned long esp0; unsigned long esp0;
unsigned long sysenter_cs;
unsigned long eip; unsigned long eip;
unsigned long esp; unsigned long esp;
unsigned long fs; unsigned long fs;
...@@ -428,6 +429,7 @@ struct thread_struct { ...@@ -428,6 +429,7 @@ struct thread_struct {
#define INIT_THREAD { \ #define INIT_THREAD { \
.vm86_info = NULL, \ .vm86_info = NULL, \
.sysenter_cs = __KERNEL_CS, \
.io_bitmap_ptr = NULL, \ .io_bitmap_ptr = NULL, \
} }
...@@ -447,21 +449,13 @@ struct thread_struct { ...@@ -447,21 +449,13 @@ struct thread_struct {
.io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, \ .io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, \
} }
static inline void load_esp0(struct tss_struct *tss, unsigned long esp0) static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread)
{ {
tss->esp0 = esp0; tss->esp0 = thread->esp0;
/* This can only happen when SEP is enabled, no need to test "SEP"arately */ /* This can only happen when SEP is enabled, no need to test "SEP"arately */
if ((unlikely(tss->ss1 != __KERNEL_CS))) { if (unlikely(tss->ss1 != thread->sysenter_cs)) {
tss->ss1 = __KERNEL_CS; tss->ss1 = thread->sysenter_cs;
wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
}
}
static inline void disable_sysenter(struct tss_struct *tss)
{
if (cpu_has_sep) {
tss->ss1 = 0;
wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment