diff options
| author | Frans Kaashoek <kaashoek@Frans-Kaashoeks-MacBook-Pro.local> | 2011-07-29 07:31:27 -0400 | 
|---|---|---|
| committer | Frans Kaashoek <kaashoek@Frans-Kaashoeks-MacBook-Pro.local> | 2011-07-29 07:31:27 -0400 | 
| commit | 9aa0337dc1452a911ac52698c833246a618fc9f3 (patch) | |
| tree | 28e25817d4f7c9f7f1e6988949012f46d6c28fb7 | |
| parent | dccb915282854476ce47752df6631dcce3b8f661 (diff) | |
| download | xv6-labs-9aa0337dc1452a911ac52698c833246a618fc9f3.tar.gz xv6-labs-9aa0337dc1452a911ac52698c833246a618fc9f3.tar.bz2 xv6-labs-9aa0337dc1452a911ac52698c833246a618fc9f3.zip | |
Map kernel high
Very important to give qemu memory through PHYSTOP :(
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | bootmain.c | 11 | ||||
| -rw-r--r-- | bootother.S | 14 | ||||
| -rw-r--r-- | console.c | 6 | ||||
| -rw-r--r-- | defs.h | 2 | ||||
| -rw-r--r-- | exec.c | 1 | ||||
| -rw-r--r-- | ide.c | 1 | ||||
| -rw-r--r-- | kalloc.c | 22 | ||||
| -rw-r--r-- | main.c | 33 | ||||
| -rw-r--r-- | mmu.h | 8 | ||||
| -rw-r--r-- | mp.c | 4 | ||||
| -rw-r--r-- | multiboot.S | 11 | ||||
| -rw-r--r-- | param.h | 2 | ||||
| -rw-r--r-- | proc.c | 1 | ||||
| -rw-r--r-- | spinlock.c | 3 | ||||
| -rw-r--r-- | syscall.c | 1 | ||||
| -rw-r--r-- | sysproc.c | 1 | ||||
| -rw-r--r-- | trap.c | 1 | ||||
| -rw-r--r-- | vm.c | 127 | ||||
| -rw-r--r-- | x86.h | 24 | 
20 files changed, 207 insertions, 70 deletions
| @@ -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) @@ -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();  } diff --git a/bootother.S b/bootother.S index 37b899b..2c97207 100644 --- a/bootother.S +++ b/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) @@ -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,5 +1,6 @@  #include "types.h"  #include "param.h" +#include "memlayout.h"  #include "mmu.h"  #include "proc.h"  #include "defs.h" @@ -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" @@ -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;  } @@ -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,7 +60,8 @@ 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();  } @@ -66,16 +70,25 @@ mainc(void)  // Bootstrap CPU comes here from mainc().  // Other CPUs jump here from bootother.S.  static void -mpmain(void) +mpboot(void)  { -  if(cpunum() != mpbcpu()){ -    seginit(); -    lapicinit(cpunum()); -  }    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) +{    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) @@ -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 @@ -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) diff --git a/multiboot.S b/multiboot.S index 2579b6d..84ab638 100644 --- a/multiboot.S +++ b/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 @@ -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,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,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,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. + +// page map for during boot +// XXX build a static page table in assembly +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 -kvmalloc(void) +pginit(char* (*alloc)(void))  { -  kpgdir = setupkvm(); +  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; @@ -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)  { | 
