summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/gdt.c
blob: d996dcb5637e80c7ff9d9748400c208d306ea7f9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#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();
}