Trap.c

 avatar
unknown
plain_text
5 months ago
5.1 kB
11
Indexable
void
trap(struct trapframe *tf)
{
  int va;
  char* mem;
  if(tf->trapno == T_SYSCALL){
    if(myproc()->killed)
      exit();
    myproc()->tf = tf;
    syscall();
    if(myproc()->killed)
      exit();
    return;
  }

  switch(tf->trapno){
  case T_IRQ0 + IRQ_TIMER:
    if(cpuid() == 0){
      acquire(&tickslock);
      ticks++;
      wakeup(&ticks);
      release(&tickslock);
    }
    lapiceoi();
    break;
  case T_IRQ0 + IRQ_IDE:
    ideintr();
    lapiceoi();
    break;
  case T_IRQ0 + IRQ_IDE+1:
    // Bochs generates spurious IDE1 interrupts.
    break;
  case T_IRQ0 + IRQ_KBD:
    kbdintr();
    lapiceoi();
    break;
  case T_IRQ0 + IRQ_COM1:
    uartintr();
    lapiceoi();
    break;
  case T_IRQ0 + 7:
  case T_IRQ0 + IRQ_SPURIOUS:
    cprintf("cpu%d: spurious interrupt at %x:%x\n",
            cpuid(), tf->cs, tf->eip);
    lapiceoi();
    break;
	case T_PGFLT:
      #ifdef LAZY
        
        va = rcr2();
        struct proc *curproc = myproc();
        //cprintf("[LAZY] Pagefault Occured for pid: %d\n", curproc->pid);
        va = PGROUNDDOWN(va);
        if(va <= curproc->sz){
          mem = kalloc();
          if(mem == 0){
            //cprintf("[LAZY] Out of memory for pid %d\n", curproc->pid);
            myproc()->killed = 1;
          }else{
            memset(mem, 0, PGSIZE);
            if(mappages(curproc->pgdir, (char*)va, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0){
              //cprintf("[LAZY] Mapping failed for pid %d at va %x\n", curproc->pid, va);
              myproc()->killed = 1;
            }else{
            	//cprintf("[LAZY] Allocated and mapped page: pid %d va %x\n", curproc->pid, va);
            	break;
            }
          }
        }else{
          cprintf("pid %d %s: trap %d err %d on cpu %d "
          "eip 0x%x addr 0x%x--kill proc\n",
          myproc()->pid, myproc()->name, tf->trapno,
          tf->err, cpuid(), tf->eip, rcr2());
          myproc()->killed = 1;
        }
      #endif
      #ifdef LOCALITY
      		
	    va = rcr2(); // Get the faulting virtual address from CR2 register
	    struct proc *curproc = myproc(); // Current process
	    //cprintf("[LOCALITY] Pagefault Occured for pid: %d\n", curproc->pid);
	    va = PGROUNDDOWN(va); // Align the address to the nearest page boundary

	    // Check if the faulting address is valid
	    if (va >= curproc->sz || va >= KERNBASE) {
		//cprintf("[LOCALITY] Invalid page fault address: pid %d va %x\n", curproc->pid, va);
		curproc->killed = 1; // Kill the process for invalid access
		break;
	    }

	    // Allocate and map the faulting page and two subsequent pages
	    for (int i = 0; i < 3; i++) {
		uint new_va = va + i * PGSIZE; // Compute the virtual address for each page

		// Ensure the new address is within the process size
		/*if (new_va > curproc->sz){
			cprintf("[LOCALITY] Cannot allocate new address(%d) > process size(%d)\n",new_va, curproc->sz);
		    break;
		}*/

		// Check if the page is already mapped
		pte_t *pte = walkpgdir(curproc->pgdir, (void*)new_va, 0);
		if (pte && (*pte & PTE_P)) // Skip if already mapped
		    continue;

		// Allocate physical memory
		mem = kalloc();
		if (mem == 0) {
		    //cprintf("[LOCALITY] Out of memory for pid %d\n", curproc->pid);
		    curproc->killed = 1; // Kill process on memory allocation failure
		    break;
		}
		memset(mem, 0, PGSIZE); // Clear the allocated memory

		// Map the page to the process's address space
		if (mappages(curproc->pgdir, (void*)new_va, PGSIZE, V2P(mem), PTE_W | PTE_U) < 0) {
		    kfree(mem); // Free memory if mapping fails
		    //cprintf("[LOCALITY] Mapping failed for pid %d at va %x\n", curproc->pid, new_va);
		    curproc->killed = 1;
		    break;
		}
		/*else{
			//cprintf("[LOCALITY] Allocated and mapped page: pid %d va %x\n", curproc->pid, new_va);
			//break;
		}*/
	    }
	#endif

	break;
  //PAGEBREAK: 13
  default:
    if(myproc() == 0 || (tf->cs&3) == 0){
      // In kernel, it must be our mistake.
      cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
              tf->trapno, cpuid(), tf->eip, rcr2());
      panic("trap");
    }
    // In user space, assume process misbehaved.
    cprintf("pid %d %s: trap %d err %d on cpu %d "
            "eip 0x%x addr 0x%x--kill proc\n",
            myproc()->pid, myproc()->name, tf->trapno,
            tf->err, cpuid(), tf->eip, rcr2());
    myproc()->killed = 1;
  }

  // Force process exit if it has been killed and is in user space.
  // (If it is still executing in the kernel, let it keep running
  // until it gets to the regular system call return.)
  if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER)
    exit();

  #if !defined(SJF) && !defined(PRIORITY)
    // Force process to give up CPU on clock tick.
    // If interrupts were on while locks held, would need to check nlock.
    if(myproc() && myproc()->state == RUNNING &&
      tf->trapno == T_IRQ0+IRQ_TIMER)
      yield();
  #endif

  // Check if the process has been killed since we yielded
  if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER)
    exit();
}
Editor is loading...
Leave a Comment