#ifndef _KERNEL_PLATFORM_X86_GDT_H #define _KERNEL_PLATFORM_X86_GDT_H #include #include #ifdef __x86_64__ #define GDT_MAX_ENTRIES 7 // TSS takes 2 entries. // Marking that code segment contains native 64-bit code. #define GDT_LONGMODE_FLAG 1 #define GDT_DB_FLAG 0 #else #define GDT_MAX_ENTRIES 6 #define GDT_LONGMODE_FLAG 0 #define GDT_DB_FLAG 1 #endif #define GDT_SEG_NULL 0 // kernel code #define GDT_SEG_KCODE 1 // kernel code #define GDT_SEG_KDATA 2 // kernel data+stack #define GDT_SEG_UCODE 3 // user code #define GDT_SEG_UDATA 4 // user data+stack #define GDT_SEG_TSS 5 // task state NOT USED CURRENTLY #define GDT_SEGF_X 0x8 // exec #define GDT_SEGF_A 0x1 // accessed #define GDT_SEGF_R 0x2 // readable (if exec) #define GDT_SEGF_C 0x4 // conforming seg (if exec) #define GDT_SEGF_W 0x2 // writeable (if non-exec) #define GDT_SEGF_D 0x4 // grows down (if non-exec) #define FL_IF 0x00000200 #define DPL_KERN 0x0 #define DPL_USER 0x3 struct PACKED gdt_desc { union { struct { uint32_t lim_15_0 : 16; uint32_t base_15_0 : 16; uint32_t base_23_16 : 8; uint32_t type : 4; uint32_t dt : 1; uint32_t dpl : 2; uint32_t p : 1; uint32_t lim_19_16 : 4; uint32_t avl : 1; uint32_t l : 1; uint32_t db : 1; uint32_t g : 1; uint32_t base_31_24 : 8; }; uint32_t raw; }; }; typedef struct gdt_desc gdt_desc_t; extern gdt_desc_t gdt[GDT_MAX_ENTRIES]; #define GDT_SEG_CODE_DESC(vtype, vbase, vlimit, vdpl) \ (gdt_desc_t) \ { \ .lim_15_0 = ((vlimit) >> 12) & 0xffff, \ .base_15_0 = (uint32_t)(vbase)&0xffff, \ .base_23_16 = ((uint32_t)(vbase) >> 16) & 0xff, \ .type = vtype, \ .dt = 1, \ .dpl = vdpl, \ .p = 1, \ .lim_19_16 = ((uint32_t)(vlimit) >> 28), \ .avl = 0, \ .l = GDT_LONGMODE_FLAG, \ .db = GDT_DB_FLAG, \ .g = 1, \ .base_31_24 = (uint32_t)(vbase) >> 24 \ } #define GDT_SEG_DATA_DESC(vtype, vbase, vlimit, vdpl) \ (gdt_desc_t) \ { \ .lim_15_0 = ((vlimit) >> 12) & 0xffff, \ .base_15_0 = (uint32_t)(vbase)&0xffff, \ .base_23_16 = ((uint32_t)(vbase) >> 16) & 0xff, \ .type = vtype, \ .dt = 1, \ .dpl = vdpl, \ .p = 1, \ .lim_19_16 = ((uint32_t)(vlimit) >> 28), \ .avl = 0, \ .l = 0, \ .db = 1, \ .g = 1, \ .base_31_24 = (uint32_t)(vbase) >> 24 \ } #define GDT_SEG_TSS_DESC(vtype, vbase, vlimit, vdpl) \ (gdt_desc_t) \ { \ .lim_15_0 = ((vlimit)) & 0xffff, \ .base_15_0 = (uint32_t)(vbase)&0xffff, \ .base_23_16 = ((uint32_t)(vbase) >> 16) & 0xff, \ .type = vtype, \ .dt = 0, \ .dpl = vdpl, \ .p = 1, \ .lim_19_16 = ((uint32_t)(vlimit) >> 16), \ .avl = 0, \ .l = 0, \ .db = 0, \ .g = 0, \ .base_31_24 = (uint32_t)(vbase) >> 24 \ } #define GDT_SEG_SET_RAW(rawvalue) \ (gdt_desc_t) \ { \ .raw = rawvalue \ } void gdt_setup(); #endif // _KERNEL_PLATFORM_X86_GDT_H