source: mainline/kernel/arch/amd64/src/interrupt.c@ 4491338

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4491338 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.0 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 amd64interrupt
30 * @{
31 */
32/** @file
33 */
34
35#include <arch/interrupt.h>
36#include <print.h>
37#include <debug.h>
38#include <panic.h>
39#include <arch/drivers/i8259.h>
40#include <func.h>
41#include <cpu.h>
42#include <arch/asm.h>
43#include <mm/tlb.h>
44#include <mm/as.h>
45#include <arch.h>
46#include <arch/asm.h>
47#include <proc/scheduler.h>
48#include <proc/thread.h>
49#include <proc/task.h>
50#include <synch/spinlock.h>
51#include <arch/ddi/ddi.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(int n, istate_t *istate)
65{
66 char *symbol;
67
68 symbol = symtab_fmt_name_lookup(istate->rip);
69
70 printf("-----EXCEPTION(%d) OCCURED----- ( %s )\n", n, __func__);
71 printf("%%rip: %#llx (%s)\n", istate->rip, symbol);
72 printf("ERROR_WORD=%#llx\n", istate->error_word);
73 printf("%%cs=%#llx, rflags=%#llx, %%cr0=%#llx\n", istate->cs,
74 istate->rflags, read_cr0());
75 printf("%%rax=%#llx, %%rcx=%#llx, %%rdx=%#llx\n", istate->rax,
76 istate->rcx, istate->rdx);
77 printf("%%rsi=%#llx, %%rdi=%#llx, %%r8=%#llx\n", istate->rsi,
78 istate->rdi, istate->r8);
79 printf("%%r9=%#llx, %%r10=%#llx, %%r11=%#llx\n", istate->r9,
80 istate->r10, istate->r11);
81 printf("%%rsp=%#llx\n", &istate->stack[0]);
82}
83
84static void trap_virtual_eoi(void)
85{
86 if (eoi_function)
87 eoi_function();
88 else
89 panic("No eoi_function.");
90
91}
92
93static void null_interrupt(int n, istate_t *istate)
94{
95 fault_if_from_uspace(istate, "Unserviced interrupt: %d.", n);
96 decode_istate(n, istate);
97 panic("Unserviced interrupt.");
98}
99
100static void de_fault(int n, istate_t *istate)
101{
102 fault_if_from_uspace(istate, "Divide error.");
103 decode_istate(n, istate);
104 panic("Divide error.");
105}
106
107/** General Protection Fault. */
108static void gp_fault(int n, istate_t *istate)
109{
110 if (TASK) {
111 size_t ver;
112
113 spinlock_lock(&TASK->lock);
114 ver = TASK->arch.iomapver;
115 spinlock_unlock(&TASK->lock);
116
117 if (CPU->arch.iomapver_copy != ver) {
118 /*
119 * This fault can be caused by an early access
120 * to I/O port because of an out-dated
121 * I/O Permission bitmap installed on CPU.
122 * Install the fresh copy and restart
123 * the instruction.
124 */
125 io_perm_bitmap_install();
126 return;
127 }
128 fault_if_from_uspace(istate, "General protection fault.");
129 }
130
131 decode_istate(n, istate);
132 panic("General protection fault.");
133}
134
135static void ss_fault(int n, istate_t *istate)
136{
137 fault_if_from_uspace(istate, "Stack fault.");
138 decode_istate(n, istate);
139 panic("Stack fault.");
140}
141
142static void nm_fault(int n, istate_t *istate)
143{
144#ifdef CONFIG_FPU_LAZY
145 scheduler_fpu_lazy_request();
146#else
147 fault_if_from_uspace(istate, "FPU fault.");
148 panic("FPU fault.");
149#endif
150}
151
152#ifdef CONFIG_SMP
153static void tlb_shootdown_ipi(int n, istate_t *istate)
154{
155 trap_virtual_eoi();
156 tlb_shootdown_ipi_recv();
157}
158#endif
159
160/** Handler of IRQ exceptions */
161static void irq_interrupt(int n, istate_t *istate)
162{
163 ASSERT(n >= IVT_IRQBASE);
164
165 int inum = n - IVT_IRQBASE;
166 bool ack = false;
167 ASSERT(inum < IRQ_COUNT);
168 ASSERT((inum != IRQ_PIC_SPUR) && (inum != IRQ_PIC1));
169
170 irq_t *irq = irq_dispatch_and_lock(inum);
171 if (irq) {
172 /*
173 * The IRQ handler was found.
174 */
175
176 if (irq->preack) {
177 /* Send EOI before processing the interrupt */
178 trap_virtual_eoi();
179 ack = true;
180 }
181 irq->handler(irq);
182 spinlock_unlock(&irq->lock);
183 } else {
184 /*
185 * Spurious interrupt.
186 */
187#ifdef CONFIG_DEBUG
188 printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum);
189#endif
190 }
191
192 if (!ack)
193 trap_virtual_eoi();
194}
195
196void interrupt_init(void)
197{
198 int i;
199
200 for (i = 0; i < IVT_ITEMS; i++)
201 exc_register(i, "null", (iroutine) null_interrupt);
202
203 for (i = 0; i < IRQ_COUNT; i++) {
204 if ((i != IRQ_PIC_SPUR) && (i != IRQ_PIC1))
205 exc_register(IVT_IRQBASE + i, "irq",
206 (iroutine) irq_interrupt);
207 }
208
209 exc_register(0, "de_fault", (iroutine) de_fault);
210 exc_register(7, "nm_fault", (iroutine) nm_fault);
211 exc_register(12, "ss_fault", (iroutine) ss_fault);
212 exc_register(13, "gp_fault", (iroutine) gp_fault);
213 exc_register(14, "ident_mapper", (iroutine) ident_page_fault);
214
215#ifdef CONFIG_SMP
216 exc_register(VECTOR_TLB_SHOOTDOWN_IPI, "tlb_shootdown",
217 (iroutine) tlb_shootdown_ipi);
218#endif
219}
220
221void trap_virtual_enable_irqs(uint16_t irqmask)
222{
223 if (enable_irqs_function)
224 enable_irqs_function(irqmask);
225 else
226 panic("No enable_irqs_function.");
227}
228
229void trap_virtual_disable_irqs(uint16_t irqmask)
230{
231 if (disable_irqs_function)
232 disable_irqs_function(irqmask);
233 else
234 panic("No disable_irqs_function.");
235}
236
237/** @}
238 */
Note: See TracBrowser for help on using the repository browser.