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
|
||||
.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
|
||||
|
|
75
bootother.S
75
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
|
||||
|
|
2
defs.h
2
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);
|
||||
|
|
24
main.c
24
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()
|
||||
|
|
6
proc.c
6
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;
|
||||
}
|
||||
|
||||
|
|
14
proc.h
14
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
|
||||
|
|
|
@ -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
2
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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue