source: mainline/kernel/arch/ia32/src/interrupt.c@ 8fb47ec0

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8fb47ec0 was 4491338, checked in by Jakub Jermar <jakub@…>, 16 years ago

Recognize the Division Error fault on ia32 and amd64.
Now when an application divides e.g. by zero, it will be killed with an
appropriate message (i.e. "Division error.") instead of dummy
"Unserviced interrupt: 0".

  • Property mode set to 100644
File size: 6.6 KB
Line 
1/*
2 * Copyright (c) 2001-2004 Jakub Jermar
3 * All rights reserved.
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 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup ia32interrupt
30 * @{
31 */
32/** @file
33 */
34
35#include <arch/interrupt.h>
36#include <syscall/syscall.h>
37#include <print.h>
38#include <debug.h>
39#include <panic.h>
40#include <arch/drivers/i8259.h>
41#include <func.h>
42#include <cpu.h>
43#include <arch/asm.h>
44#include <mm/tlb.h>
45#include <mm/as.h>
46#include <arch.h>
47#include <proc/thread.h>
48#include <proc/task.h>
49#include <synch/spinlock.h>
50#include <arch/ddi/ddi.h>
51#include <ipc/sysipc.h>
52#include <interrupt.h>
53#include <ddi/irq.h>
54#include <symtab.h>
55
56/*
57 * Interrupt and exception dispatching.
58 */
59
60void (* disable_irqs_function)(uint16_t irqmask) = NULL;
61void (* enable_irqs_function)(uint16_t irqmask) = NULL;
62void (* eoi_function)(void) = NULL;
63
64void decode_istate(istate_t *istate)
65{
66 char *symbol;
67
68 symbol = symtab_fmt_name_lookup(istate->eip);
69
70 if (CPU)
71 printf("----------------EXCEPTION OCCURED (cpu%u)----------------\n", CPU->id);
72 else
73 printf("----------------EXCEPTION OCCURED----------------\n");
74
75 printf("%%eip: %#lx (%s)\n", istate->eip, symbol);
76 printf("ERROR_WORD=%#lx\n", istate->error_word);
77 printf("%%cs=%#lx,flags=%#lx\n", istate->cs, istate->eflags);
78 printf("%%eax=%#lx, %%ecx=%#lx, %%edx=%#lx, %%esp=%p\n", istate->eax, istate->ecx, istate->edx, &istate->stack[0]);
79 printf("stack: %#lx, %#lx, %#lx, %#lx\n", istate->stack[0], istate->stack[1], istate->stack[2], istate->stack[3]);
80 printf(" %#lx, %#lx, %#lx, %#lx\n", istate->stack[4], istate->stack[5], istate->stack[6], istate->stack[7]);
81}
82
83static void trap_virtual_eoi(void)
84{
85 if (eoi_function)
86 eoi_function();
87 else
88 panic("No eoi_function.");
89
90}
91
92static void null_interrupt(int n, istate_t *istate)
93{
94 fault_if_from_uspace(istate, "Unserviced interrupt: %d.", n);
95
96 decode_istate(istate);
97 panic("Unserviced interrupt: %d.", n);
98}
99
100static void de_fault(int n, istate_t *istate)
101{
102 fault_if_from_uspace(istate, "Divide error.");
103
104 decode_istate(istate);
105 panic("Divide error.");
106}
107
108/** General Protection Fault. */
109static void gp_fault(int n __attribute__((unused)), istate_t *istate)
110{
111 if (TASK) {
112 size_t ver;
113
114 spinlock_lock(&TASK->lock);
115 ver = TASK->arch.iomapver;
116 spinlock_unlock(&TASK->lock);
117
118 if (CPU->arch.iomapver_copy != ver) {
119 /*
120 * This fault can be caused by an early access
121 * to I/O port because of an out-dated
122 * I/O Permission bitmap installed on CPU.
123 * Install the fresh copy and restart
124 * the instruction.
125 */
126 io_perm_bitmap_install();
127 return;
128 }
129 fault_if_from_uspace(istate, "General protection fault.");
130 }
131
132 decode_istate(istate);
133 panic("General protection fault.");
134}
135
136static void ss_fault(int n __attribute__((unused)), istate_t *istate)
137{
138 fault_if_from_uspace(istate, "Stack fault.");
139
140 decode_istate(istate);
141 panic("Stack fault.");
142}
143
144static void simd_fp_exception(int n __attribute__((unused)), istate_t *istate)
145{
146 uint32_t mxcsr;
147 asm (
148 "stmxcsr %[mxcsr]\n"
149 : [mxcsr] "=m" (mxcsr)
150 );
151 fault_if_from_uspace(istate, "SIMD FP exception(19), MXCSR: %#zx.",
152 (unative_t) mxcsr);
153
154 decode_istate(istate);
155 printf("MXCSR: %#lx\n", mxcsr);
156 panic("SIMD FP exception(19).");
157}
158
159static void nm_fault(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
160{
161#ifdef CONFIG_FPU_LAZY
162 scheduler_fpu_lazy_request();
163#else
164 fault_if_from_uspace(istate, "FPU fault.");
165 panic("FPU fault.");
166#endif
167}
168
169#ifdef CONFIG_SMP
170static void tlb_shootdown_ipi(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
171{
172 trap_virtual_eoi();
173 tlb_shootdown_ipi_recv();
174}
175#endif
176
177/** Handler of IRQ exceptions */
178static void irq_interrupt(int n, istate_t *istate __attribute__((unused)))
179{
180 ASSERT(n >= IVT_IRQBASE);
181
182 int inum = n - IVT_IRQBASE;
183 bool ack = false;
184 ASSERT(inum < IRQ_COUNT);
185 ASSERT((inum != IRQ_PIC_SPUR) && (inum != IRQ_PIC1));
186
187 irq_t *irq = irq_dispatch_and_lock(inum);
188 if (irq) {
189 /*
190 * The IRQ handler was found.
191 */
192
193 if (irq->preack) {
194 /* Send EOI before processing the interrupt */
195 trap_virtual_eoi();
196 ack = true;
197 }
198 irq->handler(irq);
199 spinlock_unlock(&irq->lock);
200 } else {
201 /*
202 * Spurious interrupt.
203 */
204#ifdef CONFIG_DEBUG
205 printf("cpu%u: spurious interrupt (inum=%d)\n", CPU->id, inum);
206#endif
207 }
208
209 if (!ack)
210 trap_virtual_eoi();
211}
212
213void interrupt_init(void)
214{
215 int i;
216
217 for (i = 0; i < IVT_ITEMS; i++)
218 exc_register(i, "null", (iroutine) null_interrupt);
219
220 for (i = 0; i < IRQ_COUNT; i++) {
221 if ((i != IRQ_PIC_SPUR) && (i != IRQ_PIC1))
222 exc_register(IVT_IRQBASE + i, "irq", (iroutine) irq_interrupt);
223 }
224
225 exc_register(0, "de_fault", (iroutine) de_fault);
226 exc_register(7, "nm_fault", (iroutine) nm_fault);
227 exc_register(12, "ss_fault", (iroutine) ss_fault);
228 exc_register(13, "gp_fault", (iroutine) gp_fault);
229 exc_register(19, "simd_fp", (iroutine) simd_fp_exception);
230
231#ifdef CONFIG_SMP
232 exc_register(VECTOR_TLB_SHOOTDOWN_IPI, "tlb_shootdown", (iroutine) tlb_shootdown_ipi);
233#endif
234}
235
236void trap_virtual_enable_irqs(uint16_t irqmask)
237{
238 if (enable_irqs_function)
239 enable_irqs_function(irqmask);
240 else
241 panic("No enable_irqs_function.");
242}
243
244void trap_virtual_disable_irqs(uint16_t irqmask)
245{
246 if (disable_irqs_function)
247 disable_irqs_function(irqmask);
248 else
249 panic("No disable_irqs_function.");
250}
251
252/** @}
253 */
Note: See TracBrowser for help on using the repository browser.