1 /*
2 * Copyright (c) 2009 Corey Tabaka
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8
9 #include <lk/compiler.h>
10 #include <arch/x86/descriptor.h>
11
12 /* not the best way to do this, but easy for now */
13 typedef union {
14 struct {
15 uint16_t limit_15_0;
16 uint16_t base_15_0;
17 uint8_t base_23_16;
18
19 uint8_t type : 4;
20 uint8_t s : 1;
21 uint8_t dpl : 2;
22 uint8_t p : 1;
23
24 uint8_t limit_19_16 : 4;
25 uint8_t avl : 1;
26 uint8_t reserved_0 : 1;
27 uint8_t d_b : 1;
28 uint8_t g : 1;
29
30 uint8_t base_31_24;
31 } __PACKED seg_desc_legacy;
32
33 struct {
34 uint32_t base_63_32;
35 uint32_t reserved_1;
36 } __PACKED seg_desc_64;
37 } __PACKED seg_desc_t;
38
39 extern seg_desc_t _gdt[];
40
set_global_desc(seg_sel_t sel,void * base,uint32_t limit,uint8_t present,uint8_t ring,uint8_t sys,uint8_t type,uint8_t gran,uint8_t bits)41 void set_global_desc(seg_sel_t sel, void *base, uint32_t limit,
42 uint8_t present, uint8_t ring, uint8_t sys, uint8_t type, uint8_t gran, uint8_t bits) {
43 // convert selector into index
44 uint16_t index = sel >> 3;
45
46 _gdt[index].seg_desc_legacy.limit_15_0 = limit & 0x0000ffff;
47 _gdt[index].seg_desc_legacy.limit_19_16 = (limit & 0x000f0000) >> 16;
48
49 _gdt[index].seg_desc_legacy.base_15_0 = ((uintptr_t) base) & 0x0000ffff;
50 _gdt[index].seg_desc_legacy.base_23_16 = (((uintptr_t) base) & 0x00ff0000) >> 16;
51 _gdt[index].seg_desc_legacy.base_31_24 = ((uintptr_t) base) >> 24;
52
53 _gdt[index].seg_desc_legacy.type = type & 0x0f; // segment type
54 _gdt[index].seg_desc_legacy.p = present != 0; // present
55 _gdt[index].seg_desc_legacy.dpl = ring & 0x03; // descriptor privilege level
56 _gdt[index].seg_desc_legacy.g = gran != 0; // granularity
57 _gdt[index].seg_desc_legacy.s = sys != 0; // system / non-system
58 _gdt[index].seg_desc_legacy.d_b = bits != 0; // 16 / 32 bit
59
60 #ifdef ARCH_X86_64
61 if (TSS_SELECTOR == sel) {
62 _gdt[index + 1].seg_desc_64.base_63_32 = (uint32_t)((uintptr_t) base >> 32);
63 _gdt[index + 1].seg_desc_64.reserved_1 = 0;
64 }
65 #endif
66 }
67