soc/amd/stoneyridge: remove LIDS field from global NVS
[coreboot.git] / payloads / libpayload / arch / x86 / exception_asm.S
blobb3395d0e4b0e5c16828f46a7f94b3c56bca08cea
1 /*
2  *
3  * Copyright 2013 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 4
30         .global exception_stack_end
31 exception_stack_end:
32         .long 0
33         .global exception_state
34 exception_state:
35         .long 0
37 /* Some temporary variables which are used while saving exception state. */
38 vector:
39         .long 0
40 error_code:
41         .long 0
42 old_esp:
43         .long 0
44 old_eax:
45         .long 0
47         .align 8
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         movl    $0, error_code
59         movl    $\num, vector
60         jmp     exception_common
61         .endm
63         .macro stub_err num
64 exception_stub_\num:
65         popl    error_code
66         movl    $\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          * 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.
121          */
122         mov     %esp, old_esp
123         addl    $12, old_esp
124         mov     %eax, old_eax
125         mov     %esp, %eax
126         mov     exception_stack_end, %esp
128         /*
129          * Push values onto the top of the exception stack to form an
130          * exception state structure.
131          */
132         pushl   vector
133         pushl   error_code
134         pushl   %gs
135         pushl   %fs
136         pushl   %es
137         pushl   %ds
138         pushl   %ss
139         pushl   4(%eax)
140         pushl   8(%eax)
141         pushl   (%eax)
142         pushl   %edi
143         pushl   %esi
144         pushl   %ebp
145         pushl   old_esp
146         pushl   %ebx
147         pushl   %edx
148         pushl   %ecx
149         pushl   old_eax
151         /*
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
155          * is being used.
156          */
157         mov     %esp, exception_state
158         call    exception_dispatch
160         /*
161          * Restore state from the exception state structure, including any
162          * changes that might have been made.
163          */
164         popl    old_eax
165         popl    %ecx
166         popl    %edx
167         popl    %ebx
168         popl    old_esp
170         mov     old_esp, %eax
171         subl    $12, %eax
173         popl    %ebp
174         popl    %esi
175         popl    %edi
176         popl    (%eax)
177         popl    8(%eax)
178         popl    4(%eax)
179         popl    %ss
180         popl    %ds
181         popl    %es
182         popl    %fs
183         popl    %gs
185         mov     %eax, %esp
186         mov     old_eax, %eax
188         /* Return from the exception. */
189         iretl
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
194  * from coreboot.
195  */
196         .align 8
197 gdt:
198         /* selgdt 0, unused */
199         .word 0x0000, 0x0000
200         .byte 0x00, 0x00, 0x00, 0x00
202         /* selgdt 8, unused */
203         .word 0x0000, 0x0000
204         .byte 0x00, 0x00, 0x00, 0x00
206         /* selgdt 0x10, flat 4GB code segment */
207         .word 0xffff, 0x0000
208         .byte 0x00, 0x9b, 0xcf, 0x00
210         /* selgdt 0x18, flat 4GB data segment */
211         .word 0xffff, 0x0000
212         .byte 0x00, 0x93, 0xcf, 0x00
213 gdt_end:
215 /* GDT pointer for use with lgdt */
216 gdt_ptr:
217         .word   gdt_end - gdt - 1
218         .long   gdt
220         /*
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
223          * for us.
224          */
225         .macro interrupt_gate target
226         .long \target
227         .long \target
228         .endm
230         .altmacro
231         .macro  user_defined_gates from, to
232         interrupt_gate  exception_stub_\from
233         .if     \to-\from
234         user_defined_gates      %(from+1),\to
235         .endif
236         .endm
238         .align 8
239         .global idt
240 idt:
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
277 idt_end:
279 /* IDT pointer for use with lidt */
280 idt_ptr:
281         .word idt_end - idt - 1
282         .long idt
284         .global exception_init_asm
285 exception_init_asm:
286         /* Save eax so we can use it as a temporary variable. */
287         pushl   %eax
289         /* Install the GDT. */
290         lgdt    gdt_ptr
291         /* Load the segment registers from it. */
292         ljmp    $0x10, $1f
293 1:      movl    $0x18, %eax
294         movl    %eax, %ds
295         movl    %eax, %es
296         movl    %eax, %ss
297         movl    %eax, %fs
298         movl    %eax, %gs
300         /*
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.
304          */
305         movl    $idt, %eax
307         andl    $0x0000ffff, (%eax)
308         orl     $0x00100000, (%eax)
309         andl    $0xffff0000, 4(%eax)
310         orl     $0x0000ee00, 4(%eax)
311         addl    $8, %eax
312         cmp     $idt_end, %eax
313         jne     1b
315         /* Install the IDT. */
316         lidt    idt_ptr
318         /* Restore eax and return to the caller. */
319         popl    %eax
320         ret