soc/amd/stoneyridge: remove LIDS field from global NVS
[coreboot.git] / payloads / libpayload / arch / x86 / exception.c
blob23d1b05b9a69ff6232f60559be9fb7387fe73c90
1 /*
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
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.
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.
29 #include <arch/exception.h>
30 #include <exception.h>
31 #include <libpayload.h>
32 #include <stdint.h>
33 #include <arch/apic.h>
35 #define IF_FLAG (1 << 9)
37 u32 exception_stack[0x400] __attribute__((aligned(8)));
39 static interrupt_handler handlers[256];
41 static const char *names[EXC_COUNT] = {
42 [EXC_DE] = "Divide by Zero",
43 [EXC_DB] = "Debug",
44 [EXC_NMI] = "Non-Maskable-Interrupt",
45 [EXC_BP] = "Breakpoint",
46 [EXC_OF] = "Overflow",
47 [EXC_BR] = "Bound Range",
48 [EXC_UD] = "Invalid Opcode",
49 [EXC_NM] = "Device Not Available",
50 [EXC_DF] = "Double Fault",
51 [EXC_TS] = "Invalid TSS",
52 [EXC_NP] = "Segment Not Present",
53 [EXC_SS] = "Stack Fault",
54 [EXC_GP] = "General Protection Fault",
55 [EXC_PF] = "Page Fault",
56 [EXC_MF] = "x87 Floating Point",
57 [EXC_AC] = "Alignment Check",
58 [EXC_MC] = "Machine Check",
59 [EXC_XF] = "SIMD Floating Point",
60 [EXC_SX] = "Security",
63 static void print_segment_error_code(u32 code)
65 printf("%#x - descriptor %#x in the ", code, (code >> 3) & 0x1FFF);
66 if (code & (0x1 << 1)) {
67 printf("IDT");
68 } else {
69 if (code & 0x04)
70 printf("LDT");
71 else
72 printf("GDT");
74 if (code & (0x1 << 0))
75 printf(", external to the CPU");
76 else
77 printf(", internal to the CPU");
80 static void print_page_fault_error_code(u32 code)
82 printf("%#x -", code);
83 if (code & (0x1 << 0))
84 printf(" page protection");
85 else
86 printf(" page not present");
87 if (code & (0x1 << 1))
88 printf(", write");
89 else
90 printf(", read");
91 if (code & (0x1 << 2))
92 printf(", user");
93 else
94 printf(", supervisor");
95 if (code & (0x1 << 3))
96 printf(", reserved bits set");
97 if (code & (0x1 << 4))
98 printf(", instruction fetch");
101 static void print_raw_error_code(u32 code)
103 printf("%#x", code);
106 static void dump_stack(uintptr_t addr, size_t bytes)
108 int i, j;
109 const int line = 8;
110 uint32_t *ptr = (uint32_t *)(addr & ~(line * sizeof(*ptr) - 1));
112 printf("Dumping stack:\n");
113 for (i = bytes / sizeof(*ptr); i >= 0; i -= line) {
114 printf("%p: ", ptr + i);
115 for (j = i; j < i + line; j++)
116 printf("%08x ", *(ptr + j));
117 printf("\n");
121 static void dump_exception_state(void)
123 printf("%s Exception\n", names[exception_state->vector]);
125 printf("Error code: ");
126 switch (exception_state->vector) {
127 case EXC_PF:
128 print_page_fault_error_code(exception_state->error_code);
129 break;
130 case EXC_TS:
131 case EXC_NP:
132 case EXC_SS:
133 case EXC_GP:
134 print_segment_error_code(exception_state->error_code);
135 break;
136 case EXC_DF:
137 case EXC_AC:
138 case EXC_SX:
139 print_raw_error_code(exception_state->error_code);
140 break;
141 default:
142 printf("n/a");
143 break;
145 printf("\n");
146 printf("EIP: 0x%08x\n", exception_state->regs.eip);
147 printf("CS: 0x%04x\n", exception_state->regs.cs);
148 printf("EFLAGS: 0x%08x\n", exception_state->regs.eflags);
149 printf("EAX: 0x%08x\n", exception_state->regs.eax);
150 printf("ECX: 0x%08x\n", exception_state->regs.ecx);
151 printf("EDX: 0x%08x\n", exception_state->regs.edx);
152 printf("EBX: 0x%08x\n", exception_state->regs.ebx);
153 printf("ESP: 0x%08x\n", exception_state->regs.esp);
154 printf("EBP: 0x%08x\n", exception_state->regs.ebp);
155 printf("ESI: 0x%08x\n", exception_state->regs.esi);
156 printf("EDI: 0x%08x\n", exception_state->regs.edi);
157 printf("DS: 0x%04x\n", exception_state->regs.ds);
158 printf("ES: 0x%04x\n", exception_state->regs.es);
159 printf("SS: 0x%04x\n", exception_state->regs.ss);
160 printf("FS: 0x%04x\n", exception_state->regs.fs);
161 printf("GS: 0x%04x\n", exception_state->regs.gs);
164 void exception_dispatch(void)
166 die_if(exception_state->vector >= ARRAY_SIZE(handlers),
167 "Invalid vector %u\n", exception_state->vector);
169 u8 vec = exception_state->vector;
171 if (handlers[vec]) {
172 handlers[vec](vec);
173 goto success;
174 } else if (vec >= EXC_COUNT
175 && CONFIG(LP_IGNORE_UNKNOWN_INTERRUPTS)) {
176 goto success;
177 } else if (vec >= EXC_COUNT
178 && CONFIG(LP_LOG_UNKNOWN_INTERRUPTS)) {
179 printf("Ignoring interrupt vector %u\n", vec);
180 goto success;
183 die_if(vec >= EXC_COUNT || !names[vec], "Bad exception vector %u\n",
184 vec);
186 dump_exception_state();
187 dump_stack(exception_state->regs.esp, 512);
188 /* We don't call apic_eoi because we don't want to ack the interrupt and
189 allow another interrupt to wake the processor. */
190 halt();
191 return;
193 success:
194 if (CONFIG(LP_ENABLE_APIC))
195 apic_eoi(vec);
198 void exception_init(void)
200 exception_stack_end = exception_stack + ARRAY_SIZE(exception_stack);
201 exception_init_asm();
204 void set_interrupt_handler(u8 vector, interrupt_handler handler)
206 handlers[vector] = handler;
209 static uint32_t eflags(void)
211 uint32_t eflags;
212 asm volatile(
213 "pushf\n\t"
214 "pop %0\n\t"
215 : "=rm" (eflags));
216 return eflags;
219 void enable_interrupts(void)
221 asm volatile (
222 "sti\n"
223 : : : "cc"
226 void disable_interrupts(void)
228 asm volatile (
229 "cli\n"
230 : : : "cc"
234 int interrupts_enabled(void)
236 return !!(eflags() & IF_FLAG);