1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
;------------------------------------------------------------------------------
;
; Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Abstract:
;
; Switch the stack from temporary memory to permanent memory.
;
;------------------------------------------------------------------------------
SECTION .text
extern ASM_PFX(SwapStack)
extern ASM_PFX(FeaturePcdGet (PcdFspSaveRestorePageTableEnable))
; Page table related bits in CR0/CR4/EFER
%define CR0_PG_MASK 0x80010000 ; CR0.PG and CR0.WP
%define CR4_PG_MASK 0x10B0 ; CR4.PSE, CR4.PAE, CR4.PGE and CR4.LA57
%define EFER_PG_MASK 0x800 ; EFER.NXE
;------------------------------------------------------------------------------
; UINT32
; EFIAPI
; Pei2LoaderSwitchStack (
; VOID
; )
;------------------------------------------------------------------------------
global ASM_PFX(Pei2LoaderSwitchStack)
ASM_PFX(Pei2LoaderSwitchStack):
xor eax, eax
jmp ASM_PFX(FspSwitchStack)
;------------------------------------------------------------------------------
; UINT32
; EFIAPI
; Loader2PeiSwitchStack (
; VOID
; )
;------------------------------------------------------------------------------
global ASM_PFX(Loader2PeiSwitchStack)
ASM_PFX(Loader2PeiSwitchStack):
jmp ASM_PFX(FspSwitchStack)
;------------------------------------------------------------------------------
; UINT32
; EFIAPI
; FspSwitchStack (
; VOID
; )
;------------------------------------------------------------------------------
global ASM_PFX(FspSwitchStack)
ASM_PFX(FspSwitchStack):
; Save current contexts
push eax
pushfd
cli
pushad
;
; Allocate 4x4 bytes on the stack.
;
sub esp, 16
cmp byte [dword ASM_PFX(FeaturePcdGet (PcdFspSaveRestorePageTableEnable))], 0
jz SkipPagetableSave
add esp, 16
; Save EFER MSR lower 32 bits
push ecx
push eax
mov ecx, 0xC0000080
rdmsr
mov edx, eax
pop eax
pop ecx
push edx
; Save CR registers
mov eax, cr4
push eax
mov eax, cr3
push eax
mov eax, cr0
push eax
SkipPagetableSave:
sub esp, 8
sidt [esp]
; Load new stack
push esp
call ASM_PFX(SwapStack)
mov esp, eax
; Restore previous contexts
lidt [esp]
add esp, 8
cmp byte [dword ASM_PFX(FeaturePcdGet (PcdFspSaveRestorePageTableEnable))], 0
jz SkipPagetableRestore
; [esp] stores new cr0
; [esp+4] stores new cr3
; [esp+8] stores new cr4
; [esp+12] stores new Efer
;
; When new EFER.NXE == 1, the restore flow is: EFER --> CRx
; Otherwise: CRx --> EFER
; When new CR0.PG == 1, the restore flow for CRx is: CR3 --> CR4 --> CR0
; Otherwise, the restore flow is: CR0 --> CR3 --> CR4
;
; If NXE bit is changed to 1, change NXE before CR register
; This is because Nx bit in page table entry in new CR3 will be invalid
; if updating CR3 before EFER MSR.
;
mov eax, [esp+12]
bt eax, 11
jnc SkipEferLabel1
; Restore EFER MSR
mov ecx, 0xC0000080
rdmsr
and eax, ~EFER_PG_MASK
mov ebx, [esp+12]
and ebx, EFER_PG_MASK
or eax, ebx
wrmsr
SkipEferLabel1:
;
; if new cr0 is to disable page table, change CR0 before CR3/CR4
;
mov eax, [esp]
bt eax, 31
jc SkipCr0Label1
; Restore CR0
mov edx, cr0
and edx, ~CR0_PG_MASK
mov eax, [esp]
and eax, CR0_PG_MASK
or edx, eax
mov cr0, edx
SkipCr0Label1:
; Restore CR3/CR4
mov eax, [esp+4]
mov cr3, eax
mov edx, cr4
and edx, ~CR4_PG_MASK
mov eax, [esp+8]
and eax, CR4_PG_MASK
or edx, eax
mov cr4, edx
;
; if new cr0 is to enable page table, change CR0 after CR3/CR4
;
mov eax, [esp]
bt eax, 31
jnc SkipCr0Label2
; Restore CR0
mov edx, cr0
and edx, ~CR0_PG_MASK
mov eax, [esp]
and eax, CR0_PG_MASK
or edx, eax
mov cr0, edx
SkipCr0Label2:
;
; If NXE bit is changed to 0, change NXE after than CR regiser
;
mov eax, [esp+12]
bt eax, 11
jc SkipEferLabel2
; Restore EFER MSR
mov ecx, 0xC0000080
rdmsr
and eax, ~EFER_PG_MASK
mov ebx, [esp+12]
and ebx, EFER_PG_MASK
or eax, ebx
wrmsr
SkipEferLabel2:
SkipPagetableRestore:
; pop page table related registers.
add esp, 16
popad
popfd
add esp, 4
ret
|