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
29 #include <arch/exception.h>
30 #include <exception.h>
31 #include <libpayload.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",
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)) {
74 if (code
& (0x1 << 0))
75 printf(", external to the CPU");
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");
86 printf(" page not present");
87 if (code
& (0x1 << 1))
91 if (code
& (0x1 << 2))
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
)
106 static void dump_stack(uintptr_t addr
, size_t bytes
)
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
));
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
) {
128 print_page_fault_error_code(exception_state
->error_code
);
134 print_segment_error_code(exception_state
->error_code
);
139 print_raw_error_code(exception_state
->error_code
);
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
;
174 } else if (vec
>= EXC_COUNT
175 && CONFIG(LP_IGNORE_UNKNOWN_INTERRUPTS
)) {
177 } else if (vec
>= EXC_COUNT
178 && CONFIG(LP_LOG_UNKNOWN_INTERRUPTS
)) {
179 printf("Ignoring interrupt vector %u\n", vec
);
183 die_if(vec
>= EXC_COUNT
|| !names
[vec
], "Bad exception vector %u\n",
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. */
194 if (CONFIG(LP_ENABLE_APIC
))
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)
219 void enable_interrupts(void)
226 void disable_interrupts(void)
234 int interrupts_enabled(void)
236 return !!(eflags() & IF_FLAG
);