]> Devi Nivas Git - cs3210-lab1.git/commitdiff
add some comments
authorRobert Morris <rtm@nephron.lcs.mit.edu>
Fri, 6 Aug 2010 01:16:55 +0000 (21:16 -0400)
committerRobert Morris <rtm@nephron.lcs.mit.edu>
Fri, 6 Aug 2010 01:16:55 +0000 (21:16 -0400)
find out the hard way why user and kernel must have separate segment descriptors

asm.h
bootasm.S
bootother.S
main.c
proc.h
vm.c

diff --git a/asm.h b/asm.h
index 0c052dbd6cd75898b78f0d3180e93fcc4ea4cc54..68210d788b3cf1868c98fb277cd7c79729f69794 100644 (file)
--- a/asm.h
+++ b/asm.h
@@ -6,6 +6,8 @@
         .word 0, 0;                                             \
         .byte 0, 0, 0, 0
 
+// The 0xC0 means the limit is in 4096-byte units
+// and (for executable segments) 32-bit mode.
 #define SEG_ASM(type,base,lim)                                  \
         .word (((lim) >> 12) & 0xffff), ((base) & 0xffff);      \
         .byte (((base) >> 16) & 0xff), (0x90 | (type)),         \
index f6af25570884cde8a43c2e9d66f5adde5b2e2ff7..56175cefbf9c501c3e8494670d5098214af99498 100644 (file)
--- a/bootasm.S
+++ b/bootasm.S
@@ -51,8 +51,10 @@ seta20.2:
   orl     $CR0_PE, %eax
   movl    %eax, %cr0
   
-  # Jump to next instruction, but in 32-bit code segment.
-  # Switches processor into 32-bit mode.
+  # This ljmp is how you load the CS (Code Segment) register.
+  # SEG_ASM produces segment descriptors with the 32-bit mode
+  # flag set (the D flag), so addresses and word operands will
+  # default to 32 bits after this jump.
   ljmp    $(SEG_KCODE<<3), $start32
 
 .code32                       # Assemble for 32-bit mode
index 11d32f131d24a284692711a9fed1a42acce5fc91..899669ad9f8904e10bbaaf8fd7f62909e68459e3 100644 (file)
@@ -45,8 +45,10 @@ start:
   orl     $CR0_PE, %eax
   movl    %eax, %cr0
 
-  # Jump to next instruction, but in 32-bit code segment.
-  # Switches processor into 32-bit mode.
+  # This ljmp is how you load the CS (Code Segment) register.
+  # SEG_ASM produces segment descriptors with the 32-bit mode
+  # flag set (the D flag), so addresses and word operands will
+  # default to 32 bits after this jump.
   ljmp    $(SEG_KCODE<<3), $start32
 
 .code32                       # Assemble for 32-bit mode
diff --git a/main.c b/main.c
index 8be66e3eeb2863a0ba664d980eff409e57208f8c..a6088cb5858df9fd3431b1481b8ae87dadbdc909 100644 (file)
--- a/main.c
+++ b/main.c
@@ -16,13 +16,13 @@ main(void)
 {
   mpinit();        // collect info about this machine
   lapicinit(mpbcpu());
-  ksegment();
+  ksegment();      // set up segments
   picinit();       // interrupt controller
   ioapicinit();    // another interrupt controller
   consoleinit();   // I/O devices & their interrupts
   uartinit();      // serial port
-  pminit();        // physical memory for kernel
-  jkstack();       // Jump to mainc on a properly-allocated stack 
+  pminit();        // discover how much memory there is
+  jkstack();       // call mainc() on a properly-allocated stack 
 }
 
 void
@@ -41,7 +41,7 @@ void
 mainc(void)
 {
   cprintf("\ncpu%d: starting xv6\n\n", cpu->id);
-  kvmalloc();      // allocate the kernel page table
+  kvmalloc();      // initialze the kernel page table
   pinit();         // process table
   tvinit();        // trap vectors
   binit();         // buffer cache
@@ -57,8 +57,9 @@ mainc(void)
   mpmain();
 }
 
-// Bootstrap processor gets here after setting up the hardware.
-// Additional processors start here.
+// Common CPU setup code.
+// Bootstrap CPU comes here from mainc().
+// Other CPUs jump here from bootother.S.
 static void
 mpmain(void)
 {
@@ -66,11 +67,11 @@ mpmain(void)
     ksegment();
     lapicinit(cpunum());
   }
-  vminit();        // Run with paging on each processor
+  vminit();        // turn on paging
   cprintf("cpu%d: starting\n", cpu->id);
-  idtinit();
+  idtinit();       // load idt register
   xchg(&cpu->booted, 1);
-  scheduler();
+  scheduler();     // start running processes
 }
 
 static void
@@ -85,6 +86,7 @@ bootothers(void)
   // placed the start of bootother.S there.
   code = (uchar *) 0x7000;
   memmove(code, _binary_bootother_start, (uint)_binary_bootother_size);
+
   for(c = cpus; c < cpus+ncpu; c++){
     if(c == cpus+cpunum())  // We've started already.
       continue;
@@ -95,7 +97,7 @@ bootothers(void)
     *(void**)(code-8) = mpmain;
     lapicstartap(c->id, (uint)code);
 
-    // Wait for cpu to get through bootstrap.
+    // Wait for cpu to finish mpmain()
     while(c->booted == 0)
       ;
   }
diff --git a/proc.h b/proc.h
index ebc42f1702ba297d2c045c0d6dac76135b1fc50f..5e5d031ca1fddf2dbb9a811a464b93b593dc4bf2 100644 (file)
--- a/proc.h
+++ b/proc.h
@@ -3,8 +3,8 @@
 #define SEG_KCODE 1  // kernel code
 #define SEG_KDATA 2  // kernel data+stack
 #define SEG_KCPU  3  // kernel per-cpu data
-#define SEG_UCODE 4
-#define SEG_UDATA 5
+#define SEG_UCODE 4  // user code
+#define SEG_UDATA 5  // user data+stack
 #define SEG_TSS   6  // this process's task state
 #define NSEGS     7
 
diff --git a/vm.c b/vm.c
index c94e9a3762e165e341e3f1138c26c7e6f6cb4101..9ea5e928f1e4276c1536ac5198fb114bb40c1d8a 100644 (file)
--- a/vm.c
+++ b/vm.c
@@ -93,12 +93,15 @@ ksegment(void)
 {
   struct cpu *c;
 
-  // Map once virtual addresses to linear addresses using identity map
+  // Map virtual addresses to linear addresses using identity map.
+  // Cannot share a CODE descriptor for both kernel and user
+  // because it would have to have DPL_USR, but the CPU forbids
+  // an interrupt from CPL=0 to DPL=3.
   c = &cpus[cpunum()];
   c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0);
   c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
-  c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0x0, 0xffffffff, DPL_USER);
-  c->gdt[SEG_UDATA] = SEG(STA_W, 0x0, 0xffffffff, DPL_USER);
+  c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER);
+  c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);
 
   // map cpu, and curproc
   c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 8, 0);