diff options
| author | Robert Morris <rtm@csail.mit.edu> | 2010-09-13 15:34:44 -0400 | 
|---|---|---|
| committer | Robert Morris <rtm@csail.mit.edu> | 2010-09-13 15:34:44 -0400 | 
| commit | faad047ab22cbe989c208bff5ecb42608ecb8d7b (patch) | |
| tree | b47cd8948dcbc5c86117982245b53f4e9c95dc30 | |
| parent | 124fe7e457c0dc9b671c7ffccb56004eb61da4f0 (diff) | |
| download | xv6-labs-faad047ab22cbe989c208bff5ecb42608ecb8d7b.tar.gz xv6-labs-faad047ab22cbe989c208bff5ecb42608ecb8d7b.tar.bz2 xv6-labs-faad047ab22cbe989c208bff5ecb42608ecb8d7b.zip | |
change some comments, maybe more informative
delete most comments from bootother.S (since copy of bootasm.S)
ksegment() -> seginit()
move more stuff from main() to mainc()
| -rw-r--r-- | bootasm.S | 11 | ||||
| -rw-r--r-- | bootother.S | 75 | ||||
| -rw-r--r-- | defs.h | 2 | ||||
| -rw-r--r-- | main.c | 24 | ||||
| -rw-r--r-- | proc.c | 6 | ||||
| -rw-r--r-- | proc.h | 14 | ||||
| -rw-r--r-- | spinlock.c | 2 | ||||
| -rw-r--r-- | vm.c | 2 | 
8 files changed, 70 insertions, 66 deletions
| @@ -13,7 +13,7 @@  .code16                       # Assemble for 16-bit mode  .globl start  start: -  cli                         # Disable interrupts +  cli                         # BIOS enabled interrupts ; disable    # Set up the important data segment registers (DS, ES, SS).    xorw    %ax,%ax             # Segment number zero @@ -45,7 +45,8 @@ seta20.2:    # Switch from real to protected mode, using a bootstrap GDT    # and segment translation that makes virtual addresses     # identical to physical addresses, so that the  -  # effective memory map does not change during the switch. +  # effective memory map does not change after subsequent +  # loads of segment registers.    lgdt    gdtdesc    movl    %cr0, %eax    orl     $CR0_PE, %eax @@ -57,7 +58,11 @@ seta20.2:    # default to 32 bits after this jump.    ljmp    $(SEG_KCODE<<3), $start32 -.code32                       # Assemble for 32-bit mode +# tell the assembler to generate 0x66 prefixes for 16-bit +# instructions like movw, and to generate 32-bit immediate +# addresses. +.code32 +  start32:    # Set up the protected-mode data segment registers    movw    $(SEG_KDATA<<3), %ax    # Our data segment selector diff --git a/bootother.S b/bootother.S index 899669a..186873e 100644 --- a/bootother.S +++ b/bootother.S @@ -9,80 +9,69 @@  # Because this code sets DS to zero, it must sit  # at an address in the low 2^16 bytes.  # -# Bootothers (in main.c) sends the STARTUPs, one at a time. -# It puts this code (start) at 0x7000. -# It puts the correct %esp in start-4, -# and the place to jump to in start-8. +# Bootothers (in main.c) sends the STARTUPs one at a time. +# It copies this code (start) at 0x7000. +# It puts the address of a newly allocated per-core stack in start-4, +# and the address of the place to jump to (mpmain) in start-8.  #  # This code is identical to bootasm.S except:  #   - it does not need to enable A20  #   - it uses the address at start-4 for the %esp  #   - it jumps to the address at start-8 instead of calling bootmain -#define SEG_KCODE 1  // kernel code -#define SEG_KDATA 2  // kernel data+stack +#define SEG_KCODE 1 +#define SEG_KDATA 2 -#define CR0_PE    1  // protected mode enable bit +#define CR0_PE    1 -.code16                       # Assemble for 16-bit mode +.code16             .globl start  start: -  cli                         # Disable interrupts +  cli             -  # Set up the important data segment registers (DS, ES, SS). -  xorw    %ax,%ax             # Segment number zero -  movw    %ax,%ds             # -> Data Segment -  movw    %ax,%es             # -> Extra Segment -  movw    %ax,%ss             # -> Stack Segment +  xorw    %ax,%ax +  movw    %ax,%ds +  movw    %ax,%es +  movw    %ax,%ss  //PAGEBREAK! -  # Switch from real to protected mode, using a bootstrap GDT -  # and segment translation that makes virtual addresses  -  # identical to physical addresses, so that the  -  # effective memory map does not change during the switch.    lgdt    gdtdesc    movl    %cr0, %eax    orl     $CR0_PE, %eax    movl    %eax, %cr0 -  # 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 +.code32  start32: -  # Set up the protected-mode data segment registers -  movw    $(SEG_KDATA<<3), %ax    # Our data segment selector -  movw    %ax, %ds                # -> DS: Data Segment -  movw    %ax, %es                # -> ES: Extra Segment -  movw    %ax, %ss                # -> SS: Stack Segment -  movw    $0, %ax                 # Zero segments not ready for use -  movw    %ax, %fs                # -> FS -  movw    %ax, %gs                # -> GS +  movw    $(SEG_KDATA<<3), %ax +  movw    %ax, %ds +  movw    %ax, %es +  movw    %ax, %ss +  movw    $0, %ax +  movw    %ax, %fs +  movw    %ax, %gs -  # Set up the stack pointer and call into C. +  # switch to the stack allocated by bootothers()    movl    start-4, %esp + +  # call mpmain()    call	*(start-8) -  # If the call returns (it shouldn't), trigger a Bochs -  # breakpoint if running under Bochs, then loop. -  movw    $0x8a00, %ax            # 0x8a00 -> port 0x8a00 +  movw    $0x8a00, %ax    movw    %ax, %dx    outw    %ax, %dx -  movw    $0x8ae0, %ax            # 0x8ae0 -> port 0x8a00 +  movw    $0x8ae0, %ax    outw    %ax, %dx  spin:    jmp     spin -# Bootstrap GDT -.p2align 2                                # force 4 byte alignment +.p2align 2  gdt: -  SEG_NULLASM                             # null seg -  SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)   # code seg -  SEG_ASM(STA_W, 0x0, 0xffffffff)         # data seg +  SEG_NULLASM +  SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) +  SEG_ASM(STA_W, 0x0, 0xffffffff)  gdtdesc: -  .word   (gdtdesc - gdt - 1)                            # sizeof(gdt) - 1 -  .long   gdt                             # address gdt +  .word   (gdtdesc - gdt - 1) +  .long   gdt @@ -152,7 +152,7 @@ void            uartintr(void);  void            uartputc(int);  // vm.c -void            ksegment(void); +void            seginit(void);  void            kvmalloc(void);  void            vmenable(void);  pde_t*          setupkvm(void); @@ -11,16 +11,14 @@ void jkstack(void)  __attribute__((noreturn));  void mainc(void);  // Bootstrap processor starts running C code here. +// Allocate a real stack and switch to it, first +// doing some setup required for memory allocator to work.  int  main(void)  {    mpinit();        // collect info about this machine    lapicinit(mpbcpu()); -  ksegment();      // set up segments -  picinit();       // interrupt controller -  ioapicinit();    // another interrupt controller -  consoleinit();   // I/O devices & their interrupts -  uartinit();      // serial port +  seginit();       // set up segments    kinit();         // initialize memory allocator    jkstack();       // call mainc() on a properly-allocated stack   } @@ -37,10 +35,16 @@ jkstack(void)    panic("jkstack");  } +// Set up hardware and software. +// Runs only on the boostrap processor.  void  mainc(void)  {    cprintf("\ncpu%d: starting xv6\n\n", cpu->id); +  picinit();       // interrupt controller +  ioapicinit();    // another interrupt controller +  consoleinit();   // I/O devices & their interrupts +  uartinit();      // serial port    kvmalloc();      // initialize the kernel page table    pinit();         // process table    tvinit();        // trap vectors @@ -64,16 +68,17 @@ static void  mpmain(void)  {    if(cpunum() != mpbcpu()) { -    ksegment(); +    seginit();      lapicinit(cpunum());    }    vmenable();        // turn on paging    cprintf("cpu%d: starting\n", cpu->id);    idtinit();       // load idt register -  xchg(&cpu->booted, 1); +  xchg(&cpu->booted, 1); // tell bootothers() we're up    scheduler();     // start running processes  } +// Start the non-boot processors.  static void  bootothers(void)  { @@ -91,10 +96,13 @@ bootothers(void)      if(c == cpus+cpunum())  // We've started already.        continue; -    // Fill in %esp, %eip and start code on cpu. +    // Tell bootother.S what stack to use and the address of mpmain; +    // it expects to find these two addresses stored just before +    // its first instruction.      stack = kalloc();      *(void**)(code-4) = stack + KSTACKSIZE;      *(void**)(code-8) = mpmain; +      lapicstartap(c->id, (uint)code);      // Wait for cpu to finish mpmain() @@ -65,7 +65,8 @@ procdump(void)  //PAGEBREAK: 32  // Look in the process table for an UNUSED proc. -// If found, change state to EMBRYO and return it. +// If found, change state to EMBRYO and initialize +// state required to run in the kernel.  // Otherwise return 0.  static struct proc*  allocproc(void) @@ -97,7 +98,7 @@ found:    p->tf = (struct trapframe*)sp;    // Set up new context to start executing at forkret, -  // which returns to trapret (see below). +  // which returns to trapret.    sp -= 4;    *(uint*)sp = (uint)trapret; @@ -105,6 +106,7 @@ found:    p->context = (struct context*)sp;    memset(p->context, 0, sizeof *p->context);    p->context->eip = (uint)forkret; +    return p;  } @@ -11,7 +11,7 @@  // Per-CPU state  struct cpu {    uchar id;                    // Local APIC ID; index into cpus[] below -  struct context *scheduler;   // Switch here to enter scheduler +  struct context *scheduler;   // swtch() here to enter scheduler    struct taskstate ts;         // Used by x86 to find stack for interrupt    struct segdesc gdt[NSEGS];   // x86 global descriptor table    volatile uint booted;        // Has the CPU started? @@ -20,7 +20,7 @@ struct cpu {    // Cpu-local storage variables; see below    struct cpu *cpu; -  struct proc *proc; +  struct proc *proc;           // The currently-running process.  };  extern struct cpu cpus[NCPU]; @@ -29,13 +29,13 @@ extern int ncpu;  // Per-CPU variables, holding pointers to the  // current cpu and to the current process.  // The asm suffix tells gcc to use "%gs:0" to refer to cpu -// and "%gs:4" to refer to proc.  ksegment sets up the +// and "%gs:4" to refer to proc.  seginit sets up the  // %gs segment register so that %gs refers to the memory  // holding those two variables in the local cpu's struct cpu.  // This is similar to how thread-local variables are implemented  // in thread libraries such as Linux pthreads. -extern struct cpu *cpu asm("%gs:0");       // This cpu. -extern struct proc *proc asm("%gs:4");     // Current proc on this cpu. +extern struct cpu *cpu asm("%gs:0");       // &cpus[cpunum()] +extern struct proc *proc asm("%gs:4");     // cpus[cpunum()].proc  //PAGEBREAK: 17  // Saved registers for kernel context switches. @@ -61,13 +61,13 @@ enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };  // Per-process state  struct proc {    uint sz;                     // Size of process memory (bytes) -  pde_t* pgdir;                // Linear address of proc's pgdir +  pde_t* pgdir;                // Page table    char *kstack;                // Bottom of kernel stack for this process    enum procstate state;        // Process state    volatile int pid;            // Process ID    struct proc *parent;         // Parent process    struct trapframe *tf;        // Trap frame for current syscall -  struct context *context;     // Switch here to run process +  struct context *context;     // swtch() here to run process    void *chan;                  // If non-zero, sleeping on chan    int killed;                  // If non-zero, have been killed    struct file *ofile[NOFILE];  // Open files @@ -23,7 +23,7 @@ initlock(struct spinlock *lk, char *name)  void  acquire(struct spinlock *lk)  { -  pushcli(); +  pushcli(); // disable interrupts to avoid deadlock.    if(holding(lk))      panic("acquire"); @@ -13,7 +13,7 @@ static pde_t *kpgdir;  // for use in scheduler()  // Set up CPU's kernel segment descriptors.  // Run once at boot time on each CPU.  void -ksegment(void) +seginit(void)  {    struct cpu *c; | 
