#include "tables.h" #include "tss.h" enum { GDT_SEGMENT_KERNEL_NULL = 0, GDT_SEGMENT_KERNEL_CODE, GDT_SEGMENT_KERNEL_DATA, GDT_SEGMENT_USER_NULL, GDT_SEGMENT_USER_DATA, GDT_SEGMENT_USER_CODE, GDT_SEGMENT_TSS_LOW, GDT_SEGMENT_TSS_HIGH, GDT_SEGMENT_COUNT }; __attribute__((aligned(0x1000))) static struct SegmentDescriptor s_gdtd[GDT_SEGMENT_COUNT] = { { 0 }, /* Kernel NULL */ { /* Kernel Code (64-bit RO EX DPL0) */ .limit_0_15 = 0xFFFF, .base_0_15 = 0, .base_16_23 = 0, .type = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_WRITEABLE, .s = 1, .dpl = 0, .p = 1, .limit_16_19 = 0xF, .avl = 0, .l = 1, .d_b = 0, .g = 1, .base_24_31 = 0 }, { /* Kernel Data (64-bit RW DPL0) */ .limit_0_15 = 0xFFFF, .base_0_15 = 0, .base_16_23 = 0, .type = CD_SEGMENT_TYPE_WRITEABLE, .s = 1, .dpl = 0, .p = 1, .limit_16_19 = 0xF, .avl = 0, .l = 0, .d_b = 1, .g = 1, .base_24_31 = 0 }, { 0 }, /* User NULL */ { /* User Data (64-bit RO EX DPL3)*/ .limit_0_15 = 0xFFFF, .base_0_15 = 0, .base_16_23 = 0, .type = CD_SEGMENT_TYPE_WRITEABLE, .s = 1, .dpl = 3, .p = 1, .limit_16_19 = 0xF, .avl = 0, .l = 0, .d_b = 1, .g = 1, .base_24_31 = 0, }, { /* User Code (64-bit RO EX DPL3)*/ .limit_0_15 = 0xFFFF, .base_0_15 = 0, .base_16_23 = 0, .type = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_WRITEABLE, .s = 1, .dpl = 3, .p = 1, .limit_16_19 = 0xF, .avl = 0, .l = 1, .d_b = 0, .g = 1, .base_24_31 = 0, }, { /* TSS Low */ .limit_0_15 = 0, .base_0_15 = 0, .base_16_23 = 0, .type = S_SEGMENT_TYPE_TSS_AVAIL, .avl = 0, .s = 0, .dpl = 0, .p = 1, .limit_16_19 = 0, .l = 0, .d_b = 0, .g = 0, .base_24_31 = 0, }, { 0 } }; static struct XDTR s_gdtr = { .length = sizeof(s_gdtd) - 1, .address = (uintptr_t)&s_gdtd }; static struct TSS s_tss = { }; extern void x86_64_lgdt(struct XDTR *gdtr); extern void x86_64_flush_tss(void); void x86_64_load_gdt(void) { { struct SegmentDescriptor *tss_lo = &s_gdtd[GDT_SEGMENT_TSS_LOW]; struct SegmentDescriptor *tss_hi = &s_gdtd[GDT_SEGMENT_TSS_HIGH]; uintptr_t tssb = (uintptr_t)&s_tss; tss_lo->base_0_15 = tssb & 0xFFFF; tss_lo->base_16_23 = (tssb >> 16) & 0xFF; tss_lo->base_24_31 = (tssb >> 24) & 0xFF; tss_hi->limit_0_15 = (tssb >> 32) & 0xFFFF; tss_hi->base_0_15 = (tssb >> 48) & 0xFFFF; size_t tssl = sizeof(struct TSS) - 1; tss_lo->limit_0_15 = tssl & 0xFFFF; tss_lo->limit_16_19 = (tssl >> 16) & 0xF; s_tss.iobp = sizeof(struct TSS); } x86_64_lgdt(&s_gdtr); x86_64_flush_tss(); } void tss_set_rsp(uint8_t dpl, uintptr_t rsp) { s_tss.rsp[dpl][0] = rsp & 0xFFFFFFFF; s_tss.rsp[dpl][1] = (rsp >> 32) & 0xFFFFFFFF; }