• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1;
2; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
3; This program and the accompanying materials
4; are licensed and made available under the terms and conditions of the BSD License
5; which accompanies this distribution.  The full text of the license may be found at
6; http://opensource.org/licenses/bsd-license.php.
7;
8; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10;
11;
12; Module Name:
13;
14;    Thunk64To32.asm
15;
16; Abstract:
17;
18;   This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then
19;   transit back to long mode.
20;
21;-------------------------------------------------------------------------------
22    .code
23;----------------------------------------------------------------------------
24; Procedure:    AsmExecute32BitCode
25;
26; Input:        None
27;
28; Output:       None
29;
30; Prototype:    UINT32
31;               AsmExecute32BitCode (
32;                 IN UINT64           Function,
33;                 IN UINT64           Param1,
34;                 IN UINT64           Param2,
35;                 IN IA32_DESCRIPTOR  *InternalGdtr
36;                 );
37;
38;
39; Description:  A thunk function to execute 32-bit code in long mode.
40;
41;----------------------------------------------------------------------------
42AsmExecute32BitCode    PROC
43    ;
44    ; save IFLAG and disable it
45    ;
46    pushfq
47    cli
48
49    ;
50    ; save orignal GDTR and CS
51    ;
52    mov     rax, ds
53    push    rax
54    mov     rax, cs
55    push    rax
56    sub     rsp, 10h
57    sgdt    fword ptr [rsp]
58    ;
59    ; load internal GDT
60    ;
61    lgdt    fword ptr [r9]
62    ;
63    ; Save general purpose register and rflag register
64    ;
65    pushfq
66    push    rdi
67    push    rsi
68    push    rbp
69    push    rbx
70
71    ;
72    ; save CR3
73    ;
74    mov     rax, cr3
75    mov     rbp, rax
76
77    ;
78    ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode
79    ;
80    mov     rax, 10h              ; load long mode selector
81    shl     rax, 32
82    mov     r9, OFFSET ReloadCS   ;Assume the ReloadCS is under 4G
83    or      rax, r9
84    push    rax
85    ;
86    ; Save parameters for 32-bit function call
87    ;
88    mov     rax, r8
89    shl     rax, 32
90    or      rax, rdx
91    push    rax
92    ;
93    ; save the 32-bit function entry and the return address into stack which will be
94    ; retrieve in compatibility mode.
95    ;
96    mov     rax, OFFSET ReturnBack   ;Assume the ReloadCS is under 4G
97    shl     rax, 32
98    or      rax, rcx
99    push    rax
100
101    ;
102    ; let rax save DS
103    ;
104    mov     rax, 018h
105
106    ;
107    ; Change to Compatible Segment
108    ;
109    mov     rcx, 08h               ; load compatible mode selector
110    shl     rcx, 32
111    mov     rdx, OFFSET Compatible ; assume address < 4G
112    or      rcx, rdx
113    push    rcx
114    retf
115
116Compatible:
117    ; reload DS/ES/SS to make sure they are correct referred to current GDT
118    mov     ds, ax
119    mov     es, ax
120    mov     ss, ax
121
122    ;
123    ; Disable paging
124    ;
125    mov     rcx, cr0
126    btc     ecx, 31
127    mov     cr0, rcx
128    ;
129    ; Clear EFER.LME
130    ;
131    mov     ecx, 0C0000080h
132    rdmsr
133    btc     eax, 8
134    wrmsr
135
136; Now we are in protected mode
137    ;
138    ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G
139    ;
140    pop    rax                 ; Here is the function entry
141    ;
142    ; Now the parameter is at the bottom of the stack,  then call in to IA32 function.
143    ;
144    jmp   rax
145ReturnBack:
146    mov   ebx, eax             ; save return status
147    pop   rcx                  ; drop param1
148    pop   rcx                  ; drop param2
149
150    ;
151    ; restore CR4
152    ;
153    mov     rax, cr4
154    bts     eax, 5
155    mov     cr4, rax
156
157    ;
158    ; restore CR3
159    ;
160    mov     eax, ebp
161    mov     cr3, rax
162
163    ;
164    ; Set EFER.LME to re-enable ia32-e
165    ;
166    mov     ecx, 0C0000080h
167    rdmsr
168    bts     eax, 8
169    wrmsr
170    ;
171    ; Enable paging
172    ;
173    mov     rax, cr0
174    bts     eax, 31
175    mov     cr0, rax
176; Now we are in compatible mode
177
178    ;
179    ; Reload cs register
180    ;
181    retf
182ReloadCS:
183    ;
184    ; Now we're in Long Mode
185    ;
186    ;
187    ; Restore C register and eax hold the return status from 32-bit function.
188    ; Note: Do not touch rax from now which hold the return value from IA32 function
189    ;
190    mov     eax, ebx ; put return status to EAX
191    pop     rbx
192    pop     rbp
193    pop     rsi
194    pop     rdi
195    popfq
196    ;
197    ; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.
198    ;
199    lgdt    fword ptr[rsp]
200    ;
201    ; drop GDT descriptor in stack
202    ;
203    add     rsp, 10h
204    ;
205    ; switch to orignal CS and GDTR
206    ;
207    pop     r9                 ; get  CS
208    shl     r9,  32            ; rcx[32..47] <- Cs
209    mov     rcx, OFFSET @F
210    or      rcx, r9
211    push    rcx
212    retf
213@@:
214    ;
215    ; Reload original DS/ES/SS
216    ;
217    pop     rcx
218    mov     ds, rcx
219    mov     es, rcx
220    mov     ss, rcx
221
222    ;
223    ; Restore IFLAG
224    ;
225    popfq
226
227    ret
228AsmExecute32BitCode   ENDP
229
230    END
231