3 * Copyright 2013 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 * Save off the stack pointer and old eax value and install the
119 * exception stack. eax points to the old stack which has the
120 * exception ip, cs, and flags.
126 mov exception_stack_end, %esp
129 * Push values onto the top of the exception stack to form an
130 * exception state structure.
152 * Call the C exception handler. It will find the exception state
153 * using the exception_state global pointer. Not
154 * passing parameters means we don't have to worry about what ABI
157 mov %esp, exception_state
158 call exception_dispatch
161 * Restore state from the exception state structure, including any
162 * changes that might have been made.
188 /* Return from the exception. */
192 * We need segment selectors for the IDT, so we need to know where things are
193 * in the GDT. We set one up here which is pretty standard and largely copied
198 /* selgdt 0, unused */
200 .byte 0x00, 0x00, 0x00, 0x00
202 /* selgdt 8, unused */
204 .byte 0x00, 0x00, 0x00, 0x00
206 /* selgdt 0x10, flat 4GB code segment */
208 .byte 0x00, 0x9b, 0xcf, 0x00
210 /* selgdt 0x18, flat 4GB data segment */
212 .byte 0x00, 0x93, 0xcf, 0x00
215 /* GDT pointer for use with lgdt */
217 .word gdt_end - gdt - 1
221 * Record the target and construct the actual entry at init time. This
222 * is necessary because the linker doesn't want to construct the entry
225 .macro interrupt_gate target
231 .macro user_defined_gates from, to
232 interrupt_gate exception_stub_\from
234 user_defined_gates %(\from+1),\to
241 interrupt_gate exception_stub_0
242 interrupt_gate exception_stub_1
243 interrupt_gate exception_stub_2
244 interrupt_gate exception_stub_3
245 interrupt_gate exception_stub_4
246 interrupt_gate exception_stub_5
247 interrupt_gate exception_stub_6
248 interrupt_gate exception_stub_7
249 interrupt_gate exception_stub_8
250 interrupt_gate exception_stub_9
251 interrupt_gate exception_stub_10
252 interrupt_gate exception_stub_11
253 interrupt_gate exception_stub_12
254 interrupt_gate exception_stub_13
255 interrupt_gate exception_stub_14
256 interrupt_gate exception_stub_15
257 interrupt_gate exception_stub_16
258 interrupt_gate exception_stub_17
259 interrupt_gate exception_stub_18
260 interrupt_gate exception_stub_19
261 interrupt_gate exception_stub_20
262 interrupt_gate exception_stub_21
263 interrupt_gate exception_stub_22
264 interrupt_gate exception_stub_23
265 interrupt_gate exception_stub_24
266 interrupt_gate exception_stub_25
267 interrupt_gate exception_stub_26
268 interrupt_gate exception_stub_27
269 interrupt_gate exception_stub_28
270 interrupt_gate exception_stub_29
271 interrupt_gate exception_stub_30
272 interrupt_gate exception_stub_31
273 user_defined_gates 32, 63
274 user_defined_gates 64, 127
275 user_defined_gates 128, 191
276 user_defined_gates 192, 255
279 /* IDT pointer for use with lidt */
281 .word idt_end - idt - 1
284 .global exception_init_asm
286 /* Save eax so we can use it as a temporary variable. */
289 /* Install the GDT. */
291 /* Load the segment registers from it. */
301 * Loop over the entries which start out as two copies of the target
302 * address. We can turn them into real interrupt gates by selectively
303 * replacing certain bit fields.
307 andl $0x0000ffff, (%eax)
308 orl $0x00100000, (%eax)
309 andl $0xffff0000, 4(%eax)
310 orl $0x0000ee00, 4(%eax)
315 /* Install the IDT. */
318 /* Restore eax and return to the caller. */