pagetable lab initialized
This commit is contained in:
79
kernel/vm.c
79
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,8 +32,16 @@ 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);
|
||||
kvmmap(kpgtbl, PLIC, PLIC, 0x4000000, PTE_R | PTE_W);
|
||||
|
||||
// map kernel text executable and read-only.
|
||||
kvmmap(kpgtbl, KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X);
|
||||
@@ -92,6 +102,11 @@ walk(pagetable_t pagetable, uint64 va, int alloc)
|
||||
pte_t *pte = &pagetable[PX(level, va)];
|
||||
if(*pte & PTE_V) {
|
||||
pagetable = (pagetable_t)PTE2PA(*pte);
|
||||
#ifdef LAB_PGTBL
|
||||
if(PTE_LEAF(*pte)) {
|
||||
return pte;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if(!alloc || (pagetable = (pde_t*)kalloc()) == 0)
|
||||
return 0;
|
||||
@@ -125,6 +140,7 @@ walkaddr(pagetable_t pagetable, uint64 va)
|
||||
return pa;
|
||||
}
|
||||
|
||||
|
||||
// add a mapping to the kernel page table.
|
||||
// only used when booting.
|
||||
// does not flush TLB or enable paging.
|
||||
@@ -179,15 +195,19 @@ uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free)
|
||||
{
|
||||
uint64 a;
|
||||
pte_t *pte;
|
||||
int sz;
|
||||
|
||||
if((va % PGSIZE) != 0)
|
||||
panic("uvmunmap: not aligned");
|
||||
|
||||
for(a = va; a < va + npages*PGSIZE; a += PGSIZE){
|
||||
for(a = va; a < va + npages*PGSIZE; a += sz){
|
||||
sz = PGSIZE;
|
||||
if((pte = walk(pagetable, a, 0)) == 0)
|
||||
panic("uvmunmap: walk");
|
||||
if((*pte & PTE_V) == 0)
|
||||
if((*pte & PTE_V) == 0) {
|
||||
printf("va=%ld pte=%ld\n", a, *pte);
|
||||
panic("uvmunmap: not mapped");
|
||||
}
|
||||
if(PTE_FLAGS(*pte) == PTE_V)
|
||||
panic("uvmunmap: not a leaf");
|
||||
if(do_free){
|
||||
@@ -227,6 +247,7 @@ uvmfirst(pagetable_t pagetable, uchar *src, uint sz)
|
||||
memmove(mem, src, sz);
|
||||
}
|
||||
|
||||
|
||||
// Allocate PTEs and physical memory to grow process from oldsz to
|
||||
// newsz, which need not be page aligned. Returns new size or 0 on error.
|
||||
uint64
|
||||
@@ -234,19 +255,23 @@ uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int xperm)
|
||||
{
|
||||
char *mem;
|
||||
uint64 a;
|
||||
int sz;
|
||||
|
||||
if(newsz < oldsz)
|
||||
return oldsz;
|
||||
|
||||
oldsz = PGROUNDUP(oldsz);
|
||||
for(a = oldsz; a < newsz; a += PGSIZE){
|
||||
for(a = oldsz; a < newsz; a += sz){
|
||||
sz = PGSIZE;
|
||||
mem = kalloc();
|
||||
if(mem == 0){
|
||||
uvmdealloc(pagetable, a, oldsz);
|
||||
return 0;
|
||||
}
|
||||
memset(mem, 0, PGSIZE);
|
||||
if(mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_R|PTE_U|xperm) != 0){
|
||||
#ifndef LAB_SYSCALL
|
||||
memset(mem, 0, sz);
|
||||
#endif
|
||||
if(mappages(pagetable, a, sz, (uint64)mem, PTE_R|PTE_U|xperm) != 0){
|
||||
kfree(mem);
|
||||
uvmdealloc(pagetable, a, oldsz);
|
||||
return 0;
|
||||
@@ -316,8 +341,11 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
|
||||
uint64 pa, i;
|
||||
uint flags;
|
||||
char *mem;
|
||||
int szinc;
|
||||
|
||||
for(i = 0; i < sz; i += PGSIZE){
|
||||
for(i = 0; i < sz; i += szinc){
|
||||
szinc = PGSIZE;
|
||||
szinc = PGSIZE;
|
||||
if((pte = walk(old, i, 0)) == 0)
|
||||
panic("uvmcopy: pte should exist");
|
||||
if((*pte & PTE_V) == 0)
|
||||
@@ -363,13 +391,21 @@ copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
|
||||
|
||||
while(len > 0){
|
||||
va0 = PGROUNDDOWN(dstva);
|
||||
if(va0 >= MAXVA)
|
||||
if (va0 >= MAXVA)
|
||||
return -1;
|
||||
pte = walk(pagetable, va0, 0);
|
||||
if(pte == 0 || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0 ||
|
||||
(*pte & PTE_W) == 0)
|
||||
if((pte = walk(pagetable, va0, 0)) == 0) {
|
||||
// printf("copyout: pte should exist 0x%x %d\n", dstva, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// forbid copyout over read-only user text pages.
|
||||
if((*pte & PTE_W) == 0)
|
||||
return -1;
|
||||
|
||||
pa0 = walkaddr(pagetable, va0);
|
||||
if(pa0 == 0)
|
||||
return -1;
|
||||
pa0 = PTE2PA(*pte);
|
||||
n = PGSIZE - (dstva - va0);
|
||||
if(n > len)
|
||||
n = len;
|
||||
@@ -389,7 +425,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 +485,20 @@ copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef LAB_PGTBL
|
||||
void
|
||||
vmprint(pagetable_t pagetable) {
|
||||
// your code here
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef LAB_PGTBL
|
||||
pte_t*
|
||||
pgpte(pagetable_t pagetable, uint64 va) {
|
||||
return walk(pagetable, va, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user