Move filesys_init into main_thread.
[pintos-anon] / src / threads / interrupt.c
index 90587756988a71b0e4c2125e6dd4898f3e9e7073..6945e0a2d6843089c9e8421bc1e987d5038dcc94 100644 (file)
@@ -88,10 +88,13 @@ pic_init (void)
    If we don't acknowledge the IRQ, we'll never get it again, so
    this is important.  */
 static void
-pic_eoi (void
+pic_eoi (int irq
 {
   /* FIXME?  The Linux code is much more complicated. */
+  ASSERT (irq >= 0x20 && irq < 0x30);
   outb (0x20, 0x20);
+  if (irq >= 0x28)
+    outb (0xa0, 0x20);
 }
 \f
 #define INTR_CNT 256
@@ -102,8 +105,8 @@ static const char *intr_names[INTR_CNT];
 
 void intr_handler (struct intr_frame *args);
 
-bool intr_in_progress;
-bool yield_on_return;
+static bool intr_in_progress;
+static bool yield_on_return;
 
 const char *
 intr_name (int vec) 
@@ -117,16 +120,13 @@ intr_name (int vec)
 void
 intr_handler (struct intr_frame *args) 
 {
-  bool external;
-  
-  yield_on_return = false;
-
-  external = args->vec_no >= 0x20 && args->vec_no < 0x30;
+  bool external = args->vec_no >= 0x20 && args->vec_no < 0x30;
   if (external) 
     {
       ASSERT (intr_get_level () == IF_OFF);
       ASSERT (!intr_context ());
       intr_in_progress = true;
+      yield_on_return = false;
     }
 
   intr_handlers[args->vec_no] (args);
@@ -136,11 +136,11 @@ intr_handler (struct intr_frame *args)
       ASSERT (intr_get_level () == IF_OFF);
       ASSERT (intr_context ());
       intr_in_progress = false;
-      pic_eoi (); 
-    }
+      pic_eoi (args->vec_no); 
 
-  if (yield_on_return) 
-    thread_yield (); 
+      if (yield_on_return) 
+        thread_yield (); 
+    }
 }
 
 bool
@@ -152,6 +152,7 @@ intr_context (void)
 void
 intr_yield_on_return (void) 
 {
+  ASSERT (intr_context ());
   yield_on_return = true;
 }
 
@@ -159,38 +160,43 @@ intr_handler_func intr_panic NO_RETURN;
 intr_handler_func intr_kill NO_RETURN;
 
 static uint64_t
-make_intr_gate (void (*target) (void),
-                int dpl)
+make_gate (void (*target) (void), int dpl, enum seg_type type)
 {
   uint32_t offset = (uint32_t) target;
   uint32_t e0 = ((offset & 0xffff)            /* Offset 15:0. */
                  | (SEL_KCSEG << 16));        /* Target code segment. */
   uint32_t e1 = ((offset & 0xffff0000)        /* Offset 31:16. */
                  | (1 << 15)                  /* Present. */
-                 | (dpl << 13)                /* Descriptor privilege. */
+                 | ((uint32_t) dpl << 13)     /* Descriptor privilege. */
                  | (SYS_SYSTEM << 12)         /* System. */
-                 | (TYPE_INT_32 << 8));       /* 32-bit interrupt gate. */
+                 | ((uint32_t) type << 8));   /* Gate type. */
   return e0 | ((uint64_t) e1 << 32);
 }
 
 static uint64_t
-make_trap_gate (void (*target) (void),
-                int dpl)
+make_intr_gate (void (*target) (void), int dpl)
+{
+  return make_gate (target, dpl, TYPE_INT_32);
+}
+
+static uint64_t
+make_trap_gate (void (*target) (void), int dpl)
 {
-  return make_intr_gate (target, dpl) | (1 << 8);
+  return make_gate (target, dpl, TYPE_TRAP_32);
 }
 
-/* We don't support nested interrupts generated by external
-   hardware, so these interrupts (vec_no 0x20...0x2f) should
-   specify IF_OFF for LEVEL.  Otherwise a timer interrupt could
-   cause a task switch during interrupt handling.  Most other
-   interrupts can and should be handled with interrupts
-   enabled. */
 void
 intr_register (uint8_t vec_no, int dpl, enum if_level level,
                intr_handler_func *handler,
                const char *name) 
 {
+  /* Interrupts generated by external hardware (0x20 <= VEC_NO <=
+     0x2f) should specify IF_OFF for LEVEL.  Otherwise a timer
+     interrupt could cause a task switch during interrupt
+     handling.  Most other interrupts can and should be handled
+     with interrupts enabled. */
+  ASSERT (vec_no < 0x20 || vec_no > 0x2f || level == IF_OFF);
+
   if (level == IF_ON)
     idt[vec_no] = make_trap_gate (intr_stubs[vec_no], dpl);
   else
@@ -272,17 +278,18 @@ intr_kill (struct intr_frame *f)
   switch (f->cs)
     {
     case SEL_UCSEG:
-      printk ("[%p] Interrupt %#04x (%s), killing process.\n",
-              thread_current (), f->vec_no, intr_name (f->vec_no));
+      printk ("%s: dying due to interrupt %#04x (%s).\n",
+              thread_current ()->name, f->vec_no, intr_name (f->vec_no));
       thread_exit (); 
 
-    default:
-      panic ("Interrupt %#04x (%s) in unknown segment %04x",
-             f->vec_no, intr_name (f->vec_no), f->cs);
-
     case SEL_KCSEG:
-      printk ("intr_kill -> panic %d\n", f->vec_no);
+      printk ("Kernel bug - unexpected interrupt in kernel context\n");
       intr_panic (f);
+
+    default:
+      printk ("Interrupt %#04x (%s) in unknown segment %04x\n",
+             f->vec_no, intr_name (f->vec_no), f->cs);
+      thread_exit ();
     }
 }