diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/defs.h | 8 | ||||
| -rw-r--r-- | kernel/exec.c | 4 | ||||
| -rw-r--r-- | kernel/kalloc.c | 14 | ||||
| -rw-r--r-- | kernel/memlayout.h | 17 | ||||
| -rw-r--r-- | kernel/proc.c | 65 | ||||
| -rw-r--r-- | kernel/proc.h | 2 | ||||
| -rw-r--r-- | kernel/riscv.h | 1 | ||||
| -rw-r--r-- | kernel/syscall.c | 60 | ||||
| -rw-r--r-- | kernel/syscall.h | 11 | ||||
| -rw-r--r-- | kernel/sysinfo.c | 24 | ||||
| -rw-r--r-- | kernel/sysinfo.h | 4 | ||||
| -rw-r--r-- | kernel/sysproc.c | 39 | ||||
| -rw-r--r-- | kernel/vm.c | 27 | 
13 files changed, 271 insertions, 5 deletions
| diff --git a/kernel/defs.h b/kernel/defs.h index a3c962b..bd85d1f 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,8 @@ 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); +int             pgaccess(uint64 base, int len, uint64 mask);  // swtch.S  void            swtch(struct context*, struct context*); @@ -141,6 +145,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); @@ -173,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/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/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/proc.c b/kernel/proc.c index 58a8a0b..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);  } @@ -299,6 +319,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 +709,43 @@ 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; +} + +// 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 d021857..c816ae2 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 @@ -100,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 ed65409..394b980 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -101,6 +101,15 @@ 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); +#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. @@ -126,8 +135,51 @@ 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 +[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", +#ifdef LAB_NET +[SYS_connect] "connect", +#endif +#ifdef LAB_PGTBL +[SYS_pgaccess] "pgaccess", +#endif +[SYS_trace]   "trace", +[SYS_sysinfo] "sysinfo",  }; + +  void  syscall(void)  { @@ -139,9 +191,17 @@ 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);      p->trapframe->a0 = -1;    }  } + 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/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 3b4d5bd..bd9d0f0 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,22 @@ sys_sleep(void)    return 0;  } + +#ifdef LAB_PGTBL +int +sys_pgaccess(void) +{ +  uint64 base, mask; +  int len; + +   +  argaddr(0, &base); +  argint(1, &len); +  argaddr(2, &mask); +  return pgaccess(base, len, mask); +} +#endif +  uint64  sys_kill(void)  { @@ -91,3 +106,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); +} + 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); +} | 
