diff options
author | Mole Shang <[email protected]> | 2024-02-16 10:20:27 +0800 |
---|---|---|
committer | Mole Shang <[email protected]> | 2024-02-16 10:20:27 +0800 |
commit | a98c56a811142e5ede3332a7a444cca45f628769 (patch) | |
tree | c93ff7090da7b6ef911932be283818c2f6a03784 /kernel/vm.c | |
parent | 0d65be5d1d880afafbf08c2adb605cf9f72216e2 (diff) | |
parent | 99015f3a985b2fd051606636743a2a2969b216e8 (diff) | |
download | xv6-labs-a98c56a811142e5ede3332a7a444cca45f628769.tar.gz xv6-labs-a98c56a811142e5ede3332a7a444cca45f628769.tar.bz2 xv6-labs-a98c56a811142e5ede3332a7a444cca45f628769.zip |
Merge branch 'lock' into thread
Conflicts:
.gitignore
Makefile
conf/lab.mk
Diffstat (limited to 'kernel/vm.c')
-rw-r--r-- | kernel/vm.c | 85 |
1 files changed, 65 insertions, 20 deletions
diff --git a/kernel/vm.c b/kernel/vm.c index 5c31e87..be7d042 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -4,6 +4,8 @@ #include "elf.h" #include "riscv.h" #include "defs.h" +#include "spinlock.h" +#include "proc.h" #include "fs.h" /* @@ -30,6 +32,14 @@ kvmmake(void) // virtio mmio disk interface kvmmap(kpgtbl, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W); +#ifdef LAB_NET + // PCI-E ECAM (configuration space), for pci.c + kvmmap(kpgtbl, 0x30000000L, 0x30000000L, 0x10000000, PTE_R | PTE_W); + + // pci.c maps the e1000's registers here. + kvmmap(kpgtbl, 0x40000000L, 0x40000000L, 0x20000, PTE_R | PTE_W); +#endif + // PLIC kvmmap(kpgtbl, PLIC, PLIC, 0x400000, PTE_R | PTE_W); @@ -136,9 +146,8 @@ kvmmap(pagetable_t kpgtbl, uint64 va, uint64 pa, uint64 sz, int perm) } // Create PTEs for virtual addresses starting at va that refer to -// physical addresses starting at pa. -// va and size MUST be page-aligned. -// Returns 0 on success, -1 if walk() couldn't +// physical addresses starting at pa. va and size might not +// be page-aligned. Returns 0 on success, -1 if walk() couldn't // allocate a needed page-table page. int mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm) @@ -146,17 +155,11 @@ mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm) uint64 a, last; pte_t *pte; - if((va % PGSIZE) != 0) - panic("mappages: va not aligned"); - - if((size % PGSIZE) != 0) - panic("mappages: size not aligned"); - if(size == 0) panic("mappages: size"); - a = va; - last = va + size - PGSIZE; + a = PGROUNDDOWN(va); + last = PGROUNDDOWN(va + size - 1); for(;;){ if((pte = walk(pagetable, a, 1)) == 0) return -1; @@ -186,8 +189,10 @@ uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free) for(a = va; a < va + npages*PGSIZE; a += PGSIZE){ if((pte = walk(pagetable, a, 0)) == 0) panic("uvmunmap: walk"); - if((*pte & PTE_V) == 0) + if((*pte & PTE_V) == 0) { + printf("va=%p pte=%p\n", a, *pte); panic("uvmunmap: not mapped"); + } if(PTE_FLAGS(*pte) == PTE_V) panic("uvmunmap: not a leaf"); if(do_free){ @@ -315,20 +320,26 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz) pte_t *pte; uint64 pa, i; uint flags; - char *mem; + // char *mem; for(i = 0; i < sz; i += PGSIZE){ if((pte = walk(old, i, 0)) == 0) panic("uvmcopy: pte should exist"); if((*pte & PTE_V) == 0) panic("uvmcopy: page not present"); - pa = PTE2PA(*pte); - flags = PTE_FLAGS(*pte); + // do not do the actual copy, just increase the refcnt and mark pages readonly COW + /* if((mem = kalloc()) == 0) goto err; memmove(mem, (char*)pa, PGSIZE); - if(mappages(new, i, PGSIZE, (uint64)mem, flags) != 0){ - kfree(mem); + */ + *pte &= ~PTE_W; + *pte |= PTE_C; + pa = PTE2PA(*pte); + refcnt_inc(pa); + flags = PTE_FLAGS(*pte); + if(mappages(new, i, PGSIZE, (uint64)pa, flags) != 0){ + // kfree(mem); goto err; } } @@ -359,17 +370,24 @@ int copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len) { uint64 n, va0, pa0; - pte_t *pte; + // pte_t *pte; while(len > 0){ va0 = PGROUNDDOWN(dstva); - if(va0 >= MAXVA) + + if(cow_handler(pagetable, va0) < 0) return -1; + + /* pte = walk(pagetable, va0, 0); if(pte == 0 || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0 || (*pte & PTE_W) == 0) return -1; pa0 = PTE2PA(*pte); + */ + pa0 = walkaddr(pagetable, va0); + if(pa0 == 0) + return -1; n = PGSIZE - (dstva - va0); if(n > len) n = len; @@ -389,7 +407,7 @@ int copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len) { uint64 n, va0, pa0; - + while(len > 0){ va0 = PGROUNDDOWN(srcva); pa0 = walkaddr(pagetable, va0); @@ -449,3 +467,30 @@ copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max) return -1; } } + +static void +walkprint(pagetable_t pgtbl, int level) +{ + for(int i = 0; i < 512; i++){ + pte_t pte = pgtbl[i]; + if(pte & PTE_V){ + for(int j = 0; j < level; j++){ + printf(" .."); + } + printf("%d: pte %p pa %p\n", i, pte, PTE2PA(pte)); + if((pte & (PTE_R|PTE_W|PTE_X)) == 0){ + // this PTE points to a lower-level page table. + walkprint((pagetable_t)PTE2PA(pte), level+1); + } + } + } +} + +// Print the contents of a page table +void +vmprint(pagetable_t pgtbl) +{ + printf("page table %p\n", pgtbl); + + walkprint(pgtbl, 1); +} |