diff --git a/include/x86/gdt.h b/include/x86/gdt.h index 6eaf402..50e4860 100644 --- a/include/x86/gdt.h +++ b/include/x86/gdt.h @@ -21,6 +21,25 @@ struct GDTR { uint64_t base; }; +__attribute__ ((packed)) +struct TSS { + uint32_t reserved0; + uint64_t rsp0; + uint64_t rsp1; + uint64_t rsp2; + uint64_t reserved1; + uint64_t ist1; + uint64_t ist2; + uint64_t ist3; + uint64_t ist4; + uint64_t ist5; + uint64_t ist6; + uint64_t ist7; + uint64_t reserved2; + uint16_t reserved3; + uint16_t iopb; +}; + static inline struct GDTR storegdt(void) { diff --git a/src/proc.c b/src/proc.c index add365d..e25b74f 100644 --- a/src/proc.c +++ b/src/proc.c @@ -3,18 +3,21 @@ #include "procvisor.h" #include "bootstrap.h" -#define GDT_SIZE ( 3 * sizeof (struct segdescr)) +#define GDT_SIZE ( 5 * sizeof (struct segdescr)) #define IDT_SIZE (256 * sizeof (struct intdescr)) +#define TSS_SIZE (sizeof (struct TSS)) struct procvisor *procvisors[256]; static void -proc_fill_host_gdt(struct GDTR gdtr) +proc_fill_host_gdt(struct GDTR gdtr, struct TSS *tss) { struct segdescr *descrs = (void *)gdtr.base; setsegdescr(&descrs[0], 0, 0, 0, 0); // null setsegdescr(&descrs[1], 0, 0xffffff, 0x9B, 0xA0); // code setsegdescr(&descrs[2], 0, 0xffffff, 0x93, 0xC0); // data + setsegdescr(&descrs[3], (uintptr_t)tss, TSS_SIZE - 1, 0x89, 0x00); // TSS + *(uint64_t *)(&descrs[4]) = (uintptr_t)tss >> 32;// TSS (continued) } static void @@ -37,22 +40,26 @@ proc_setup(void) top -= sizeof (struct procvisor); struct procvisor *pv = (void *)top; + // Carve out IDT + top -= IDT_SIZE; + pv->host_idtr.base = (uintptr_t)top; + pv->host_idtr.limit = IDT_SIZE - 1; + // Carve out GDT top -= GDT_SIZE; pv->host_gdtr.base = (uintptr_t)top; pv->host_gdtr.limit = GDT_SIZE - 1; - // Carve out IDT - top -= IDT_SIZE; - pv->host_idtr.base = (uintptr_t)top; - pv->host_idtr.limit = IDT_SIZE - 1; + // Carve out TSS + top -= TSS_SIZE; + pv->host_tss = (void *)top; // Leave the rest as stack top -= ((uintptr_t)top & 0xf); // align on 16-byte boundary pv->host_stack = top; // Fill out GDT & IDT structures - proc_fill_host_gdt(pv->host_gdtr); + proc_fill_host_gdt(pv->host_gdtr, pv->host_tss); proc_fill_host_idt(pv->host_idtr); // Register procvisor & return diff --git a/src/procvisor.h b/src/procvisor.h index a710c0d..5d332c2 100644 --- a/src/procvisor.h +++ b/src/procvisor.h @@ -7,9 +7,10 @@ /* Per-processor visor state and structures */ struct procvisor { - void *host_stack; - struct GDTR host_gdtr; struct IDTR host_idtr; + struct GDTR host_gdtr; + struct TSS *host_tss; + void *host_stack; //void *host_cr3; //void *vmctl; }; diff --git a/src/vintel.c b/src/vintel.c index aac4a21..f60baeb 100644 --- a/src/vintel.c +++ b/src/vintel.c @@ -181,6 +181,7 @@ vintel_init_host(void) vmwrite(HOST_DS_SELECTOR, 0x10); vmwrite(HOST_FS_SELECTOR, 0x00); vmwrite(HOST_GS_SELECTOR, 0x00); + vmwrite(HOST_TR_SELECTOR, 0x18); // Set control registers vmwrite(HOST_CR0, readcr0());