diff options
Diffstat (limited to 'arch/x86_64/gdt.c')
-rw-r--r-- | arch/x86_64/gdt.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/arch/x86_64/gdt.c b/arch/x86_64/gdt.c new file mode 100644 index 0000000..e8ca912 --- /dev/null +++ b/arch/x86_64/gdt.c @@ -0,0 +1,111 @@ +#include "arch/x86_64/tables.h" +#include "arch/x86_64/processor.h" +#include "string.h" + +static segment_descriptor_t s_gdt[] = { + { 0 }, //Kernel NULL + { //Kernel Code + .limit_0_15 = 0xFFFF, + .base_0_15 = 0x0, + .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 = 0x0 + }, + { //Kernel Data + .limit_0_15 = 0xFFFF, + .base_0_15 = 0x0, + .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 = 0x0 + }, + { 0 }, //User NULL + { //User Data + .limit_0_15 = 0xFFFF, + .base_0_15 = 0x0, + .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 = 0x0 + }, + { //User Code + .limit_0_15 = 0xFFFF, + .base_0_15 = 0x0, + .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 = 0x0 + }, + { //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 } //TSS High +}; + +void +gdt_setup(processor_t *processor) +{ + memcpy(processor->gdt, s_gdt, sizeof(s_gdt)); + + processor->gdtr.base = (uintptr_t)&s_gdt; + processor->gdtr.length = sizeof(s_gdt) - 1; + + segment_descriptor_t *tss_lo = &processor->gdt[GDT_ENTRY_TSS_LOW]; + segment_descriptor_t *tss_hi = &processor->gdt[GDT_ENTRY_TSS_HIGH]; + + uintptr_t tssb = (uintptr_t)&processor->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(tss_t); + tss_lo->limit_0_15 = tssl & 0xFFFF; + tss_lo->limit_16_19 = (tssl >> 16) & 0xF; + + processor->tss.iopb = tssl; + + extern void gdt_load(void*); + gdt_load(&processor->gdtr); + + extern void tss_flush(uint16_t); + tss_flush(GDT_ENTRY_TSS_LOW * sizeof(segment_descriptor_t)); +} |