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
 | 
			
		||||
 | 
			
		||||
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) -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
 | 
			
		||||
CPUS := 2
 | 
			
		||||
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) -serial mon:stdio $(QEMUOPTS)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								bootmain.c
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								bootmain.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -8,6 +8,7 @@
 | 
			
		|||
#include "types.h"
 | 
			
		||||
#include "elf.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
 | 
			
		||||
#define SECTSIZE  512
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +20,7 @@ bootmain(void)
 | 
			
		|||
  struct elfhdr *elf;
 | 
			
		||||
  struct proghdr *ph, *eph;
 | 
			
		||||
  void (*entry)(void);
 | 
			
		||||
  uchar* va;
 | 
			
		||||
  uchar* pa;
 | 
			
		||||
 | 
			
		||||
  elf = (struct elfhdr*)0x10000;  // scratch space
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,15 +35,15 @@ bootmain(void)
 | 
			
		|||
  ph = (struct proghdr*)((uchar*)elf + elf->phoff);
 | 
			
		||||
  eph = ph + elf->phnum;
 | 
			
		||||
  for(; ph < eph; ph++){
 | 
			
		||||
    va = (uchar*)ph->va;
 | 
			
		||||
    readseg(va, ph->filesz, ph->offset);
 | 
			
		||||
    pa = (uchar*)ph->pa;
 | 
			
		||||
    readseg(pa, ph->filesz, ph->offset);
 | 
			
		||||
    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.
 | 
			
		||||
  // Does not return!
 | 
			
		||||
  entry = (void(*)(void))(elf->entry);
 | 
			
		||||
  entry = (void(*)(void))(elf->entry & 0xFFFFFF);
 | 
			
		||||
  entry();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								bootother.S
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								bootother.S
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
#include "asm.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +25,8 @@
 | 
			
		|||
 | 
			
		||||
#define CR0_PE    1
 | 
			
		||||
 | 
			
		||||
#define RELOC1(x) ((x) + KERNBASE)    // same as V2P, but without casts
 | 
			
		||||
 | 
			
		||||
.code16           
 | 
			
		||||
.globl start
 | 
			
		||||
start:
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +43,7 @@ start:
 | 
			
		|||
  movl    %eax, %cr0
 | 
			
		||||
 | 
			
		||||
//PAGEBREAK!
 | 
			
		||||
  ljmp    $(SEG_KCODE<<3), $start32
 | 
			
		||||
  ljmpl    $(SEG_KCODE<<3), $(start32+KERNBASE)
 | 
			
		||||
 | 
			
		||||
.code32
 | 
			
		||||
start32:
 | 
			
		||||
| 
						 | 
				
			
			@ -53,10 +56,10 @@ start32:
 | 
			
		|||
  movw    %ax, %gs
 | 
			
		||||
 | 
			
		||||
  # switch to the stack allocated by bootothers()
 | 
			
		||||
  movl    start-4, %esp
 | 
			
		||||
  movl    RELOC1(start-4), %esp
 | 
			
		||||
 | 
			
		||||
  # call mpmain()
 | 
			
		||||
  call	*(start-8)
 | 
			
		||||
  call	*(RELOC1(start)-8)
 | 
			
		||||
 | 
			
		||||
  movw    $0x8a00, %ax
 | 
			
		||||
  movw    %ax, %dx
 | 
			
		||||
| 
						 | 
				
			
			@ -69,8 +72,9 @@ spin:
 | 
			
		|||
.p2align 2
 | 
			
		||||
gdt:
 | 
			
		||||
  SEG_NULLASM
 | 
			
		||||
  SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)
 | 
			
		||||
  SEG_ASM(STA_W, 0x0, 0xffffffff)
 | 
			
		||||
  SEG_ASM(STA_X|STA_R, -KERNBASE, 0xffffffff)
 | 
			
		||||
  SEG_ASM(STA_W, -KERNBASE, 0xffffffff)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
gdtdesc:
 | 
			
		||||
  .word   (gdtdesc - gdt - 1)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@
 | 
			
		|||
#include "spinlock.h"
 | 
			
		||||
#include "fs.h"
 | 
			
		||||
#include "file.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "proc.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +61,9 @@ cprintf(char *fmt, ...)
 | 
			
		|||
  if(locking)
 | 
			
		||||
    acquire(&cons.lock);
 | 
			
		||||
 | 
			
		||||
  if (fmt == 0)
 | 
			
		||||
    panic("null fmt");
 | 
			
		||||
 | 
			
		||||
  argp = (uint*)(void*)(&fmt + 1);
 | 
			
		||||
  state = 0;
 | 
			
		||||
  for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
 | 
			
		||||
