summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2010-09-13 15:34:44 -0400
committerRobert Morris <[email protected]>2010-09-13 15:34:44 -0400
commitfaad047ab22cbe989c208bff5ecb42608ecb8d7b (patch)
treeb47cd8948dcbc5c86117982245b53f4e9c95dc30
parent124fe7e457c0dc9b671c7ffccb56004eb61da4f0 (diff)
downloadxv6-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.S11
-rw-r--r--bootother.S75
-rw-r--r--defs.h2
-rw-r--r--main.c24
-rw-r--r--proc.c6
-rw-r--r--proc.h14
-rw-r--r--spinlock.c2
-rw-r--r--vm.c2
8 files changed, 70 insertions, 66 deletions
diff --git a/bootasm.S b/bootasm.S
index 56175ce..f5d1678 100644
--- a/bootasm.S
+++ b/bootasm.S
@@ -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
diff --git a/defs.h b/defs.h
index 93a8bc6..7408d4d 100644
--- a/defs.h
+++ b/defs.h
@@ -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);
diff --git a/main.c b/main.c
index 8ddf261..beac4da 100644
--- a/main.c
+++ b/main.c
@@ -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()
diff --git a/proc.c b/proc.c
index 6f7bdb6..2e8a0a4 100644
--- a/proc.c
+++ b/proc.c
@@ -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;
}
diff --git a/proc.h b/proc.h
index 4a80a28..7ffaffb 100644
--- a/proc.h
+++ b/proc.h
@@ -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
diff --git a/spinlock.c b/spinlock.c
index 68cfbe9..281748a 100644
--- a/spinlock.c
+++ b/spinlock.c
@@ -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");
diff --git a/vm.c b/vm.c
index 5c6f943..c57fa53 100644
--- a/vm.c
+++ b/vm.c
@@ -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;