Skip to content

Latest commit

 

History

History
190 lines (161 loc) · 3.93 KB

Lab5 xv6 lazy page allocation.md

File metadata and controls

190 lines (161 loc) · 3.93 KB

Lab: xv6 lazy page allocation

我们主要修改了四个函数,分别是 kernel/file.c中的 sys_sbrk()kernel/vm.c 中的 copyout()copyin(), 以及 kernel/trap.c中的 usertrap()

void
usertrap(void)
{
  int which_dev = 0;

  if((r_sstatus() & SSTATUS_SPP) != 0)
    panic("usertrap: not from user mode");

  // send interrupts and exceptions to kerneltrap(),
  // since we're now in the kernel.
  w_stvec((uint64)kernelvec);

  struct proc *p = myproc();
  
  // save user program counter.
  p->trapframe->epc = r_sepc();
  
  if(r_scause() == 8){
    // system call

    if(p->killed)
      exit(-1);

    // sepc points to the ecall instruction,
    // but we want to return to the next instruction.
    p->trapframe->epc += 4;

    // an interrupt will change sstatus &c registers,
    // so don't enable until done with those registers.
    intr_on();

    syscall();
  } else if((which_dev = devintr()) != 0){
    // ok
  } else if(r_scause() == 13 || r_scause() == 15){
        uint64 va0 = PGROUNDDOWN(r_stval());
  	if (va0 + PGSIZE > PGROUNDUP(p->sz) ||va0 < PGROUNDDOWN(p->trapframe->sp) || va0 > MAXVA ||va0 + PGSIZE > MAXVA ){
  	     p->killed = 1;
  	}
  	else{
	    char* mem = kalloc();
	    if(mem != 0){
        	    memset(mem, 0, PGSIZE);
	    if(mappages(p -> pagetable, va0, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0){
	       kfree(mem);
              p->killed = 1;
	    }
	    }
	    else{
	    	    	p -> killed = 1;
	    }
      }
  }
  else {
    printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);
    printf("            sepc=%p stval=%p\n", r_sepc(), r_stval());
    p->killed = 1;
  }

  if(p->killed)
    exit(-1);

  // give up the CPU if this is a timer interrupt.
  if(which_dev == 2)
    yield();

  usertrapret();
}
int
copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
{
  uint64 n, va0, pa0;
  while(len > 0){
    va0 = PGROUNDDOWN(dstva);
    pa0 = walkaddr(pagetable, va0);
    if(pa0 == 0){
       if (va0 + PGSIZE > PGROUNDUP(myproc()->sz) ||va0 < PGROUNDDOWN(myproc()->trapframe->sp) || va0 > MAXVA || va0 + PGSIZE > MAXVA){
            return -1;
        }
  	else{
  	   char* mem = kalloc();
           if(mem != 0){
	    memset(mem, 0, PGSIZE);
	   if(mappages(myproc() -> pagetable, va0, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0){
              kfree(mem);
	      return -1;
	    }
	    }
	    else{
	    	return -1;
	    }
      }
      pa0 = walkaddr(pagetable, va0);
      if (pa0 == 0)
      	return -1;
    }
    n = PGSIZE - (dstva - va0);
    if(n > len)
      n = len;
    memmove((void *)(pa0 + (dstva - va0)), src, n);

    len -= n;
    src += n;
    dstva = va0 + PGSIZE;
  }
 return 0;
int
copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len)
{
  uint64 n, va0, pa0;

  while(len > 0){
   
    va0 = PGROUNDDOWN(srcva);
    pa0 = walkaddr(pagetable, va0);
     if(pa0 == 0){
       if (va0 + PGSIZE > PGROUNDUP(myproc()->sz) ||va0 < PGROUNDDOWN(myproc()->trapframe->sp) || va0 > MAXVA || va0 + PGSIZE > MAXVA){
  	    return -1;
        }
  	else{
  	   char* mem = kalloc();
           if(mem != 0){
	    memset(mem, 0, PGSIZE);
	   if(mappages(myproc() -> pagetable, va0, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0){
              kfree(mem);
	      return -1;
	    }
	    }
	    else{
	    	return -1;
	    }
      }
      pa0 = walkaddr(pagetable, va0);
      if (pa0 == 0)
      	return -1;
    }
    n = PGSIZE - (srcva - va0);
    if(n > len)
      n = len;
    memmove(dst, (void *)(pa0 + (srcva - va0)), n);

    len -= n;
   dst += n;
    srcva = va0 + PGSIZE;
  }
  return 0;
}
uint64
sys_sbrk(void)
{
  int addr;
  int n;

  if(argint(0, &n) < 0)
    return -1;
  addr = myproc()->sz;
  if (n >= 0){
      if (addr + n > MAXVA || addr > MAXVA)
        return -1;
      else
      myproc() -> sz = myproc() -> sz + n;
  }
  else{
  	if(growproc(n) < 0)
             return -1;
  }
  return addr;
}