Skip to content
Snippets Groups Projects
Commit 1afc9d3f authored by Robert Morris's avatar Robert Morris
Browse files

add some comments

find out the hard way why user and kernel must have separate segment descriptors
parent c9959978
No related branches found
No related tags found
No related merge requests found
......@@ -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)), \
......
......@@ -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
......
......@@ -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
......
......@@ -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
......@@ -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
......@@ -57,8 +57,9 @@ 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)
{
......@@ -66,11 +67,11 @@ mpmain(void)
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
......@@ -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;
......@@ -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)
;
}
......
......@@ -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
......
......@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment