diff --git a/Makefile b/Makefile
index 8f820e1e7ef448ba50b7b6bb0a413b22780f224a..37924e228c78ca4012807d1adb0929942276697b 100644
--- a/Makefile
+++ b/Makefile
@@ -159,7 +159,7 @@ clean:
 
 # make a printout
 FILES = $(shell grep -v '^\#' runoff.list)
-PRINT = runoff.list $(FILES)
+PRINT = runoff.list runoff.spec $(FILES)
 
 xv6.pdf: $(PRINT)
 	./runoff
diff --git a/README b/README
index 286d336d2b2a7b6b50e3e2b333f139d101f28921..c46ec2a06f4b77f7d7a524e5330efa69beb39f38 100644
--- a/README
+++ b/README
@@ -20,6 +20,9 @@ The following people made contributions:
     Cliff Frey (MP)
     Xiao Yu (MP)
 
+In addition, we are grateful for the patches submitted by Greg Price,
+Yandong Mao, and Hitoshi Mitake.
+
 The code in the files that constitute xv6 is
 Copyright 2006-2007 Frans Kaashoek, Robert Morris, and Russ Cox.
 
diff --git a/kalloc.c b/kalloc.c
index 43e80e80a273aa2217eaf7c84cb06cee6bb9bacf..5f690f55399b3e82458d4dd5fe3d9a2ed0226e99 100644
--- a/kalloc.c
+++ b/kalloc.c
@@ -29,6 +29,7 @@ kinit(void)
     kfree(p);
 }
 
+//PAGEBREAK: 21
 // Free the page of physical memory pointed at by v,
 // which normally should have been returned by a
 // call to kalloc().  (The exception is when
diff --git a/mmu.h b/mmu.h
index db40f2588f964fb5e8b4bbdba9a6bbb77591fc4c..475eae8d561390b7cc044221ef93fc6f9ba8c980 100644
--- a/mmu.h
+++ b/mmu.h
@@ -24,6 +24,20 @@
 #define FL_VIP          0x00100000      // Virtual Interrupt Pending
 #define FL_ID           0x00200000      // ID flag
 
