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