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