#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_CODE_CONFORMING,
.s = 1,
.dpl = 0,
.p = 1,
.limit_16_19 = 0xF,
.l = 1,
.d_b = 0,
.g = 0,
.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,
.l = 1,
.d_b = 0,
.g = 0,
.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,
.l = 1,
.d_b = 0,
.g = 0,
.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_CODE_CONFORMING,
.s = 1,
.dpl = 3,
.p = 1,
.limit_16_19 = 0xF,
.l = 1,
.d_b = 0,
.g = 0,
.base_24_31 = 0,
},
{ /* TSS Low */
.limit_0_15 = sizeof(struct TSS),
.base_0_15 = 0,
.base_16_23 = 0,
.type = S_SEGMENT_TYPE_TSS_AVAIL,
.avl = 1,
.s = 0,
.dpl = 0,
.p = 1,
.limit_16_19 = 0,
.l = 1,
.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;
}
x86_64_lgdt(&s_gdtr);
x86_64_flush_tss();
}