]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Core/DxeIplX64Peim/x64/LongMode.asm
Remove IDT
[mirror_edk2.git] / EdkModulePkg / Core / DxeIplX64Peim / x64 / LongMode.asm
CommitLineData
e20ee534
LG
1 TITLE LongMode.asm: Assembly code for the entering long mode
2
3;------------------------------------------------------------------------------
4;*
5;* Copyright (c) 2006, Intel Corporation
6;* All rights reserved. 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;* LongMode.asm
15;*
16;* Abstract:
17;*
18;* Transition from 32-bit protected mode EFI environment into x64
19;* 64-bit bit long mode.
20;*
21;------------------------------------------------------------------------------
22
23.686p
24.model flat
25
26;
27; Create the exception handler code in IA32 C code
28;
29
30.code
31.stack
32.MMX
33.XMM
34
35_LoadGo64Gdt PROC Near Public
36 push ebp ; C prolog
37 push edi
38 mov ebp, esp
39 ;
40 ; Disable interrupts
41 ;
42 cli
43 ;
44 ; Reload the selectors
45 ; Note:
46 ; Make the Selectors 64-bit ready
47 ;
48 mov edi, OFFSET gdtr ; Load GDT register
49 mov ax,cs ; Get the selector data from our code image
50 mov es,ax
51 lgdt FWORD PTR es:[edi] ; and update the GDTR
52
53 db 067h
54 db 0eah ; Far Jump Offset:Selector to reload CS
55 dd OFFSET DataSelectorRld; Offset is ensuing instruction boundary
56 dw LINEAR_CODE_SEL ; Selector is our code selector, 10h
57DataSelectorRld::
58 mov ax, SYS_DATA_SEL ; Update the Base for the new selectors, too
59 mov ds, ax
60 mov es, ax
61 mov fs, ax
62 mov gs, ax
63 mov ss, ax
64
65 pop edi
66 pop ebp
67 ret
68_LoadGo64Gdt endp
69
70
71; VOID
72; ActivateLongMode (
73; IN EFI_PHYSICAL_ADDRESS PageTables,
74; IN EFI_PHYSICAL_ADDRESS HobStart,
75; IN EFI_PHYSICAL_ADDRESS Stack,
76; IN EFI_PHYSICAL_ADDRESS PpisNeededByDxeIplEntryPoint,
77; IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
78; )
79;
80; Input: [ebp][0h] = Original ebp
81; [ebp][4h] = Return address
82; [ebp][8h] = PageTables
83; [ebp][10h] = HobStart
84; [ebp][18h] = Stack
85; [ebp][20h] = CodeEntryPoint1 <--- Call this first (for each call, pass HOB pointer)
86; [ebp][28h] = CodeEntryPoint2 <--- Call this second
87;
88;
89_ActivateLongMode PROC Near Public
90 push ebp ; C prolog
91 mov ebp, esp
92
93 ;
94 ; Use CPUID to determine if the processor supports long mode.
95 ;
96 mov eax, 80000000h ; Extended-function code 8000000h.
97 cpuid ; Is largest extended function
98 cmp eax, 80000000h ; any function > 80000000h?
99 jbe no_long_mode ; If not, no long mode.
100 mov eax, 80000001h ; Extended-function code 8000001h.
101 cpuid ; Now EDX = extended-features flags.
102 bt edx, 29 ; Test if long mode is supported.
103 jnc no_long_mode ; Exit if not supported.
104
105 ;
106 ; Enable the 64-bit page-translation-table entries by
107 ; setting CR4.PAE=1 (this is _required_ before activating
108 ; long mode). Paging is not enabled until after long mode
109 ; is enabled.
110 ;
111 mov eax, cr4
112 bts eax, 5
113 mov cr4, eax
114
115 ;
116 ; Get the long-mode page tables, and initialize the
117 ; 64-bit CR3 (page-table base address) to point to the base
118 ; of the PML4 page table. The PML4 page table must be located
119 ; below 4 Gbytes because only 32 bits of CR3 are loaded when
120 ; the processor is not in 64-bit mode.
121 ;
122 mov eax, [ebp+8h] ; Get Page Tables
123 mov cr3, eax ; Initialize CR3 with PML4 base.
124
125 ;
126 ; Enable long mode (set EFER.LME=1).
127 ;
128 mov ecx, 0c0000080h ; EFER MSR number.
129 rdmsr ; Read EFER.
130 bts eax, 8 ; Set LME=1.
131 wrmsr ; Write EFER.
132
133 ;
134 ; Enable paging to activate long mode (set CR0.PG=1)
135 ;
136
137
138 mov eax, cr0 ; Read CR0.
139 bts eax, 31 ; Set PG=1.
140 mov cr0, eax ; Write CR0.
141 jmp go_to_long_mode
142go_to_long_mode:
143
144 ;
145 ; This is the next instruction after enabling paging. Jump to long mode
146 ;
147 db 067h
148 db 0eah ; Far Jump Offset:Selector to reload CS
149 dd OFFSET in_long_mode; Offset is ensuing instruction boundary
150 dw SYS_CODE64_SEL ; Selector is our code selector, 10h
151in_long_mode::
152 mov ax, SYS_DATA64_SEL
153 mov es, ax
154 mov ss, ax
155 mov ds, ax
156;; jmp $
157
158
159 ;
160 ; We're in long mode, so marshall the arguments to call the
161 ; passed in function pointers
162 ; Recall
163 ; [ebp][10h] = HobStart
164 ; [ebp][18h] = Stack
165 ; [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer)
166 ; [ebp][28h] = DxeCoreEntryPoint <--- Call this second
167 ;
168 db 48h
169 mov ebx, [ebp+18h] ; Setup the stack
170 db 48h
171 mov esp, ebx ; On a new stack now
172
173
174;; 00000905 FF D0 call rax
175
176 db 48h
177 mov ecx, [ebp+10h] ; Pass Hob Start in RCX
178 db 48h
179 mov eax, [ebp+28h] ; Get the function pointer for
180 ; DxeCoreEntryPoint into EAX
181
182;; 00000905 FF D0 call rax
183 db 0ffh
184 db 0d0h
185
186 ;
187 ; WE SHOULD NEVER GET HERE!!!!!!!!!!!!!
188 ;
189no_long_mode:
190 jmp no_long_mode
191_ActivateLongMode endp
192
193 align 16
194
195gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
196 dd OFFSET GDT_BASE ; (GDT base gets set above)
197
198;-----------------------------------------------------------------------------;
199; global descriptor table (GDT)
200;-----------------------------------------------------------------------------;
201
202 align 16
203
204public GDT_BASE
205GDT_BASE:
206; null descriptor
207NULL_SEL equ $-GDT_BASE ; Selector [0]
208 dw 0 ; limit 15:0
209 dw 0 ; base 15:0
210 db 0 ; base 23:16
211 db 0 ; type
212 db 0 ; limit 19:16, flags
213 db 0 ; base 31:24
214
215; linear data segment descriptor
216LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
217 dw 0FFFFh ; limit 0xFFFFF
218 dw 0 ; base 0
219 db 0
220 db 092h ; present, ring 0, data, expand-up, writable
221 db 0CFh ; page-granular, 32-bit
222 db 0
223
224; linear code segment descriptor
225LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
226 dw 0FFFFh ; limit 0xFFFFF
227 dw 0 ; base 0
228 db 0
229 db 09Fh ; present, ring 0, data, expand-up, writable
230 db 0CFh ; page-granular, 32-bit
231 db 0
232
233; system data segment descriptor
234SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
235 dw 0FFFFh ; limit 0xFFFFF
236 dw 0 ; base 0
237 db 0
238 db 093h ; present, ring 0, data, expand-up, writable
239 db 0CFh ; page-granular, 32-bit
240 db 0
241
242; system code segment descriptor
243SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
244 dw 0FFFFh ; limit 0xFFFFF
245 dw 0 ; base 0
246 db 0
247 db 09Ah ; present, ring 0, data, expand-up, writable
248 db 0CFh ; page-granular, 32-bit
249 db 0
250
251; spare segment descriptor
252SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
253 dw 0 ; limit 0xFFFFF
254 dw 0 ; base 0
255 db 0
256 db 0 ; present, ring 0, data, expand-up, writable
257 db 0 ; page-granular, 32-bit
258 db 0
259
260;
261; system data segment descriptor
262;
263SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
264 dw 0FFFFh ; limit 0xFFFFF
265 dw 0 ; base 0
266 db 0
267 db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
268 db 0CFh ; G | D | L | AVL | Segment [19..16]
269 db 0
270
271;
272; system code segment descriptor
273;
274SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
275 dw 0FFFFh ; limit 0xFFFFF
276 dw 0 ; base 0
277 db 0
278 db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
279 db 0AFh ; G | D | L | AVL | Segment [19..16]
280 db 0
281
282; spare segment descriptor
283SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
284 dw 0 ; limit 0xFFFFF
285 dw 0 ; base 0
286 db 0
287 db 0 ; present, ring 0, data, expand-up, writable
288 db 0 ; page-granular, 32-bit
289 db 0
290
291GDT_END:
292
e20ee534
LG
293END
294