summaryrefslogblamecommitdiffstats
path: root/arch/x86_64/gdt.c
blob: d996dcb5637e80c7ff9d9748400c208d306ea7f9 (plain) (tree)




























































































































                                                                         
#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();
}