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:
Robert Morris 2010-09-13 15:34:44 -04:00
parent 124fe7e457
commit faad047ab2
8 changed files with 70 additions and 66 deletions

View file

@ -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

View file

@ -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

2
defs.h
View file

@ -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);

24
main.c
View file

@ -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()

6
proc.c
View file

@ -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;
}

14
proc.h
View file

@ -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

View file

@ -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");

2
vm.c
View file

@ -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;