kernel/trap.c
//
// handle an interrupt, exception, or system call from user space.
// called from trampoline.S
//
handle an interrupt, exception, or system call from user space.
handle an interrupt exception or system call from user space .
void
usertrap(void)
{
  int which_dev = 0;
  if((r_sstatus() & SSTATUS_SPP) != 0)
    panic("usertrap: not from user mode");
  w_stvec((uint64)kernelvec);
  struct proc *p = myproc();
  p->trapframe->epc = r_sepc();
  if(r_scause() == 8){
    if(p->killed)
      exit(-1);
    p->trapframe->epc += 4;
    intr_on();
    syscall();
  } else if((which_dev = devintr()) != 0){
  } else if(r_scause() == 0xd){
    uint64 va = r_stval();
    struct vmarea *vma = 0;
    for(vma = p->vma; vma < p->vma + 16; vma++){
      acquire(&vma->lock);
      if(vma->f != 0){
        if(vma->addr <= va && va < vma->addr + vma->length){
          break;
        }
      }
      release(&vma->lock);
    }
    if(vma == p->vma + 16){
      goto fail;
    }
    uint64 pva = PGROUNDDOWN(va);
    char *mem = kalloc();
    if(mem == 0){
      release(&vma->lock);
      goto fail;
    }
    memset(mem, 0, PGSIZE);
    int perm = PTE_U;
    if(vma->perm & PROT_READ)
      perm |= PTE_R;;
    if(vma->perm & PROT_WRITE)
      perm |= PTE_W;
    if(vma->perm & PROT_EXEC)
      perm |= PTE_X;
    if(mappages(p->pagetable, pva, PGSIZE, (uint64)mem, perm) != 0){
      kfree(mem);
      release(&vma->lock);
      goto fail;
    }
    struct file *fi = vma->f;
    int offset = vma->offset;
    int addr = vma->addr;
    release(&vma->lock);
    begin_op();
    ilock(fi->ip);
    readi(fi->ip, 1, va, offset + va - addr, PGSIZE);
    iunlock(fi->ip);
    end_op();
  } else {
  fail:
    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);
  if(which_dev == 2)
    yield();
  usertrapret();
}
void usertrap ( void ) { int which_dev = 0 ; if ( ( r_sstatus ( ) & SSTATUS_SPP ) != 0 ) panic ( " " ) ; w_stvec ( ( uint64 ) kernelvec ) ; struct proc * p = myproc ( ) ; p -> trapframe -> epc = r_sepc ( ) ; if ( r_scause ( ) == 8 ) { if ( p -> killed ) exit ( -1 ) ; p -> trapframe -> epc += 4 ; intr_on ( ) ; syscall ( ) ; } else if ( ( which_dev = devintr ( ) ) != 0 ) { } else if ( r_scause ( ) == 0xd ) { uint64 va = r_stval ( ) ; struct vmarea * vma = 0 ; for ( vma = p -> vma ; vma < p -> vma + 16 ; vma ++ ) { acquire ( & vma -> lock ) ; if ( vma -> f != 0 ) { if ( vma -> addr <= va && va < vma -> addr + vma -> length ) { break ; } } release ( & vma -> lock ) ; } if ( vma == p -> vma + 16 ) { goto fail ; } uint64 pva = PGROUNDDOWN ( va ) ; char * mem = kalloc ( ) ; if ( mem == 0 ) { release ( & vma -> lock ) ; goto fail ; } memset ( mem , 0 , PGSIZE ) ; int perm = PTE_U ; if ( vma -> perm & PROT_READ ) perm |= PTE_R ; ; if ( vma -> perm & PROT_WRITE ) perm |= PTE_W ; if ( vma -> perm & PROT_EXEC ) perm |= PTE_X ; if ( mappages ( p -> pagetable , pva , PGSIZE , ( uint64 ) mem , perm ) != 0 ) { kfree ( mem ) ; release ( & vma -> lock ) ; goto fail ; } struct file * fi = vma -> f ; int offset = vma -> offset ; int addr = vma -> addr ; release ( & vma -> lock ) ; begin_op ( ) ; ilock ( fi -> ip ) ; readi ( fi -> ip , 1 , va , offset + va - addr , PGSIZE ) ; iunlock ( fi -> ip ) ; end_op ( ) ; } else { fail : printf ( " \n " , r_scause ( ) , p -> pid ) ; printf ( " \n " , r_sepc ( ) , r_stval ( ) ) ; p -> killed = 1 ; } if ( p -> killed ) exit ( -1 ) ; if ( which_dev == 2 ) yield ( ) ; usertrapret ( ) ; }
handle an interrupt, exception, or system call from user space.
handle an interrupt exception or system call from user space .
// send interrupts and exceptions to kerneltrap(), // since we're now in the kernel. // save user program counter. // system call // sepc points to the ecall instruction, // but we want to return to the next instruction. // an interrupt will change sstatus &c registers, // so don't enable until done with those registers. // ok // printf("trap get %d\n", vma - p->vma); // printf("no found\n"); // printf("trap vma ip %p %p ref = %d offset = %p\n", vma->f->ip, va, vma->f->ip->ref, offset); // give up the CPU if this is a timer interrupt.