2 * GeekOS interrupt handling data structures and functions
3 * Copyright (c) 2001,2003 David H. Hovemeyer <daveho@cs.umd.edu>
6 * This is free software. You are permitted to use,
7 * redistribute, and modify it as specified in the file "COPYING".
10 #include <geekos/idt.h> /* x86-specific int handling stuff */
11 #include <geekos/screen.h>
12 #include <geekos/kassert.h>
13 #include <geekos/int.h>
14 #include <geekos/serial.h>
15 #include <geekos/debug.h>
17 #include <geekos/cpu.h>
20 * Defined in lowlevel.asm.
22 ulong_t Get_Current_EFLAGS(void);
24 /* ----------------------------------------------------------------------
25 * Private functions and data
26 * ---------------------------------------------------------------------- */
39 char *exception_names[] = {
45 "#BR (BOUND Range Exceeded)",
46 "#UD (Invalid Opcode)",
47 "#NM (No Math Coprocessor)",
49 "Coprocessor Segment Overrun",
51 "#NP (Segment Not Present)",
52 "#SS (Stack Segment Fault)",
53 "#GP (General Protection Fault)",
56 "#MF (Math Fault x87)",
57 "#AC (Alignment Check)",
58 "#MC (Machine Check)",
59 "#XF (SIMD FP Exception)",
298 char *exception_type_names[] = {
299 "External Interrupt",
302 "Hardware Exception",
305 "Software Exception",
313 * A dummy interrupt handler function.
314 * Ensures that the low-level interrupt code always
315 * has a handler to call.
317 static void Dummy_Interrupt_Handler(struct Interrupt_State* state)
321 /* A "feature" of some chipsets is that if an interrupt is raised by mistake
322 * then its automatically assigned to IRQ 7(Int 39).
323 * Makes perfect sense...
325 * http://forums12.itrc.hp.com/service/forums/questionanswer.do?admit=109447627+1204759699215+28353475&threadId=1118488
327 if (state->intNum != 39) {
328 Print("Unexpected Interrupt! Ignoring!\n");
329 SerialPrint("*** Unexpected interrupt! *** Ignoring!\n");
330 Dump_Interrupt_State(state);
338 static void Print_Selector(const char* regName, uint_t value)
340 Print("%s: index=%d, ti=%d, rpl=%d\n",
341 regName, value >> 3, (value >> 2) & 1, value & 3);
345 static void SerialPrint_Selector(const char* regName, uint_t value)
347 SerialPrint("%s: index=%d, ti=%d, rpl=%d\n",
348 regName, value >> 3, (value >> 2) & 1, value & 3);
351 /* ----------------------------------------------------------------------
353 * ---------------------------------------------------------------------- */
356 * Initialize the interrupt system.
358 void Init_Interrupts(void)
362 PrintBoth("Initializing Interrupts\n");
364 /* Low-level initialization. Build and initialize the IDT. */
368 * Initialize all entries of the handler table with a dummy handler.
369 * This will ensure that we always have a handler function to call.
371 for (i = 0; i < NUM_IDT_ENTRIES; ++i) {
372 Install_Interrupt_Handler(i, Dummy_Interrupt_Handler);
379 /* Re-enable interrupts */
384 * Query whether or not interrupts are currently enabled.
386 bool Interrupts_Enabled(void)
388 ulong_t eflags = Get_Current_EFLAGS();
389 return (eflags & EFLAGS_IF) != 0;
393 * Dump interrupt state struct to screen
395 void Dump_Interrupt_State(struct Interrupt_State* state)
397 uint_t errorCode = state->errorCode;
399 SerialPrint("eax=%08x ebx=%08x ecx=%08x edx=%08x\n"
400 "esi=%08x edi=%08x ebp=%08x\n"
401 "eip=%08x cs=%08x eflags=%08x\n"
402 "Interrupt number=%d (%s), error code=%d\n"
403 "index=%d, TI=%d, IDT=%d, EXT=%d\n",
404 state->eax, state->ebx, state->ecx, state->edx,
405 state->esi, state->edi, state->ebp,
406 state->eip, state->cs, state->eflags,
407 state->intNum, exception_names[state->intNum], errorCode,
408 errorCode >> 3, (errorCode >> 2) & 1, (errorCode >> 1) & 1, errorCode & 1
412 if (Is_User_Interrupt(state)) {
413 struct User_Interrupt_State *ustate = (struct User_Interrupt_State*) state;
414 SerialPrint("user esp=%08x, user ss=%08x\n", ustate->espUser, ustate->ssUser);
416 SerialPrint_Selector("cs", state->cs);
417 SerialPrint_Selector("ds", state->ds);
418 SerialPrint_Selector("es", state->es);
419 SerialPrint_Selector("fs", state->fs);
420 SerialPrint_Selector("gs", state->gs);