| 
						 | 
				
			
			@ -121,7 +125,7 @@ panic(char *s)
 | 
			
		|||
//PAGEBREAK: 50
 | 
			
		||||
#define BACKSPACE 0x100
 | 
			
		||||
#define CRTPORT 0x3d4
 | 
			
		||||
static ushort *crt = (ushort*)0xb8000;  // CGA memory
 | 
			
		||||
static ushort *crt = (ushort*)P2V(0xb8000);  // CGA memory
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
cgaputc(int c)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								defs.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								defs.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -62,6 +62,7 @@ extern uchar    ioapicid;
 | 
			
		|||
void            ioapicinit(void);
 | 
			
		||||
 | 
			
		||||
// kalloc.c
 | 
			
		||||
char*           pgalloc(void);
 | 
			
		||||
char*           kalloc(void);
 | 
			
		||||
void            kfree(char*);
 | 
			
		||||
void            kinit(void);
 | 
			
		||||
| 
						 | 
				
			
			@ -160,6 +161,7 @@ void            uartintr(void);
 | 
			
		|||
void            uartputc(int);
 | 
			
		||||
 | 
			
		||||
// vm.c
 | 
			
		||||
void            pginit(char* (*alloc)());
 | 
			
		||||
void            seginit(void);
 | 
			
		||||
void            kvmalloc(void);
 | 
			
		||||
void            vmenable(void);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								exec.c
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								exec.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
#include "types.h"
 | 
			
		||||
#include "param.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "proc.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								ide.c
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								ide.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
#include "types.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "param.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "proc.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										22
									
								
								kalloc.c
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								kalloc.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -5,6 +5,7 @@
 | 
			
		|||
#include "types.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "param.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "spinlock.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,6 +19,20 @@ struct {
 | 
			
		|||
} kmem;
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
void
 | 
			
		||||
