From 18998096701a1d4695b2097006d7afc2a539bd89 Mon Sep 17 00:00:00 2001
From: Robert Morris <rtm@csail.mit.edu>
Date: Fri, 8 Sep 2023 09:24:27 -0400
Subject: 3rd lab

---
 kernel/memlayout.h | 17 ++++++++++++++++-
 kernel/syscall.c   | 15 +++++++++++++++
 kernel/syscall.h   | 11 +++++++++++
 kernel/sysproc.c   | 15 ++++++++++++---
 4 files changed, 54 insertions(+), 4 deletions(-)

(limited to 'kernel')

diff --git a/kernel/memlayout.h b/kernel/memlayout.h
index cac3cb1..74d2fd4 100644
--- a/kernel/memlayout.h
+++ b/kernel/memlayout.h
@@ -25,6 +25,10 @@
 #define VIRTIO0 0x10001000
 #define VIRTIO0_IRQ 1
 
+#ifdef LAB_NET
+#define E1000_IRQ 33
+#endif
+
 // core local interruptor (CLINT), which contains the timer.
 #define CLINT 0x2000000L
 #define CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 8*(hartid))
@@ -34,8 +38,11 @@
 #define PLIC 0x0c000000L
 #define PLIC_PRIORITY (PLIC + 0x0)
 #define PLIC_PENDING (PLIC + 0x1000)
+#define PLIC_MENABLE(hart) (PLIC + 0x2000 + (hart)*0x100)
 #define PLIC_SENABLE(hart) (PLIC + 0x2080 + (hart)*0x100)
+#define PLIC_MPRIORITY(hart) (PLIC + 0x200000 + (hart)*0x2000)
 #define PLIC_SPRIORITY(hart) (PLIC + 0x201000 + (hart)*0x2000)
+#define PLIC_MCLAIM(hart) (PLIC + 0x200004 + (hart)*0x2000)
 #define PLIC_SCLAIM(hart) (PLIC + 0x201004 + (hart)*0x2000)
 
 // the kernel expects there to be RAM
@@ -50,7 +57,7 @@
 
 // map kernel stacks beneath the trampoline,
 // each surrounded by invalid guard pages.
-#define KSTACK(p) (TRAMPOLINE - ((p)+1)* 2*PGSIZE)
+#define KSTACK(p) (TRAMPOLINE - (p)*2*PGSIZE - 3*PGSIZE)
 
 // User memory layout.
 // Address zero first:
@@ -59,6 +66,14 @@
 //   fixed-size stack
 //   expandable heap
 //   ...
+//   USYSCALL (shared with kernel)
 //   TRAPFRAME (p->trapframe, used by the trampoline)
 //   TRAMPOLINE (the same page as in the kernel)
 #define TRAPFRAME (TRAMPOLINE - PGSIZE)
+#ifdef LAB_PGTBL
+#define USYSCALL (TRAPFRAME - PGSIZE)
+
+struct usyscall {
+  int pid;  // Process ID
+};
+#endif
diff --git a/kernel/syscall.c b/kernel/syscall.c
index ed65409..beea0ef 100644
--- a/kernel/syscall.c
+++ b/kernel/syscall.c
@@ -102,6 +102,13 @@ extern uint64 sys_link(void);
 extern uint64 sys_mkdir(void);
 extern uint64 sys_close(void);
 
