Commit a75c54f9 authored by Rusty Russell's avatar Rusty Russell Committed by Andi Kleen

[PATCH] i386: i386 separate hardware-defined TSS from Linux additions

On Thu, 2007-03-29 at 13:16 +0200, Andi Kleen wrote:
> Please clean it up properly with two structs.

Not sure about this, now I've done it.  Running it here.

If you like it, I can do x86-64 as well.

==
lguest defines its own TSS struct because the "struct tss_struct"
contains linux-specific additions.  Andi asked me to split the struct
in processor.h.

Unfortunately it makes usage a little awkward.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
parent 82d1bb72
...@@ -93,7 +93,7 @@ void foo(void) ...@@ -93,7 +93,7 @@ void foo(void)
OFFSET(pbe_next, pbe, next); OFFSET(pbe_next, pbe, next);
/* Offset from the sysenter stack to tss.esp0 */ /* Offset from the sysenter stack to tss.esp0 */
DEFINE(TSS_sysenter_esp0, offsetof(struct tss_struct, esp0) - DEFINE(TSS_sysenter_esp0, offsetof(struct tss_struct, x86_tss.esp0) -
sizeof(struct tss_struct)); sizeof(struct tss_struct));
DEFINE(PAGE_SIZE_asm, PAGE_SIZE); DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
......
...@@ -33,7 +33,7 @@ static void doublefault_fn(void) ...@@ -33,7 +33,7 @@ static void doublefault_fn(void)
printk("double fault, tss at %08lx\n", tss); printk("double fault, tss at %08lx\n", tss);
if (ptr_ok(tss)) { if (ptr_ok(tss)) {
struct tss_struct *t = (struct tss_struct *)tss; struct i386_hw_tss *t = (struct i386_hw_tss *)tss;
printk("eip = %08lx, esp = %08lx\n", t->eip, t->esp); printk("eip = %08lx, esp = %08lx\n", t->eip, t->esp);
...@@ -49,18 +49,21 @@ static void doublefault_fn(void) ...@@ -49,18 +49,21 @@ static void doublefault_fn(void)
} }
struct tss_struct doublefault_tss __cacheline_aligned = { struct tss_struct doublefault_tss __cacheline_aligned = {
.esp0 = STACK_START, .x86_tss = {
.ss0 = __KERNEL_DS, .esp0 = STACK_START,
.ldt = 0, .ss0 = __KERNEL_DS,
.io_bitmap_base = INVALID_IO_BITMAP_OFFSET, .ldt = 0,
.io_bitmap_base = INVALID_IO_BITMAP_OFFSET,
.eip = (unsigned long) doublefault_fn, .eip = (unsigned long) doublefault_fn,
.eflags = X86_EFLAGS_SF | 0x2, /* 0x2 bit is always set */ /* 0x2 bit is always set */
.esp = STACK_START, .eflags = X86_EFLAGS_SF | 0x2,
.es = __USER_DS, .esp = STACK_START,
.cs = __KERNEL_CS, .es = __USER_DS,
.ss = __KERNEL_DS, .cs = __KERNEL_CS,
.ds = __USER_DS, .ss = __KERNEL_DS,
.ds = __USER_DS,
.__cr3 = __pa(swapper_pg_dir) .__cr3 = __pa(swapper_pg_dir)
}
}; };
...@@ -114,7 +114,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) ...@@ -114,7 +114,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
* Reset the owner so that a process switch will not set * Reset the owner so that a process switch will not set
* tss->io_bitmap_base to IO_BITMAP_OFFSET. * tss->io_bitmap_base to IO_BITMAP_OFFSET.
*/ */
tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
tss->io_bitmap_owner = NULL; tss->io_bitmap_owner = NULL;
put_cpu(); put_cpu();
......
...@@ -375,7 +375,7 @@ void exit_thread(void) ...@@ -375,7 +375,7 @@ void exit_thread(void)
t->io_bitmap_max = 0; t->io_bitmap_max = 0;
tss->io_bitmap_owner = NULL; tss->io_bitmap_owner = NULL;
tss->io_bitmap_max = 0; tss->io_bitmap_max = 0;
tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
put_cpu(); put_cpu();
} }
} }
...@@ -554,7 +554,7 @@ static noinline void __switch_to_xtra(struct task_struct *next_p, ...@@ -554,7 +554,7 @@ static noinline void __switch_to_xtra(struct task_struct *next_p,
* Disable the bitmap via an invalid offset. We still cache * Disable the bitmap via an invalid offset. We still cache
* the previous bitmap owner and the IO bitmap contents: * the previous bitmap owner and the IO bitmap contents:
*/ */
tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
return; return;
} }
...@@ -564,7 +564,7 @@ static noinline void __switch_to_xtra(struct task_struct *next_p, ...@@ -564,7 +564,7 @@ static noinline void __switch_to_xtra(struct task_struct *next_p,
* matches the next task, we dont have to do anything but * matches the next task, we dont have to do anything but
* to set a valid offset in the TSS: * to set a valid offset in the TSS:
*/ */
tss->io_bitmap_base = IO_BITMAP_OFFSET; tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
return; return;
} }
/* /*
...@@ -576,7 +576,7 @@ static noinline void __switch_to_xtra(struct task_struct *next_p, ...@@ -576,7 +576,7 @@ static noinline void __switch_to_xtra(struct task_struct *next_p,
* redundant copies when the currently switched task does not * redundant copies when the currently switched task does not
* perform any I/O during its timeslice. * perform any I/O during its timeslice.
*/ */
tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
} }
/* /*
......
...@@ -183,10 +183,10 @@ void enable_sep_cpu(void) ...@@ -183,10 +183,10 @@ void enable_sep_cpu(void)
return; return;
} }
tss->ss1 = __KERNEL_CS; tss->x86_tss.ss1 = __KERNEL_CS;
tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss; tss->x86_tss.esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0); wrmsr(MSR_IA32_SYSENTER_ESP, tss->x86_tss.esp1, 0);
wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0); wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0);
put_cpu(); put_cpu();
} }
......
...@@ -596,7 +596,7 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs, ...@@ -596,7 +596,7 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs,
* and we set the offset field correctly. Then we let the CPU to * and we set the offset field correctly. Then we let the CPU to
* restart the faulting instruction. * restart the faulting instruction.
*/ */
if (tss->io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY && if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
thread->io_bitmap_ptr) { thread->io_bitmap_ptr) {
memcpy(tss->io_bitmap, thread->io_bitmap_ptr, memcpy(tss->io_bitmap, thread->io_bitmap_ptr,
thread->io_bitmap_max); thread->io_bitmap_max);
...@@ -609,7 +609,7 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs, ...@@ -609,7 +609,7 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs,
thread->io_bitmap_max, 0xff, thread->io_bitmap_max, 0xff,
tss->io_bitmap_max - thread->io_bitmap_max); tss->io_bitmap_max - thread->io_bitmap_max);
tss->io_bitmap_max = thread->io_bitmap_max; tss->io_bitmap_max = thread->io_bitmap_max;
tss->io_bitmap_base = IO_BITMAP_OFFSET; tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
tss->io_bitmap_owner = thread; tss->io_bitmap_owner = thread;
put_cpu(); put_cpu();
return; return;
......
...@@ -230,14 +230,14 @@ static void vmi_set_tr(void) ...@@ -230,14 +230,14 @@ static void vmi_set_tr(void)
static void vmi_load_esp0(struct tss_struct *tss, static void vmi_load_esp0(struct tss_struct *tss,
struct thread_struct *thread) struct thread_struct *thread)
{ {
tss->esp0 = thread->esp0; tss->x86_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 != thread->sysenter_cs)) { if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
tss->ss1 = thread->sysenter_cs; tss->x86_tss.ss1 = thread->sysenter_cs;
wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0); wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
} }
vmi_ops.set_kernel_stack(__KERNEL_DS, tss->esp0); vmi_ops.set_kernel_stack(__KERNEL_DS, tss->x86_tss.esp0);
} }
static void vmi_flush_tlb_user(void) static void vmi_flush_tlb_user(void)
......
...@@ -291,7 +291,8 @@ typedef struct { ...@@ -291,7 +291,8 @@ typedef struct {
struct thread_struct; struct thread_struct;
struct tss_struct { /* This is the TSS defined by the hardware. */
struct i386_hw_tss {
unsigned short back_link,__blh; unsigned short back_link,__blh;
unsigned long esp0; unsigned long esp0;
unsigned short ss0,__ss0h; unsigned short ss0,__ss0h;
...@@ -315,6 +316,11 @@ struct tss_struct { ...@@ -315,6 +316,11 @@ struct tss_struct {
unsigned short gs, __gsh; unsigned short gs, __gsh;
unsigned short ldt, __ldth; unsigned short ldt, __ldth;
unsigned short trace, io_bitmap_base; unsigned short trace, io_bitmap_base;
} __attribute__((packed));
struct tss_struct {
struct i386_hw_tss x86_tss;
/* /*
* The extra 1 is there because the CPU will access an * The extra 1 is there because the CPU will access an
* additional byte beyond the end of the IO permission * additional byte beyond the end of the IO permission
...@@ -381,10 +387,12 @@ struct thread_struct { ...@@ -381,10 +387,12 @@ struct thread_struct {
* be within the limit. * be within the limit.
*/ */
#define INIT_TSS { \ #define INIT_TSS { \
.esp0 = sizeof(init_stack) + (long)&init_stack, \ .x86_tss = { \
.ss0 = __KERNEL_DS, \ .esp0 = sizeof(init_stack) + (long)&init_stack, \
.ss1 = __KERNEL_CS, \ .ss0 = __KERNEL_DS, \
.io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \ .ss1 = __KERNEL_CS, \
.io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
}, \
.io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, \ .io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, \
} }
...@@ -493,10 +501,10 @@ static inline void rep_nop(void) ...@@ -493,10 +501,10 @@ static inline void rep_nop(void)
static inline void native_load_esp0(struct tss_struct *tss, struct thread_struct *thread) static inline void native_load_esp0(struct tss_struct *tss, struct thread_struct *thread)
{ {
tss->esp0 = thread->esp0; tss->x86_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 != thread->sysenter_cs)) { if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
tss->ss1 = thread->sysenter_cs; tss->x86_tss.ss1 = thread->sysenter_cs;
wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0); wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 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