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