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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since acc7ce4 was acc7ce4, checked in by Martin Decky <martin@…>, 14 years ago

uspace interrupt controller drivers for i8259 and APIC (non-functional yet)
convert NE2000 driver to use these drivers (not enabling the IRQ in kernel), this solves the "spurious interrupt" issue
(however, on SMP machines this renders the driver unusable for now since the APIC driver does not do anything yet)

  • Property mode set to 100644
File size: 6.8 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#include <stacktrace.h>
56
57/*
58 * Interrupt and exception dispatching.
59 */
60
61void (* disable_irqs_function)(uint16_t irqmask) = NULL;
62void (* enable_irqs_function)(uint16_t irqmask) = NULL;
63void (* eoi_function)(void) = NULL;
64const char *irqs_info = NULL;
65
66void istate_decode(istate_t *istate)
67{
68 printf("cs =%#0" PRIx32 "\teip=%p\t"
69 "efl=%#0" PRIx32 "\terr=%#0" PRIx32 "\n",
70 istate->cs, (void *) istate->eip,
71 istate->eflags, istate->error_word);
72
73 printf("ds =%#0" PRIx32 "\tes =%#0" PRIx32 "\t"
74 "fs =%#0" PRIx32 "\tgs =%#0" PRIx32 "\n",
75 istate->ds, istate->es, istate->fs, istate->gs);
76
77 if (istate_from_uspace(istate))
78 printf("ss =%#0" PRIx32 "\n", istate->ss);
79
80 printf("eax=%#0" PRIx32 "\tebx=%#0" PRIx32 "\t"
81 "ecx=%#0" PRIx32 "\tedx=%#0" PRIx32 "\n",
82 istate->eax, istate->ebx, istate->ecx, istate->edx);
83
84 printf("esi=%p\tedi=%p\tebp=%p\tesp=%p\n",
85 (void *) istate->esi, (void *) istate->edi,
86 (void *) istate->ebp,
87 istate_from_uspace(istate) ? ((void *) istate->esp) :
88 &istate->esp);
89}
90
91static void trap_virtual_eoi(void)
92{
93 if (eoi_function)
94 eoi_function();
95 else
96 panic("No eoi_function.");
97
98}
99
100static void null_interrupt(unsigned int n, istate_t *istate)
101{
102 fault_if_from_uspace(istate, "Unserviced interrupt: %u.", n);
103 panic_badtrap(istate, n, "Unserviced interrupt: %u.", n);
104}
105
106static void de_fault(unsigned int n, istate_t *istate)
107{
108 fault_if_from_uspace(istate, "Divide error.");
109 panic_badtrap(istate, n, "Divide error.");
110}
111
112/** General Protection Fault. */
113static void gp_fault(unsigned int n __attribute__((unused)), istate_t *istate)
114{
115 if (TASK) {
116 irq_spinlock_lock(&TASK->lock, false);
117 size_t ver = TASK->arch.iomapver;
118 irq_spinlock_unlock(&TASK->lock, false);
119
120 if (CPU->arch.iomapver_copy != ver) {
121 /*
122 * This fault can be caused by an early access
123 * to I/O port because of an out-dated
124 * I/O Permission bitmap installed on CPU.
125 * Install the fresh copy and restart
126 * the instruction.
127 */
128 io_perm_bitmap_install();
129 return;
130 }
131 fault_if_from_uspace(istate, "General protection fault.");
132 }
133 panic_badtrap(istate, n, "General protection fault.");
134}
135
136static void ss_fault(unsigned int n __attribute__((unused)), istate_t *istate)
137{
138 fault_if_from_uspace(istate, "Stack fault.");
139 panic_badtrap(istate, n, "Stack fault.");
140}
141
142static void simd_fp_exception(unsigned int n __attribute__((unused)), istate_t *istate)
143{
144 uint32_t mxcsr;
145 asm volatile (
146 "stmxcsr %[mxcsr]\n"
147 : [mxcsr] "=m" (mxcsr)
148 );
149
150 fault_if_from_uspace(istate, "SIMD FP exception(19), MXCSR=%#0" PRIx32 ".",
151 mxcsr);
152 panic_badtrap(istate, n, "SIMD FP exception");
153}
154
155static void nm_fault(unsigned int n __attribute__((unused)),
156 istate_t *istate __attribute__((unused)))
157{
158#ifdef CONFIG_FPU_LAZY
159 scheduler_fpu_lazy_request();
160#else
161 fault_if_from_uspace(istate, "FPU fault.");
162 panic_badtrap(istate, n, "FPU fault.");
163#endif
164}
165
166#ifdef CONFIG_SMP
167static void tlb_shootdown_ipi(unsigned int n __attribute__((unused)),
168 istate_t *istate __attribute__((unused)))
169{
170 trap_virtual_eoi();
171 tlb_shootdown_ipi_recv();
172}
173#endif
174
175/** Handler of IRQ exceptions */
176static void irq_interrupt(unsigned int n, istate_t *istate __attribute__((unused)))
177{
178 ASSERT(n >= IVT_IRQBASE);
179
180 unsigned int inum = n - IVT_IRQBASE;
181 bool ack = false;
182 ASSERT(inum < IRQ_COUNT);
183 ASSERT((inum != IRQ_PIC_SPUR) && (inum != IRQ_PIC1));
184
185 irq_t *irq = irq_dispatch_and_lock(inum);
186 if (irq) {
187 /*
188 * The IRQ handler was found.
189 */
190
191 if (irq->preack) {
192 /* Send EOI before processing the interrupt */
193 trap_virtual_eoi();
194 ack = true;
195 }
196 irq->handler(irq);
197 irq_spinlock_unlock(&irq->lock, false);
198 } else {
199 /*
200 * Spurious interrupt.
201 */
202#ifdef CONFIG_DEBUG
203 printf("cpu%u: spurious interrupt (inum=%u)\n", CPU->id, inum);
204#endif
205 }
206
207 if (!ack)
208 trap_virtual_eoi();
209}
210
211void interrupt_init(void)
212{
213 unsigned int i;
214
215 for (i = 0; i < IVT_ITEMS; i++)
216 exc_register(i, "null", false, (iroutine_t) null_interrupt);
217
218 for (i = 0; i < IRQ_COUNT; i++) {
219 if ((i != IRQ_PIC_SPUR) && (i != IRQ_PIC1))
220 exc_register(IVT_IRQBASE + i, "irq", true,
221 (iroutine_t) irq_interrupt);
222 }
223
224 exc_register(0, "de_fault", true, (iroutine_t) de_fault);
225 exc_register(7, "nm_fault", true, (iroutine_t) nm_fault);
226 exc_register(12, "ss_fault", true, (iroutine_t) ss_fault);
227 exc_register(13, "gp_fault", true, (iroutine_t) gp_fault);
228 exc_register(19, "simd_fp", true, (iroutine_t) simd_fp_exception);
229
230#ifdef CONFIG_SMP
231 exc_register(VECTOR_TLB_SHOOTDOWN_IPI, "tlb_shootdown", true,
232 (iroutine_t) 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.