diff --git a/am/include/x86.h b/am/include/x86.h index 73de4a0f..49a66f34 100644 --- a/am/include/x86.h +++ b/am/include/x86.h @@ -1,6 +1,3 @@ -#ifndef __X86_H__ -#define __X86_H__ - // CPU rings #define DPL_KERN 0x0 // Kernel (ring 0) #define DPL_USER 0x3 // User (ring 3) @@ -120,30 +117,36 @@ typedef struct { uint32_t base_31_24 : 8; // High bits of segment base address } SegDesc; +#define SEG16(type, base, lim, dpl) (SegDesc) \ +{ (lim) & 0xffff, (uintptr_t)(base) & 0xffff, \ + ((uintptr_t)(base) >> 16) & 0xff, type, 0, dpl, 1, \ + (uintptr_t)(lim) >> 16, 0, 0, 1, 0, (uintptr_t)(base) >> 24 } + +#define SEG32(type, base, lim, dpl) (SegDesc) \ +{ ((lim) >> 12) & 0xffff, (uintptr_t)(base) & 0xffff, \ + ((uintptr_t)(base) >> 16) & 0xff, type, 1, dpl, 1, \ + (uintptr_t)(lim) >> 28, 0, 0, 1, 1, (uintptr_t)(base) >> 24 } + #define SEG64(type, dpl) (SegDesc) \ { 0, 0, 0, type, 1, dpl, 1, 0, 0, 1, 0, 0 } -#define SEG32(type, base, lim, dpl) (SegDesc) \ -{ ((lim) >> 12) & 0xffff, (uint32_t)(base) & 0xffff, \ - ((uint32_t)(base) >> 16) & 0xff, type, 1, dpl, 1, \ - (uint32_t)(lim) >> 28, 0, 0, 1, 1, (uint32_t)(base) >> 24 } - -#define SEG16(type, base, lim, dpl) (SegDesc) \ -{ (lim) & 0xffff, (uint32_t)(base) & 0xffff, \ +#define SEGTSS64(type, base, lim, dpl) (SegDesc) \ +{ (lim) & 0xffff, (uint32_t)(base) & 0xffff, \ ((uint32_t)(base) >> 16) & 0xff, type, 0, dpl, 1, \ - (uint32_t)(lim) >> 16, 0, 0, 1, 0, (uint32_t)(base) >> 24 } + (uint32_t)(lim) >> 16, 0, 0, 0, 0, (uint32_t)(base) >> 24 } + // Gate descriptors for interrupts and traps typedef struct { - uint32_t off_15_0 : 16; // Low 16 bits of offset in segment - uint32_t cs : 16; // Code segment selector - uint32_t args : 5; // # args, 0 for interrupt/trap gates - uint32_t rsv1 : 3; // Reserved(should be zero I guess) - uint32_t type : 4; // Type(STS_{TG,IG32,TG32}) - uint32_t s : 1; // Must be 0 (system) - uint32_t dpl : 2; // Descriptor(meaning new) privilege level - uint32_t p : 1; // Present - uint32_t off_31_16 : 16; // High bits of offset in segment + uint32_t off_15_0 : 16; // Low 16 bits of offset in segment + uint32_t cs : 16; // Code segment selector + uint32_t args : 5; // # args, 0 for interrupt/trap gates + uint32_t rsv1 : 3; // Reserved(should be zero I guess) + uint32_t type : 4; // Type(STS_{TG,IG32,TG32}) + uint32_t s : 1; // Must be 0 (system) + uint32_t dpl : 2; // Descriptor(meaning new) privilege level + uint32_t p : 1; // Present + uint32_t off_31_16 : 16; // High bits of offset in segment } GateDesc32; #define GATE32(type, cs, entry, dpl) (GateDesc32) \ @@ -151,17 +154,17 @@ typedef struct { 1, (uint32_t)(entry) >> 16 } typedef struct { - uint32_t off_15_0 : 16; - uint32_t cs : 16; - uint32_t isv : 3; - uint32_t zero1 : 5; - uint32_t type : 4; - uint32_t zero2 : 1; - uint32_t dpl : 2; - uint32_t p : 1; + uint32_t off_15_0 : 16; + uint32_t cs : 16; + uint32_t isv : 3; + uint32_t zero1 : 5; + uint32_t type : 4; + uint32_t zero2 : 1; + uint32_t dpl : 2; + uint32_t p : 1; uint32_t off_31_16 : 16; uint32_t off_63_32 : 32; - uint32_t rsv : 32; + uint32_t rsv : 32; } GateDesc64; #define GATE64(type, cs, entry, dpl) (GateDesc64) \ @@ -323,6 +326,4 @@ static inline void stack_switch_call(void *sp, void *entry, uintptr_t arg) { ); } -#endif - -#endif +#endif // __ASSEMBLER__ diff --git a/am/src/x86_64/qemu/trm.c b/am/src/x86_64/qemu/trm.c index 64b593a0..be6c6836 100644 --- a/am/src/x86_64/qemu/trm.c +++ b/am/src/x86_64/qemu/trm.c @@ -97,14 +97,13 @@ void __am_lapic_init() { void __am_percpu_initgdt() { #if __x86_64__ SegDesc *gdt = CPU->gdt; - uint64_t tss = (uint64_t)(&CPU->tss); - gdt[SEG_KCODE] = SEG64(STA_X | STA_R, DPL_KERN); - gdt[SEG_KDATA] = SEG64(STA_W, DPL_KERN); - gdt[SEG_UCODE] = SEG64(STA_X | STA_R, DPL_USER); - gdt[SEG_UDATA] = SEG64(STA_W, DPL_USER); - ((uint64_t *)gdt)[SEG_TSS+0] = (sizeof(CPU->tss) - 1) | ((tss & 0xffffff) << 16) | - (0x00e9LL << 40) | (((tss >> 24) & 0xff) << 56); - ((uint64_t *)gdt)[SEG_TSS+1] = (tss >> 32); + TSS64 *tss = &CPU->tss; + gdt[SEG_KCODE] = SEG64(STA_X | STA_R, DPL_KERN); + gdt[SEG_KDATA] = SEG64(STA_W, DPL_KERN); + gdt[SEG_UCODE] = SEG64(STA_X | STA_R, DPL_USER); + gdt[SEG_UDATA] = SEG64(STA_W, DPL_USER); + gdt[SEG_TSS] = SEG16(STS_T32A, tss, sizeof(*tss)-1, DPL_KERN); + bug_on((uintptr_t)tss >> 32); set_gdt(gdt, sizeof(gdt[0]) * (NR_SEG + 1)); set_tr(KSEL(SEG_TSS)); #else diff --git a/am/src/x86_64/qemu/x86_64-qemu.h b/am/src/x86_64/qemu/x86_64-qemu.h index e4e16bbd..8688b63b 100644 --- a/am/src/x86_64/qemu/x86_64-qemu.h +++ b/am/src/x86_64/qemu/x86_64-qemu.h @@ -1,6 +1,3 @@ -#ifndef __X86_64_QEMU_H__ -#define __X86_64_QEMU_H__ - #define MAX_CPU 8 #define BOOT_REC_ADDR 0x07000 #define ARG_ADDR 0x10000 @@ -132,5 +129,3 @@ void __am_percpu_initlapic(); void __am_stop_the_world(); #endif - -#endif