1 /*
2 * Copyright (c) 2009 Corey Tabaka
3 * Copyright (c) 2018 Intel Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files
7 * (the "Software"), to deal in the Software without restriction,
8 * including without limitation the rights to use, copy, modify, merge,
9 * publish, distribute, sublicense, and/or sell copies of the Software,
10 * and to permit persons to whom the Software is furnished to do so,
11 * subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <arch/arch_ops.h>
26 #include <arch/x86/descriptor.h>
27 #include <compiler.h>
28 #include <debug.h>
29
30 /*
31 * Descriptors are always 64-bit except TSS (or LDT) Descriptor in 64-bit mode.
32 * In 64-bit mode, TSS descriptor is defined as 128 bits, low 64 bits of TSS
33 * have same definition as legacy descriptor, high 64 bits contain base address
34 * bits 63:32 of descriptor.
35 *
36 * High 32 bits of base address of descriptor should be set when dealing with
37 * TSS descriptor.
38 */
39 typedef union {
40 struct {
41 uint16_t limit_15_0;
42 uint16_t base_15_0;
43 uint8_t base_23_16;
44
45 uint8_t type : 4;
46 uint8_t s : 1;
47 uint8_t dpl : 2;
48 uint8_t p : 1;
49
50 uint8_t limit_19_16 : 4;
51 uint8_t avl : 1;
52 uint8_t reserved_0 : 1;
53 uint8_t d_b : 1;
54 uint8_t g : 1;
55
56 uint8_t base_31_24;
57 } __PACKED legacy;
58
59 struct {
60 uint32_t base_32_63;
61 uint16_t rsvd_1;
62 uint16_t rsvd_2;
63 } __PACKED tss_high;
64 } __PACKED seg_desc_t;
65
66 extern seg_desc_t _gdt[];
67
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)68 void set_global_desc(seg_sel_t sel,
69 void *base,
70 uint32_t limit,
71 uint8_t present,
72 uint8_t ring,
73 uint8_t sys,
74 uint8_t type,
75 uint8_t gran,
76 uint8_t bits)
77 {
78 /* convert selector into index */
79 uint16_t index = sel >> 3;
80
81 /* For legacy descriptors and low 32 bit of 64-bit TSS only */
82 _gdt[index].legacy.limit_15_0 = limit & 0x0000ffff;
83 _gdt[index].legacy.limit_19_16 = (limit & 0x000f0000) >> 16;
84
85 _gdt[index].legacy.base_15_0 = ((uint64_t)base) & 0x0000ffff;
86 _gdt[index].legacy.base_23_16 = (((uint64_t)base) & 0x00ff0000) >> 16;
87 _gdt[index].legacy.base_31_24 = ((uint64_t)base) >> 24;
88
89 _gdt[index].legacy.type = type & 0x0f; /* segment type */
90 _gdt[index].legacy.p = (present != 0); /* present */
91 _gdt[index].legacy.dpl = ring & 0x03; /* descriptor privilege level */
92 _gdt[index].legacy.g = (gran != 0); /* granularity */
93 _gdt[index].legacy.s = (sys != 0); /* system / non-system */
94 _gdt[index].legacy.d_b = (bits != 0); /* 16 / 32 bit */
95
96 /* high bits of 64-bit TSS only */
97 if (sel >= TSS_SELECTOR) {
98 index = sel >> 3;
99
100 /* update high bits of 64-bit TSS now */
101 _gdt[index + 1].tss_high.base_32_63 = (uint64_t)base >> 32;
102 }
103 }
104
get_tss_base(void)105 tss_t *get_tss_base(void)
106 {
107 volatile uint cpu = arch_curr_cpu_num();
108
109 if (cpu >= SMP_MAX_CPUS) {
110 panic("Invalid CPU ID\n");
111 }
112
113 return &system_tss[cpu];
114 }
115