x86/efi: Delete most of the efi_call* macros
[cascardo/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_call)
77         SAVE_XMM
78         mov (%rsp), %rax
79         mov 8(%rax), %rax
80         subq $48, %rsp
81         mov %r9, 32(%rsp)
82         mov %rax, 40(%rsp)
83         mov %r8, %r9
84         mov %rcx, %r8
85         mov %rsi, %rcx
86         SWITCH_PGT
87         call *%rdi
88         RESTORE_PGT
89         addq $48, %rsp
90         RESTORE_XMM
91         ret
92 ENDPROC(efi_call)
93
94 #ifdef CONFIG_EFI_MIXED
95
96 /*
97  * We run this function from the 1:1 mapping.
98  *
99  * This function must be invoked with a 1:1 mapped stack.
100  */
101 ENTRY(__efi64_thunk)
102         movl    %ds, %eax
103         push    %rax
104         movl    %es, %eax
105         push    %rax
106         movl    %ss, %eax
107         push    %rax
108
109         subq    $32, %rsp
110         movl    %esi, 0x0(%rsp)
111         movl    %edx, 0x4(%rsp)
112         movl    %ecx, 0x8(%rsp)
113         movq    %r8, %rsi
114         movl    %esi, 0xc(%rsp)
115         movq    %r9, %rsi
116         movl    %esi,  0x10(%rsp)
117
118         sgdt    save_gdt(%rip)
119
120         leaq    1f(%rip), %rbx
121         movq    %rbx, func_rt_ptr(%rip)
122
123         /* Switch to gdt with 32-bit segments */
124         movl    64(%rsp), %eax
125         lgdt    (%rax)
126
127         leaq    efi_enter32(%rip), %rax
128         pushq   $__KERNEL_CS
129         pushq   %rax
130         lretq
131
132 1:      addq    $32, %rsp
133
134         lgdt    save_gdt(%rip)
135
136         pop     %rbx
137         movl    %ebx, %ss
138         pop     %rbx
139         movl    %ebx, %es
140         pop     %rbx
141         movl    %ebx, %ds
142
143         /*
144          * Convert 32-bit status code into 64-bit.
145          */
146         test    %rax, %rax
147         jz      1f
148         movl    %eax, %ecx
149         andl    $0x0fffffff, %ecx
150         andl    $0xf0000000, %eax
151         shl     $32, %rax
152         or      %rcx, %rax
153 1:
154         ret
155 ENDPROC(__efi64_thunk)
156
157 ENTRY(efi_exit32)
158         movq    func_rt_ptr(%rip), %rax
159         push    %rax
160         mov     %rdi, %rax
161         ret
162 ENDPROC(efi_exit32)
163
164         .code32
165 /*
166  * EFI service pointer must be in %edi.
167  *
168  * The stack should represent the 32-bit calling convention.
169  */
170 ENTRY(efi_enter32)
171         movl    $__KERNEL_DS, %eax
172         movl    %eax, %ds
173         movl    %eax, %es
174         movl    %eax, %ss
175
176         /* Reload pgtables */
177         movl    %cr3, %eax
178         movl    %eax, %cr3
179
180         /* Disable paging */
181         movl    %cr0, %eax
182         btrl    $X86_CR0_PG_BIT, %eax
183         movl    %eax, %cr0
184
185         /* Disable long mode via EFER */
186         movl    $MSR_EFER, %ecx
187         rdmsr
188         btrl    $_EFER_LME, %eax
189         wrmsr
190
191         call    *%edi
192
193         /* We must preserve return value */
194         movl    %eax, %edi
195
196         /*
197          * Some firmware will return with interrupts enabled. Be sure to
198          * disable them before we switch GDTs.
199          */
200         cli
201
202         movl    68(%esp), %eax
203         movl    %eax, 2(%eax)
204         lgdtl   (%eax)
205
206         movl    %cr4, %eax
207         btsl    $(X86_CR4_PAE_BIT), %eax
208         movl    %eax, %cr4
209
210         movl    %cr3, %eax
211         movl    %eax, %cr3
212
213         movl    $MSR_EFER, %ecx
214         rdmsr
215         btsl    $_EFER_LME, %eax
216         wrmsr
217
218         xorl    %eax, %eax
219         lldt    %ax
220
221         movl    72(%esp), %eax
222         pushl   $__KERNEL_CS
223         pushl   %eax
224
225         /* Enable paging */
226         movl    %cr0, %eax
227         btsl    $X86_CR0_PG_BIT, %eax
228         movl    %eax, %cr0
229         lret
230 ENDPROC(efi_enter32)
231
232         .data
233         .balign 8
234         .global efi32_boot_gdt
235 efi32_boot_gdt: .word   0
236                 .quad   0
237
238 save_gdt:       .word   0
239                 .quad   0
240 func_rt_ptr:    .quad   0
241
242         .global efi_gdt64
243 efi_gdt64:
244         .word   efi_gdt64_end - efi_gdt64
245         .long   0                       /* Filled out by user */
246         .word   0
247         .quad   0x0000000000000000      /* NULL descriptor */
248         .quad   0x00af9a000000ffff      /* __KERNEL_CS */
249         .quad   0x00cf92000000ffff      /* __KERNEL_DS */
250         .quad   0x0080890000000000      /* TS descriptor */
251         .quad   0x0000000000000000      /* TS continued */
252 efi_gdt64_end:
253 #endif /* CONFIG_EFI_MIXED */
254
255         .data
256 ENTRY(efi_scratch)
257         .fill 3,8,0
258         .byte 0
259         .quad 0