diff options
| -rw-r--r-- | asm.h | 2 | ||||
| -rw-r--r-- | bootasm.S | 6 | ||||
| -rw-r--r-- | bootother.S | 6 | ||||
| -rw-r--r-- | main.c | 22 | ||||
| -rw-r--r-- | proc.h | 4 | ||||
| -rw-r--r-- | vm.c | 9 | 
6 files changed, 30 insertions, 19 deletions
| @@ -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)),         \ @@ -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 diff --git a/bootother.S b/bootother.S index 11d32f1..899669a 100644 --- a/bootother.S +++ b/bootother.S @@ -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 @@ -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)        ;    } @@ -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 @@ -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); | 
