diff options
-rw-r--r-- | answers-pgtbl.txt | 0 | ||||
-rw-r--r-- | kernel/defs.h | 2 | ||||
-rw-r--r-- | kernel/exec.c | 4 | ||||
-rw-r--r-- | kernel/proc.c | 45 | ||||
-rw-r--r-- | kernel/proc.h | 1 | ||||
-rw-r--r-- | kernel/riscv.h | 1 | ||||
-rw-r--r-- | kernel/syscall.c | 7 | ||||
-rw-r--r-- | kernel/syscall.h | 2 | ||||
-rw-r--r-- | kernel/sysproc.c | 10 | ||||
-rw-r--r-- | kernel/vm.c | 27 | ||||
-rw-r--r-- | time.txt | 2 | ||||
-rwxr-xr-x | user/usys.pl | 4 |
12 files changed, 97 insertions, 8 deletions
diff --git a/answers-pgtbl.txt b/answers-pgtbl.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/answers-pgtbl.txt diff --git a/kernel/defs.h b/kernel/defs.h index c8eeef3..bd85d1f 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -109,6 +109,7 @@ int either_copyout(int user_dst, uint64 dst, void *src, uint64 len); int either_copyin(void *dst, int user_src, uint64 src, uint64 len); void procdump(void); int get_nproc(void); +int pgaccess(uint64 base, int len, uint64 mask); // swtch.S void swtch(struct context*, struct context*); @@ -179,6 +180,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..35b35f5 100644 --- a/kernel/exec.c +++ b/kernel/exec.c @@ -128,6 +128,10 @@ 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/proc.c b/kernel/proc.c index 5aa616f..3d215a5 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -132,6 +132,14 @@ found: return 0; } + // Allocate a usyscall page and fill pid. + if((p->usyscall = (struct usyscall *)kalloc()) == 0){ + freeproc(p); + release(&p->lock); + return 0; + } + p->usyscall->pid = p->pid; + // An empty user page table. p->pagetable = proc_pagetable(p); if(p->pagetable == 0){ @@ -158,6 +166,9 @@ freeproc(struct proc *p) if(p->trapframe) kfree((void*)p->trapframe); p->trapframe = 0; + if(p->usyscall) + kfree((void*)p->usyscall); + p->usyscall = 0; if(p->pagetable) proc_freepagetable(p->pagetable, p->sz); p->pagetable = 0; @@ -172,7 +183,7 @@ freeproc(struct proc *p) } // Create a user page table for a given process, with no user memory, -// but with trampoline and trapframe pages. +// but with trampoline, trapframe and usyscall pages. pagetable_t proc_pagetable(struct proc *p) { @@ -202,6 +213,14 @@ proc_pagetable(struct proc *p) return 0; } + // map the usyscall page below the trapframe page, for + // ugetpid(). + if(mappages(pagetable, USYSCALL, PGSIZE, + (uint64)(p->usyscall), PTE_R | PTE_U) < 0){ + uvmunmap(pagetable, USYSCALL, 1, 0); + uvmfree(pagetable, 0); + return 0; + } return pagetable; } @@ -212,6 +231,7 @@ proc_freepagetable(pagetable_t pagetable, uint64 sz) { uvmunmap(pagetable, TRAMPOLINE, 1, 0); uvmunmap(pagetable, TRAPFRAME, 1, 0); + uvmunmap(pagetable, USYSCALL, 1, 0); uvmfree(pagetable, sz); } @@ -706,3 +726,26 @@ get_nproc(void) return n; } + +// lab pagetable: report which pages have been accessed (r/w) +// according to PTE_A and store it in a bit mask (3rd param) +int +pgaccess(uint64 base, int len, uint64 mask_addr) +{ + struct proc *p = myproc(); + pagetable_t pgtbl = p->pagetable; + pte_t *pte; + int mask = 0; + + // iterater thru pages + for(int i = 0; i < len; i++) { + pte = walk(pgtbl, base + i * PGSIZE, 0); + if(*pte & PTE_A) { + *pte &= (~PTE_A); // clear PTE_A to avoid setting it forever + mask |= (1L << i); + } + } + + // now copyout the mask to user memory + return copyout(pgtbl, mask_addr, (char *)&mask, sizeof(mask)); +} diff --git a/kernel/proc.h b/kernel/proc.h index 4a2ca6c..c816ae2 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -101,6 +101,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 diff --git a/kernel/riscv.h b/kernel/riscv.h index 20a01db..33fa9ee 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) // riscv access bit // shift a physical address to the right place for a PTE. #define PA2PTE(pa) ((((uint64)pa) >> 12) << 10) diff --git a/kernel/syscall.c b/kernel/syscall.c index 4907f0f..394b980 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -168,6 +168,12 @@ static char *syscall_names[] = { [SYS_link] "link", [SYS_mkdir] "mkdir", [SYS_close] "close", +#ifdef LAB_NET +[SYS_connect] "connect", +#endif +#ifdef LAB_PGTBL +[SYS_pgaccess] "pgaccess", +#endif [SYS_trace] "trace", [SYS_sysinfo] "sysinfo", }; @@ -198,3 +204,4 @@ syscall(void) p->trapframe->a0 = -1; } } + diff --git a/kernel/syscall.h b/kernel/syscall.h index d930252..8da572e 100644 --- a/kernel/syscall.h +++ b/kernel/syscall.h @@ -31,5 +31,3 @@ #define SYS_munmap 28 #define SYS_connect 29 #define SYS_pgaccess 30 -#define SYS_trace 22 -#define SYS_sysinfo 23 diff --git a/kernel/sysproc.c b/kernel/sysproc.c index 4cf0697..bd9d0f0 100644 --- a/kernel/sysproc.c +++ b/kernel/sysproc.c @@ -74,8 +74,14 @@ sys_sleep(void) int sys_pgaccess(void) { - // lab pgtbl: your code here. - return 0; + uint64 base, mask; + int len; + + + argaddr(0, &base); + argint(1, &len); + argaddr(2, &mask); + return pgaccess(base, len, mask); } #endif diff --git a/kernel/vm.c b/kernel/vm.c index 5c31e87..9c17fe7 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -449,3 +449,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); +} @@ -1 +1 @@ -4 +3 diff --git a/user/usys.pl b/user/usys.pl index 9a93999..f084c63 100755 --- a/user/usys.pl +++ b/user/usys.pl @@ -36,7 +36,7 @@ entry("getpid"); entry("sbrk"); entry("sleep"); entry("uptime"); -entry("connect"); -entry("pgaccess"); entry("trace"); entry("sysinfo"); +entry("connect"); +entry("pgaccess"); |