+// Control Register flags
+#define CR0_PE		0x00000001	// Protection Enable
+#define CR0_MP		0x00000002	// Monitor coProcessor
+#define CR0_EM		0x00000004	// Emulation
+#define CR0_TS		0x00000008	// Task Switched
+#define CR0_ET		0x00000010	// Extension Type
+#define CR0_NE		0x00000020	// Numeric Errror
+#define CR0_WP		0x00010000	// Write Protect
+#define CR0_AM		0x00040000	// Alignment Mask
+#define CR0_NW		0x20000000	// Not Writethrough
+#define CR0_CD		0x40000000	// Cache Disable
+#define CR0_PG		0x80000000	// Paging
+
+//PAGEBREAK!
 // Segment Descriptor
 struct segdesc {
   uint lim_15_0 : 16;  // Low bits of segment limit
@@ -46,7 +60,6 @@ struct segdesc {
 { ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff,      \
   ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1,       \
   (uint)(lim) >> 28, 0, 0, 1, 1, (uint)(base) >> 24 }
-
 #define SEG16(type, base, lim, dpl) (struct segdesc)  \
 { (lim) & 0xffff, (uint)(base) & 0xffff,              \
   ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1,       \
@@ -62,8 +75,6 @@ struct segdesc {
 #define STA_R       0x2     // Readable (executable segments)
 #define STA_A       0x1     // Accessed
 
-// 
-
 // System segment type bits
 #define STS_T16A    0x1     // Available 16-bit TSS
 #define STS_LDT     0x2     // Local Descriptor Table
@@ -78,7 +89,6 @@ struct segdesc {
 #define STS_IG32    0xE     // 32-bit Interrupt Gate
 #define STS_TG32    0xF     // 32-bit Trap Gate
 
-
 // A linear address 'la' has a three-part structure as follows:
 //
 // +--------10------+-------10-------+---------12----------+
@@ -130,21 +140,6 @@ struct segdesc {
 
 typedef uint pte_t;
 
-// Control Register flags
-#define CR0_PE		0x00000001	// Protection Enable
-#define CR0_MP		0x00000002	// Monitor coProcessor
-#define CR0_EM		0x00000004	// Emulation
-#define CR0_TS		0x00000008	// Task Switched
-#define CR0_ET		0x00000010	// Extension Type
-#define CR0_NE		0x00000020	// Numeric Errror
-#define CR0_WP		0x00010000	// Write Protect
-#define CR0_AM		0x00040000	// Alignment Mask
-#define CR0_NW		0x20000000	// Not Writethrough
-#define CR0_CD		0x40000000	// Cache Disable
-#define CR0_PG		0x80000000	// Paging
-
-
-// PAGEBREAK: 40
 // Task state segment format
 struct taskstate {
   uint link;         // Old ts selector
diff --git a/proc.c b/proc.c
index 5ac27800edf2bf639b35266fae78f5cb05f32ca5..0dc77b80b5ae453f41cf2880dd9bbb71b1af2fe0 100644
--- a/proc.c
+++ b/proc.c
@@ -120,7 +120,8 @@ userinit(void)
     panic("userinit: out of memory?");
   if (!allocuvm(p->pgdir, 0x0, (int)_binary_initcode_size))
     panic("userinit: out of memory?");
-  inituvm(p->pgdir, 0x0, _binary_initcode_start, (int)_binary_initcode_size);
+  inituvm(p->pgdir, 0x0, _binary_initcode_start,
+          (int)_binary_initcode_size);
   p->sz = PGROUNDUP((int)_binary_initcode_size);
   memset(p->tf, 0, sizeof(*p->tf));
   p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
diff --git a/runoff b/runoff
index 21ee8ed5ebdef5814dfabfe435db2947ef604dea..14db25284f6a70efa4b0befcbfec991d6e6d92b4 100755
--- a/runoff
+++ b/runoff
@@ -82,23 +82,25 @@ perl -e '
 			next;
 		}
 		
-		if(/(left|right): (.*)/){
+		if(/(left|right)(\+?): (.*)/){
 			$what = $1;
-			$file = $2;
+			$tens = ($2 eq "+" ? "5" : "0");
+			$file = $3;
 			if(!defined($toc{$file})){
 				print STDERR "Have no toc for $file\n";
 				next;
 			}
-			# this assumes that sheet 1 of code is a left page
-			# double-check the PDF
+			# this assumes that sheet 1 of code is a right page
+			# double-check the PDF.  swap the two regexps below
+			# otherwise.
 			if(!$leftwarn++) {
-				print STDERR "assuming that sheet 1 is a left page.  double-check!\n";
+				print STDERR "assuming that sheet 1 is a right page.  double-check!\n";
 			}
-			if($what eq "left" && !($toc{$file} =~ /^\d[13579]0/)){
+			if($what eq "left" && !($toc{$file} =~ /^\d[02468]$tens/)){
 				print STDERR "$file does not start on a fresh left page [$toc{$file}]\n";
 			}
 			# why does this not work if I inline $x in the if?
-			$x = ($toc{$file} =~ /^\d[02468]0/);
+			$x = ($toc{$file} =~ /^\d[13579]$tens/);
 			if($what eq "right" && !$x){
 				print STDERR "$file does not start on a fresh right page [$toc{$file}] [$x]\n";
 			}
diff --git a/runoff.list b/runoff.list
index 3258398868983f0df5e4ab61c64f00957744014c..025bbe22ac0e8d59d00f25e78daa968b95e460fb 100644
--- a/runoff.list
+++ b/runoff.list
@@ -9,8 +9,8 @@ elf.h
 
 # startup
 bootasm.S
-bootother.S
 bootmain.c
+bootother.S
 main.c
 
 # locks
@@ -23,7 +23,6 @@ proc.c
 swtch.S
 kalloc.c
 vm.c
-
 # system calls
 traps.h
 vectors.pl
@@ -46,8 +45,6 @@ file.c
 sysfile.c
 exec.c
 
-
-
 # pipes
 pipe.c
 
@@ -73,3 +70,5 @@ init.c
 sh.c
 
 
+
+
diff --git a/runoff.spec b/runoff.spec
index e4cfd426bd8ac8b6831f0296e9635df88d08777f..e6f5a955cfe595698f97d9ab8414d5487b24c1de 100644
--- a/runoff.spec
+++ b/runoff.spec
@@ -16,15 +16,15 @@ even: main.c
 # odd: init.c
 
 # spinlock.h either
-# spinlock.c either
+right: spinlock.c  # mild preference
 even: proc.h  # mild preference
 
 # goal is to have two action-packed 2-page spreads,
 # one with
-#     ksegment usegment allocproc userinit growproc fork
+#     allocproc userinit growproc fork
 # and another with
 #     scheduler sched yield forkret sleep wakeup1 wakeup
-right: proc.c   # VERY important
+right+: proc.c   # VERY important
 
 # setjmp.S either
 # vm.c either
diff --git a/trap.c b/trap.c
index daee22f6e842a359287a84162b40088747654e9d..ae26739276c0e930c7ece65bbf3cce985c65da83 100644
--- a/trap.c
+++ b/trap.c
@@ -83,7 +83,8 @@ trap(struct trapframe *tf)
       panic("trap");
     }
     // In user space, assume process misbehaved.
-    cprintf("pid %d %s: trap %d err %d on cpu %d eip 0x%x addr 0x%x--kill proc\n",
+    cprintf("pid %d %s: trap %d err %d on cpu %d "
+            "eip 0x%x addr 0x%x--kill proc\n",
             proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip, 
 	    rcr2());
     proc->killed = 1;
diff --git a/x86.h b/x86.h
index b9fa8b8ac4455561495838cabeb84c48ba4a861d..33e240dd9bdf2774ed756752d8cac1b30506c499 100644
--- a/x86.h
+++ b/x86.h
@@ -90,23 +90,26 @@ readeflags(void)
   return eflags;
 }
 
+static inline void
+loadgs(ushort v)
+{
+  asm volatile("movw %0, %%gs" : : "r" (v));
+}
+
 static inline uint
-xchg(volatile uint *addr, uint newval)
+rebp(void)
 {
-  uint result;
-  
-  // The + in "+m" denotes a read-modify-write operand.
-  asm volatile("lock; xchgl %0, %1" :
-               "+m" (*addr), "=a" (result) :
-               "1" (newval) :
-               "cc");
-  return result;
+  uint val;
+  asm volatile("movl %%ebp,%0" : "=r" (val));
+  return val;
 }
 
-static inline void
-loadgs(ushort v)
+static inline uint
+resp(void)
 {
-  asm volatile("movw %0, %%gs" : : "r" (v));
+  uint val;
+  asm volatile("movl %%esp,%0" : "=r" (val));
+  return val;
 }
 
 static inline void
@@ -121,66 +124,62 @@ sti(void)
   asm volatile("sti");
 }
 
-static inline void lcr0(uint val)
-{
-  asm volatile("movl %0,%%cr0" : : "r" (val));
-}
-
-static inline uint rcr0(void)
+static inline uint
+xchg(volatile uint *addr, uint newval)
 {
-  uint val;
-  asm volatile("movl %%cr0,%0" : "=r" (val));
-  return val;
+  uint result;
+  
+  // The + in "+m" denotes a read-modify-write operand.
+  asm volatile("lock; xchgl %0, %1" :
+               "+m" (*addr), "=a" (result) :
+               "1" (newval) :
+               "cc");
+  return result;
 }
 
-static inline uint rcr2(void)
+static inline void
+nop_pause(void)
 {
-  uint val;
-  asm volatile("movl %%cr2,%0" : "=r" (val));
-  return val;
+  asm volatile("pause" : :);
 }
 
-static inline void lcr3(uint val) 
+//PAGEBREAK!
+static inline void
+lcr0(uint val)
 {
-  asm volatile("movl %0,%%cr3" : : "r" (val));
+  asm volatile("movl %0,%%cr0" : : "r" (val));
 }
 
-static inline uint rcr3(void)
+static inline uint
+rcr0(void)
 {
   uint val;
-  asm volatile("movl %%cr3,%0" : "=r" (val));
+  asm volatile("movl %%cr0,%0" : "=r" (val));
   return val;
 }
 
-static inline void lebp(uint val)
-{
-  asm volatile("movl %0,%%ebp" : : "r" (val));
-}
-
-static inline uint rebp(void)
+static inline uint
+rcr2(void)
 {
   uint val;
-  asm volatile("movl %%ebp,%0" : "=r" (val));
+  asm volatile("movl %%cr2,%0" : "=r" (val));
   return val;
 }
 
-static inline void lesp(uint val)
+static inline void
+lcr3(uint val) 
 {
-  asm volatile("movl %0,%%esp" : : "r" (val));
+  asm volatile("movl %0,%%cr3" : : "r" (val));
 }
 
-static inline uint resp(void)
+static inline uint
+rcr3(void)
 {
   uint val;
-  asm volatile("movl %%esp,%0" : "=r" (val));
+  asm volatile("movl %%cr3,%0" : "=r" (val));
   return val;
 }
 
-static inline void nop_pause(void)
-{
-  asm volatile("pause" : :);
-}
-
 //PAGEBREAK: 36
 // Layout of the trap frame built on the stack by the
 // hardware and by trapasm.S, and passed to trap().