1 /*
2  * Copyright (C) 2018-2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef GDT_H
8 #define GDT_H
9 
10 /* GDT is defined in assembly so it can be used to switch modes before long mode
11  * is established.
12  * With 64-bit EFI this is not required since are already in long mode when EFI
13  * transfers control to the hypervisor.  However, for any instantiation of the
14  * ACRN Hypervisor that requires a boot from reset the GDT will be
15  * used as mode transitions are being made to ultimately end up in long mode.
16  * For this reason we establish the GDT in assembly.
17  * This should not affect usage and convenience of interacting with the GDT in C
18  * as the complete definition of the GDT is driven by the defines in this file.
19  *
20  * Unless it proves to be not viable we will use a single GDT for all hypervisor
21  * CPUs, with space for per CPU LDT and TSS.
22  */
23 
24 /*
25  * Segment selectors in x86-64 and i386 are the same size, 8 bytes.
26  * Local Descriptor Table (LDT) selectors are 16 bytes on x86-64 instead of 8
27  * bytes.
28  * Task State Segment (TSS) selectors are 16 bytes on x86-64 instead of 8 bytes.
29  */
30 #define X64_SEG_DESC_SIZE (0x8U)	/* In long mode SEG Descriptors are 8 bytes */
31 #define X64_LDT_DESC_SIZE (0x10U)/* In long mode LDT Descriptors are 16 bytes */
32 #define X64_TSS_DESC_SIZE (0x10U)/* In long mode TSS Descriptors are 16 bytes */
33 
34 /*****************************************************************************
35  *
36  * BEGIN: Definition of the GDT.
37  *
38  * NOTE:
39  * If you change the size of the GDT or rearrange the location of descriptors
40  * within the GDT you must change both the defines and the C structure header.
41  *
42  *****************************************************************************/
43 /* Number of global 8 byte segments descriptor(s) */
44 #define    HOST_GDT_RING0_SEG_SELECTORS   (0x3U)	/* rsvd, code, data */
45 /* Offsets of global 8 byte segment descriptors */
46 #define    HOST_GDT_RING0_RSVD_SEL        (0x0000U)
47 #define    HOST_GDT_RING0_CODE_SEL        (0x0008U)
48 #define    HOST_GDT_RING0_DATA_SEL        (0x0010U)
49 /* Number of global 16 byte LDT descriptor(s) */
50 #define    HOST_GDT_RING0_TSS_SELECTORS   (0x1U)
51 /* One for each CPU in the hypervisor. */
52 
53 /*****************************************************************************
54  *
55  * END: Definition of the GDT.
56  *
57  *****************************************************************************/
58 
59 /* Offset to start of LDT Descriptors */
60 #define HOST_GDT_RING0_LDT_SEL		\
61 	(HOST_GDT_RING0_SEG_SELECTORS * X64_SEG_DESC_SIZE)
62 /* Offset to start of LDT Descriptors */
63 #define HOST_GDT_RING0_CPU_TSS_SEL (HOST_GDT_RING0_LDT_SEL)
64 /* Size of the GDT */
65 #define HOST_GDT_SIZE							\
66 	(HOST_GDT_RING0_CPU_TSS_SEL +					\
67 		(HOST_GDT_RING0_TSS_SELECTORS * X64_TSS_DESC_SIZE))
68 
69 #ifndef ASSEMBLER
70 
71 #include <types.h>
72 #include <asm/cpu.h>
73 
74 #define TSS_AVAIL  (9U)
75 
76 /*
77  * Definition of 16 byte TSS and LDT selectors.
78  */
79 struct tss_64_descriptor {
80 		uint32_t low32_value;
81 		uint32_t high32_value;
82 		uint32_t base_addr_63_32;
83 		uint32_t offset_12;
84 } __aligned(8);
85 
86 /*****************************************************************************
87  *
88  * BEGIN: Definition of the GDT.
89  *
90  * NOTE:
91  * If you change the size of the GDT or rearrange the location of descriptors
92  * within the GDT you must change both the defines and the C structure header.
93  *
94  *****************************************************************************/
95 struct host_gdt {
96 	uint64_t rsvd;
97 
98 	uint64_t code_segment_descriptor;
99 	uint64_t data_segment_descriptor;
100 	struct tss_64_descriptor host_gdt_tss_descriptors;
101 } __aligned(8);
102 
103 /*****************************************************************************
104  *
105  * END: Definition of the GDT.
106  *
107  *****************************************************************************/
108 
109 /*
110  * x86-64 Task State Segment (TSS) definition.
111  */
112 struct tss_64 {
113 	uint32_t rsvd1;
114 	uint64_t rsp0;
115 	uint64_t rsp1;
116 	uint64_t rsp2;
117 	uint32_t rsvd2;
118 	uint32_t rsvd3;
119 	uint64_t ist1;
120 	uint64_t ist2;
121 	uint64_t ist3;
122 	uint64_t ist4;
123 	uint64_t ist5;
124 	uint64_t ist6;
125 	uint64_t ist7;
126 	uint32_t rsvd4;
127 	uint32_t rsvd5;
128 	uint16_t rsvd6;
129 	uint16_t io_map_base_addr;
130 } __packed __aligned(16);
131 
132 /*
133  * Definition of the GDT descriptor.
134  */
135 struct host_gdt_descriptor {
136 	uint16_t len;
137 	struct host_gdt *gdt;
138 } __packed;
139 
140 void load_gdtr_and_tr(void);
141 
142 #endif /* end #ifndef ASSEMBLER */
143 
144 #endif /* GDT_H */
145