| 
						 | 
				
			
			@ -26,8 +41,8 @@ kinit(void)
 | 
			
		|||
  char *p;
 | 
			
		||||
 | 
			
		||||
  initlock(&kmem.lock, "kmem");
 | 
			
		||||
  p = (char*)PGROUNDUP((uint)end);
 | 
			
		||||
  for(; p + PGSIZE <= (char*)PHYSTOP; p += PGSIZE)
 | 
			
		||||
  p = (char*)PGROUNDUP((uint)newend);
 | 
			
		||||
  for(; p + PGSIZE <= (char*)p2v(PHYSTOP); p += PGSIZE)
 | 
			
		||||
    kfree(p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +56,7 @@ kfree(char *v)
 | 
			
		|||
{
 | 
			
		||||
  struct run *r;
 | 
			
		||||
 | 
			
		||||
  if((uint)v % PGSIZE || v < end || (uint)v >= PHYSTOP) 
 | 
			
		||||
  if((uint)v % PGSIZE || v < end || v2p(v) >= PHYSTOP) 
 | 
			
		||||
    panic("kfree");
 | 
			
		||||
 | 
			
		||||
  // Fill with junk to catch dangling refs.
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +82,7 @@ kalloc(void)
 | 
			
		|||
  if(r)
 | 
			
		||||
    kmem.freelist = r->next;
 | 
			
		||||
  release(&kmem.lock);
 | 
			
		||||
  cprintf("kalloc: 0x%x\n", r);
 | 
			
		||||
  return (char*)r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										33
									
								
								main.c
									
										
									
									
									
								
							
							
						
						
									
										33
									
								
								main.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
#include "types.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "param.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "proc.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -9,6 +10,8 @@ static void bootothers(void);
 | 
			
		|||
static void mpmain(void);
 | 
			
		||||
void jmpkstack(void)  __attribute__((noreturn));
 | 
			
		||||
void mainc(void);
 | 
			
		||||
static volatile int newpgdir;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Bootstrap processor starts running C code here.
 | 
			
		||||
// Allocate a real stack and switch to it, first
 | 
			
		||||
| 
						 | 
				
			
			@ -16,6 +19,7 @@ void mainc(void);
 | 
			
		|||
int
 | 
			
		||||
main(void)
 | 
			
		||||
{
 | 
			
		||||
  pginit(pgalloc);
 | 
			
		||||
  mpinit();        // collect info about this machine
 | 
			
		||||
  lapicinit(mpbcpu());
 | 
			
		||||
  seginit();       // set up segments
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +50,6 @@ mainc(void)
 | 
			
		|||
  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
 | 
			
		||||
  binit();         // buffer cache
 | 
			
		||||
| 
						 | 
				
			
			@ -57,25 +60,35 @@ mainc(void)
 | 
			
		|||
    timerinit();   // uniprocessor timer
 | 
			
		||||
  userinit();      // first user process
 | 
			
		||||
  bootothers();    // start other processors
 | 
			
		||||
 | 
			
		||||
  kvmalloc();      // new kernel page table wo. bottom mapped
 | 
			
		||||
  newpgdir = 1;
 | 
			
		||||
  // Finish setting up this processor in 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.
 | 
			
		||||
// Bootstrap CPU comes here from mainc().
 | 
			
		||||
// Other CPUs jump here from bootother.S.
 | 
			
		||||
static void
 | 
			
		||||
mpmain(void)
 | 
			
		||||
{
 | 
			
		||||
  if(cpunum() != mpbcpu()){
 | 
			
		||||
    seginit();
 | 
			
		||||
    lapicinit(cpunum());
 | 
			
		||||
  }
 | 
			
		||||
  vmenable();        // turn on paging
 | 
			
		||||
  cprintf("cpu%d: starting\n", cpu->id);
 | 
			
		||||
  idtinit();       // load idt register
 | 
			
		||||
  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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +104,7 @@ bootothers(void)
 | 
			
		|||
  // Write bootstrap code to unused memory at 0x7000.
 | 
			
		||||
  // The linker has placed the image of bootother.S in
 | 
			
		||||
  // _binary_bootother_start.
 | 
			
		||||
  code = (uchar*)0x7000;
 | 
			
		||||
  code = p2v(0x7000);
 | 
			
		||||
  memmove(code, _binary_bootother_start, (uint)_binary_bootother_size);
 | 
			
		||||
 | 
			
		||||
  for(c = cpus; c < cpus+ncpu; c++){
 | 
			
		||||
| 
						 | 
				
			
			@ -103,9 +116,9 @@ bootothers(void)
 | 
			
		|||
    // its first instruction.
 | 
			
		||||
    stack = kalloc();
 | 
			
		||||
    *(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()
 | 
			
		||||
    while(c->booted == 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								mmu.h
									
										
									
									
									
								
							
							
						
						
									
										8
									
								
								mmu.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -106,18 +106,10 @@ struct segdesc {
 | 
			
		|||
// construct linear address from indexes and offset
 | 
			
		||||
#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.
 | 
			
		||||
#define NPDENTRIES	1024		// page directory entries per page directory
 | 
			
		||||
#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 PDXSHIFT	22		// offset of PDX in a linear address
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								mp.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								mp.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -5,6 +5,7 @@
 | 
			
		|||
#include "types.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "param.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
#include "mp.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -39,6 +40,7 @@ mpsearch1(uchar *addr, int len)
 | 
			
		|||
{
 | 
			
		||||
  uchar *e, *p;
 | 
			
		||||
 | 
			
		||||
  addr = p2v((uint) addr);
 | 
			
		||||
  e = addr+len;
 | 
			
		||||
  for(p = addr; p < e; p += sizeof(struct mp))
 | 
			
		||||
    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)
 | 
			
		||||
    return 0;
 | 
			
		||||
  conf = (struct mpconf*)mp->physaddr;
 | 
			
		||||
  conf = (struct mpconf*) p2v((uint) mp->physaddr);
 | 
			
		||||
  if(memcmp(conf, "PCMP", 4) != 0)
 | 
			
		||||
    return 0;
 | 
			
		||||
  if(conf->version != 1 && conf->version != 4)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								multiboot.S
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								multiboot.S
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -15,6 +15,9 @@
 | 
			
		|||
# }
 | 
			
		||||
 | 
			
		||||
#include "asm.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
 | 
			
		||||
#define RELOC(x) ((x) - KERNBASE)    // same as V2P, but without casts
 | 
			
		||||
 | 
			
		||||
#define STACK 4096
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +45,7 @@ multiboot_header:
 | 
			
		|||
# boot loader - bootasm.S - sets up.
 | 
			
		||||
.globl multiboot_entry
 | 
			
		||||
multiboot_entry:
 | 
			
		||||
  lgdt gdtdesc
 | 
			
		||||
  lgdt RELOC(gdtdesc)
 | 
			
		||||
  ljmp $(SEG_KCODE<<3), $mbstart32
 | 
			
		||||
 | 
			
		||||
mbstart32:
 | 
			
		||||
| 
						 | 
				
			
			@ -65,11 +68,11 @@ spin:
 | 
			
		|||
.p2align 2                                # force 4 byte alignment
 | 
			
		||||
gdt:
 | 
			
		||||
  SEG_NULLASM                             # null seg
 | 
			
		||||
  SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)   # code seg
 | 
			
		||||
  SEG_ASM(STA_W, 0x0, 0xffffffff)         # data seg
 | 
			
		||||
  SEG_ASM(STA_X|STA_R, -KERNBASE, 0xffffffff)   # code seg
 | 
			
		||||
  SEG_ASM(STA_W, -KERNBASE, 0xffffffff)         # data seg
 | 
			
		||||
 | 
			
		||||
gdtdesc:
 | 
			
		||||
  .word   (gdtdesc - gdt - 1)             # sizeof(gdt) - 1
 | 
			
		||||
  .long   gdt                             # address gdt
 | 
			
		||||
  .long   RELOC(gdt)                      # address gdt
 | 
			
		||||
 | 
			
		||||
.comm stack, STACK
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								param.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								param.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -7,8 +7,6 @@
 | 
			
		|||
#define NINODE       50  // maximum number of active i-nodes
 | 
			
		||||
#define NDEV         10  // maximum major device number
 | 
			
		||||
#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 LOGSIZE      10  // size of log
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								proc.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
#include "types.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "param.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
#include "proc.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@
 | 
			
		|||
#include "defs.h"
 | 
			
		||||
#include "param.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "proc.h"
 | 
			
		||||
#include "spinlock.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +72,7 @@ getcallerpcs(void *v, uint pcs[])
 | 
			
		|||
  
 | 
			
		||||
  ebp = (uint*)v - 2;
 | 
			
		||||
  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;
 | 
			
		||||
    pcs[i] = ebp[1];     // saved %eip
 | 
			
		||||
    ebp = (uint*)ebp[0]; // saved %ebp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
#include "types.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "param.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "proc.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
#include "x86.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "param.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "proc.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								trap.c
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								trap.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
#include "types.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "param.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "proc.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										129
									
								
								vm.c
									
										
									
									
									
								
							
							
						
						
									
										129
									
								
								vm.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2,20 +2,71 @@
 | 
			
		|||
#include "types.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
#include "memlayout.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "proc.h"
 | 
			
		||||
#include "elf.h"
 | 
			
		||||
 | 
			
		||||
extern char data[];  // defined in data.S
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
void
 | 
			
		||||
kvmalloc(void)
 | 
			
		||||
 | 
			
		||||
// page map for during boot
 | 
			
		||||
// XXX build a static page table in assembly
 | 
			
		||||
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.
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +108,7 @@ walkpgdir(pde_t *pgdir, const void *va, int create)
 | 
			
		|||
 | 
			
		||||
  pde = &pgdir[PDX(va)];
 | 
			
		||||
  if(*pde & PTE_P){
 | 
			
		||||
    pgtab = (pte_t*)PTE_ADDR(*pde);
 | 
			
		||||
    pgtab = (pte_t*)p2v(PTE_ADDR(*pde));
 | 
			
		||||
  } else {
 | 
			
		||||
    if(!create || (pgtab = (pte_t*)kalloc()) == 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
 | 
			
		||||
    // be further restricted by the permissions in the page table 
 | 
			
		||||
    // 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)];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
// than its memory.
 | 
			
		||||
// 
 | 
			
		||||
//
 | 
			
		||||
// setupkvm() and exec() set up every page table like this:
 | 
			
		||||
//   0..640K          : user memory (text, data, stack, heap)
 | 
			
		||||
//   640K..1M         : mapped direct (for IO space)
 | 
			
		||||
//   1M..end          : mapped direct (for the kernel's text and data)
 | 
			
		||||
//   end..PHYSTOP     : mapped direct (kernel heap and user pages)
 | 
			
		||||
//   0..KERNBASE      : user memory (text, data, stack, heap), mapped to some phys mem
 | 
			
		||||
//   KERNBASE+640K..KERNBASE+1M: mapped to 640K..1M
 | 
			
		||||
//   KERNBASE+1M..KERNBASE+end : mapped to 1M..end
 | 
			
		||||
//   KERNBASE+end..KERBASE+PHYSTOP     : mapped to end..PHYSTOP (free memory)
 | 
			
		||||
//   0xfe000000..0    : mapped direct (devices such as ioapic)
 | 
			
		||||
//
 | 
			
		||||
// The kernel allocates memory for its heap and for user memory
 | 
			
		||||
// between kernend and the end of physical memory (PHYSTOP).
 | 
			
		||||
// The virtual address space of each user program includes the kernel
 | 
			
		||||
// (which is inaccessible in user mode).  The user program addresses
 | 
			
		||||
// range from 0 till 640KB (USERTOP), which where the I/O hole starts
 | 
			
		||||
// (both in physical memory and in the kernel's virtual address
 | 
			
		||||
// space).
 | 
			
		||||
// (which is inaccessible in user mode).  The user program sits in
 | 
			
		||||
// the bottom of the address space, and the kernel at the top at KERNBASE.
 | 
			
		||||
static struct kmap {
 | 
			
		||||
  void *p;
 | 
			
		||||
  void *e;
 | 
			
		||||
  void *l;
 | 
			
		||||
  uint p;
 | 
			
		||||
  uint e;
 | 
			
		||||
  int perm;
 | 
			
		||||
} kmap[] = {
 | 
			
		||||
  {(void*)USERTOP,    (void*)0x100000, PTE_W},  // I/O space
 | 
			
		||||
  {(void*)0x100000,   data,            0    },  // kernel text, rodata
 | 
			
		||||
  {data,              (void*)PHYSTOP,  PTE_W},  // kernel data, memory
 | 
			
		||||
  {(void*)0xFE000000, 0,               PTE_W},  // device mappings
 | 
			
		||||
  { (void *)IOSPACEB, IOSPACEB, IOSPACEE, PTE_W},  // I/O space
 | 
			
		||||
  { P2V(IOSPACEB), IOSPACEB, IOSPACEE, PTE_W},  // I/O space
 | 
			
		||||
  { (void *)KERNLINK, V2P(KERNLINK), V2P(data),  0},  // kernel text, rodata
 | 
			
		||||
  { 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.
 | 
			
		||||
| 
						 | 
				
			
			@ -142,12 +194,21 @@ setupkvm(void)
 | 
			
		|||
  memset(pgdir, 0, PGSIZE);
 | 
			
		||||
  k = kmap;
 | 
			
		||||
  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 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.
 | 
			
		||||
void
 | 
			
		||||
vmenable(void)
 | 
			
		||||
| 
						 | 
				
			
			@ -158,6 +219,16 @@ vmenable(void)
 | 
			
		|||
  cr0 = rcr0();
 | 
			
		||||
  cr0 |= CR0_PG;
 | 
			
		||||
  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,
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +236,7 @@ vmenable(void)
 | 
			
		|||
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.
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +251,7 @@ switchuvm(struct proc *p)
 | 
			
		|||
  ltr(SEG_TSS << 3);
 | 
			
		||||
  if(p->pgdir == 0)
 | 
			
		||||
    panic("switchuvm: no pgdir");
 | 
			
		||||
  lcr3(PADDR(p->pgdir));  // switch to new address space
 | 
			
		||||
  lcr3(v2p(p->pgdir));  // switch to new address space
 | 
			
		||||
  popcli();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -195,7 +266,7 @@ inituvm(pde_t *pgdir, char *init, uint sz)
 | 
			
		|||
    panic("inituvm: more than a page");
 | 
			
		||||
  mem = kalloc();
 | 
			
		||||
  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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -245,7 +316,7 @@ allocuvm(pde_t *pgdir, uint oldsz, uint newsz)
 | 
			
		|||
      return 0;
 | 
			
		||||
    }
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -289,7 +360,7 @@ freevm(pde_t *pgdir)
 | 
			
		|||
  deallocuvm(pgdir, USERTOP, 0);
 | 
			
		||||
  for(i = 0; i < NPDENTRIES; i++){
 | 
			
		||||
    if(pgdir[i] & PTE_P)
 | 
			
		||||
      kfree((char*)PTE_ADDR(pgdir[i]));
 | 
			
		||||
      kfree(p2v(PTE_ADDR(pgdir[i])));
 | 
			
		||||
  }
 | 
			
		||||
  kfree((char*)pgdir);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -315,7 +386,7 @@ copyuvm(pde_t *pgdir, uint sz)
 | 
			
		|||
    if((mem = kalloc()) == 0)
 | 
			
		||||
      goto bad;
 | 
			
		||||
    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;
 | 
			
		||||
  }
 | 
			
		||||
  return d;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										24
									
								
								x86.h
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								x86.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -96,6 +96,30 @@ loadgs(ushort 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
 | 
			
		||||
rebp(void)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue