-#include "interrupt.h"
+#include "threads/interrupt.h"
+#include <debug.h>
#include <inttypes.h>
#include <stdint.h>
-#include "intr-stubs.h"
-#include "debug.h"
-#include "io.h"
-#include "lib.h"
-#include "mmu.h"
-#include "thread.h"
-#include "timer.h"
+#include <stdio.h>
+#include "threads/flags.h"
+#include "threads/intr-stubs.h"
+#include "threads/io.h"
+#include "threads/mmu.h"
+#include "threads/thread.h"
+#include "devices/timer.h"
/* Number of x86 interrupts. */
#define INTR_CNT 256
intr_get_level (void)
{
uint32_t flags;
-
- asm ("pushfl; popl %0" : "=g" (flags));
+
+ /* Push the flags register on the processor stack, then pop the
+ value off the stack into `flags'. See [IA32-v2b] "PUSHF"
+ and "POP" and [IA32-v3] 5.8.1. */
+ asm volatile ("pushf; pop %0" : "=g" (flags));
return flags & FLAG_IF ? INTR_ON : INTR_OFF;
}
intr_enable (void)
{
enum intr_level old_level = intr_get_level ();
+ ASSERT (!intr_context ());
+
+ /* Enable interrupts by setting the interrupt flag.
+ See [IA32-v2b] "STI" and [IA32-v3] 5.8.1. */
asm volatile ("sti");
+
return old_level;
}
intr_disable (void)
{
enum intr_level old_level = intr_get_level ();
+
+ /* Disable interrupts by clearing the interrupt flag.
+ See [IA32-v2b] "CLI" and [IA32-v3] 5.8.1. */
asm volatile ("cli");
+
return old_level;
}
\f
/* Initialize interrupt controller. */
pic_init ();
- /* Load IDT register. */
+ /* Initialize IDT. */
+ for (i = 0; i < INTR_CNT; i++)
+ idt[i] = make_intr_gate (intr_stubs[i], 0);
+
+ /* Load IDT register.
+ See [IA32-v2a] "LIDT" and [IA32-v3] 5.10. */
idtr_operand = make_idtr_operand (sizeof idt - 1, idt);
asm volatile ("lidt %0" :: "m" (idtr_operand));
intr_names[11] = "#NP Segment Not Present";
intr_names[12] = "#SS Stack Fault Exception";
intr_names[13] = "#GP General Protection Exception";
+ intr_names[14] = "#PF Page-Fault Exception";
intr_names[16] = "#MF x87 FPU Floating-Point Error";
intr_names[17] = "#AC Alignment Check Exception";
intr_names[18] = "#MC Machine-Check Exception";
bool external;
intr_handler_func *handler;
+ /* External interrupts are special.
+ We only handle one at a time (so interrupts must be off)
+ and they need to be acknowledged on the PIC (see below).
+ An external interrupt handler cannot sleep. */
external = frame->vec_no >= 0x20 && frame->vec_no < 0x30;
if (external)
{
void
intr_dump_frame (const struct intr_frame *f)
{
- uint32_t cr2, ss;
- asm ("movl %%cr2, %0" : "=r" (cr2));
- asm ("movl %%ss, %0" : "=r" (ss));
+ uint32_t cr2;
+
+ /* Store current value of CR2 into `cr2'.
+ CR2 is the linear address of the last page fault.
+ See [IA32-v2a] "MOV--Move to/from Control Registers" and
+ [IA32-v3] 5.14 "Interrupt 14--Page Fault Exception
+ (#PF)". */
+ asm ("mov %0, %%cr2" : "=r" (cr2));
- printk ("Interrupt %#04x (%s) at eip=%p\n",
+ printf ("Interrupt %#04x (%s) at eip=%p\n",
f->vec_no, intr_names[f->vec_no], f->eip);
- printk (" cr2=%08"PRIx32" error=%08"PRIx32"\n", cr2, f->error_code);
- printk (" eax=%08"PRIx32" ebx=%08"PRIx32" ecx=%08"PRIx32" edx=%08"PRIx32"\n",
+ printf (" cr2=%08"PRIx32" error=%08"PRIx32"\n", cr2, f->error_code);
+ printf (" eax=%08"PRIx32" ebx=%08"PRIx32" ecx=%08"PRIx32" edx=%08"PRIx32"\n",
f->eax, f->ebx, f->ecx, f->edx);
- printk (" esi=%08"PRIx32" edi=%08"PRIx32" esp=%08"PRIx32" ebp=%08"PRIx32"\n",
+ printf (" esi=%08"PRIx32" edi=%08"PRIx32" esp=%08"PRIx32" ebp=%08"PRIx32"\n",
f->esi, f->edi, (uint32_t) f->esp, f->ebp);
- printk (" cs=%04"PRIx16" ds=%04"PRIx16" es=%04"PRIx16" ss=%04"PRIx16"\n",
- f->cs, f->ds, f->es, f->cs != SEL_KCSEG ? f->ss : ss);
+ printf (" cs=%04"PRIx16" ds=%04"PRIx16" es=%04"PRIx16" ss=%04"PRIx16"\n",
+ f->cs, f->ds, f->es, f->ss);
}
/* Returns the name of interrupt VEC. */