Comments.
[pintos-anon] / src / userprog / exception.c
index 79ba7a921b61042e111cce1b0c6231f7ed1cc8ea..745adaa086e4614245748ddd3cbc6c6262b1f5de 100644 (file)
@@ -1,9 +1,12 @@
-#include "exception.h"
+#include "userprog/exception.h"
 #include <inttypes.h>
 #include <inttypes.h>
-#include "lib.h"
-#include "gdt.h"
-#include "interrupt.h"
-#include "thread.h"
+#include <stdio.h>
+#include "userprog/gdt.h"
+#include "threads/interrupt.h"
+#include "threads/thread.h"
+
+/* Number of page faults processed. */
+static long long page_fault_cnt;
 
 static void kill (struct intr_frame *);
 static void page_fault (struct intr_frame *);
 
 static void kill (struct intr_frame *);
 static void page_fault (struct intr_frame *);
@@ -12,9 +15,10 @@ static void page_fault (struct intr_frame *);
    programs.
 
    In a real Unix-like OS, most of these interrupts would be
    programs.
 
    In a real Unix-like OS, most of these interrupts would be
-   passed along to the user process in the form of signals, but
-   we don't implement signals.  Instead, we'll make them simply
-   kill the user process.
+   passed along to the user process in the form of signals, as
+   described in [SV-386] 3-24 and 3-25, but we don't implement
+   signals.  Instead, we'll make them simply kill the user
+   process.
 
    Page faults are an exception.  Here they are treated the same
    way as other exceptions, but this will need to change to
 
    Page faults are an exception.  Here they are treated the same
    way as other exceptions, but this will need to change to
@@ -53,6 +57,13 @@ exception_init (void)
   intr_register (14, 0, INTR_OFF, page_fault, "#PF Page-Fault Exception");
 }
 
   intr_register (14, 0, INTR_OFF, page_fault, "#PF Page-Fault Exception");
 }
 
+/* Prints exception statistics. */
+void
+exception_print_stats (void) 
+{
+  printf ("Exception: %lld page faults\n", page_fault_cnt);
+}
+
 /* Handler for an exception (probably) caused by a user process. */
 static void
 kill (struct intr_frame *f) 
 /* Handler for an exception (probably) caused by a user process. */
 static void
 kill (struct intr_frame *f) 
@@ -72,9 +83,8 @@ kill (struct intr_frame *f)
     case SEL_UCSEG:
       /* User's code segment, so it's a user exception, as we
          expected.  Kill the user process.  */
     case SEL_UCSEG:
       /* User's code segment, so it's a user exception, as we
          expected.  Kill the user process.  */
-      printk ("%s: dying due to interrupt %#04x (%s).\n",
-              thread_name (thread_current ()),
-              f->vec_no, intr_name (f->vec_no));
+      printf ("%s: dying due to interrupt %#04x (%s).\n",
+              thread_name (), f->vec_no, intr_name (f->vec_no));
       intr_dump_frame (f);
       thread_exit (); 
 
       intr_dump_frame (f);
       thread_exit (); 
 
@@ -89,7 +99,7 @@ kill (struct intr_frame *f)
     default:
       /* Some other code segment?  Shouldn't happen.  Panic the
          kernel. */
     default:
       /* Some other code segment?  Shouldn't happen.  Panic the
          kernel. */
-      printk ("Interrupt %#04x (%s) in unknown segment %04x\n",
+      printf ("Interrupt %#04x (%s) in unknown segment %04x\n",
              f->vec_no, intr_name (f->vec_no), f->cs);
       thread_exit ();
     }
              f->vec_no, intr_name (f->vec_no), f->cs);
       thread_exit ();
     }
@@ -101,7 +111,8 @@ kill (struct intr_frame *f)
 #define PF_U 0x4    /* 0: kernel, 1: user process. */
 
 /* Page fault handler.  This is a skeleton that must be filled in
 #define PF_U 0x4    /* 0: kernel, 1: user process. */
 
 /* Page fault handler.  This is a skeleton that must be filled in
-   to implement virtual memory.
+   to implement virtual memory.  Some solutions to project 2 may
+   also require modifying this code.
 
    At entry, the address that faulted is in CR2 (Control Register
    2) and information about the fault, formatted as described in
 
    At entry, the address that faulted is in CR2 (Control Register
    2) and information about the fault, formatted as described in
@@ -113,27 +124,36 @@ kill (struct intr_frame *f)
 static void
 page_fault (struct intr_frame *f) 
 {
 static void
 page_fault (struct intr_frame *f) 
 {
-  bool not_present, write, user;
-  uint32_t fault_addr;
+  bool not_present;  /* True: not-present page, false: writing r/o page. */
+  bool write;        /* True: access was write, false: access was read. */
+  bool user;         /* True: access by user, false: access by kernel. */
+  void *fault_addr;  /* Fault address. */
+
+  /* Obtain faulting address, the virtual address that was
+     accessed to cause the fault.  It may point to code or to
+     data.  It is not necessarily the address of the instruction
+     that caused the fault (that's f->eip).
+     See [IA32-v2a] "MOV--Move to/from Control Registers" and
+     [IA32-v3] 5.14 "Interrupt 14--Page Fault Exception
+     (#PF)". */
+  asm ("movl %%cr2, %0" : "=r" (fault_addr));
+
+  /* Turn interrupts back on (they were only off so that we could
+     be assured of reading CR2 before it changed). */
+  intr_enable ();
+
+  /* Count page faults. */
+  page_fault_cnt++;
 
   /* Determine cause. */
   not_present = (f->error_code & PF_P) == 0;
   write = (f->error_code & PF_W) != 0;
   user = (f->error_code & PF_U) != 0;
 
 
   /* Determine cause. */
   not_present = (f->error_code & PF_P) == 0;
   write = (f->error_code & PF_W) != 0;
   user = (f->error_code & PF_U) != 0;
 
-  /* Obtain faulting address.
-
-     (The faulting address is not necesarily the address of the
-     instruction that caused the fault--that's in F's eip
-     member.  Rather, it's the linear address that was accessed
-     to cause the fault, which is probably an address of data,
-     not code.) */
-  asm ("movl %%cr2, %0" : "=r" (fault_addr));
-
   /* To implement virtual memory, delete the rest of the function
      body, and replace it with code that brings in the page to
      which fault_addr refers. */
   /* To implement virtual memory, delete the rest of the function
      body, and replace it with code that brings in the page to
      which fault_addr refers. */
-  printk ("Page fault on address %08"PRIx32": %s %s page in %s context.\n",
+  printf ("Page fault at %p: %s error %s page in %s context.\n",
           fault_addr,
           not_present ? "not present" : "rights violation",
           write ? "writing" : "reading",
           fault_addr,
           not_present ? "not present" : "rights violation",
           write ? "writing" : "reading",