Map kernel high
Very important to give qemu memory through PHYSTOP :(
This commit is contained in:
parent
dccb915282
commit
9aa0337dc1
20 changed files with 208 additions and 71 deletions
4
Makefile
4
Makefile
|
@ -109,7 +109,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
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \
|
||||||
ifndef CPUS
|
ifndef CPUS
|
||||||
CPUS := 2
|
CPUS := 2
|
||||||
endif
|
endif
|
||||||
QEMUOPTS = -hdb fs.img xv6.img -smp $(CPUS)
|
QEMUOPTS = -hdb fs.img xv6.img -smp $(CPUS) -m 512
|
||||||
|
|
||||||
qemu: fs.img xv6.img
|
qemu: fs.img xv6.img
|
||||||
$(QEMU) -serial mon:stdio $(QEMUOPTS)
|
$(QEMU) -serial mon:stdio $(QEMUOPTS)
|
||||||
|
|
11
bootmain.c
11
bootmain.c
|
@ -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)
|
||||||
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)
|
||||||
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);
|
||||||
entry();
|
entry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
bootother.S
14
bootother.S
|
@ -1,4 +1,5 @@
|
||||||
#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,6 +25,8 @@
|
||||||
|
|
||||||
#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:
|
||||||
|
@ -40,7 +43,7 @@ start:
|
||||||
movl %eax, %cr0
|
movl %eax, %cr0
|
||||||
|
|
||||||
//PAGEBREAK!
|
//PAGEBREAK!
|
||||||
ljmp $(SEG_KCODE<<3), $start32
|
ljmpl $(SEG_KCODE<<3), $(start32+KERNBASE)
|
||||||
|
|
||||||
.code32
|
.code32
|
||||||
start32:
|
start32:
|
||||||
|
@ -53,10 +56,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 +72,9 @@ 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)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "memlayout.h"
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
|
@ -60,6 +61,9 @@ cprintf(char *fmt, ...)
|
||||||
if(locking)
|
if(locking)
|
||||||
acquire(&cons.lock);
|
acquire(&cons.lock);
|
||||||
|
|
||||||
|
if (fmt == 0)
|
||||||
|
panic("null fmt");
|
||||||
|
|
||||||
argp = (uint*)(void*)(&fmt + 1);
|
argp = (uint*)(void*)(&fmt + 1);
|
||||||
state = 0;
|
state = 0;
|
||||||
for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
|
for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
|
||||||
|
@ -121,7 +125,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)
|
||||||
|
|
2
defs.h
2
defs.h
|
@ -62,6 +62,7 @@ extern uchar ioapicid;
|
||||||
void ioapicinit(void);
|
void ioapicinit(void);
|
||||||
|
|
||||||
// kalloc.c
|
// kalloc.c
|
||||||
|
char* pgalloc(void);
|
||||||
char* kalloc(void);
|
char* kalloc(void);
|
||||||
void kfree(char*);
|
void kfree(char*);
|
||||||
void kinit(void);
|
void kinit(void);
|
||||||
|
@ -160,6 +161,7 @@ void uartintr(void);
|
||||||
void uartputc(int);
|
void uartputc(int);
|
||||||
|
|
||||||
// vm.c
|
// vm.c
|
||||||
|
void pginit(char* (*alloc)());
|
||||||
void seginit(void);
|
void seginit(void);
|
||||||
void kvmalloc(void);
|
void kvmalloc(void);
|
||||||
void vmenable(void);
|
void vmenable(void);
|
||||||
|
|
1
exec.c
1
exec.c
|
@ -1,5 +1,6 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
|
#include "memlayout.h"
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
1
ide.c
1
ide.c
|
@ -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 "proc.h"
|
#include "proc.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
|
|
22
kalloc.c
22
kalloc.c
|
@ -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"
|
||||||
|
|
||||||
|
@ -18,6 +19,20 @@ struct {
|
||||||
} kmem;
|
} kmem;
|
||||||
|
|
||||||
extern char end[]; // first address after kernel loaded from ELF file
|
extern char end[]; // first address after kernel loaded from ELF file
|
||||||
|
char *newend;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize free list of physical pages.
|
// Initialize free list of physical pages.
|
||||||
void
|
void
|
||||||
|
@ -26,8 +41,8 @@ kinit(void)
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
initlock(&kmem.lock, "kmem");
|
initlock(&kmem.lock, "kmem");
|
||||||
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(p);
|
kfree(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +56,7 @@ kfree(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");
|
||||||
|
|
||||||
// Fill with junk to catch dangling refs.
|
// Fill with junk to catch dangling refs.
|
||||||
|
@ -67,6 +82,7 @@ kalloc(void)
|
||||||
if(r)
|
if(r)
|
||||||
kmem.freelist = r->next;
|
kmem.freelist = r->next;
|
||||||
release(&kmem.lock);
|
release(&kmem.lock);
|
||||||
|
cprintf("kalloc: 0x%x\n", r);
|
||||||
return (char*)r;
|
return (char*)r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
33
main.c
33
main.c
|
@ -1,6 +1,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 "proc.h"
|
#include "proc.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
|
@ -9,6 +10,8 @@ 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
|
||||||
|
@ -16,6 +19,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
|
||||||
|
@ -46,7 +50,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
|
|
||||||
pinit(); // process table
|
pinit(); // process table
|
||||||
tvinit(); // trap vectors
|
tvinit(); // trap vectors
|
||||||
binit(); // buffer cache
|
binit(); // buffer cache
|
||||||
|
@ -57,25 +60,35 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Common CPU setup code.
|
||||||
|
// Bootstrap CPU comes here from mainc().
|
||||||
|
// Other CPUs jump here from bootother.S.
|
||||||
|
static void
|
||||||
|
mpboot(void)
|
||||||
|
{
|
||||||
|
vmenable(); // turn on paging
|
||||||
|
seginit();
|
||||||
|
lapicinit(cpunum());
|
||||||
|
mpmain();
|
||||||
|
}
|
||||||
|
|
||||||
// Common CPU setup code.
|
// Common CPU setup code.
|
||||||
// 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)
|
mpmain(void)
|
||||||
{
|
{
|
||||||
if(cpunum() != mpbcpu()){
|
|
||||||
seginit();
|
|
||||||
lapicinit(cpunum());
|
|
||||||
}
|
|
||||||
vmenable(); // turn on paging
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +104,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++){
|
||||||
|
@ -103,9 +116,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)
|
||||||
|
|
8
mmu.h
8
mmu.h
|
@ -106,18 +106,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
|
||||||
|
|
||||||
|
|
4
mp.c
4
mp.c
|
@ -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"
|
||||||
|
@ -39,6 +40,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)
|
||||||
|
@ -83,7 +85,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)
|
||||||
|
|
11
multiboot.S
11
multiboot.S
|
@ -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:
|
||||||
# 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:
|
||||||
.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
|
||||||
|
|
2
param.h
2
param.h
|
@ -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 0x1000000 // use phys mem up to here as free pool
|
|
||||||
#define MAXARG 32 // max exec arguments
|
#define MAXARG 32 // max exec arguments
|
||||||
#define LOGSIZE 10 // size of log
|
#define LOGSIZE 10 // size of log
|
||||||
|
|
||||||
|
|
1
proc.c
1
proc.c
|
@ -1,6 +1,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 "x86.h"
|
#include "x86.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
|
|
|
@ -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 "proc.h"
|
#include "proc.h"
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
|
@ -71,7 +72,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
|
||||||
|
|
|
@ -1,6 +1,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 "proc.h"
|
#include "proc.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
|
|
|
@ -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 "proc.h"
|
#include "proc.h"
|
||||||
|
|
||||||
|
|
1
trap.c
1
trap.c
|
@ -1,6 +1,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 "proc.h"
|
#include "proc.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
|
|
129
vm.c
129
vm.c
|
@ -2,20 +2,71 @@
|
||||||
#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 "proc.h"
|
#include "proc.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
|
|
||||||
extern char data[]; // defined in data.S
|
extern char data[]; // defined in data.S
|
||||||
|
|
||||||
static pde_t *kpgdir; // for use in scheduler()
|
static pde_t *kpgdir; // for use in scheduler()
|
||||||
|
struct segdesc gdt[NSEGS];
|
||||||
|
|
||||||
// Allocate one page table for the machine for the kernel address
|
|
||||||
// space for scheduler processes.
|
// page map for during boot
|
||||||
void
|
// XXX build a static page table in assembly
|
||||||
kvmalloc(void)
|
static void
|
||||||
|
pgmap(void *va, void *last, uint pa)
|
||||||
{
|
{
|
||||||
kpgdir = setupkvm();
|
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); // map pa 0 at va 0
|
||||||
|
pgmap((void *) KERNBASE, (void *) (KERNBASE+PHYSTOP), 0); // map pa 0 at va KERNBASE
|
||||||
|
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.
|
||||||
|
@ -57,7 +108,7 @@ walkpgdir(pde_t *pgdir, const void *va, int create)
|
||||||
|
|
||||||
pde = &pgdir[PDX(va)];
|
pde = &pgdir[PDX(va)];
|
||||||
if(*pde & PTE_P){
|
if(*pde & PTE_P){
|
||||||
pgtab = (pte_t*)PTE_ADDR(*pde);
|
pgtab = (pte_t*)p2v(PTE_ADDR(*pde));
|
||||||
} else {
|
} else {
|
||||||
if(!create || (pgtab = (pte_t*)kalloc()) == 0)
|
if(!create || (pgtab = (pte_t*)kalloc()) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -66,7 +117,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.
|
||||||
*pde = PADDR(pgtab) | PTE_P | PTE_W | PTE_U;
|
*pde = v2p(pgtab) | PTE_P | PTE_W | PTE_U;
|
||||||
}
|
}
|
||||||
return &pgtab[PTX(va)];
|
return &pgtab[PTX(va)];
|
||||||
}
|
}
|
||||||
|
@ -105,29 +156,30 @@ mappages(pde_t *pgdir, void *la, uint size, uint pa, int perm)
|
||||||
// page protection bits prevent it from using anything other
|
// page protection bits prevent it from using anything other
|
||||||
// than its memory.
|
// than its memory.
|
||||||
//
|
//
|
||||||
|
//
|
||||||
// setupkvm() and exec() set up every page table like this:
|
// setupkvm() and exec() set up every page table like this:
|
||||||
// 0..640K : user memory (text, data, stack, heap)
|
// 0..KERNBASE : user memory (text, data, stack, heap), mapped to some phys mem
|
||||||
// 640K..1M : mapped direct (for IO space)
|
// KERNBASE+640K..KERNBASE+1M: mapped to 640K..1M
|
||||||
// 1M..end : mapped direct (for the kernel's text and data)
|
// KERNBASE+1M..KERNBASE+end : mapped to 1M..end
|
||||||
// end..PHYSTOP : mapped direct (kernel heap and user pages)
|
// KERNBASE+end..KERBASE+PHYSTOP : mapped to end..PHYSTOP (free memory)
|
||||||
// 0xfe000000..0 : mapped direct (devices such as ioapic)
|
// 0xfe000000..0 : mapped direct (devices such as ioapic)
|
||||||
//
|
//
|
||||||
// The kernel allocates memory for its heap and for user memory
|
// The kernel allocates memory for its heap and for user memory
|
||||||
// between kernend and the end of physical memory (PHYSTOP).
|
// between kernend and the end of physical memory (PHYSTOP).
|
||||||
// The virtual address space of each user program includes the kernel
|
// The virtual address space of each user program includes the kernel
|
||||||
// (which is inaccessible in user mode). The user program addresses
|
// (which is inaccessible in user mode). The user program sits in
|
||||||
// range from 0 till 640KB (USERTOP), which where the I/O hole starts
|
// the bottom of the address space, and the kernel at the top at KERNBASE.
|
||||||
// (both in physical memory and in the kernel's virtual address
|
|
||||||
// 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.
|
||||||
|
@ -142,12 +194,21 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocate one page table for the machine for the kernel address
|
||||||
|
// space for scheduler processes.
|
||||||
|
void
|
||||||
|
kvmalloc(void)
|
||||||
|
{
|
||||||
|
kpgdir = setupkvm();
|
||||||
|
switchkvm();
|
||||||
|
}
|
||||||
|
|
||||||
// Turn on paging.
|
// Turn on paging.
|
||||||
void
|
void
|
||||||
vmenable(void)
|
vmenable(void)
|
||||||
|
@ -158,6 +219,16 @@ vmenable(void)
|
||||||
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,
|
||||||
|
@ -165,7 +236,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.
|
||||||
|
@ -180,7 +251,7 @@ switchuvm(struct proc *p)
|
||||||
ltr(SEG_TSS << 3);
|
ltr(SEG_TSS << 3);
|
||||||
if(p->pgdir == 0)
|
if(p->pgdir == 0)
|
||||||
panic("switchuvm: no pgdir");
|
panic("switchuvm: no pgdir");
|
||||||
lcr3(PADDR(p->pgdir)); // switch to new address space
|
lcr3(v2p(p->pgdir)); // switch to new address space
|
||||||
popcli();
|
popcli();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +266,7 @@ inituvm(pde_t *pgdir, char *init, uint sz)
|
||||||
panic("inituvm: more than a page");
|
panic("inituvm: more than a page");
|
||||||
mem = kalloc();
|
mem = kalloc();
|
||||||
memset(mem, 0, PGSIZE);
|
memset(mem, 0, PGSIZE);
|
||||||
mappages(pgdir, 0, PGSIZE, PADDR(mem), PTE_W|PTE_U);
|
mappages(pgdir, 0, PGSIZE, v2p(mem), PTE_W|PTE_U);
|
||||||
memmove(mem, init, sz);
|
memmove(mem, init, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +316,7 @@ allocuvm(pde_t *pgdir, uint oldsz, uint newsz)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memset(mem, 0, PGSIZE);
|
memset(mem, 0, PGSIZE);
|
||||||
mappages(pgdir, (char*)a, PGSIZE, PADDR(mem), PTE_W|PTE_U);
|
mappages(pgdir, (char*)a, PGSIZE, v2p(mem), PTE_W|PTE_U);
|
||||||
}
|
}
|
||||||
return newsz;
|
return newsz;
|
||||||
}
|
}
|
||||||
|
@ -289,7 +360,7 @@ freevm(pde_t *pgdir)
|
||||||
deallocuvm(pgdir, USERTOP, 0);
|
deallocuvm(pgdir, USERTOP, 0);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -315,7 +386,7 @@ copyuvm(pde_t *pgdir, uint sz)
|
||||||
if((mem = kalloc()) == 0)
|
if((mem = kalloc()) == 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
memmove(mem, (char*)pa, PGSIZE);
|
memmove(mem, (char*)pa, PGSIZE);
|
||||||
if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0)
|
if(mappages(d, (void*)i, PGSIZE, v2p(mem), PTE_W|PTE_U) < 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
|
|
24
x86.h
24
x86.h
|
@ -96,6 +96,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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue