This interface, already used in taskswitch.c, is a bit easier to use. Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> --- lib/x86/desc.c | 20 +++++++++++--------- lib/x86/desc.h | 8 +++++--- x86/taskswitch2.c | 15 +++++++-------- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/lib/x86/desc.c b/lib/x86/desc.c index ac60686..b8b5452 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -228,10 +228,11 @@ unsigned exception_error_code(void) */ static gdt_entry_t gdt[10]; -#define TSS_GDT_OFFSET 4 -void set_gdt_entry(int num, u32 base, u32 limit, u8 access, u8 gran) +void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran) { + int num = sel >> 3; + /* Setup the descriptor base address */ gdt[num].base_low = (base & 0xFFFF); gdt[num].base_middle = (base >> 16) & 0xFF; @@ -261,15 +262,15 @@ void setup_gdt(void) /* The second entry is our Code Segment. The base address * is 0, the limit is 4GBytes, it uses 4KByte granularity, * uses 32-bit opcodes, and is a Code Segment descriptor. */ - set_gdt_entry(1, 0, 0xFFFFFFFF, 0x9A, 0xcf); + set_gdt_entry(KERNEL_CS, 0, 0xFFFFFFFF, 0x9A, 0xcf); /* The third entry is our Data Segment. It's EXACTLY the * same as our code segment, but the descriptor type in * this entry's access byte says it's a Data Segment */ - set_gdt_entry(2, 0, 0xFFFFFFFF, 0x92, 0xcf); + set_gdt_entry(KERNEL_DS, 0, 0xFFFFFFFF, 0x92, 0xcf); /* Same as code register above but not present */ - set_gdt_entry(3, 0, 0xFFFFFFFF, 0x1A, 0xcf); + set_gdt_entry(NP_SEL, 0, 0xFFFFFFFF, 0x1A, 0xcf); /* Flush out the old GDT and install the new changes! */ @@ -280,7 +281,7 @@ void setup_gdt(void) "mov %0, %%fs\n\t" "mov %0, %%gs\n\t" "mov %0, %%ss\n\t" - "jmp $0x08, $.Lflush2\n\t" + "jmp $" xstr(KERNEL_CS), $.Lflush2\n\t" ".Lflush2: "::"r"(0x10)); } @@ -315,10 +316,11 @@ void setup_tss32(void) tss[i].ss0 = tss[i].ss1 = tss[i].ss2 = 0x10; tss[i].esp = tss[i].esp0 = tss[i].esp1 = tss[i].esp2 = (u32)tss_stack[i] + 4096; - tss[i].cs = 0x08; - tss[i].ds = tss[i].es = tss[i].fs = tss[i].gs = tss[i].ss = 0x10; + tss[i].cs = KERNEL_CS; + tss[i].ds = tss[i].es = tss[i].fs = tss[i].gs = + tss[i].ss = KERNEL_DS; tss[i].iomap_base = (u16)desc_size; - set_gdt_entry(TSS_GDT_OFFSET + i, (u32)&tss[i], + set_gdt_entry(TSS_MAIN + (i << 3), (u32)&tss[i], desc_size - 1, 0x89, 0x0f); } diff --git a/lib/x86/desc.h b/lib/x86/desc.h index b795aad..e3f1ea0 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -71,16 +71,18 @@ typedef struct { #define UD_VECTOR 6 #define GP_VECTOR 13 +#define KERNEL_CS 0x08 +#define KERNEL_DS 0x10 +#define NP_SEL 0x18 #define TSS_MAIN 0x20 #define TSS_INTR 0x28 - -#define NP_SEL 0x18 +#define FIRST_SPARE_SEL 0x30 unsigned exception_vector(void); unsigned exception_error_code(void); void set_idt_entry(int vec, void *addr, int dpl); void set_idt_sel(int vec, u16 sel); -void set_gdt_entry(int num, u32 base, u32 limit, u8 access, u8 gran); +void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran); void set_idt_task_gate(int vec, u16 sel); void set_intr_task_gate(int e, void *fn); void print_current_tss_info(void); diff --git a/x86/taskswitch2.c b/x86/taskswitch2.c index 08bcce9..de7e969 100644 --- a/x86/taskswitch2.c +++ b/x86/taskswitch2.c @@ -5,9 +5,8 @@ #include "processor.h" #include "vm.h" -#define FREE_GDT_INDEX 6 -#define MAIN_TSS_INDEX (FREE_GDT_INDEX + 0) -#define VM86_TSS_INDEX (FREE_GDT_INDEX + 1) +#define MAIN_TSS_SEL (FIRST_SPARE_SEL + 0) +#define VM86_TSS_SEL (FIRST_SPARE_SEL + 8) static volatile int test_count; static volatile unsigned int test_divider; @@ -217,15 +216,15 @@ void test_vm86_switch(void) vm86_start[1] = 0x0b; /* Main TSS */ - set_gdt_entry(MAIN_TSS_INDEX, (u32)&main_tss, sizeof(tss32_t) - 1, 0x89, 0); - ltr(MAIN_TSS_INDEX << 3); + set_gdt_entry(MAIN_TSS_SEL, (u32)&main_tss, sizeof(tss32_t) - 1, 0x89, 0); + ltr(MAIN_TSS_SEL); main_tss = (tss32_t) { - .prev = VM86_TSS_INDEX << 3, + .prev = VM86_TSS_SEL, .cr3 = read_cr3(), }; /* VM86 TSS (marked as busy, so we can iret to it) */ - set_gdt_entry(VM86_TSS_INDEX, (u32)&vm86_tss, sizeof(tss32_t) - 1, 0x8b, 0); + set_gdt_entry(VM86_TSS_SEL, (u32)&vm86_tss, sizeof(tss32_t) - 1, 0x8b, 0); vm86_tss = (tss32_t) { .eflags = 0x20002, .cr3 = read_cr3(), @@ -236,7 +235,7 @@ void test_vm86_switch(void) }; /* Setup task gate to main TSS for #UD */ - set_idt_task_gate(6, MAIN_TSS_INDEX << 3); + set_idt_task_gate(6, MAIN_TSS_SEL); /* Jump into VM86 task with iret, #UD lets it come back immediately */ printf("Switch to VM86 task and back\n"); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html