提交 87877e44 创建 作者: Nickolai Zeldovich's avatar Nickolai Zeldovich

Merge branch 'scale' of git+ssh://pdos.csail.mit.edu/home/am0/6.828/xv6 into scale

...@@ -114,7 +114,7 @@ bootother: bootother.S ...@@ -114,7 +114,7 @@ bootother: bootother.S
$(CC) $(CFLAGS) -nostdinc -I. -c bootother.S $(CC) $(CFLAGS) -nostdinc -I. -c bootother.S
$(LD) $(LDFLAGS) -N -e start -Ttext 0x7000 -o bootother.out bootother.o $(LD) $(LDFLAGS) -N -e start -Ttext 0x7000 -o bootother.out bootother.o
$(OBJCOPY) -S -O binary bootother.out bootother $(OBJCOPY) -S -O binary bootother.out bootother
$(OBJDUMP) -S bootother.o > bootother.asm $(OBJDUMP) -S bootother.out > bootother.asm
initcode: initcode.S initcode: initcode.S
$(CC) $(CFLAGS) -nostdinc -I. -c initcode.S $(CC) $(CFLAGS) -nostdinc -I. -c initcode.S
...@@ -123,7 +123,7 @@ initcode: initcode.S ...@@ -123,7 +123,7 @@ initcode: initcode.S
$(OBJDUMP) -S initcode.o > initcode.asm $(OBJDUMP) -S initcode.o > initcode.asm
kernel: $(OBJS) multiboot.o data.o bootother initcode kernel: $(OBJS) multiboot.o data.o bootother initcode
$(LD) $(LDFLAGS) -Ttext 0x100000 -e main -o kernel multiboot.o data.o $(OBJS) -b binary initcode bootother $(LD) $(LDFLAGS) -T kernel.ld -e multiboot_entry -o kernel multiboot.o data.o $(OBJS) -b binary initcode bootother
$(OBJDUMP) -S kernel > kernel.asm $(OBJDUMP) -S kernel > kernel.asm
$(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym $(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "types.h" #include "types.h"
#include "elf.h" #include "elf.h"
#include "x86.h" #include "x86.h"
#include "memlayout.h"
#define SECTSIZE 512 #define SECTSIZE 512
...@@ -19,7 +20,7 @@ bootmain(void) ...@@ -19,7 +20,7 @@ bootmain(void)
struct elfhdr *elf; struct elfhdr *elf;
struct proghdr *ph, *eph; struct proghdr *ph, *eph;
void (*entry)(void); void (*entry)(void);
uchar* va; uchar *pa;
elf = (struct elfhdr*)0x10000; // scratch space elf = (struct elfhdr*)0x10000; // scratch space
...@@ -34,15 +35,15 @@ bootmain(void) ...@@ -34,15 +35,15 @@ bootmain(void)
ph = (struct proghdr*)((uchar*)elf + elf->phoff); ph = (struct proghdr*)((uchar*)elf + elf->phoff);
eph = ph + elf->phnum; eph = ph + elf->phnum;
for(; ph < eph; ph++){ for(; ph < eph; ph++){
va = (uchar*)ph->va; pa = (uchar*)ph->pa;
readseg(va, ph->filesz, ph->offset); readseg(pa, ph->filesz, ph->offset);
if(ph->memsz > ph->filesz) if(ph->memsz > ph->filesz)
stosb(va + ph->filesz, 0, ph->memsz - ph->filesz); stosb(pa + ph->filesz, 0, ph->memsz - ph->filesz);
} }
// Call the entry point from the ELF header. // Call the entry point from the ELF header.
// Does not return! // Does not return!
entry = (void(*)(void))(elf->entry); entry = (void(*)(void))(elf->entry & 0xFFFFFF); // XXX get ridd off 0xFFFFF
entry(); entry();
} }
......
#include "asm.h" #include "asm.h"
#include "memlayout.h"
# Each non-boot CPU ("AP") is started up in response to a STARTUP # Each non-boot CPU ("AP") is started up in response to a STARTUP
# IPI from the boot CPU. Section B.4.2 of the Multi-Processor # IPI from the boot CPU. Section B.4.2 of the Multi-Processor
...@@ -24,10 +25,16 @@ ...@@ -24,10 +25,16 @@
#define CR0_PE 1 #define CR0_PE 1
#define RELOC1(x) ((x) + KERNBASE) // same as V2P, but without casts
.code16 .code16
.globl start .globl start
start: start:
cli cli
## movw $0xb800, %ax
## movw %ax, %es
## movw $65, %es:(0x0)
xorw %ax,%ax xorw %ax,%ax
movw %ax,%ds movw %ax,%ds
...@@ -38,13 +45,14 @@ start: ...@@ -38,13 +45,14 @@ start:
movl %cr0, %eax movl %cr0, %eax
orl $CR0_PE, %eax orl $CR0_PE, %eax
movl %eax, %cr0 movl %eax, %cr0
ljmpl $(SEG_KCODE<< 3), $(start32+KERNBASE)
//PAGEBREAK!
ljmp $(SEG_KCODE<<3), $start32
.code32 .code32
start32: start32:
# movw $65, 0xb8002
movw $(SEG_KDATA<<3), %ax movw $(SEG_KDATA<<3), %ax
movw %ax, %ds movw %ax, %ds
movw %ax, %es movw %ax, %es
movw %ax, %ss movw %ax, %ss
...@@ -53,10 +61,10 @@ start32: ...@@ -53,10 +61,10 @@ start32:
movw %ax, %gs movw %ax, %gs
# switch to the stack allocated by bootothers() # switch to the stack allocated by bootothers()
movl start-4, %esp movl RELOC1(start-4), %esp
# call mpmain() # call mpmain()
call *(start-8) call *(RELOC1(start)-8)
movw $0x8a00, %ax movw $0x8a00, %ax
movw %ax, %dx movw %ax, %dx
...@@ -69,8 +77,8 @@ spin: ...@@ -69,8 +77,8 @@ spin:
.p2align 2 .p2align 2
gdt: gdt:
SEG_NULLASM SEG_NULLASM
SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) SEG_ASM(STA_X|STA_R, -KERNBASE, 0xffffffff)
SEG_ASM(STA_W, 0x0, 0xffffffff) SEG_ASM(STA_W, -KERNBASE, 0xffffffff)
gdtdesc: gdtdesc:
.word (gdtdesc - gdt - 1) .word (gdtdesc - gdt - 1)
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "condvar.h" #include "condvar.h"
#include "fs.h" #include "fs.h"
#include "file.h" #include "file.h"
#include "memlayout.h"
#include "mmu.h" #include "mmu.h"
#include "queue.h" #include "queue.h"
#include "proc.h" #include "proc.h"
...@@ -177,7 +178,7 @@ panic(char *s) ...@@ -177,7 +178,7 @@ panic(char *s)
//PAGEBREAK: 50 //PAGEBREAK: 50
#define BACKSPACE 0x100 #define BACKSPACE 0x100
#define CRTPORT 0x3d4 #define CRTPORT 0x3d4
static ushort *crt = (ushort*)0xb8000; // CGA memory static ushort *crt = (ushort*)P2V(0xb8000); // CGA memory
static void static void
cgaputc(int c) cgaputc(int c)
......
...@@ -73,6 +73,7 @@ extern uchar ioapicid; ...@@ -73,6 +73,7 @@ extern uchar ioapicid;
void ioapicinit(void); void ioapicinit(void);
// kalloc.c // kalloc.c
char* pgalloc(void);
void kinit(void); void kinit(void);
char* kalloc(void); char* kalloc(void);
void kfree(char*); void kfree(char*);
...@@ -187,6 +188,8 @@ void uartintr(void); ...@@ -187,6 +188,8 @@ void uartintr(void);
void uartputc(int); void uartputc(int);
// vm.c // vm.c
void printpgdir(pde_t*);
void pginit(char* (*alloc)());
void seginit(void); void seginit(void);
void kvmalloc(void); void kvmalloc(void);
void vmenable(void); void vmenable(void);
......
#include "types.h" #include "types.h"
#include "param.h" #include "param.h"
#include "memlayout.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h" #include "spinlock.h"
#include "condvar.h" #include "condvar.h"
......
...@@ -605,7 +605,7 @@ namex(char *path, int nameiparent, char *name) ...@@ -605,7 +605,7 @@ namex(char *path, int nameiparent, char *name)
{ {
struct inode *ip, *next; struct inode *ip, *next;
if(*path == '/') if(*path == '/')
ip = iget(ROOTDEV, ROOTINO); ip = iget(ROOTDEV, ROOTINO);
else else
ip = idup(proc->cwd); ip = idup(proc->cwd);
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "types.h" #include "types.h"
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "memlayout.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h" #include "spinlock.h"
#include "condvar.h" #include "condvar.h"
...@@ -94,7 +95,7 @@ void ...@@ -94,7 +95,7 @@ void
ideintr(void) ideintr(void)
{ {
struct buf *b; struct buf *b;
// Take first buffer off queue. // Take first buffer off queue.
acquire(&idelock); acquire(&idelock);
if((b = idequeue) == 0){ if((b = idequeue) == 0){
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "types.h" #include "types.h"
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "memlayout.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h" #include "spinlock.h"
#include "condvar.h" #include "condvar.h"
...@@ -17,10 +18,25 @@ void kminit(void); ...@@ -17,10 +18,25 @@ void kminit(void);
struct kmem kmems[NCPU]; struct kmem kmems[NCPU];
extern char end[]; // first address after kernel loaded from ELF file extern char end[]; // first address after kernel loaded from ELF file
char *newend;
enum { kalloc_memset = 0 }; enum { kalloc_memset = 0 };
static int kinited __attribute__ ((aligned (CACHELINE))); static int kinited __attribute__ ((aligned (CACHELINE)));
// simple page allocator to get off the ground during boot
char *
pgalloc(void)
{
if (newend == 0)
newend = end;
void *p = (void*)PGROUNDUP((uint)newend);
memset(p, 0, PGSIZE);
newend = newend + PGSIZE;
return p;
}
static void __attribute__((unused)) static void __attribute__((unused))
kmemprint(void) kmemprint(void)
{ {
...@@ -43,8 +59,9 @@ kfree_pool(struct kmem *m, char *v) ...@@ -43,8 +59,9 @@ kfree_pool(struct kmem *m, char *v)
{ {
struct run *r; struct run *r;
if((uint)v % PGSIZE || v < end || (uint)v >= PHYSTOP) if((uint)v % PGSIZE || v < end || v2p(v) >= PHYSTOP) {
panic("kfree"); panic("kfree_pool");
}
// Fill with junk to catch dangling refs. // Fill with junk to catch dangling refs.
if (kinited && kalloc_memset) if (kinited && kalloc_memset)
...@@ -84,9 +101,10 @@ kinit(void) ...@@ -84,9 +101,10 @@ kinit(void)
initlock(&kmems[c].lock, kmems[c].name); initlock(&kmems[c].lock, kmems[c].name);
} }
p = (char*)PGROUNDUP((uint)end); p = (char*)PGROUNDUP((uint)newend);
for(; p + PGSIZE <= (char*)PHYSTOP; p += PGSIZE) for(; p + PGSIZE <= (char*)p2v(PHYSTOP); p += PGSIZE) {
kfree_pool(&kmems[((uintptr_t)p) / (PHYSTOP/NCPU)], p); kfree_pool(&kmems[((uintptr_t) v2p(p)) / (PHYSTOP/NCPU)], p);
}
kminit(); kminit();
kinited = 1; kinited = 1;
} }
......
#include "types.h" #include "types.h"
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "memlayout.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h" #include "spinlock.h"
#include "condvar.h" #include "condvar.h"
...@@ -12,6 +13,7 @@ static void bootothers(void); ...@@ -12,6 +13,7 @@ static void bootothers(void);
static void mpmain(void); static void mpmain(void);
void jmpkstack(void) __attribute__((noreturn)); void jmpkstack(void) __attribute__((noreturn));
void mainc(void); void mainc(void);
static volatile int newpgdir;
// Bootstrap processor starts running C code here. // Bootstrap processor starts running C code here.
// Allocate a real stack and switch to it, first // Allocate a real stack and switch to it, first
...@@ -19,6 +21,7 @@ void mainc(void); ...@@ -19,6 +21,7 @@ void mainc(void);
int int
main(void) main(void)
{ {
pginit(pgalloc);
mpinit(); // collect info about this machine mpinit(); // collect info about this machine
lapicinit(mpbcpu()); lapicinit(mpbcpu());
seginit(); // set up segments seginit(); // set up segments
...@@ -49,7 +52,6 @@ mainc(void) ...@@ -49,7 +52,6 @@ mainc(void)
ioapicinit(); // another interrupt controller ioapicinit(); // another interrupt controller
consoleinit(); // I/O devices & their interrupts consoleinit(); // I/O devices & their interrupts
uartinit(); // serial port uartinit(); // serial port
kvmalloc(); // initialize the kernel page table
rcuinit(); // initialize rcu module rcuinit(); // initialize rcu module
nsinit(); // initialize name space module nsinit(); // initialize name space module
pinit(); // process table pinit(); // process table
...@@ -62,6 +64,8 @@ mainc(void) ...@@ -62,6 +64,8 @@ mainc(void)
timerinit(); // uniprocessor timer timerinit(); // uniprocessor timer
userinit(); // first user process userinit(); // first user process
bootothers(); // start other processors bootothers(); // start other processors
kvmalloc(); // new kernel page table wo. bottom mapped
newpgdir = 1;
// Finish setting up this processor in mpmain. // Finish setting up this processor in mpmain.
mpmain(); mpmain();
} }
...@@ -70,16 +74,22 @@ mainc(void) ...@@ -70,16 +74,22 @@ mainc(void)
// Bootstrap CPU comes here from mainc(). // Bootstrap CPU comes here from mainc().
// Other CPUs jump here from bootother.S. // Other CPUs jump here from bootother.S.
static void static void
mpmain(void) mpboot(void)
{ {
if(cpunum() != mpbcpu()){
seginit();
lapicinit(cpunum());
}
vmenable(); // turn on paging vmenable(); // turn on paging
seginit();
lapicinit(cpunum());
mpmain();
}
static void
mpmain(void)
{
cprintf("cpu%d: starting\n", cpu->id); cprintf("cpu%d: starting\n", cpu->id);
idtinit(); // load idt register idtinit(); // load idt register
xchg(&cpu->booted, 1); // tell bootothers() we're up xchg(&cpu->booted, 1); // tell bootothers() we're up
while (!newpgdir) ; // wait until we have new page dir
switchkvm(); // switch to new page dir
scheduler(); // start running processes scheduler(); // start running processes
} }
...@@ -95,7 +105,7 @@ bootothers(void) ...@@ -95,7 +105,7 @@ bootothers(void)
// Write bootstrap code to unused memory at 0x7000. // Write bootstrap code to unused memory at 0x7000.
// The linker has placed the image of bootother.S in // The linker has placed the image of bootother.S in
// _binary_bootother_start. // _binary_bootother_start.
code = (uchar*)0x7000; code = p2v(0x7000);
memmove(code, _binary_bootother_start, (uint)_binary_bootother_size); memmove(code, _binary_bootother_start, (uint)_binary_bootother_size);
for(c = cpus; c < cpus+ncpu; c++){ for(c = cpus; c < cpus+ncpu; c++){
...@@ -107,9 +117,9 @@ bootothers(void) ...@@ -107,9 +117,9 @@ bootothers(void)
// its first instruction. // its first instruction.
stack = kalloc(); stack = kalloc();
*(void**)(code-4) = stack + KSTACKSIZE; *(void**)(code-4) = stack + KSTACKSIZE;
*(void**)(code-8) = mpmain; *(void**)(code-8) = mpboot;
lapicstartap(c->id, (uint)code); lapicstartap(c->id, v2p(code));
// Wait for cpu to finish mpmain() // Wait for cpu to finish mpmain()
while(c->booted == 0) while(c->booted == 0)
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#define CR0_CD 0x40000000 // Cache Disable #define CR0_CD 0x40000000 // Cache Disable
#define CR0_PG 0x80000000 // Paging #define CR0_PG 0x80000000 // Paging
//PAGEBREAK! //PAGEBREAK!
// Segment Descriptor // Segment Descriptor
struct segdesc { struct segdesc {
...@@ -111,18 +112,10 @@ struct segdesc { ...@@ -111,18 +112,10 @@ struct segdesc {
// construct linear address from indexes and offset // construct linear address from indexes and offset
#define PGADDR(d, t, o) ((uint)((d) << PDXSHIFT | (t) << PTXSHIFT | (o))) #define PGADDR(d, t, o) ((uint)((d) << PDXSHIFT | (t) << PTXSHIFT | (o)))
// turn a kernel linear address into a physical address.
// all of the kernel data structures have linear and
// physical addresses that are equal.
#define PADDR(a) ((uint)(a))
// Page directory and page table constants. // Page directory and page table constants.
#define NPDENTRIES 1024 // page directory entries per page directory #define NPDENTRIES 1024 // page directory entries per page directory
#define NPTENTRIES 1024 // page table entries per page table #define NPTENTRIES 1024 // page table entries per page table
#define PGSIZE 4096 // bytes mapped by a page
#define PGSHIFT 12 // log2(PGSIZE)
#define PTXSHIFT 12 // offset of PTX in a linear address #define PTXSHIFT 12 // offset of PTX in a linear address
#define PDXSHIFT 22 // offset of PDX in a linear address #define PDXSHIFT 22 // offset of PDX in a linear address
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "types.h" #include "types.h"
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "memlayout.h"
#include "mp.h" #include "mp.h"
#include "x86.h" #include "x86.h"
#include "mmu.h" #include "mmu.h"
...@@ -42,6 +43,7 @@ mpsearch1(uchar *addr, int len) ...@@ -42,6 +43,7 @@ mpsearch1(uchar *addr, int len)
{ {
uchar *e, *p; uchar *e, *p;
addr = p2v((uint) addr);
e = addr+len; e = addr+len;
for(p = addr; p < e; p += sizeof(struct mp)) for(p = addr; p < e; p += sizeof(struct mp))
if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0) if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0)
...@@ -86,7 +88,7 @@ mpconfig(struct mp **pmp) ...@@ -86,7 +88,7 @@ mpconfig(struct mp **pmp)
if((mp = mpsearch()) == 0 || mp->physaddr == 0) if((mp = mpsearch()) == 0 || mp->physaddr == 0)
return 0; return 0;
conf = (struct mpconf*)mp->physaddr; conf = (struct mpconf*) p2v((uint) mp->physaddr);
if(memcmp(conf, "PCMP", 4) != 0) if(memcmp(conf, "PCMP", 4) != 0)
return 0; return 0;
if(conf->version != 1 && conf->version != 4) if(conf->version != 1 && conf->version != 4)
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
# } # }
#include "asm.h" #include "asm.h"
#include "memlayout.h"
#define RELOC(x) ((x) - KERNBASE) // same as V2P, but without casts
#define STACK 4096 #define STACK 4096
...@@ -42,7 +45,7 @@ multiboot_header: ...@@ -42,7 +45,7 @@ multiboot_header:
# boot loader - bootasm.S - sets up. # boot loader - bootasm.S - sets up.
.globl multiboot_entry .globl multiboot_entry
multiboot_entry: multiboot_entry:
lgdt gdtdesc lgdt RELOC(gdtdesc)
ljmp $(SEG_KCODE<<3), $mbstart32 ljmp $(SEG_KCODE<<3), $mbstart32
mbstart32: mbstart32:
...@@ -65,11 +68,11 @@ spin: ...@@ -65,11 +68,11 @@ spin:
.p2align 2 # force 4 byte alignment .p2align 2 # force 4 byte alignment
gdt: gdt:
SEG_NULLASM # null seg SEG_NULLASM # null seg
SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg SEG_ASM(STA_X|STA_R, -KERNBASE, 0xffffffff) # code seg
SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg SEG_ASM(STA_W, -KERNBASE, 0xffffffff) # data seg
gdtdesc: gdtdesc:
.word (gdtdesc - gdt - 1) # sizeof(gdt) - 1 .word (gdtdesc - gdt - 1) # sizeof(gdt) - 1
.long gdt # address gdt .long RELOC(gdt) # address gdt
.comm stack, STACK .comm stack, STACK
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
#define NINODE 50 // maximum number of active i-nodes #define NINODE 50 // maximum number of active i-nodes
#define NDEV 10 // maximum major device number #define NDEV 10 // maximum major device number
#define ROOTDEV 1 // device number of file system root disk #define ROOTDEV 1 // device number of file system root disk
#define USERTOP 0xA0000 // end of user address space
#define PHYSTOP 0x10000000 // use phys mem up to here as free pool
#define MAXARG 32 // max exec arguments #define MAXARG 32 // max exec arguments
#define MAXNAME 16 // max string names #define MAXNAME 16 // max string names
#define MINCYCTHRESH 1000000 // min cycles a proc executes on a core before allowed to be stolen #define MINCYCTHRESH 1000000 // min cycles a proc executes on a core before allowed to be stolen
......
#include "types.h" #include "types.h"
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "memlayout.h"
#include "mmu.h" #include "mmu.h"
#include "x86.h" #include "x86.h"
#include "spinlock.h" #include "spinlock.h"
...@@ -506,6 +507,7 @@ scheduler(void) ...@@ -506,6 +507,7 @@ scheduler(void)
// cprintf("%d: no longer idle, running %d\n", cpu->id, p->pid); // cprintf("%d: no longer idle, running %d\n", cpu->id, p->pid);
idle[cpu->id] = 0; idle[cpu->id] = 0;
} }
release(&runq->lock); release(&runq->lock);
// Switch to chosen process. It is the process's job // Switch to chosen process. It is the process's job
...@@ -560,6 +562,7 @@ sched(void) ...@@ -560,6 +562,7 @@ sched(void)
proc->curcycles += rdtsc() - proc->tsc; proc->curcycles += rdtsc() - proc->tsc;
mtrace_fcall_register(proc->pid, 0, 0, mtrace_pause); mtrace_fcall_register(proc->pid, 0, 0, mtrace_pause);
mtrace_call_set(0, cpunum()); mtrace_call_set(0, cpunum());
swtch(&proc->context, cpu->scheduler); swtch(&proc->context, cpu->scheduler);
cpu->intena = intena; cpu->intena = intena;
} }
...@@ -587,7 +590,7 @@ forkret(void) ...@@ -587,7 +590,7 @@ forkret(void)
// in which to call cv_sleep(). // in which to call cv_sleep().
if(proc->cwd == 0) if(proc->cwd == 0)
proc->cwd = namei("/"); proc->cwd = namei("/");
// Return to "caller", actually trapret (see allocproc). // Return to "caller", actually trapret (see allocproc).
} }
......
...@@ -143,7 +143,7 @@ extern struct ns *nspid; ...@@ -143,7 +143,7 @@ extern struct ns *nspid;
// holding those two variables in the local cpu's struct cpu. // holding those two variables in the local cpu's struct cpu.
// This is similar to how thread-local variables are implemented // This is similar to how thread-local variables are implemented
// in thread libraries such as Linux pthreads. // in thread libraries such as Linux pthreads.
extern struct cpu *cpu __asm("%gs:0"); // &cpus[cpunum()] extern struct cpu *cpu __asm("%gs:0"); // &cpus[cpunum()].cpu
extern struct proc *proc __asm("%gs:4"); // cpus[cpunum()].proc extern struct proc *proc __asm("%gs:4"); // cpus[cpunum()].proc
extern struct kmem *kmem __asm("%gs:8"); // &kmems[cpunum()] extern struct kmem *kmem __asm("%gs:8"); // &cpu[cpunum()].kmem
extern struct runq *runq __asm("%gs:12"); // &runqs[cpunum()] extern struct runq *runq __asm("%gs:12"); // &cpu[cpunum()].runq
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "x86.h" #include "x86.h"
#include "memlayout.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h" #include "spinlock.h"
#include "condvar.h" #include "condvar.h"
...@@ -94,7 +95,7 @@ getcallerpcs(void *v, uint pcs[]) ...@@ -94,7 +95,7 @@ getcallerpcs(void *v, uint pcs[])
ebp = (uint*)v - 2; ebp = (uint*)v - 2;
for(i = 0; i < 10; i++){ for(i = 0; i < 10; i++){
if(ebp == 0 || ebp < (uint*)0x100000 || ebp == (uint*)0xffffffff) if(ebp == 0 || ebp < (uint*)KERNBASE || ebp == (uint*)0xffffffff)
break; break;
pcs[i] = ebp[1]; // saved %eip pcs[i] = ebp[1]; // saved %eip
ebp = (uint*)ebp[0]; // saved %ebp ebp = (uint*)ebp[0]; // saved %ebp
......
#include "types.h" #include "types.h"
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "memlayout.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h" #include "spinlock.h"
#include "condvar.h" #include "condvar.h"
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "x86.h" #include "x86.h"
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "memlayout.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h" #include "spinlock.h"
#include "condvar.h" #include "condvar.h"
...@@ -135,7 +136,7 @@ sys_unmap(void) ...@@ -135,7 +136,7 @@ sys_unmap(void)
(void*) (PGROUNDDOWN(addr)), (void*) (PGROUNDDOWN(addr)),
(void*) (PGROUNDDOWN(addr)+PGROUNDUP(len))); (void*) (PGROUNDDOWN(addr)+PGROUNDUP(len)));
cli(); cli();
lcr3(PADDR(proc->vmap->pgdir)); lcr3(v2p(proc->vmap->pgdir));
for (uint i = 0; i < ncpu; i++) for (uint i = 0; i < ncpu; i++)
if (i != cpu->id) if (i != cpu->id)
lapic_tlbflush(i); lapic_tlbflush(i);
......
#include "types.h" #include "types.h"
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "memlayout.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h" #include "spinlock.h"
#include "condvar.h" #include "condvar.h"
...@@ -32,7 +33,7 @@ tvinit(void) ...@@ -32,7 +33,7 @@ tvinit(void)
void void
idtinit(void) idtinit(void)
{ {
lidt(idt, sizeof(idt)); lidt(idt, sizeof(idt));
} }
//PAGEBREAK: 41 //PAGEBREAK: 41
...@@ -48,7 +49,6 @@ trap(struct trapframe *tf) ...@@ -48,7 +49,6 @@ trap(struct trapframe *tf)
exit(); exit();
return; return;
} }
switch(tf->trapno){ switch(tf->trapno){
case T_IRQ0 + IRQ_TIMER: case T_IRQ0 + IRQ_TIMER:
if(cpu->id == 0){ if(cpu->id == 0){
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "types.h" #include "types.h"
#include "defs.h" #include "defs.h"
#include "x86.h" #include "x86.h"
#include "memlayout.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h" #include "spinlock.h"
#include "condvar.h" #include "condvar.h"
...@@ -14,6 +15,64 @@ extern char data[]; // defined in data.S ...@@ -14,6 +15,64 @@ extern char data[]; // defined in data.S
static pde_t *kpgdir __attribute__ ((aligned (CACHELINE))); // for use in scheduler() static pde_t *kpgdir __attribute__ ((aligned (CACHELINE))); // for use in scheduler()
struct segdesc gdt[NSEGS];
// page map for during boot
static void
pgmap(void *va, void *last, uint pa)
{
pde_t *pde;
pte_t *pgtab;
pte_t *pte;
for(;;){
pde = &kpgdir[PDX(va)];
pde_t pdev = *pde;
if (pdev == 0) {
pgtab = (pte_t *) pgalloc();
*pde = v2p(pgtab) | PTE_P | PTE_W;
} else {
pgtab = (pte_t*)p2v(PTE_ADDR(pdev));
}
pte = &pgtab[PTX(va)];
*pte = pa | PTE_W | PTE_P;
if(va == last)
break;
va += PGSIZE;
pa += PGSIZE;
}
}
// set up a page table to get off the ground
void
pginit(char* (*alloc)(void))
{
uint cr0;
kpgdir = (pde_t *) alloc();
pgmap((void *) 0, (void *) PHYSTOP, 0);
pgmap((void *) KERNBASE, (void *) (KERNBASE+PHYSTOP), 0);
pgmap((void*)0xFE000000, 0, 0xFE000000);
switchkvm(); // load kpgdir into cr3
cr0 = rcr0();
cr0 |= CR0_PG;
lcr0(cr0); // paging on
// new gdt
gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0);
gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
lgdt((void *)v2p(gdt), sizeof(gdt));
loadgs(SEG_KDATA << 3);
loadfs(SEG_KDATA << 3);
loades(SEG_KDATA << 3);
loadds(SEG_KDATA << 3);
loadss(SEG_KDATA << 3);
__asm volatile("ljmp %0,$1f\n 1:\n" :: "i" (SEG_KCODE << 3)); // reload cs
}
// Set up CPU's kernel segment descriptors. // Set up CPU's kernel segment descriptors.
// Run once at boot time on each CPU. // Run once at boot time on each CPU.
void void
...@@ -34,7 +93,8 @@ seginit(void) ...@@ -34,7 +93,8 @@ seginit(void)
// Map cpu, curproc, kmem, runq // Map cpu, curproc, kmem, runq
c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 16, 0); c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 16, 0);
lgdt(c->gdt, sizeof(c->gdt)); // lgt((void *) v2p((void*)(c->gdt)), sizeof(c->gdt));
lgdt((void *)(c->gdt), sizeof(c->gdt));
loadgs(SEG_KCPU << 3); loadgs(SEG_KCPU << 3);
// Initialize cpu-local storage. // Initialize cpu-local storage.
...@@ -44,6 +104,31 @@ seginit(void) ...@@ -44,6 +104,31 @@ seginit(void)
runq = &runqs[cpunum()]; runq = &runqs[cpunum()];
} }
void
printpgdir(pde_t *pgdir)
{
pde_t *pde;
pte_t *pgtab;
pte_t pte;
for (uint i = 0; i < NPDENTRIES; i++) {
pde = &pgdir[i];
pde_t pdev = *pde;
if (pdev & PTE_P) {
pgtab = (pte_t*)p2v(PTE_ADDR(pdev));
cprintf("%d: p 0x%x v 0x%x\n", i, PTE_ADDR(pdev), pgtab);
for (uint j = 0; j < NPTENTRIES; j++) {
pte = pgtab[j];
if (pte & PTE_P) {
void *pg = p2v(PTE_ADDR(pte));
if (pg != 0)
; // cprintf(" %d: 0x%x v 0x%x\n", j, pte, pg);
}
}
}
}
}
// Return the address of the PTE in page table pgdir // Return the address of the PTE in page table pgdir
// that corresponds to linear address va. If create!=0, // that corresponds to linear address va. If create!=0,
// create any required page table pages. // create any required page table pages.
...@@ -57,7 +142,7 @@ walkpgdir(pde_t *pgdir, const void *va, int create) ...@@ -57,7 +142,7 @@ walkpgdir(pde_t *pgdir, const void *va, int create)
pde = &pgdir[PDX(va)]; pde = &pgdir[PDX(va)];
pde_t pdev = *pde; pde_t pdev = *pde;
if(pdev & PTE_P){ if(pdev & PTE_P){
pgtab = (pte_t*)PTE_ADDR(pdev); pgtab = (pte_t*)p2v(PTE_ADDR(pdev));
} else { } else {
if(!create || (pgtab = (pte_t*)kalloc()) == 0) if(!create || (pgtab = (pte_t*)kalloc()) == 0)
return 0; return 0;
...@@ -66,7 +151,7 @@ walkpgdir(pde_t *pgdir, const void *va, int create) ...@@ -66,7 +151,7 @@ walkpgdir(pde_t *pgdir, const void *va, int create)
// The permissions here are overly generous, but they can // The permissions here are overly generous, but they can
// be further restricted by the permissions in the page table // be further restricted by the permissions in the page table
// entries, if necessary. // entries, if necessary.
if (!__sync_bool_compare_and_swap(pde, pdev, PADDR(pgtab) | PTE_P | PTE_W | PTE_U)) { if (!__sync_bool_compare_and_swap(pde, pdev, v2p(pgtab) | PTE_P | PTE_W | PTE_U)) {
kfree((void*) pgtab); kfree((void*) pgtab);
goto retry; goto retry;
} }
...@@ -82,7 +167,7 @@ mappages(pde_t *pgdir, void *la, uint size, uint pa, int perm) ...@@ -82,7 +167,7 @@ mappages(pde_t *pgdir, void *la, uint size, uint pa, int perm)
{ {
char *a, *last; char *a, *last;
pte_t *pte; pte_t *pte;
a = PGROUNDDOWN(la); a = PGROUNDDOWN(la);
last = PGROUNDDOWN(la + size - 1); last = PGROUNDDOWN(la + size - 1);
for(;;){ for(;;){
...@@ -136,8 +221,6 @@ clearpages(pde_t *pgdir, void *begin, void *end) ...@@ -136,8 +221,6 @@ clearpages(pde_t *pgdir, void *begin, void *end)
} }
} }
// The mappings from logical to linear are one to one (i.e.,
// segmentation doesn't do anything).
// There is one page table per process, plus one that's used // There is one page table per process, plus one that's used
// when a CPU is not running any process (kpgdir). // when a CPU is not running any process (kpgdir).
// A user process uses the same page table as the kernel; the // A user process uses the same page table as the kernel; the
...@@ -159,14 +242,16 @@ clearpages(pde_t *pgdir, void *begin, void *end) ...@@ -159,14 +242,16 @@ clearpages(pde_t *pgdir, void *begin, void *end)
// (both in physical memory and in the kernel's virtual address // (both in physical memory and in the kernel's virtual address
// space). // space).
static struct kmap { static struct kmap {
void *p; void *l;
void *e; uint p;
uint e;
int perm; int perm;
} kmap[] = { } kmap[] = {
{(void*)USERTOP, (void*)0x100000, PTE_W}, // I/O space { (void *)IOSPACEB, IOSPACEB, IOSPACEE, PTE_W}, // I/O space
{(void*)0x100000, data, 0 }, // kernel text, rodata { P2V(IOSPACEB), IOSPACEB, IOSPACEE, PTE_W}, // I/O space
{data, (void*)PHYSTOP, PTE_W}, // kernel data, memory { (void *)KERNLINK, V2P(KERNLINK), V2P(data), 0}, // kernel text, rodata
{(void*)0xFE000000, 0, PTE_W}, // device mappings { data, V2P(data), PHYSTOP, PTE_W}, // kernel data, memory
{ (void*)0xFE000000, 0xFE000000, 0, PTE_W}, // device mappings
}; };
// Set up kernel part of a page table. // Set up kernel part of a page table.
...@@ -181,7 +266,7 @@ setupkvm(void) ...@@ -181,7 +266,7 @@ setupkvm(void)
memset(pgdir, 0, PGSIZE); memset(pgdir, 0, PGSIZE);
k = kmap; k = kmap;
for(k = kmap; k < &kmap[NELEM(kmap)]; k++) for(k = kmap; k < &kmap[NELEM(kmap)]; k++)
if(mappages(pgdir, k->p, k->e - k->p, (uint)k->p, k->perm) < 0) if(mappages(pgdir, k->l, k->e - k->p, (uint)k->p, k->perm) < 0)
return 0; return 0;
return pgdir; return pgdir;
...@@ -193,6 +278,7 @@ void ...@@ -193,6 +278,7 @@ void
kvmalloc(void) kvmalloc(void)
{ {
kpgdir = setupkvm(); kpgdir = setupkvm();
switchkvm();
} }
// Turn on paging. // Turn on paging.
...@@ -202,9 +288,20 @@ vmenable(void) ...@@ -202,9 +288,20 @@ vmenable(void)
uint cr0; uint cr0;
switchkvm(); // load kpgdir into cr3 switchkvm(); // load kpgdir into cr3
cr0 = rcr0(); cr0 = rcr0();
cr0 |= CR0_PG; cr0 |= CR0_PG;
lcr0(cr0); lcr0(cr0);
struct cpu *c = &cpus[0];
lgdt((void *)v2p((void *)(c->gdt)), sizeof(c->gdt));
loadgs(SEG_KCPU << 3);
loadfs(SEG_KDATA << 3);
loades(SEG_KDATA << 3);
loadds(SEG_KDATA << 3);
loadss(SEG_KDATA << 3);
__asm volatile("ljmp %0,$1f\n 1:\n" :: "i" (SEG_KCODE << 3)); // reload cs
} }
// Switch h/w page table register to the kernel-only page table, // Switch h/w page table register to the kernel-only page table,
...@@ -212,7 +309,7 @@ vmenable(void) ...@@ -212,7 +309,7 @@ vmenable(void)
void void
switchkvm(void) switchkvm(void)
{ {
lcr3(PADDR(kpgdir)); // switch to the kernel page table lcr3(v2p(kpgdir)); // switch to the kernel page table
} }
// Switch TSS and h/w page table to correspond to process p. // Switch TSS and h/w page table to correspond to process p.
...@@ -223,11 +320,11 @@ switchuvm(struct proc *p) ...@@ -223,11 +320,11 @@ switchuvm(struct proc *p)
cpu->gdt[SEG_TSS] = SEG16(STS_T32A, &cpu->ts, sizeof(cpu->ts)-1, 0); cpu->gdt[SEG_TSS] = SEG16(STS_T32A, &cpu->ts, sizeof(cpu->ts)-1, 0);
cpu->gdt[SEG_TSS].s = 0; cpu->gdt[SEG_TSS].s = 0;
cpu->ts.ss0 = SEG_KDATA << 3; cpu->ts.ss0 = SEG_KDATA << 3;
cpu->ts.esp0 = (uint)proc->kstack + KSTACKSIZE; cpu->ts.esp0 = (uint) proc->kstack + KSTACKSIZE;
ltr(SEG_TSS << 3); ltr(SEG_TSS << 3);
if(p->vmap == 0 || p->vmap->pgdir == 0) if(p->vmap == 0 || p->vmap->pgdir == 0)
panic("switchuvm: no vmap/pgdir"); panic("switchuvm: no vmap/pgdir");
lcr3(PADDR(p->vmap->pgdir)); // switch to new address space lcr3(v2p(p->vmap->pgdir)); // switch to new address space
popcli(); popcli();
} }
...@@ -242,7 +339,7 @@ freevm(pde_t *pgdir) ...@@ -242,7 +339,7 @@ freevm(pde_t *pgdir)
panic("freevm: no pgdir"); panic("freevm: no pgdir");
for(i = 0; i < NPDENTRIES; i++){ for(i = 0; i < NPDENTRIES; i++){
if(pgdir[i] & PTE_P) if(pgdir[i] & PTE_P)
kfree((char*)PTE_ADDR(pgdir[i])); kfree(p2v(PTE_ADDR(pgdir[i])));
} }
kfree((char*)pgdir); kfree((char*)pgdir);
} }
...@@ -498,7 +595,7 @@ vmap_copy(struct vmap *m, int share) ...@@ -498,7 +595,7 @@ vmap_copy(struct vmap *m, int share)
__sync_fetch_and_add(&c->e[i].n->ref, 1); __sync_fetch_and_add(&c->e[i].n->ref, 1);
} }
if (share) if (share)
lcr3(PADDR(m->pgdir)); // Reload hardware page table lcr3(v2p(m->pgdir)); // Reload hardware page table
release(&m->lock); release(&m->lock);
return c; return c;
...@@ -534,21 +631,6 @@ vmn_load(struct vmnode *vmn, struct inode *ip, uint offset, uint sz) ...@@ -534,21 +631,6 @@ vmn_load(struct vmnode *vmn, struct inode *ip, uint offset, uint sz)
} }
} }
//PAGEBREAK!
// Map user virtual address to kernel physical address.
char*
uva2ka(pde_t *pgdir, char *uva)
{
pte_t *pte;
pte = walkpgdir(pgdir, uva, 0);
if((*pte & PTE_P) == 0)
return 0;
if((*pte & PTE_U) == 0)
return 0;
return (char*)PTE_ADDR(*pte);
}
// Copy len bytes from p to user address va in vmap. // Copy len bytes from p to user address va in vmap.
// Most useful when vmap is not the current page table. // Most useful when vmap is not the current page table.
int int
...@@ -634,7 +716,7 @@ pagefault_wcow(struct vmap *vmap, uint va, pte_t *pte, struct vma *m, uint npg) ...@@ -634,7 +716,7 @@ pagefault_wcow(struct vmap *vmap, uint va, pte_t *pte, struct vma *m, uint npg)
// Update the hardware page tables to reflect the change to the vma // Update the hardware page tables to reflect the change to the vma
clearpages(vmap->pgdir, (void *) m->va_start, (void *) m->va_end); clearpages(vmap->pgdir, (void *) m->va_start, (void *) m->va_end);
pte = walkpgdir(vmap->pgdir, (const void *)va, 0); pte = walkpgdir(vmap->pgdir, (const void *)va, 0);
*pte = PADDR(m->n->page[npg]) | PTE_P | PTE_U | PTE_W; *pte = v2p(m->n->page[npg]) | PTE_P | PTE_U | PTE_W;
// drop my ref to vmnode // drop my ref to vmnode
vmn_decref(o); vmn_decref(o);
return 0; return 0;
...@@ -660,14 +742,14 @@ pagefault(struct vmap *vmap, uint va, uint err) ...@@ -660,14 +742,14 @@ pagefault(struct vmap *vmap, uint va, uint err)
return -1; return -1;
} }
} else if (m->va_type == COW) { } else if (m->va_type == COW) {
*pte = PADDR(m->n->page[npg]) | PTE_P | PTE_U | PTE_COW; *pte = v2p(m->n->page[npg]) | PTE_P | PTE_U | PTE_COW;
} else { } else {
if (m->n->ref != 1) { if (m->n->ref != 1) {
panic("pagefault"); panic("pagefault");
} }
*pte = PADDR(m->n->page[npg]) | PTE_P | PTE_U | PTE_W; *pte = v2p(m->n->page[npg]) | PTE_P | PTE_U | PTE_W;
} }
lcr3(PADDR(vmap->pgdir)); // Reload hardware page tables lcr3(v2p(vmap->pgdir)); // Reload hardware page tables
release(&m->lock); release(&m->lock);
return 1; return 1;
} }
...@@ -97,6 +97,30 @@ loadgs(ushort v) ...@@ -97,6 +97,30 @@ loadgs(ushort v)
__asm volatile("movw %0, %%gs" : : "r" (v)); __asm volatile("movw %0, %%gs" : : "r" (v));
} }
static inline void
loadfs(ushort v)
{
__asm volatile("movw %0, %%fs" : : "r" (v));
}
static inline void
loades(ushort v)
{
__asm volatile("movw %0, %%es" : : "r" (v));
}
static inline void
loadds(ushort v)
{
__asm volatile("movw %0, %%ds" : : "r" (v));
}
static inline void
loadss(ushort v)
{
__asm volatile("movw %0, %%ss" : : "r" (v));
}
static inline uint static inline uint
rebp(void) rebp(void)
{ {
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论