Trap.c
unknown
plain_text
a year ago
5.1 kB
12
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