Skip to content

Commit

Permalink
add some comments
Browse files Browse the repository at this point in the history
find out the hard way why user and kernel must have separate segment descriptors
  • Loading branch information
Robert Morris committed Aug 6, 2010
1 parent c995997 commit 1afc9d3
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 19 deletions.
2 changes: 2 additions & 0 deletions asm.h
Expand Up @@ -6,6 +6,8 @@
.word 0, 0; \
.byte 0, 0, 0, 0

// The 0xC0 means the limit is in 4096-byte units
// and (for executable segments) 32-bit mode.
#define SEG_ASM(type,base,lim) \
.word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \
.byte (((base) >> 16) & 0xff), (0x90 | (type)), \
Expand Down
6 changes: 4 additions & 2 deletions bootasm.S
Expand Up @@ -51,8 +51,10 @@ seta20.2:
orl $CR0_PE, %eax
movl %eax, %cr0

# Jump to next instruction, but in 32-bit code segment.
# Switches processor into 32-bit mode.
# 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
Expand Down
6 changes: 4 additions & 2 deletions bootother.S
Expand Up @@ -45,8 +45,10 @@ start:
orl $CR0_PE, %eax
movl %eax, %cr0

# Jump to next instruction, but in 32-bit code segment.
# Switches processor into 32-bit mode.
# 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
Expand Down
22 changes: 12 additions & 10 deletions main.c
Expand Up @@ -16,13 +16,13 @@ main(void)
{
mpinit(); // collect info about this machine
lapicinit(mpbcpu());
ksegment();
ksegment(); // set up segments
picinit(); // interrupt controller
ioapicinit(); // another interrupt controller
consoleinit(); // I/O devices & their interrupts
uartinit(); // serial port
pminit(); // physical memory for kernel
jkstack(); // Jump to mainc on a properly-allocated stack
pminit(); // discover how much memory there is
jkstack(); // call mainc() on a properly-allocated stack
}

void
Expand All @@ -41,7 +41,7 @@ void
mainc(void)
{
cprintf("\ncpu%d: starting xv6\n\n", cpu->id);
kvmalloc(); // allocate the kernel page table
kvmalloc(); // initialze the kernel page table
pinit(); // process table
tvinit(); // trap vectors
binit(); // buffer cache
Expand All @@ -57,20 +57,21 @@ mainc(void)
mpmain();
}

// Bootstrap processor gets here after setting up the hardware.
// Additional processors start here.
// Common CPU setup code.
// Bootstrap CPU comes here from mainc().
// Other CPUs jump here from bootother.S.
static void
mpmain(void)
{
if(cpunum() != mpbcpu()) {
ksegment();
lapicinit(cpunum());
}
vminit(); // Run with paging on each processor
vminit(); // turn on paging
cprintf("cpu%d: starting\n", cpu->id);
idtinit();
idtinit(); // load idt register
xchg(&cpu->booted, 1);
scheduler();
scheduler(); // start running processes
}

static void
Expand All @@ -85,6 +86,7 @@ bootothers(void)
// placed the start of bootother.S there.
code = (uchar *) 0x7000;
memmove(code, _binary_bootother_start, (uint)_binary_bootother_size);

for(c = cpus; c < cpus+ncpu; c++){
if(c == cpus+cpunum()) // We've started already.
continue;
Expand All @@ -95,7 +97,7 @@ bootothers(void)
*(void**)(code-8) = mpmain;
lapicstartap(c->id, (uint)code);

// Wait for cpu to get through bootstrap.
// Wait for cpu to finish mpmain()
while(c->booted == 0)
;
}
Expand Down
4 changes: 2 additions & 2 deletions proc.h
Expand Up @@ -3,8 +3,8 @@
#define SEG_KCODE 1 // kernel code
#define SEG_KDATA 2 // kernel data+stack
#define SEG_KCPU 3 // kernel per-cpu data
#define SEG_UCODE 4
#define SEG_UDATA 5
#define SEG_UCODE 4 // user code
#define SEG_UDATA 5 // user data+stack
#define SEG_TSS 6 // this process's task state
#define NSEGS 7

Expand Down
9 changes: 6 additions & 3 deletions vm.c
Expand Up @@ -93,12 +93,15 @@ ksegment(void)
{
struct cpu *c;

// Map once virtual addresses to linear addresses using identity map
// Map virtual addresses to linear addresses using identity map.
// Cannot share a CODE descriptor for both kernel and user
// because it would have to have DPL_USR, but the CPU forbids
// an interrupt from CPL=0 to DPL=3.
c = &cpus[cpunum()];
c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0);
c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0x0, 0xffffffff, DPL_USER);
c->gdt[SEG_UDATA] = SEG(STA_W, 0x0, 0xffffffff, DPL_USER);
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER);
c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);

// map cpu, and curproc
c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 8, 0);
Expand Down

0 comments on commit 1afc9d3

Please sign in to comment.