summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/defs.h2
-rw-r--r--kernel/exec.c4
-rw-r--r--kernel/proc.c45
-rw-r--r--kernel/proc.h1
-rw-r--r--kernel/riscv.h1
-rw-r--r--kernel/syscall.c7
-rw-r--r--kernel/syscall.h2
-rw-r--r--kernel/sysproc.c10
-rw-r--r--kernel/vm.c27
9 files changed, 94 insertions, 5 deletions
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);
+}