diff options
| author | Mole Shang <135e2@135e2.dev> | 2024-02-10 13:08:26 +0800 | 
|---|---|---|
| committer | Mole Shang <135e2@135e2.dev> | 2024-02-10 13:08:26 +0800 | 
| commit | c9284cd93525436cc823258ab309c1b27eeec714 (patch) | |
| tree | 35782f7314100aa821823ee94cc5d28164af8000 /kernel | |
| parent | 283d5ab4c964ab525e45fcade06d6fd7e977c43e (diff) | |
| download | xv6-labs-c9284cd93525436cc823258ab309c1b27eeec714.tar.gz xv6-labs-c9284cd93525436cc823258ab309c1b27eeec714.tar.bz2 xv6-labs-c9284cd93525436cc823258ab309c1b27eeec714.zip | |
lab pgtbl: finishpgtbl
Diffstat (limited to 'kernel')
| -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 | 
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); +} | 