+#ifdef LAB_NET
+extern uint64 sys_connect(void);
+#endif
+#ifdef LAB_PGTBL
+extern uint64 sys_pgaccess(void);
+#endif
+
 // An array mapping syscall numbers from syscall.h
 // to the function that handles the system call.
 static uint64 (*syscalls[])(void) = {
@@ -126,8 +133,16 @@ static uint64 (*syscalls[])(void) = {
 [SYS_link]    sys_link,
 [SYS_mkdir]   sys_mkdir,
 [SYS_close]   sys_close,
+#ifdef LAB_NET
+[SYS_connect] sys_connect,
+#endif
+#ifdef LAB_PGTBL
+[SYS_pgaccess] sys_pgaccess,
+#endif
 };
 
+
+
 void
 syscall(void)
 {
diff --git a/kernel/syscall.h b/kernel/syscall.h
index bc5f356..8da572e 100644
--- a/kernel/syscall.h
+++ b/kernel/syscall.h
@@ -20,3 +20,14 @@
 #define SYS_link   19
 #define SYS_mkdir  20
 #define SYS_close  21
+
+// System calls for labs
+#define SYS_trace     22
+#define SYS_sysinfo   23
+#define SYS_sigalarm  24
+#define SYS_sigreturn 25
+#define SYS_symlink   26
+#define SYS_mmap      27
+#define SYS_munmap    28
+#define SYS_connect   29
+#define SYS_pgaccess  30
diff --git a/kernel/sysproc.c b/kernel/sysproc.c
index 3b4d5bd..88644b2 100644
--- a/kernel/sysproc.c
+++ b/kernel/sysproc.c
@@ -1,7 +1,7 @@
 #include "types.h"
 #include "riscv.h"
-#include "defs.h"
 #include "param.h"
+#include "defs.h"
 #include "memlayout.h"
 #include "spinlock.h"
 #include "proc.h"
@@ -54,9 +54,8 @@ sys_sleep(void)
   int n;
   uint ticks0;
 
+
   argint(0, &n);
-  if(n < 0)
-    n = 0;
   acquire(&tickslock);
   ticks0 = ticks;
   while(ticks - ticks0 < n){
@@ -70,6 +69,16 @@ sys_sleep(void)
   return 0;
 }
 
+
+#ifdef LAB_PGTBL
+int
+sys_pgaccess(void)
+{
+  // lab pgtbl: your code here.
+  return 0;
+}
+#endif
+
 uint64
 sys_kill(void)
 {
-- 
cgit v1.2.3


From 283d5ab4c964ab525e45fcade06d6fd7e977c43e Mon Sep 17 00:00:00 2001
From: Mole Shang <135e2@135e2.dev>
Date: Thu, 18 Jan 2024 17:35:27 +0800
Subject: lab syscall: finish

Conflicts:
	kernel/syscall.c
	kernel/syscall.h
	user/user.h
	user/usys.pl
---
 kernel/defs.h    |  6 ++++++
 kernel/kalloc.c  | 14 ++++++++++++++
 kernel/proc.c    | 20 ++++++++++++++++++++
 kernel/proc.h    |  1 +
 kernel/syscall.c | 38 ++++++++++++++++++++++++++++++++++++++
 kernel/syscall.h |  2 ++
 kernel/sysinfo.c | 24 ++++++++++++++++++++++++
 kernel/sysinfo.h |  4 ++++
 kernel/sysproc.c | 18 ++++++++++++++++++
 9 files changed, 127 insertions(+)
 create mode 100644 kernel/sysinfo.c
 create mode 100644 kernel/sysinfo.h

(limited to 'kernel')

diff --git a/kernel/defs.h b/kernel/defs.h
index a3c962b..c8eeef3 100644
--- a/kernel/defs.h
+++ b/kernel/defs.h
@@ -8,6 +8,7 @@ struct spinlock;
 struct sleeplock;
 struct stat;
 struct superblock;
+struct sysinfo;
 
 // bio.c
 void            binit(void);
@@ -63,6 +64,7 @@ void            ramdiskrw(struct buf*);
 void*           kalloc(void);
 void            kfree(void *);
 void            kinit(void);
+int             get_freemem(void);
 
 // log.c
 void            initlog(int, struct superblock*);
@@ -106,6 +108,7 @@ void            yield(void);
 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);
 
 // swtch.S
 void            swtch(struct context*, struct context*);
@@ -141,6 +144,9 @@ int             fetchstr(uint64, char*, int);
 int             fetchaddr(uint64, uint64*);
 void            syscall();
 
+// sysinfo.c
+int             sys_info(uint64);
+
 // trap.c
 extern uint     ticks;
 void            trapinit(void);
diff --git a/kernel/kalloc.c b/kernel/kalloc.c
index 0699e7e..c2fdb86 100644
--- a/kernel/kalloc.c
+++ b/kernel/kalloc.c
@@ -80,3 +80,17 @@ kalloc(void)
     memset((char*)r, 5, PGSIZE); // fill with junk
   return (void*)r;
 }
+
+int
+get_freemem(void)
+{
+  int n;
+  struct run *r;
+
+  acquire(&kmem.lock);
+  for (n = 0, r = kmem.freelist; r; r = r->next)
+    n++;
+  release(&kmem.lock);
+
+  return n * PGSIZE;
+}
diff --git a/kernel/proc.c b/kernel/proc.c
index 58a8a0b..5aa616f 100644
--- a/kernel/proc.c
+++ b/kernel/proc.c
@@ -299,6 +299,9 @@ fork(void)
   // copy saved user registers.
   *(np->trapframe) = *(p->trapframe);
 
+  // inherit trace_mask
+  np->trace_mask = p->trace_mask;
+
   // Cause fork to return 0 in the child.
   np->trapframe->a0 = 0;
 
@@ -686,3 +689,20 @@ procdump(void)
     printf("\n");
   }
 }
