Code refinement.
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuGdt.c
1 /** @file
2 C based implemention of IA32 interrupt handling only
3 requiring a minimal assembly interrupt entry point.
4
5 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "CpuDxe.h"
17
18
19 //
20 // Local structure definitions
21 //
22
23 #pragma pack (1)
24
25 //
26 // Global Descriptor Entry structures
27 //
28
29 typedef struct _GDT_ENTRY {
30 UINT16 Limit15_0;
31 UINT16 Base15_0;
32 UINT8 Base23_16;
33 UINT8 Type;
34 UINT8 Limit19_16_and_flags;
35 UINT8 Base31_24;
36 } GDT_ENTRY;
37
38 typedef
39 struct _GDT_ENTRIES {
40 GDT_ENTRY Null;
41 GDT_ENTRY Linear;
42 GDT_ENTRY LinearCode;
43 GDT_ENTRY SysData;
44 GDT_ENTRY SysCode;
45 GDT_ENTRY LinearCode64;
46 GDT_ENTRY Spare4;
47 GDT_ENTRY Spare5;
48 } GDT_ENTRIES;
49
50 #define NULL_SEL OFFSET_OF (GDT_ENTRIES, Null)
51 #define LINEAR_SEL OFFSET_OF (GDT_ENTRIES, Linear)
52 #define LINEAR_CODE_SEL OFFSET_OF (GDT_ENTRIES, LinearCode)
53 #define SYS_DATA_SEL OFFSET_OF (GDT_ENTRIES, SysData)
54 #define SYS_CODE_SEL OFFSET_OF (GDT_ENTRIES, SysCode)
55 #define LINEAR_CODE64_SEL OFFSET_OF (GDT_ENTRIES, LinearCode64)
56 #define SPARE4_SEL OFFSET_OF (GDT_ENTRIES, Spare4)
57 #define SPARE5_SEL OFFSET_OF (GDT_ENTRIES, Spare5)
58
59 #if defined (MDE_CPU_IA32)
60 #define CPU_CODE_SEL LINEAR_CODE_SEL
61 #define CPU_DATA_SEL LINEAR_SEL
62 #elif defined (MDE_CPU_X64)
63 #define CPU_CODE_SEL LINEAR_CODE64_SEL
64 #define CPU_DATA_SEL LINEAR_SEL
65 #else
66 #error CPU type not supported for CPU GDT initialization!
67 #endif
68
69 //
70 // Global descriptor table (GDT) Template
71 //
72 STATIC GDT_ENTRIES GdtTemplate = {
73 //
74 // NULL_SEL
75 //
76 {
77 0x0, // limit 15:0
78 0x0, // base 15:0
79 0x0, // base 23:16
80 0x0, // type
81 0x0, // limit 19:16, flags
82 0x0, // base 31:24
83 },
84 //
85 // LINEAR_SEL
86 //
87 {
88 0x0FFFF, // limit 0xFFFFF
89 0x0, // base 0
90 0x0,
91 0x092, // present, ring 0, data, expand-up, writable
92 0x0CF, // page-granular, 32-bit
93 0x0,
94 },
95 //
96 // LINEAR_CODE_SEL
97 //
98 {
99 0x0FFFF, // limit 0xFFFFF
100 0x0, // base 0
101 0x0,
102 0x09A, // present, ring 0, data, expand-up, writable
103 0x0CF, // page-granular, 32-bit
104 0x0,
105 },
106 //
107 // SYS_DATA_SEL
108 //
109 {
110 0x0FFFF, // limit 0xFFFFF
111 0x0, // base 0
112 0x0,
113 0x092, // present, ring 0, data, expand-up, writable
114 0x0CF, // page-granular, 32-bit
115 0x0,
116 },
117 //
118 // SYS_CODE_SEL
119 //
120 {
121 0x0FFFF, // limit 0xFFFFF
122 0x0, // base 0
123 0x0,
124 0x09A, // present, ring 0, data, expand-up, writable
125 0x0CF, // page-granular, 32-bit
126 0x0,
127 },
128 //
129 // LINEAR_CODE64_SEL
130 //
131 {
132 0x0FFFF, // limit 0xFFFFF
133 0x0, // base 0
134 0x0,
135 0x09B, // present, ring 0, code, expand-up, writable
136 0x0AF, // LimitHigh (CS.L=1, CS.D=0)
137 0x0, // base (high)
138 },
139 //
140 // SPARE4_SEL
141 //
142 {
143 0x0, // limit 0
144 0x0, // base 0
145 0x0,
146 0x0, // present, ring 0, data, expand-up, writable
147 0x0, // page-granular, 32-bit
148 0x0,
149 },
150 //
151 // SPARE5_SEL
152 //
153 {
154 0x0, // limit 0
155 0x0, // base 0
156 0x0,
157 0x0, // present, ring 0, data, expand-up, writable
158 0x0, // page-granular, 32-bit
159 0x0,
160 },
161 };
162
163 /**
164 Initialize Global Descriptor Table.
165
166 **/
167 VOID
168 InitGlobalDescriptorTable (
169 VOID
170 )
171 {
172 GDT_ENTRIES *gdt;
173 IA32_DESCRIPTOR gdtPtr;
174
175 //
176 // Allocate Runtime Data for the GDT
177 //
178 gdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8);
179 ASSERT (gdt != NULL);
180 gdt = ALIGN_POINTER (gdt, 8);
181
182 //
183 // Initialize all GDT entries
184 //
185 CopyMem (gdt, &GdtTemplate, sizeof (GdtTemplate));
186
187 //
188 // Write GDT register
189 //
190 gdtPtr.Base = (UINT32)(UINTN)(VOID*) gdt;
191 gdtPtr.Limit = sizeof (GdtTemplate) - 1;
192 AsmWriteGdtr (&gdtPtr);
193
194 //
195 // Update selector (segment) registers base on new GDT
196 //
197 SetCodeSelector ((UINT16)CPU_CODE_SEL);
198 SetDataSelectors ((UINT16)CPU_DATA_SEL);
199 }
200