Lab pgtbl

tags: 6.1810

Speed up system calls

diff --git a/kernel/proc.c b/kernel/proc.c index 959b778..72068b2 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -132,6 +132,13 @@ found: return 0; } + // Allocate a usyscall page. + if ((p->usyscall = (struct usyscall *)kalloc()) == 0) { + freeproc(p); + release(&p->lock); + return 0; + } + // An empty user page table. p->pagetable = proc_pagetable(p); if(p->pagetable == 0){ @@ -145,6 +152,7 @@ found: memset(&p->context, 0, sizeof(p->context)); p->context.ra = (uint64)forkret; p->context.sp = p->kstack + PGSIZE; + p->usyscall->pid = p->pid; return p; } @@ -155,6 +163,9 @@ found: static void freeproc(struct proc *p) { + if (p->usyscall) + kfree((void*)p->usyscall); + p->usyscall = 0; if(p->trapframe) kfree((void*)p->trapframe); p->trapframe = 0; @@ -202,6 +213,15 @@ proc_pagetable(struct proc *p) return 0; } + // map the usyscall page just below the trapframe page + if (mappages(pagetable, USYSCALL, PGSIZE, + (uint64)(p->usyscall), PTE_R | PTE_U) < 0) { + uvmunmap(pagetable, TRAPFRAME, 1, 0); + uvmunmap(pagetable, TRAMPOLINE, 1, 0); + uvmfree(pagetable, 0); + return 0; + } + return pagetable; } @@ -210,6 +230,7 @@ proc_pagetable(struct proc *p) void proc_freepagetable(pagetable_t pagetable, uint64 sz) { + uvmunmap(pagetable, USYSCALL, 1, 0); uvmunmap(pagetable, TRAMPOLINE, 1, 0); uvmunmap(pagetable, TRAPFRAME, 1, 0); uvmfree(pagetable, sz); diff --git a/kernel/proc.h b/kernel/proc.h index d021857..ef84dd1 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -100,6 +100,7 @@ struct proc { uint64 sz; // Size of process memory (bytes) pagetable_t pagetable; // User page table struct trapframe *trapframe; // data page for trampoline.S + struct usyscall *usyscall; // data page for usyscall struct context context; // swtch() here to run process struct file *ofile[NOFILE]; // Open files struct inode *cwd; // Current directory

Print a page table

diff --git a/kernel/defs.h b/kernel/defs.h index a3c962b..487f4f2 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -173,6 +173,7 @@ uint64 walkaddr(pagetable_t, uint64); int copyout(pagetable_t, uint64, char *, uint64); int copyin(pagetable_t, char *, uint64, uint64); int copyinstr(pagetable_t, char *, uint64, uint64); +void vmprint(pagetable_t); // plic.c void plicinit(void); diff --git a/kernel/exec.c b/kernel/exec.c index e18bbb6..89d5d7c 100644 --- a/kernel/exec.c +++ b/kernel/exec.c @@ -128,6 +128,8 @@ exec(char *path, char **argv) p->trapframe->sp = sp; // initial stack pointer proc_freepagetable(oldpagetable, oldsz); + if (p->pid == 1) + vmprint(p->pagetable); return argc; // this ends up in a0, the first argument to main(argc, argv) bad: diff --git a/kernel/vm.c b/kernel/vm.c index 9f69783..268236d 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -437,3 +437,37 @@ copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max) return -1; } } + +void +printpte(pte_t pte, int index, int level) +{ + for (int i = level; i >= 0; i--) + printf(" .."); + printf("%d: pte %p pa %p\n", index, pte, PTE2PA(pte)); +} + +void +_vmprint(pagetable_t pagetable, int level) +{ + for (int i = 0; i < 512; i++) { + pte_t pte = pagetable[i]; + if(pte & PTE_V) { + printpte(pte, i, level); + if ((pte & (PTE_R|PTE_W|PTE_X)) == 0) { + // this PTE points to a lower-level page table. + uint64 child = PTE2PA(pte); + _vmprint((pagetable_t)child, level + 1); + } + } + } +} + +void +vmprint(pagetable_t pagetable) +{ + printf("page table 0x%16x\n", (uint64)pagetable); + _vmprint(pagetable, 0); +}

Detect which pages have been accessed

diff --git a/kernel/riscv.h b/kernel/riscv.h index 20a01db..efbb6f5 100644 --- a/kernel/riscv.h +++ b/kernel/riscv.h @@ -343,6 +343,7 @@ typedef uint64 *pagetable_t; // 512 PTEs #define PTE_W (1L << 2) #define PTE_X (1L << 3) #define PTE_U (1L << 4) // user can access +#define PTE_A (1L << 6) // access bit // shift a physical address to the right place for a PTE. #define PA2PTE(pa) ((((uint64)pa) >> 12) << 10) diff --git a/kernel/sysproc.c b/kernel/sysproc.c index 88644b2..0948503 100644 --- a/kernel/sysproc.c +++ b/kernel/sysproc.c @@ -75,6 +75,34 @@ int sys_pgaccess(void) { // lab pgtbl: your code here. + uint64 va, addr; + int size; + + argaddr(0, &va); + argint(1, &size); + argaddr(2, &addr); + + struct proc *proc = myproc(); + pagetable_t pagetable = proc->pagetable; + uint64 a, last; + pte_t *pte; + unsigned int abits = 0; + + if(size == 0) + panic("pgaccess: size"); + + a = PGROUNDDOWN(va); + last = PGROUNDDOWN(va + size * PGSIZE - 1); + last = last > MAXVA ? MAXVA : last; + for (unsigned i = 0; i < 32 && a <= last; i++, a += PGSIZE) { + if((pte = walk(pagetable, a, 0)) == 0) + continue; + if(*pte & PTE_A) { + abits |= (1 << i); + *pte &= ~PTE_A; + } + } + + copyout(pagetable, addr, (char *)&abits, sizeof(abits)); return 0; } #endif