+
+int
+get_nproc(void)
+{
+  int n = 0;
+  struct proc *p;
+
+  for(int i = 0; i < NPROC; i++) {
+    p = &proc[i];
+    acquire(&p->lock);
+    if(p->state != UNUSED)
+      n++;
+    release(&p->lock);
+  }
+
+  return n;
+}
diff --git a/kernel/proc.h b/kernel/proc.h
index d021857..4a2ca6c 100644
--- a/kernel/proc.h
+++ b/kernel/proc.h
@@ -91,6 +91,7 @@ struct proc {
   int killed;                  // If non-zero, have been killed
   int xstate;                  // Exit status to be returned to parent's wait
   int pid;                     // Process ID
+  int trace_mask;              // SYS_trace mask (1 << SYS_xxx)
 
   // wait_lock must be held when using this:
   struct proc *parent;         // Parent process
diff --git a/kernel/syscall.c b/kernel/syscall.c
index beea0ef..4907f0f 100644
--- a/kernel/syscall.c
+++ b/kernel/syscall.c
@@ -101,6 +101,8 @@ extern uint64 sys_unlink(void);
 extern uint64 sys_link(void);
 extern uint64 sys_mkdir(void);
 extern uint64 sys_close(void);
+extern uint64 sys_trace(void);
+extern uint64 sys_sysinfo(void);
 
 #ifdef LAB_NET
 extern uint64 sys_connect(void);
@@ -139,6 +141,35 @@ static uint64 (*syscalls[])(void) = {
 #ifdef LAB_PGTBL
 [SYS_pgaccess] sys_pgaccess,
 #endif
+[SYS_trace]   sys_trace,
+[SYS_sysinfo] sys_sysinfo,
+};
+
+// syscall name maps for SYS_trace:
+static char *syscall_names[] = {
+[SYS_fork]    "fork",
+[SYS_exit]    "exit",
+[SYS_wait]    "wait",
+[SYS_pipe]    "pipe",
+[SYS_read]    "read",
+[SYS_kill]    "kill",
+[SYS_exec]    "exec",
+[SYS_fstat]   "fstat",
+[SYS_chdir]   "chdir",
+[SYS_dup]     "dup",
+[SYS_getpid]  "getpid",
+[SYS_sbrk]    "sbrk",
+[SYS_sleep]   "sleep",
+[SYS_uptime]  "uptime",
+[SYS_open]    "open",
+[SYS_write]   "write",
+[SYS_mknod]   "mknod",
+[SYS_unlink]  "unlink",
+[SYS_link]    "link",
+[SYS_mkdir]   "mkdir",
+[SYS_close]   "close",
+[SYS_trace]   "trace",
+[SYS_sysinfo] "sysinfo",
 };
 
 
@@ -154,6 +185,13 @@ syscall(void)
     // Use num to lookup the system call function for num, call it,
     // and store its return value in p->trapframe->a0
     p->trapframe->a0 = syscalls[num]();
+    
+    // SYS_trace: match all the syscalls which number < mask asked
+    // p->trace_mask == 1 << SYS_xxx
+    if(p->trace_mask >> num) {
+      printf("%d: syscall %s -> %d\n", p->pid, syscall_names[num], p->trapframe->a0);
+    }
+
   } else {
     printf("%d %s: unknown sys call %d\n",
             p->pid, p->name, num);
diff --git a/kernel/syscall.h b/kernel/syscall.h
index 8da572e..d930252 100644
--- a/kernel/syscall.h
+++ b/kernel/syscall.h
@@ -31,3 +31,5 @@
 #define SYS_munmap    28
 #define SYS_connect   29
 #define SYS_pgaccess  30
+#define SYS_trace  22
+#define SYS_sysinfo 23
diff --git a/kernel/sysinfo.c b/kernel/sysinfo.c
new file mode 100644
index 0000000..c66324d
--- /dev/null
+++ b/kernel/sysinfo.c
@@ -0,0 +1,24 @@
+#include "types.h"
+#include "riscv.h"
+#include "param.h"
+#include "spinlock.h"
+#include "defs.h"
+#include "sysinfo.h"
+#include "proc.h"
+
+// Get current system info
+// addr is a user virtual address, pointing to a struct sysinfo.
+int
+sys_info(uint64 addr) {
+  struct proc *p = myproc();
+  struct sysinfo info;
+
+  // Fill nums into the sysinfo struct
+  info.freemem = get_freemem();
+  info.nproc = get_nproc();
+
+  if(copyout(p->pagetable, addr, (char *)&info, sizeof(info)) < 0)
+    return -1;
+  return 0;
+}
+
diff --git a/kernel/sysinfo.h b/kernel/sysinfo.h
new file mode 100644
index 0000000..fb878e6
--- /dev/null
+++ b/kernel/sysinfo.h
@@ -0,0 +1,4 @@
+struct sysinfo {
+  uint64 freemem;   // amount of free memory (bytes)
+  uint64 nproc;     // number of process
+};
diff --git a/kernel/sysproc.c b/kernel/sysproc.c
index 88644b2..4cf0697 100644
--- a/kernel/sysproc.c
+++ b/kernel/sysproc.c
@@ -100,3 +100,21 @@ sys_uptime(void)
   release(&tickslock);
   return xticks;
 }
+
+uint64
+sys_trace(void)
+{
+  argint(0, &myproc()->trace_mask);
+
+  return -(myproc()->trace_mask <= 1);
+}
+
+uint64
+sys_sysinfo(void)
+{
+  uint64 si; // user pointer to struct sysinfo
+
+  argaddr(0, &si);
+  return sys_info(si);
+}
+
-- 
cgit v1.2.3


From c9284cd93525436cc823258ab309c1b27eeec714 Mon Sep 17 00:00:00 2001
From: Mole Shang <135e2@135e2.dev>
Date: Sat, 10 Feb 2024 13:08:26 +0800
Subject: lab pgtbl: finish

---
 kernel/defs.h    |  2 ++
 kernel/exec.c    |  4 ++++
 kernel/proc.c    | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 kernel/proc.h    |  1 +
 kernel/riscv.h   |  1 +
 kernel/syscall.c |  7 +++++++
 kernel/syscall.h |  2 --
 kernel/sysproc.c | 10 ++++++++--
 kernel/vm.c      | 27 +++++++++++++++++++++++++++
 9 files changed, 94 insertions(+), 5 deletions(-)

(limited to 'kernel')

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);
+}
-- 
cgit v1.2.3