Merge tag 'pci-v3.15-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
[deliverable/linux.git] / arch / x86 / platform / efi / efi_stub_64.S
1 /*
2 * Function calling ABI conversion from Linux to EFI for x86_64
3 *
4 * Copyright (C) 2007 Intel Corp
5 * Bibo Mao <bibo.mao@intel.com>
6 * Huang Ying <ying.huang@intel.com>
7 */
8
9 #include <linux/linkage.h>
10 #include <asm/segment.h>
11 #include <asm/msr.h>
12 #include <asm/processor-flags.h>
13 #include <asm/page_types.h>
14
15 #define SAVE_XMM \
16 mov %rsp, %rax; \
17 subq $0x70, %rsp; \
18 and $~0xf, %rsp; \
19 mov %rax, (%rsp); \
20 mov %cr0, %rax; \
21 clts; \
22 mov %rax, 0x8(%rsp); \
23 movaps %xmm0, 0x60(%rsp); \
24 movaps %xmm1, 0x50(%rsp); \
25 movaps %xmm2, 0x40(%rsp); \
26 movaps %xmm3, 0x30(%rsp); \
27 movaps %xmm4, 0x20(%rsp); \
28 movaps %xmm5, 0x10(%rsp)
29
30 #define RESTORE_XMM \
31 movaps 0x60(%rsp), %xmm0; \
32 movaps 0x50(%rsp), %xmm1; \
33 movaps 0x40(%rsp), %xmm2; \
34 movaps 0x30(%rsp), %xmm3; \
35 movaps 0x20(%rsp), %xmm4; \
36 movaps 0x10(%rsp), %xmm5; \
37 mov 0x8(%rsp), %rsi; \
38 mov %rsi, %cr0; \
39 mov (%rsp), %rsp
40
41 /* stolen from gcc */
42 .macro FLUSH_TLB_ALL
43 movq %r15, efi_scratch(%rip)
44 movq %r14, efi_scratch+8(%rip)
45 movq %cr4, %r15
46 movq %r15, %r14
47 andb $0x7f, %r14b
48 movq %r14, %cr4
49 movq %r15, %cr4
50 movq efi_scratch+8(%rip), %r14
51 movq efi_scratch(%rip), %r15
52 .endm
53
54 .macro SWITCH_PGT
55 cmpb $0, efi_scratch+24(%rip)
56 je 1f
57 movq %r15, efi_scratch(%rip) # r15
58 # save previous CR3
59 movq %cr3, %r15
60 movq %r15, efi_scratch+8(%rip) # prev_cr3
61 movq efi_scratch+16(%rip), %r15 # EFI pgt
62 movq %r15, %cr3
63 1:
64 .endm
65
66 .macro RESTORE_PGT
67 cmpb $0, efi_scratch+24(%rip)
68 je 2f
69 movq efi_scratch+8(%rip), %r15
70 movq %r15, %cr3
71 movq efi_scratch(%rip), %r15
72 FLUSH_TLB_ALL
73 2:
74 .endm
75
76 ENTRY(efi_call0)
77 SAVE_XMM
78 subq $32, %rsp
79 SWITCH_PGT
80 call *%rdi
81 RESTORE_PGT
82 addq $32, %rsp
83 RESTORE_XMM
84 ret
85 ENDPROC(efi_call0)
86
87 ENTRY(efi_call1)
88 SAVE_XMM
89 subq $32, %rsp
90 mov %rsi, %rcx
91 SWITCH_PGT
92 call *%rdi
93 RESTORE_PGT
94 addq $32, %rsp
95 RESTORE_XMM
96 ret
97 ENDPROC(efi_call1)
98
99 ENTRY(efi_call2)
100 SAVE_XMM
101 subq $32, %rsp
102 mov %rsi, %rcx
103 SWITCH_PGT
104 call *%rdi
105 RESTORE_PGT
106 addq $32, %rsp
107 RESTORE_XMM
108 ret
109 ENDPROC(efi_call2)
110
111 ENTRY(efi_call3)
112 SAVE_XMM
113 subq $32, %rsp
114 mov %rcx, %r8
115 mov %rsi, %rcx
116 SWITCH_PGT
117 call *%rdi
118 RESTORE_PGT
119 addq $32, %rsp
120 RESTORE_XMM
121 ret
122 ENDPROC(efi_call3)
123
124 ENTRY(efi_call4)
125 SAVE_XMM
126 subq $32, %rsp
127 mov %r8, %r9
128 mov %rcx, %r8
129 mov %rsi, %rcx
130 SWITCH_PGT
131 call *%rdi
132 RESTORE_PGT
133 addq $32, %rsp
134 RESTORE_XMM
135 ret
136 ENDPROC(efi_call4)
137
138 ENTRY(efi_call5)
139 SAVE_XMM
140 subq $48, %rsp
141 mov %r9, 32(%rsp)
142 mov %r8, %r9
143 mov %rcx, %r8
144 mov %rsi, %rcx
145 SWITCH_PGT
146 call *%rdi
147 RESTORE_PGT
148 addq $48, %rsp
149 RESTORE_XMM
150 ret
151 ENDPROC(efi_call5)
152
153 ENTRY(efi_call6)
154 SAVE_XMM
155 mov (%rsp), %rax
156 mov 8(%rax), %rax
157 subq $48, %rsp
158 mov %r9, 32(%rsp)
159 mov %rax, 40(%rsp)
160 mov %r8, %r9
161 mov %rcx, %r8
162 mov %rsi, %rcx
163 SWITCH_PGT
164 call *%rdi
165 RESTORE_PGT
166 addq $48, %rsp
167 RESTORE_XMM
168 ret
169 ENDPROC(efi_call6)
170
171 #ifdef CONFIG_EFI_MIXED
172
173 /*
174 * We run this function from the 1:1 mapping.
175 *
176 * This function must be invoked with a 1:1 mapped stack.
177 */
178 ENTRY(__efi64_thunk)
179 movl %ds, %eax
180 push %rax
181 movl %es, %eax
182 push %rax
183 movl %ss, %eax
184 push %rax
185
186 subq $32, %rsp
187 movl %esi, 0x0(%rsp)
188 movl %edx, 0x4(%rsp)
189 movl %ecx, 0x8(%rsp)
190 movq %r8, %rsi
191 movl %esi, 0xc(%rsp)
192 movq %r9, %rsi
193 movl %esi, 0x10(%rsp)
194
195 sgdt save_gdt(%rip)
196
197 leaq 1f(%rip), %rbx
198 movq %rbx, func_rt_ptr(%rip)
199
200 /* Switch to gdt with 32-bit segments */
201 movl 64(%rsp), %eax
202 lgdt (%rax)
203
204 leaq efi_enter32(%rip), %rax
205 pushq $__KERNEL_CS
206 pushq %rax
207 lretq
208
209 1: addq $32, %rsp
210
211 lgdt save_gdt(%rip)
212
213 pop %rbx
214 movl %ebx, %ss
215 pop %rbx
216 movl %ebx, %es
217 pop %rbx
218 movl %ebx, %ds
219
220 /*
221 * Convert 32-bit status code into 64-bit.
222 */
223 test %rax, %rax
224 jz 1f
225 movl %eax, %ecx
226 andl $0x0fffffff, %ecx
227 andl $0xf0000000, %eax
228 shl $32, %rax
229 or %rcx, %rax
230 1:
231 ret
232 ENDPROC(__efi64_thunk)
233
234 ENTRY(efi_exit32)
235 movq func_rt_ptr(%rip), %rax
236 push %rax
237 mov %rdi, %rax
238 ret
239 ENDPROC(efi_exit32)
240
241 .code32
242 /*
243 * EFI service pointer must be in %edi.
244 *
245 * The stack should represent the 32-bit calling convention.
246 */
247 ENTRY(efi_enter32)
248 movl $__KERNEL_DS, %eax
249 movl %eax, %ds
250 movl %eax, %es
251 movl %eax, %ss
252
253 /* Reload pgtables */
254 movl %cr3, %eax
255 movl %eax, %cr3
256
257 /* Disable paging */
258 movl %cr0, %eax
259 btrl $X86_CR0_PG_BIT, %eax
260 movl %eax, %cr0
261
262 /* Disable long mode via EFER */
263 movl $MSR_EFER, %ecx
264 rdmsr
265 btrl $_EFER_LME, %eax
266 wrmsr
267
268 call *%edi
269
270 /* We must preserve return value */
271 movl %eax, %edi
272
273 /*
274 * Some firmware will return with interrupts enabled. Be sure to
275 * disable them before we switch GDTs.
276 */
277 cli
278
279 movl 68(%esp), %eax
280 movl %eax, 2(%eax)
281 lgdtl (%eax)
282
283 movl %cr4, %eax
284 btsl $(X86_CR4_PAE_BIT), %eax
285 movl %eax, %cr4
286
287 movl %cr3, %eax
288 movl %eax, %cr3
289
290 movl $MSR_EFER, %ecx
291 rdmsr
292 btsl $_EFER_LME, %eax
293 wrmsr
294
295 xorl %eax, %eax
296 lldt %ax
297
298 movl 72(%esp), %eax
299 pushl $__KERNEL_CS
300 pushl %eax
301
302 /* Enable paging */
303 movl %cr0, %eax
304 btsl $X86_CR0_PG_BIT, %eax
305 movl %eax, %cr0
306 lret
307 ENDPROC(efi_enter32)
308
309 .data
310 .balign 8
311 .global efi32_boot_gdt
312 efi32_boot_gdt: .word 0
313 .quad 0
314
315 save_gdt: .word 0
316 .quad 0
317 func_rt_ptr: .quad 0
318
319 .global efi_gdt64
320 efi_gdt64:
321 .word efi_gdt64_end - efi_gdt64
322 .long 0 /* Filled out by user */
323 .word 0
324 .quad 0x0000000000000000 /* NULL descriptor */
325 .quad 0x00af9a000000ffff /* __KERNEL_CS */
326 .quad 0x00cf92000000ffff /* __KERNEL_DS */
327 .quad 0x0080890000000000 /* TS descriptor */
328 .quad 0x0000000000000000 /* TS continued */
329 efi_gdt64_end:
330 #endif /* CONFIG_EFI_MIXED */
331
332 .data
333 ENTRY(efi_scratch)
334 .fill 3,8,0
335 .byte 0
336 .quad 0
This page took 0.037875 seconds and 5 git commands to generate.