3 * Copyright 2024 Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
30 .global exception_stack_end
33 .global exception_state
37 /* Some temporary variables which are used while saving exception state. */
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.
71 .macro user_defined_stubs from, to
74 user_defined_stubs %(\from+1),\to
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
118 * At this point, on x86-64, on the stack there is:
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.
133 movq exception_stack_end, %rsp
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.
142 * Push values onto the top of the exception stack to form an
143 * exception state structure.
148 /* push of the gs, fs, es, ds, ss and cs */
150 movl %ecx, -4(%rsp) /* gs */
152 movl %ecx, -8(%rsp) /* fs */
153 movl $0, -12(%rsp) /* es */
154 movl $0, -16(%rsp) /* ds */
156 movl %ecx, -20(%rsp) /* ss */
158 movl %ecx, -24(%rsp) /* cs */
161 push 16(%rax) /* rflags */
162 push (%rax) /* rip */
171 push 24(%rax) /* rsp */
176 push old_rcx /* rcx */
178 push old_rax /* rax */
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
186 mov %rsp, exception_state
187 call exception_dispatch
190 * Restore state from the exception state structure, including any
191 * changes that might have been made.
200 lea exception_stack, %rax
201 pop 24(%rax) /* rsp */
211 pop 16(%rax) /* rflags */
213 /* pop of the gs, fs, es, ds, ss and cs */
215 movq %rcx, 8(%rax) /* cs */
217 movq %rcx, 32(%rax) /* ss */
219 mov %rcx, %fs /* fs */
221 mov %rcx, %gs /* gs */
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
236 /* selgdt 0, unused */
238 .byte 0x00, 0x00, 0x00, 0x00
240 /* selgdt 8, unused */
242 .byte 0x00, 0x00, 0x00, 0x00
244 /* selgdt 0x10, flat 4GB code segment */
246 .byte 0x00, 0x9b, 0xcf, 0x00
248 /* selgdt 0x18, flat 4GB data segment */
250 .byte 0x00, 0x92, 0xcf, 0x00
252 /* selgdt 0x20, flat x64 code segment */
254 .byte 0x00, 0x9b, 0xaf, 0x00
257 /* GDT pointer for use with lgdt */
260 .word gdt_end - gdt - 1
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
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 */
277 .macro user_defined_gates from, to
278 interrupt_gate exception_stub_\from
280 user_defined_gates %(\from+1),\to
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
325 /* IDT pointer for use with lidt */
327 .word idt_end - idt - 1
330 .section .text.exception_init_asm
331 .globl exception_init_asm
332 .type exception_init_asm, @function
335 /* Set up IDT entries */
339 movw %di, (%rax) /* procedure entry point offset bits 0..15 */
341 movw %di, 6(%rax) /* procedure entry point offset bits 16..31 */
343 movl %edi, 8(%rax) /* procedure entry point offset bits 32..63 */
344 movl $0, 12(%rax) /* reserved */