drivers/wifi: Remove unnecessary data structure copy
[coreboot2.git] / payloads / libpayload / arch / x86 / exception_asm_64.S
blob0c1c536b50c3e70f1104a4ff756a868d04e51cd9
1 /*
2  *
3  * Copyright 2024 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
29         .align 16
30         .global exception_stack_end
31 exception_stack_end:
32         .quad 0
33         .global exception_state
34 exception_state:
35         .quad 0
37 /* Some temporary variables which are used while saving exception state. */
38 vector:
39         .quad 0
40 error_code:
41         .quad 0
42 old_rax:
43         .quad 0
44 old_rcx:
45         .quad 0
47         .align 16
50  * Each exception vector has a small stub associated with it which sets aside
51  * the error code, if any, records which vector we entered from, and calls
52  * the common exception entry point. Some exceptions have error codes and some
53  * don't, so we have a macro for each type.
54  */
56         .macro stub num
57 exception_stub_\num:
58         movq $0, error_code
59         movq $\num, vector
60         jmp exception_common
61         .endm
63         .macro stub_err num
64 exception_stub_\num:
65         pop error_code
66         movq $\num, vector
67         jmp exception_common
68         .endm
70         .altmacro
71         .macro user_defined_stubs from, to
72         stub \from
73         .if \to-\from
74         user_defined_stubs %(\from+1),\to
75         .endif
76         .endm
78         stub 0
79         stub 1
80         stub 2
81         stub 3
82         stub 4
83         stub 5
84         stub 6
85         stub 7
86         stub_err 8
87         stub 9
88         stub_err 10
89         stub_err 11
90         stub_err 12
91         stub_err 13
92         stub_err 14
93         stub 15
94         stub 16
95         stub_err 17
96         stub 18
97         stub 19
98         stub 20
99         stub 21
100         stub 22
101         stub 23
102         stub 24
103         stub 25
104         stub 26
105         stub 27
106         stub 28
107         stub 29
108         stub_err 30
109         stub 31
110         /* Split the macro so we avoid a stack overflow. */
111         user_defined_stubs 32, 63
112         user_defined_stubs 64, 127
113         user_defined_stubs 128, 191
114         user_defined_stubs 192, 255
116 exception_common:
117         /*
118          * At this point, on x86-64, on the stack there is:
119          * 0(%rsp) rip
120          * 8(%rsp) cs
121          * 16(%rsp) rflags
122          * 24(%rsp) rsp
123          * 32(%rsp) ss
124          *
125          * This section sets up the exception stack.
126          * It saves the old stack pointer (rsp) to preserve RIP, CS, RFLAGS and SS.
127          * Then sets up the new stack pointer to point to the exception stack area.
128          */
129         movq %rax, old_rax
130         movq %rcx, old_rcx
132         mov %rsp, %rax
133         movq exception_stack_end, %rsp
134         /*
135          * The `exception_state` struct is not 16-byte aligned.
136          * Push an extra 8 bytes to ensure the stack pointer
137          * is 16-byte aligned before calling exception_dispatch.
138          */
139         push $0
141         /*
142          * Push values onto the top of the exception stack to form an
143          * exception state structure.
144          */
145         push vector
146         push error_code
148         /* push of the gs, fs, es, ds, ss and cs */
149         mov %gs, %rcx
150         movl %ecx, -4(%rsp)   /* gs */
151         mov %fs, %rcx
152         movl %ecx, -8(%rsp)   /* fs */
153         movl $0, -12(%rsp)    /* es */
154         movl $0, -16(%rsp)    /* ds */
155         movq 32(%rax), %rcx
156         movl %ecx, -20(%rsp)  /* ss */
157         movq 8(%rax), %rcx
158         movl %ecx, -24(%rsp)  /* cs */
159         sub $24, %rsp
161         push 16(%rax)         /* rflags */
162         push (%rax)           /* rip */
163         push %r15
164         push %r14
165         push %r13
166         push %r12
167         push %r11
168         push %r10
169         push %r9
170         push %r8
171         push 24(%rax)         /* rsp */
172         push %rbp
173         push %rdi
174         push %rsi
175         push %rdx
176         push old_rcx          /* rcx */
177         push %rbx
178         push old_rax          /* rax */
180         /*
181          * Call the C exception handler. It will find the exception state
182          * using the exception_state global pointer. Not
183          * passing parameters means we don't have to worry about what ABI
184          * is being used.
185          */
186         mov %rsp, exception_state
187         call exception_dispatch
189         /*
190          * Restore state from the exception state structure, including any
191          * changes that might have been made.
192          */
193         pop old_rax
194         pop %rbx
195         pop old_rcx
196         pop %rdx
197         pop %rsi
198         pop %rdi
199         pop %rbp
200         lea exception_stack, %rax
201         pop 24(%rax)          /* rsp */
202         pop %r8
203         pop %r9
204         pop %r10
205         pop %r11
206         pop %r12
207         pop %r13
208         pop %r14
209         pop %r15
210         pop (%rax)            /* rip */
211         pop 16(%rax)          /* rflags */
213         /* pop of the gs, fs, es, ds, ss and cs */
214         movl (%rsp), %ecx
215         movq %rcx, 8(%rax)    /* cs */
216         movl 4(%rsp), %ecx
217         movq %rcx, 32(%rax)   /* ss */
218         movl 16(%rsp), %ecx
219         mov %rcx, %fs         /* fs */
220         movl 20(%rsp), %ecx
221         mov %rcx, %gs         /* gs */
223         mov %rax, %rsp
224         movq old_rax, %rax
225         movq old_rcx, %rcx
227         iretq
230  * We need segment selectors for the IDT, so we need to know where things are
231  * in the GDT. We set one up here which is pretty standard and largely copied
232  * from coreboot.
233  */
234         .align 16
235 gdt:
236         /* selgdt 0, unused */
237         .word 0x0000, 0x0000
238         .byte 0x00, 0x00, 0x00, 0x00
240         /* selgdt 8, unused */
241         .word 0x0000, 0x0000
242         .byte 0x00, 0x00, 0x00, 0x00
244         /* selgdt 0x10, flat 4GB code segment */
245         .word 0xffff, 0x0000
246         .byte 0x00, 0x9b, 0xcf, 0x00
248         /* selgdt 0x18, flat 4GB data segment */
249         .word 0xffff, 0x0000
250         .byte 0x00, 0x92, 0xcf, 0x00
252         /* selgdt 0x20, flat x64 code segment */
253         .word 0xffff, 0x0000
254         .byte 0x00, 0x9b, 0xaf, 0x00
255 gdt_end:
257 /* GDT pointer for use with lgdt */
258 .global gdt_ptr
259 gdt_ptr:
260         .word gdt_end - gdt - 1
261         .quad gdt
263         /*
264          * Record the target and construct the actual entry at init time. This
265          * is necessary because the linker doesn't want to construct the entry
266          * for us.
267          */
268         .macro interrupt_gate target
269         .word 0       /* patchable */
270         .word 0x20    /* Target code segment selector */
271         .word 0xee00  /* Present, Type 64-bit Interrupt Gate */
272         .word 0       /* patchable */
273         .quad \target /* patchable */
274         .endm
276         .altmacro
277         .macro  user_defined_gates from, to
278         interrupt_gate  exception_stub_\from
279         .if     \to-\from
280         user_defined_gates      %(\from+1),\to
281         .endif
282         .endm
284         .align 16
285         .global idt
286 idt:
287         interrupt_gate exception_stub_0
288         interrupt_gate exception_stub_1
289         interrupt_gate exception_stub_2
290         interrupt_gate exception_stub_3
291         interrupt_gate exception_stub_4
292         interrupt_gate exception_stub_5
293         interrupt_gate exception_stub_6
294         interrupt_gate exception_stub_7
295         interrupt_gate exception_stub_8
296         interrupt_gate exception_stub_9
297         interrupt_gate exception_stub_10
298         interrupt_gate exception_stub_11
299         interrupt_gate exception_stub_12
300         interrupt_gate exception_stub_13
301         interrupt_gate exception_stub_14
302         interrupt_gate exception_stub_15
303         interrupt_gate exception_stub_16
304         interrupt_gate exception_stub_17
305         interrupt_gate exception_stub_18
306         interrupt_gate exception_stub_19
307         interrupt_gate exception_stub_20
308         interrupt_gate exception_stub_21
309         interrupt_gate exception_stub_22
310         interrupt_gate exception_stub_23
311         interrupt_gate exception_stub_24
312         interrupt_gate exception_stub_25
313         interrupt_gate exception_stub_26
314         interrupt_gate exception_stub_27
315         interrupt_gate exception_stub_28
316         interrupt_gate exception_stub_29
317         interrupt_gate exception_stub_30
318         interrupt_gate exception_stub_31
319         user_defined_gates 32, 63
320         user_defined_gates 64, 127
321         user_defined_gates 128, 191
322         user_defined_gates 192, 255
323 idt_end:
325 /* IDT pointer for use with lidt */
326 idt_ptr:
327         .word idt_end - idt - 1
328         .quad idt
330 .section .text.exception_init_asm
331 .globl exception_init_asm
332 .type exception_init_asm, @function
334 exception_init_asm:
335         /* Set up IDT entries */
336         mov $idt, %rax
338         movq 8(%rax), %rdi
339         movw %di, (%rax)   /* procedure entry point offset bits 0..15 */
340         shr $16, %rdi
341         movw %di, 6(%rax)  /* procedure entry point offset bits 16..31 */
342         shr $16, %rdi
343         movl %edi, 8(%rax) /* procedure entry point offset bits 32..63 */
344         movl $0, 12(%rax)  /* reserved */
345         add $16, %rax
346         cmp $idt_end, %rax
347         jne 1b
349         /* Load the IDT */
350         lidt idt_ptr
351         ret