X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fthreads%2Finterrupt.c;h=3e522280a5b76ea5baae93e5daf8ecd4746b0028;hb=251b51f76f0594460e1cfbf2c05576fb445b861b;hp=d248d7200b71173a3d43c941ff60f094bb773f34;hpb=f2f8875638593bd5365cfd6a5ba7c9578e52322f;p=pintos-anon diff --git a/src/threads/interrupt.c b/src/threads/interrupt.c index d248d72..3e52228 100644 --- a/src/threads/interrupt.c +++ b/src/threads/interrupt.c @@ -3,6 +3,7 @@ #include #include #include +#include "threads/flags.h" #include "threads/intr-stubs.h" #include "threads/io.h" #include "threads/mmu.h" @@ -49,8 +50,11 @@ enum intr_level 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; } @@ -68,7 +72,12 @@ enum intr_level 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; } @@ -77,7 +86,11 @@ enum intr_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; } @@ -93,9 +106,10 @@ intr_init (void) /* Initialize IDT. */ for (i = 0; i < INTR_CNT; i++) - idt[i] = make_trap_gate (intr_stubs[i], 0); + idt[i] = make_intr_gate (intr_stubs[i], 0); - /* Load IDT register. */ + /* 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)); @@ -116,6 +130,7 @@ intr_init (void) 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"; @@ -295,14 +310,18 @@ make_idtr_operand (uint16_t limit, void *base) /* Handler for all interrupts, faults, and exceptions. This function is called by the assembly language interrupt stubs in - intr-stubs.S (see intr-stubs.pl). FRAME describes the - interrupt and the interrupted thread's registers. */ + intr-stubs.S. FRAME describes the interrupt and the + interrupted thread's registers. */ void intr_handler (struct intr_frame *frame) { 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) { @@ -342,9 +361,14 @@ intr_handler (struct intr_frame *frame) 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)); printf ("Interrupt %#04x (%s) at eip=%p\n", f->vec_no, intr_names[f->vec_no], f->eip); @@ -354,7 +378,7 @@ intr_dump_frame (const struct intr_frame *f) printf (" esi=%08"PRIx32" edi=%08"PRIx32" esp=%08"PRIx32" ebp=%08"PRIx32"\n", f->esi, f->edi, (uint32_t) f->esp, f->ebp); printf (" 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); + f->cs, f->ds, f->es, f->ss); } /* Returns the name of interrupt VEC. */