Boot framework rework (#45)
[lunaix-os.git] / lunaix-os / arch / x86 / mm / gdt.c
1 #include <lunaix/types.h>
2 #include "sys/x86_isa.h"
3
4 #define SD_TYPE(x) (x << 8)
5 #define SD_CODE_DATA(x) (x << 12)
6 #define SD_DPL(x) (x << 13)
7 #define SD_PRESENT(x) (x << 15)
8 #define SD_AVL(x) (x << 20)
9 #define SD_64BITS(x) (x << 21)
10 #define SD_32BITS(x) (x << 22)
11 #define SD_4K_GRAN(x) (x << 23)
12
13 #define SEG_LIM_L(x) (x & 0x0ffff)
14 #define SEG_LIM_H(x) (x & 0xf0000)
15 #define SEG_BASE_L(x) ((x & 0x0000ffff) << 16)
16 #define SEG_BASE_M(x) ((x & 0x00ff0000) >> 16)
17 #define SEG_BASE_H(x) (x & 0xff000000)
18
19 #define SEG_DATA_RD 0x00        // Read-Only
20 #define SEG_DATA_RDA 0x01       // Read-Only, accessed
21 #define SEG_DATA_RDWR 0x02      // Read/Write
22 #define SEG_DATA_RDWRA 0x03     // Read/Write, accessed
23 #define SEG_DATA_RDEXPD 0x04    // Read-Only, expand-down
24 #define SEG_DATA_RDEXPDA 0x05   // Read-Only, expand-down, accessed
25 #define SEG_DATA_RDWREXPD 0x06  // Read/Write, expand-down
26 #define SEG_DATA_RDWREXPDA 0x07 // Read/Write, expand-down, accessed
27 #define SEG_CODE_EX 0x08        // Execute-Only
28 #define SEG_CODE_EXA 0x09       // Execute-Only, accessed
29 #define SEG_CODE_EXRD 0x0A      // Execute/Read
30 #define SEG_CODE_EXRDA 0x0B     // Execute/Read, accessed
31 #define SEG_CODE_EXC 0x0C       // Execute-Only, conforming
32 #define SEG_CODE_EXCA 0x0D      // Execute-Only, conforming, accessed
33 #define SEG_CODE_EXRDC 0x0E     // Execute/Read, conforming
34 #define SEG_CODE_EXRDCA 0x0F    // Execute/Read, conforming, accessed
35
36 #define BIT64   (SD_64BITS(1) | SD_32BITS(0))
37 #define BIT32   (SD_64BITS(0) | SD_32BITS(1))
38
39 #define SEG_R0_CODE                                                            \
40     SD_TYPE(SEG_CODE_EXRD) | SD_CODE_DATA(1) | SD_DPL(0) | SD_PRESENT(1) |     \
41       SD_AVL(0) | SD_4K_GRAN(1)
42
43 #define SEG_R0_DATA                                                            \
44     SD_TYPE(SEG_DATA_RDWR) | SD_CODE_DATA(1) | SD_DPL(0) | SD_PRESENT(1) |     \
45       SD_AVL(0) | SD_4K_GRAN(1)
46
47 #define SEG_R3_CODE                                                            \
48     SD_TYPE(SEG_CODE_EXRD) | SD_CODE_DATA(1) | SD_DPL(3) | SD_PRESENT(1) |     \
49       SD_AVL(0) | SD_4K_GRAN(1)
50
51 #define SEG_R3_DATA                                                            \
52     SD_TYPE(SEG_DATA_RDWR) | SD_CODE_DATA(1) | SD_DPL(3) | SD_PRESENT(1) |     \
53       SD_AVL(0) | SD_4K_GRAN(1)
54
55 #define SEG_TSS SD_TYPE(9) | SD_DPL(0) | SD_PRESENT(1)
56
57
58 #ifdef CONFIG_ARCH_X86_64
59
60 x86_segdesc_t _gdt[8];
61 u16_t _gdt_limit = sizeof(_gdt) - 1;
62
63 static inline void
64 _set_gdt_entry(int index, int dpl, unsigned int flags)
65 {
66     u64_t desc = 0;
67     desc |= flags | BIT64;
68     desc |= 0xf << 16;
69     desc = desc << 32;
70     desc |= 0xffff;
71
72     _gdt[index] = desc;
73 }
74
75 static inline void
76 _set_tss(int index, ptr_t base, size_t size)
77 {
78     struct x86_sysdesc* tssd;
79     u32_t attr;
80     
81     size = size - 1;
82     tssd = (struct x86_sysdesc*)&_gdt[index];
83     tssd->hi = base >> 32;
84     
85     attr = SD_4K_GRAN(1) | SD_PRESENT(1) | SD_TYPE(9) | SD_DPL(0);
86     attr |= (SEG_LIM_H(size) << 16);
87
88     tssd->lo = (SEG_BASE_H(base) | attr | SEG_BASE_M(base)) << 32;
89     tssd->lo |= SEG_BASE_L(base) | SEG_LIM_L(size);
90 }
91
92 #else
93
94 x86_segdesc_t _gdt[6];
95 u16_t _gdt_limit = sizeof(_gdt) - 1;
96
97 static inline void
98 _set_gdt_entry(u32_t index, ptr_t base, u32_t limit, u32_t flags)
99 {
100     x86_segdesc_t* gdte = &_gdt[index];
101
102     flags |= BIT32;
103
104     gdte->hi =
105       SEG_BASE_H(base) | flags | SEG_LIM_H(limit) | SEG_BASE_M(base);
106     gdte->lo |= SEG_BASE_L(base) | SEG_LIM_L(limit);
107 }
108
109 static inline void
110 _set_tss(int index, ptr_t base, size_t size)
111 {
112     _set_gdt_entry(index, base, size - 1, SEG_TSS);
113 }
114
115 #endif
116
117
118 void
119 _init_gdt()
120 {
121     extern struct x86_tss _tss;
122
123 #ifdef CONFIG_ARCH_X86_64
124     _gdt[0] = 0;
125     _set_gdt_entry(1, 0, SEG_R0_CODE);   // kernel code
126     _set_gdt_entry(2, 3, SEG_R3_CODE);   // user code
127     _set_gdt_entry(3, 0, SEG_R0_DATA);   // generic data
128     _set_gdt_entry(4, 4, SEG_R3_DATA);   // generic data
129     _set_tss(5, (ptr_t)&_tss, sizeof(_tss));
130 #else
131     _set_gdt_entry(0, 0, 0, 0);
132     _set_gdt_entry(1, 0, 0xfffff, SEG_R0_CODE);
133     _set_gdt_entry(2, 0, 0xfffff, SEG_R3_CODE);
134     _set_gdt_entry(3, 0, 0xfffff, SEG_R0_DATA);
135     _set_gdt_entry(4, 0, 0xfffff, SEG_R3_DATA);
136     _set_tss(5, (u32_t)&_tss, sizeof(struct x86_tss) - 1);
137 #endif
138 }