void trap(struct Trapframe *tf) { //struct Trapframe *tf = &tf_; // The environment may have set DF and some versions // of GCC rely on DF being clear asm volatile("cld" ::: "cc"); // Check that interrupts are disabled. If this assertion // fails, DO NOT be tempted to fix it by inserting a "cli" in // the interrupt path. assert(!(read_eflags() & FL_IF)); cprintf("Incoming TRAP frame at %p\n", tf); if ((tf->tf_cs & 3) == 3) { // Trapped from user mode. assert(curenv); // Copy trap frame (which is currently on the stack) // into 'curenv->env_tf', so that running the environment // will restart at the trap point. curenv->env_tf = *tf; // The trapframe on the stack should be ignored from here on. tf = &curenv->env_tf; } // Record that tf is the last real trapframe so // print_trapframe can print some additional information. last_tf = tf; // Dispatch based on what type of trap occurred trap_dispatch(tf); // Return to the current environment, which should be running. assert(curenv && curenv->env_status == ENV_RUNNING); env_run(curenv); }
void trap(struct Trapframe *tf) { // The environment may have set DF and some versions // of GCC rely on DF being clear asm volatile("cld" ::: "cc"); // Check that interrupts are disabled. If this assertion // fails, DO NOT be tempted to fix it by inserting a "cli" in // the interrupt path. // Debug info // if (tf->tf_trapno != 48 && tf->tf_trapno != 32 && tf->tf_trapno != 14) cprintf("Trapno %d\n", tf->tf_trapno); assert(!(read_eflags() & FL_IF)); // cprintf("Incoming TRAP frame at %p\n", tf); if ((tf->tf_cs & 3) == 3) { // Trapped from user mode. // Copy trap frame (which is currently on the stack) // into 'curenv->env_tf', so that running the environment // will restart at the trap point. assert(curenv); curenv->env_tf = *tf; // The trapframe on the stack should be ignored from here on. tf = &curenv->env_tf; } // Dispatch based on what type of trap occurred trap_dispatch(tf); // If we made it to this point, then no other environment was // scheduled, so we should return to the current environment // if doing so makes sense. if (curenv && curenv->env_status == ENV_RUNNABLE) env_run(curenv); else sched_yield(); }
void page_fault_handler(struct Trapframe *tf) { uint32_t fault_va; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // Handle kernel-mode page faults. // LAB 3: Your code here. //cprintf("SUNUS : tf eip = %08x\n",tf->tf_eip); //sunus_dbg(0,3,page_fault_handler); if((tf->tf_cs & 0x3) != 0x3) panic("page_fault_handler @ %08x\n",fault_va); // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. // JAN,10,SUNUS if(curenv->env_pgfault_upcall) { struct UTrapframe utf; utf.utf_fault_va =fault_va; utf.utf_err = tf->tf_err; utf.utf_regs = tf->tf_regs; utf.utf_eip = tf->tf_eip; utf.utf_eip = tf->tf_eip; utf.utf_eflags = tf->tf_eflags; utf.utf_esp = tf->tf_esp; if(tf->tf_esp >= (UXSTACKTOP - PGSIZE) && tf->tf_esp <= UXSTACKTOP) /* check if it's in another PGFLT */ { //LINE 277-279 tf->tf_esp -= 4; user_mem_assert(curenv, (const void *)(tf->tf_esp - sizeof(utf) - 4), sizeof(utf), PTE_W|PTE_U);// -4 is the extra 32bit } else { tf->tf_esp = UXSTACKTOP; user_mem_assert(curenv, (const void *)(tf->tf_esp - sizeof(utf)), sizeof(utf), PTE_W|PTE_U); } tf->tf_esp -= sizeof(utf); if(tf->tf_esp < (UXSTACKTOP - PGSIZE)) { cprintf("tf->tf_esp < UXSTACKTOP - PGSIZE!\n"); env_destroy(curenv); return; } memmove((void *)(tf->tf_esp), &utf, sizeof(struct UTrapframe)); tf->tf_eip = (uintptr_t)curenv->env_pgfault_upcall; env_run(curenv); } // Destroy the environment that caused the fault. cprintf("[%08x] user fault va %08x ip %08x\n",curenv->env_id, fault_va, tf->tf_eip); print_trapframe(tf); env_destroy(curenv); }
void page_fault_handler(struct Trapframe *tf) { uint32_t fault_va; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // Handle kernel-mode page faults. if ((tf->tf_cs & 3) != 3) { panic("Page fault in kernel mode.\n"); } // LAB 3: Your code here. // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. // Destroy the environment that caused the fault. if (!curenv->env_pgfault_upcall) { cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_eip); print_trapframe(tf); env_destroy(curenv); return; } uint32_t* user_stack; if (tf->tf_esp >= UXSTACKTOP - PGSIZE && tf->tf_esp <= UXSTACKTOP - 1) { if (tf->tf_esp - sizeof(struct UTrapframe) < UXSTACKTOP - PGSIZE) { cprintf("Crossing User Stack boundaries.\n"); } tf->tf_esp = tf->tf_esp - 4; lcr3(PADDR(curenv->env_pgdir)); *((uint32_t*)tf->tf_esp) = 0; lcr3(PADDR(kern_pgdir)); user_stack = (uint32_t*)tf->tf_esp; tf->tf_esp = tf->tf_esp + 4; user_stack -= 13; user_mem_assert(curenv, (void*)user_stack, sizeof(struct UTrapframe) + 4, PTE_U | PTE_P); } else { user_stack = (uint32_t*)(UXSTACKTOP); user_stack -= 13; user_mem_assert(curenv, (void*)user_stack, sizeof(struct UTrapframe), PTE_U | PTE_P); } uint32_t user_stack_start = (uint32_t)user_stack; lcr3(PADDR(curenv->env_pgdir)); *((uint32_t*)user_stack) = fault_va; user_stack++; *((uint32_t*)user_stack) = tf->tf_err; user_stack++; *((uint32_t*)user_stack) = tf->tf_regs.reg_edi; user_stack++; *((uint32_t*)user_stack) = tf->tf_regs.reg_esi; user_stack++; *((uint32_t*)user_stack) = tf->tf_regs.reg_ebp; user_stack++; *((uint32_t*)user_stack) = tf->tf_esp; user_stack++; *((uint32_t*)user_stack) = tf->tf_regs.reg_ebx; user_stack++; *((uint32_t*)user_stack) = tf->tf_regs.reg_edx; user_stack++; *((uint32_t*)user_stack) = tf->tf_regs.reg_ecx; user_stack++; *((uint32_t*)user_stack) = tf->tf_regs.reg_eax; user_stack++; *((uint32_t*)user_stack) = tf->tf_eip; user_stack++; *((uint32_t*)user_stack) = tf->tf_eflags; user_stack++; *((uint32_t*)user_stack) = tf->tf_esp; lcr3(PADDR(kern_pgdir)); curenv->env_tf.tf_eip = (uint32_t)(curenv->env_pgfault_upcall); curenv->env_tf.tf_esp = (uint32_t)(user_stack_start); env_run(curenv); }
void page_fault_handler(struct Trapframe *tf) { uint64_t fault_va; uintptr_t stktop; uint64_t arr[20]; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // Handle kernel-mode page faults. // Ashish if ((tf->tf_cs & 0x03) == 0) panic("ERROR: Page fault occurred in kernel mode : Fault va=%x\n",fault_va); // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // Ashish if (!curenv->env_pgfault_upcall) { // Destroy the environment that caused the fault. cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_rip); print_trapframe(tf); env_destroy(curenv); } user_mem_assert(curenv, (void*)UXSTACKTOP-1, 1, PTE_P|PTE_W|PTE_U); if (tf->tf_rsp-sizeof(arr)-8 >= UXSTACKTOP) { cprintf("Exception stack overflow for env:\n", curenv->env_id); print_trapframe(tf); env_destroy(curenv); } //Store the trapframe memcpy(&(curenv->env_tf), tf, sizeof(struct Trapframe)); //Assign stacktop appropriately. In non-recursive case, stack top is UXSTACKTOP-sizeof(UTrapframe) //In recursive case, stack top will point to tf->tf_rsp-sizeof(UTrapframe)-8. Note that 8 is scratch space. if (tf->tf_rsp < UXSTACKTOP && tf->tf_rsp > UXSTACKTOP - PGSIZE) stktop = tf->tf_rsp-sizeof(arr)-8; else stktop = UXSTACKTOP-sizeof(arr); //Prepare reverse-UTrapframe arr[0]=fault_va; arr[1]=tf->tf_err; arr[2]=tf->tf_regs.reg_r15; arr[3]=tf->tf_regs.reg_r14; arr[4]=tf->tf_regs.reg_r13; arr[5]=tf->tf_regs.reg_r12; arr[6]=tf->tf_regs.reg_r11; arr[7]=tf->tf_regs.reg_r10; arr[8]=tf->tf_regs.reg_r9; arr[9]=tf->tf_regs.reg_r8; arr[10]=tf->tf_regs.reg_rsi; arr[11]=tf->tf_regs.reg_rdi; arr[12]=tf->tf_regs.reg_rbp; arr[13]=tf->tf_regs.reg_rdx; arr[14]=tf->tf_regs.reg_rcx; arr[15]=tf->tf_regs.reg_rbx; arr[16]=tf->tf_regs.reg_rax; arr[17]=tf->tf_rip; arr[18]=tf->tf_eflags; arr[19]=tf->tf_rsp; //Copy these values on the stack. memcpy((void*)(stktop), (void*)arr, sizeof(arr)); tf->tf_rsp = stktop; //Force the env to execute _pgfault_upcall from pgfault.S curenv->env_tf.tf_rip = (uintptr_t)curenv->env_pgfault_upcall; env_run(curenv); }
void page_fault_handler(struct Trapframe *tf) { uint32_t fault_va; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // Handle kernel-mode page faults. // LAB 3: Your code here. if ((tf->tf_cs & 0x3) == 0) { print_trapframe(tf); panic("page fault in kernel space"); } // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. // If no pgfault_upcall, fall to destruction. // If page faults take place in the region [USTACKTOP, UXSTACKTOP - PGSIZE), // it means the exception stack is exhausted. if (curenv->env_pgfault_upcall && (tf->tf_esp < USTACKTOP || tf->tf_esp >= UXSTACKTOP - PGSIZE)) { // Determine the starting address of the stack frame. uint32_t xtop; if (tf->tf_esp >= UXSTACKTOP - PGSIZE && tf->tf_esp < UXSTACKTOP) xtop = tf->tf_esp - sizeof(struct UTrapframe) - 4/* a required empty word */; else xtop = UXSTACKTOP - sizeof(struct UTrapframe); // Check perms user_mem_assert(curenv, (void *)xtop, UXSTACKTOP - xtop, PTE_W | PTE_U); // Push the struct UTrapframe onto the stack. struct UTrapframe *utf = (struct UTrapframe *)xtop; utf->utf_eflags = tf->tf_eflags; utf->utf_eip = tf->tf_eip; utf->utf_err = tf->tf_err; utf->utf_esp = tf->tf_esp; utf->utf_fault_va = fault_va; utf->utf_regs = tf->tf_regs; // Run current env with user-page fault handler. tf->tf_eip = (uint32_t)curenv->env_pgfault_upcall; tf->tf_esp = xtop; env_run(curenv); } // Destroy the environment that caused the fault. cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_eip); print_trapframe(tf); env_destroy(curenv); }
void page_fault_handler(struct Trapframe *tf) { uint32_t fault_va; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // Handle kernel-mode page faults. // LAB 3: Your code here. if ((tf->tf_cs & 3) == 0) { panic("kernel-mode page fault!\n"); } // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack, or the exception stack overflows, // then destroy the environment that caused the fault. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. if (curenv->env_pgfault_upcall != NULL){ struct UTrapframe *utf; if (UXSTACKTOP - PGSIZE <= tf->tf_esp && tf->tf_esp < UXSTACKTOP){ utf = (struct UTrapframe *)(tf->tf_esp - sizeof(struct UTrapframe) - 4); } else { utf = (struct UTrapframe *)(UXSTACKTOP - sizeof(struct UTrapframe)); } user_mem_assert(curenv, (void *)utf, sizeof(struct UTrapframe), PTE_U | PTE_W); utf->utf_eflags = tf->tf_eflags; utf->utf_eip = tf->tf_eip; utf->utf_err = tf->tf_err; utf->utf_esp = tf->tf_esp; utf->utf_fault_va = fault_va; utf->utf_regs = tf->tf_regs; curenv->env_tf.tf_eip = (uint32_t)curenv->env_pgfault_upcall; curenv->env_tf.tf_esp = (uint32_t)utf; env_run(curenv); } // Destroy the environment that caused the fault. cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_eip); print_trapframe(tf); env_destroy(curenv); }
void page_fault_handler(struct Trapframe *tf) { // Read processor's CR2 register to find the faulting address int ret; uint32_t fault_va = rcr2(); uint8_t * curr_stack; struct UTrapframe curr_frame; // Handle kernel-mode page faults. //deal with softint in which case error is not pushed to stack if(!(tf->tf_cs & 3)) { print_trapframe(tf); panic("page fault occurs in kernel mode\n"); } if(!curenv->env_pgfault_upcall) goto no_page_fault_handler; // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // Jie's Note : x86 first dec stack pointer and then store the value user_mem_assert(curenv,(void *)(UXSTACKTOP-PGSIZE),PGSIZE,PTE_U|PTE_W|PTE_P); if(tf->tf_esp < USTACKTOP) { curr_stack = (uint8_t *)UXSTACKTOP; } else { curr_stack = (uint8_t *) tf->tf_esp; curr_stack-=sizeof(uint32_t); memset(curr_stack,0,sizeof(uint32_t)); } if((uint32_t)curr_stack <= UXSTACKTOP-PGSIZE+sizeof(struct UTrapframe)+sizeof(uint32_t)) panic("exception stack overflow"); curr_stack-=sizeof(struct UTrapframe); // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. curr_frame.utf_fault_va = fault_va; curr_frame.utf_err = tf->tf_err; curr_frame.utf_eip = tf->tf_eip; curr_frame.utf_esp = tf->tf_esp; curr_frame.utf_eflags = tf->tf_eflags; memcpy(&(curr_frame.utf_regs),&(tf->tf_regs),sizeof(struct PushRegs)); memcpy(curr_stack,&curr_frame,sizeof(struct UTrapframe)); // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. curenv->env_tf.tf_eip = (uintptr_t)curenv->env_pgfault_upcall; curenv->env_tf.tf_esp = (uintptr_t)curr_stack; env_run(curenv); // Destroy the environment that caused the fault. no_page_fault_handler: cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_eip); print_trapframe(tf); env_destroy(curenv); }
void page_fault_handler(struct Trapframe *tf) { uint32_t fault_va; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // Handle kernel-mode page faults. // LAB 3: Your code here. if (tf->tf_cs == GD_KT) { print_trapframe(tf); panic("kernel page fault va %08x ip %08x env %x\n", fault_va, tf->tf_eip, curenv->env_id); } // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. if (!curenv->env_pgfault_upcall) { goto destroy; } // Check that exception stack is allocated user_mem_assert(curenv, (void *)(UXSTACKTOP - 4), 4, 0); uintptr_t exstack; struct UTrapframe *utf; // Figure out top where trapframe should end, leaving 1 word scratch space if (tf->tf_esp >= UXSTACKTOP-PGSIZE && tf->tf_esp <= UXSTACKTOP-1) { exstack = tf->tf_esp - 4; // recursive } else { exstack = UXSTACKTOP; // non-recursive } // Check if enough space to copy trapframe if ((exstack - sizeof(struct UTrapframe)) < UXSTACKTOP-PGSIZE) { goto destroy; } // Set up UTrapframe on exception stack utf = (struct UTrapframe *) (exstack - sizeof(struct UTrapframe)); utf->utf_fault_va = fault_va; utf->utf_err = tf->tf_err; utf->utf_regs = tf->tf_regs; utf->utf_eip = tf->tf_eip; utf->utf_eflags = tf->tf_eflags; utf->utf_esp = tf->tf_esp; // Fix trapframe to return to user handler tf->tf_esp = (uintptr_t) utf; tf->tf_eip = (uintptr_t) curenv->env_pgfault_upcall; env_run(curenv); panic("Unreachable code!\n"); destroy: // Destroy the environment that caused the fault. cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_eip); print_trapframe(tf); env_destroy(curenv); }
void page_fault_handler(struct Trapframe *tf) { uint64_t fault_va; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // Handle kernel-mode page faults. // LAB 3: Your code here. if (!(tf->tf_cs & 0x3)) { print_trapframe(tf); panic("unhandled trap in kernel"); } // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). if (curenv->env_pgfault_upcall) { struct UTrapframe *utexp; if (tf->tf_rsp <= UXSTACKTOP-1 && tf->tf_rsp >= UXSTACKTOP-PGSIZE) { utexp = (struct UTrapframe*) (tf->tf_rsp - sizeof(struct UTrapframe) - 8); } else { utexp = (struct UTrapframe*)(UXSTACKTOP - sizeof(struct UTrapframe)); } //storing that 64 bit thingy.(this was tough!, I'm weak with bits ;) ) //(time frame) to be stored...but how does it get pushed into the stack...you assign it to uxstacktop //thats brilliant. Thank you! thank you...wait a minute...see if it overflows! user_mem_assert(curenv, (void*)utexp, sizeof(struct UTrapframe), PTE_W|PTE_U); utexp->utf_fault_va = fault_va; utexp->utf_err = tf->tf_err; utexp->utf_regs = tf->tf_regs; utexp->utf_rip = tf->tf_rip; utexp->utf_eflags = tf->tf_eflags; utexp->utf_rsp = tf->tf_rsp; //How do i run the upcall...set the rip...thats nice...thank you exercise 10 :) tf->tf_rip = (uint64_t)curenv->env_pgfault_upcall; tf->tf_rsp = (uint64_t)utexp; env_run(curenv); } // LAB 4: Your code here. // Destroy the environment that caused the fault. cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_rip); print_trapframe(tf); env_destroy(curenv); }
void page_fault_handler(struct Trapframe *tf) { uint64_t fault_va; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); struct UTrapframe *utf; struct PageInfo *pp; // Handle kernel-mode page faults. // LAB 3: Your code here. if((tf->tf_cs & 3) == 0) { cprintf("fault_va is [%x]",fault_va); print_trapframe(tf); panic("Page fault hapened in kernel mode"); } // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // // LAB 4: Your code here. /*check if user env has registered a pg fault upcall.*/ //cprintf("hello1"); //cprintf("hello2"); if(curenv->env_pgfault_upcall){ //user_mem_assert(curenv,(const void *)curenv->env_pgfault_upcall,8,PTE_P|PTE_U); user_mem_assert(curenv,(const void *)UXSTACKTOP-PGSIZE,PGSIZE, PTE_W | PTE_U | PTE_P); /*If user mem assert returns , then the address is valid for the env*/ if(!(tf->tf_rsp < UXSTACKTOP && tf->tf_rsp > UXSTACKTOP-PGSIZE)){ /*1st Page Fault*/ utf = (struct UTrapframe *)(UXSTACKTOP - sizeof(struct UTrapframe)); }else{ if(tf->tf_rsp - sizeof(struct UTrapframe) - 8 < (UXSTACKTOP-PGSIZE)){ env_destroy(curenv); } else { utf = (struct UTrapframe *)(tf->tf_rsp - sizeof(struct UTrapframe) - 8); } /*Nested Page Fault*/ } /*Populate the Utrapframe*/ //user_mem_assert(curenv,(const void *)utf,sizeof(struct UTrapframe),PTE_W|PTE_U); utf->utf_eflags = tf->tf_eflags; utf->utf_err = tf->tf_err; utf->utf_fault_va = fault_va; utf->utf_regs = tf->tf_regs; utf->utf_rip = tf->tf_rip; utf->utf_rsp = tf->tf_rsp; tf->tf_rip = (uint64_t)curenv->env_pgfault_upcall; tf->tf_rsp = (uint64_t)utf; env_run(curenv); }else{ // Destroy the environment that caused the fault. cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_rip); print_trapframe(tf); env_destroy(curenv); } }
// interrupt and trap handlers void page_fault_handler(struct Trapframe *tf) { uint32_t fault_va; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // Handle kernel-mode page faults. // previlage level = 0 if ((tf->tf_cs & 3) == 0){ panic("kernel page fault"); } // LAB 3: Your code here. // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. // Now we are in kernel mode if (curenv->env_pgfault_upcall != NULL){ struct UTrapframe *utf; // Check tf_esp is in UXSTACK // -4, scratch space to save eip return address if (tf->tf_esp >= UXSTACKTOP - PGSIZE && tf->tf_esp < UXSTACKTOP){ utf = (struct UTrapframe *)(tf->tf_esp - sizeof(struct UTrapframe) - 4); } else { utf = (struct UTrapframe *)(UXSTACKTOP - sizeof(struct UTrapframe)); } // Check permission user_mem_assert(curenv, (void *)utf, sizeof(struct UTrapframe), PTE_U | PTE_W); // dump Trapframe info to UTrapframe utf->utf_fault_va = fault_va; utf->utf_err = tf->tf_err; utf->utf_regs = tf->tf_regs; utf->utf_eip = tf->tf_eip; utf->utf_eflags = tf->tf_eflags; utf->utf_esp = tf->tf_esp; // set eip to env_pgfault_upcall curenv->env_tf.tf_eip = (uint32_t)curenv->env_pgfault_upcall; curenv->env_tf.tf_esp = (uint32_t)utf; // Debug info // cprintf("Dispatch to user-mode page fault handler: fault_va %08x\n", fault_va); // if (fault_va >= USTACKTOP - PGSIZE && fault_va < USTACKTOP) cprintf("pgfautl on stack\n"); env_run(curenv); } else { cprintf("ERROR: %x env_pgfault_upcall is NULL\n", curenv->env_id); } // Destroy the environment that caused the fault. cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_eip); print_trapframe(tf); env_destroy(curenv); }
// Choose a user environment to run and run it. void sched_yield(void) { // Implement simple round-robin scheduling. // Search through 'envs' for a runnable environment, // in circular fashion starting after the previously running env, // and switch to the first such environment found. // It's OK to choose the previously running env if no other env // is runnable. // But never choose envs[0], the idle environment, // unless NOTHING else is runnable. // LAB 4: Your code here. #if LAB4A_SCHED_PRI int cur_index=0, next_index=0, priority_index=0,selected_index=0; int priority_selected = 0 ; if(NULL != curenv){ cur_index = ENVX(curenv->env_id); } next_index = (cur_index + 1)%NENV; for(;next_index != cur_index; next_index=(next_index+1)%NENV){ if((envs[next_index].env_status == ENV_RUNNABLE) && (next_index != 0)){ if(next_index & 0x01){ priority_index = next_index; priority_selected = 1; }else{ if(selected_index == 0) { selected_index=next_index; } } // env_run(&envs[next_index]); } } if(priority_selected){ env_run(&envs[priority_index]); }else{ env_run(&envs[selected_index]); } #else struct Env *penv, *pstart; int i = 0; if ((curenv == NULL) || (curenv == &envs[NENV - 1])) { // Skip envs[0] pstart = &envs[1]; } else { pstart = curenv + 1; } penv = pstart; while (1) { ++i; if ((penv == pstart) && (i > 1)) { // We've come back to start full-circle, time to break out break; } if (penv->env_status == ENV_RUNNABLE) { env_run(penv); break; } if (penv == &envs[NENV - 1]) { // Skip envs[0] penv = &envs[1]; } else { ++penv; } } #endif // Run the special idle environment when nothing else is runnable. if (envs[0].env_status == ENV_RUNNABLE) env_run(&envs[0]); else { cprintf("Destroyed all environments - nothing more to do!\n"); while (1) monitor(NULL); } }
void sched_fair_yield(void) { //Increment real_tick_used of global clock global_clock.real_tick++; int i, env_index = 1024; struct Env *e = NULL; //Find index in envs of curenv for(i = 0; i < NENV; i++) { e = &envs[i]; if(e == curenv) { env_index = i; break; } } //Decrementing timeslice for current process as it has run once if(env_index > -1 && env_index < 1024) // for scenarios when there is no current environment envs[env_index].env_se.timeslice--; // cprintf("Entering sched_fair_yield envID : %d , timeslice_remaining %d \n", env_index, envs[env_index].env_se.timeslice); i = env_index; if(envs[i].env_se.timeslice == 0) { //Current process has finished one timeslice, so increment vruntime and reset timeslice if(env_index > -1 && env_index < 1024) { envs[i].env_se.vruntime++; // Reset the timeslice on the basis of priority envs[i].env_se.timeslice = MIN_TIMESLICE * (envs[i].env_se.priority - MIN_PRIORITY + 1); } } //Terminated this loop here int flag = 0, k = 1; // variables to find the process to be scheduled next on the basis of vruntime and timeslices left uint64_t min_vruntime = 0; int timesleft = 0; env_index = -1; //setting env_index to -1, remains -1 if there is no env to be scheduled i = 1; //CHECK THIS LINE LATER while(i > 0 && i < NENV) { if(i == NENV -1) i = 1; if(envs[i].env_status == ENV_RUNNABLE)// && envs[i].env_se.timeslice > 0) { //cprintf("i: %d\n",i); if(flag == 0) { min_vruntime = envs[i].env_se.vruntime; env_index = i; timesleft = envs[i].env_se.timeslice; flag = 1; } else if(envs[i].env_se.vruntime < min_vruntime) { env_index = i; min_vruntime = envs[i].env_se.timeslice; timesleft = envs[i].env_se.timeslice; } else if(envs[i].env_se.vruntime == min_vruntime && envs[i].env_se.timeslice > timesleft) { env_index = i; timesleft = envs[i].env_se.timeslice; } } k++; if(k == NENV) break; i++; } //Check if global clock has to be incremented if(global_clock.global_tick == min_vruntime) // Change comparison operaor from <= to == { global_clock_increment(); } cprintf("******* CF Scheduler Selected Process ENV-ID [%08x] VRUNTIME: %llu TIMESLICE-LEFT: %llu ********\n",envs[env_index].env_id,envs[env_index].env_se.vruntime,envs[env_index].env_se.timeslice); if(env_index > 0) env_run(&envs[env_index]); else if(envs[0].env_status == ENV_RUNNABLE) env_run(&envs[0]); else { cprintf("Destroyed all environments - nothing more to do"); while(1) monitor(NULL); } }
void page_fault_handler(struct Trapframe *tf) { uint32_t fault_va; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // Handle kernel-mode page faults. // LAB 3: Your code here. if (tf->tf_cs == 0x8) panic("page_fault_handler: page fault in kernel mode va %08x ip %08x", fault_va, tf->tf_eip); // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack, or the exception stack overflows, // then destroy the environment that caused the fault. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. if (curenv->env_pgfault_upcall) { user_mem_assert(curenv, (void *)(UXSTACKTOP-4), 4, 0); struct UTrapframe utf; utf.utf_fault_va = fault_va; utf.utf_err = tf->tf_err; utf.utf_regs = tf->tf_regs; utf.utf_eflags = tf->tf_eflags; utf.utf_eip = tf->tf_eip; utf.utf_esp = tf->tf_esp; //If in a recursive pgfault call if (tf->tf_esp >= UXSTACKTOP-PGSIZE && tf->tf_esp < UXSTACKTOP) tf->tf_esp -= 4; else tf->tf_esp = UXSTACKTOP; tf->tf_esp -= sizeof(struct UTrapframe); //Stack overflow if (tf->tf_esp < UXSTACKTOP-PGSIZE) { cprintf("[%08x] user exception stack overflowed: va %08x ip %08x esp %08x\n", curenv->env_id, fault_va, tf->tf_eip, tf->tf_esp); print_trapframe(tf); env_destroy(curenv); return; } *(struct UTrapframe *) tf->tf_esp = utf; tf->tf_eip = (unsigned int) curenv->env_pgfault_upcall; env_run(curenv); cprintf("[DEBUG] should not reach here!\n"); } // Destroy the environment that caused the fault. cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_eip); print_trapframe(tf); env_destroy(curenv); }
// Choose a user environment to run and run it. void sched_yield(void) { // Implement simple round-robin scheduling. // Search through 'envs' for a runnable environment, // in circular fashion starting after the previously running env, // and switch to the first such environment found. // It's OK to choose the previously running env if no other env // is runnable. // But never choose envs[0], the idle environment, // unless NOTHING else is runnable. // LAB 4: Your code here. #ifndef SCHED_PRIORITY /* struct Env *env_current; int count; if(curenv != NULL) { env_current=curenv; } else { env_current=envs; } for(count=0; count<NENV; count++) { env_current++; if(envs+NENV <= env_current) { env_current=envs+1; } else { if(env_current->env_status==ENV_RUNNABLE) { env_run(env_current); } } }*/ uint32_t env_idx , n ; // if curenv's time slice has used up if (curenv) { env_idx = curenv - envs + 1 ; } else { // there's no env running env_idx = 1 ; } for (n = 0; n < NENV - 1 ; ++n) { if (envs[env_idx].env_status == ENV_RUNNABLE) { env_run(&envs[env_idx]) ; return ; } ++env_idx ; if (env_idx == NENV) { env_idx = 1 ; } } #endif #ifdef SCHED_PRIORITY struct Env *env_current; struct Env *env_max; uint32_t max_priority; int count; env_current=envs; env_max=envs; max_priority=0; for(count=0; count<NENV; count++) { env_current++; if(env_current->env_status != ENV_RUNNABLE) { continue; } if(env_current->env_priority > max_priority) { max_priority=env_current->env_priority; env_max=env_current; } } if(env_max != envs) { env_run(env_max); } #endif // Run the special idle environment when nothing else is runnable. if (envs[0].env_status == ENV_RUNNABLE) env_run(&envs[0]); else { cprintf("Destroyed all environments - nothing more to do!\n"); while (1) monitor(NULL); } // Run the special idle environment when nothing else is runnable. if (envs[0].env_status == ENV_RUNNABLE) env_run(&envs[0]); else { cprintf("Destroyed all environments - nothing more to do!\n"); while (1) monitor(NULL); } }
static void runAddingAutoPhaser(LADSPA_Handle instance, unsigned long sample_count) { AutoPhaser *plugin_data = (AutoPhaser *)instance; LADSPA_Data run_adding_gain = plugin_data->run_adding_gain; /* Attack time (s) (float value) */ const LADSPA_Data attack_p = *(plugin_data->attack_p); /* Decay time (s) (float value) */ const LADSPA_Data decay_p = *(plugin_data->decay_p); /* Modulation depth (float value) */ const LADSPA_Data depth_p = *(plugin_data->depth_p); /* Feedback (float value) */ const LADSPA_Data fb = *(plugin_data->fb); /* Spread (octaves) (float value) */ const LADSPA_Data spread = *(plugin_data->spread); /* Input (array of floats of length sample_count) */ const LADSPA_Data * const input = plugin_data->input; /* Output (array of floats of length sample_count) */ LADSPA_Data * const output = plugin_data->output; allpass * ap = plugin_data->ap; envelope * env = plugin_data->env; float sample_rate = plugin_data->sample_rate; float ym1 = plugin_data->ym1; #line 114 "phasers_1217.xml" unsigned long pos; float y, d, ofs; float attack = attack_p; float decay = decay_p; const float depth = depth_p * 0.5f; if (attack < 0.01f) { attack = 0.01f; } if (decay < 0.01f) { decay = 0.01f; } env_set_attack(env, attack * sample_rate * 0.25f); env_set_release(env, decay * sample_rate * 0.25f); for (pos = 0; pos < sample_count; pos++) { if (pos % 4 == 0) { d = env_run(env, input[pos]) * depth; ap_set_delay(ap, d); ofs = spread * 0.01562f; ap_set_delay(ap+1, d+ofs); ofs *= 2.0f; ap_set_delay(ap+2, d+ofs); ofs *= 2.0f; ap_set_delay(ap+3, d+ofs); ofs *= 2.0f; ap_set_delay(ap+4, d+ofs); ofs *= 2.0f; ap_set_delay(ap+5, d+ofs); } //Run allpass filters in series y = ap_run(ap, input[pos] + ym1 * fb); y = ap_run(ap+1, y); y = ap_run(ap+2, y); y = ap_run(ap+3, y); y = ap_run(ap+4, y); y = ap_run(ap+5, y); buffer_write(output[pos], y); ym1 = y; } plugin_data->ym1 = ym1; }
void trap(struct Trapframe *tf) { // The environment may have set DF and some versions // of GCC rely on DF being clear asm volatile("cld" ::: "cc"); // Halt the CPU if some other CPU has called panic() extern char *panicstr; if (panicstr) asm volatile("hlt"); // Re-acqurie the big kernel lock if we were halted in // sched_yield() //if(tf->tf_eip >= KERNBASE && tf->tf_trapno >= IRQ_OFFSET) // lock_kernel(); if (xchg(&thiscpu->cpu_status, CPU_STARTED) == CPU_HALTED) lock_kernel(); // Check that interrupts are disabled. If this assertion // fails, DO NOT be tempted to fix it by inserting a "cli" in // the interrupt path. assert(!(read_eflags() & FL_IF)); if ((tf->tf_cs & 3) == 3) { // Trapped from user mode. // Acquire the big kernel lock before doing any // serious kernel work. // LAB 4: Your code here. lock_kernel(); assert(curenv); // Garbage collect if current enviroment is a zombie if (curenv->env_status == ENV_DYING) { env_free(curenv); curenv = NULL; sched_yield(); } // Copy trap frame (which is currently on the stack) // into 'curenv->env_tf', so that running the environment // will restart at the trap point. curenv->env_tf = *tf; // The trapframe on the stack should be ignored from here on. tf = &curenv->env_tf; } // Record that tf is the last real trapframe so // print_trapframe can print some additional information. last_tf = tf; // Dispatch based on what type of trap occurred trap_dispatch(tf); // If we made it to this point, then no other environment was // scheduled, so we should return to the current environment // if doing so makes sense. thiscpu->cpu_ts.ts_esp0 = KSTACKTOP-cpunum()*(KSTKSIZE+KSTKGAP); thiscpu->cpu_ts.ts_ss0 = GD_KD; thiscpu->cpu_ts.ts_eflags = 0; if (curenv && curenv->env_status == ENV_RUNNING) env_run(curenv); else sched_yield(); }
void page_fault_handler(struct Trapframe *tf) { struct UTrapframe *utfp; uint32_t fault_va; void *handler = NULL; int i; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // If the low two bits of tf_cs are 0, the current privilage level // is 0, or kernel mode. Panic!!! if((tf->tf_cs&0x3) == 0) panic("page fault in kernel mode"); // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // Try to find an appropriate page fault handler. First search through // the environment's region handlers, and if fault_va is contained in // any of them, use the associated handler. for(i = 0; i < MAXHANDLERS; i++) { if(curenv->env_pgfault_handlers[i].erh_handler != NULL && fault_va >= curenv->env_pgfault_handlers[i].erh_minaddr && fault_va < curenv->env_pgfault_handlers[i].erh_maxaddr) { handler = curenv->env_pgfault_handlers[i].erh_handler; break; } } // If there is no appropriate region handler, use env_pgfault_global if(handler == NULL) handler = curenv->env_pgfault_global; // Check if a user-installed handler exists if(handler != NULL) { // If tf is on the exception stack, push a word onto the stack, // otherwise set up UXSTACKTOP as the user exception stack. // 'utfp' is used to more easily push values to the user stack. if(tf->tf_esp < UXSTACKTOP && tf->tf_esp >= UXSTACKTOP-PGSIZE) { // Creates space for a new UTrapframe plus one extra word utfp = ((struct UTrapframe *)(tf->tf_esp-4))-1; } else { // Creates space for a new UTrapframe utfp = ((struct UTrapframe *)UXSTACKTOP)-1; } // Check that utfp exists and is writable user_mem_assert(curenv, utfp, sizeof(struct UTrapframe), PTE_W); // If the stack isn't overflown, press on! if((int)utfp >= UXSTACKTOP-PGSIZE) { // Push values onto the stack utfp->utf_esp = tf->tf_esp; utfp->utf_eflags = tf->tf_eflags; utfp->utf_eip = tf->tf_eip; utfp->utf_regs = tf->tf_regs; utfp->utf_err = tf->tf_err; utfp->utf_fault_va = fault_va; // Now return to the user-defined handler, switching // to the newly created stack tf->tf_eip = (int)curenv->env_pgfault_upcall; // There should be one more word on the stack to store // the handler pointer to use. This allows for multiple // handlers to be registered simultaneously. tf->tf_esp = (int)utfp-4; *((void **)tf->tf_esp) = handler; env_run(curenv); } } // Destroy the environment that caused the fault. cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_eip); print_trapframe(tf); env_destroy(curenv); }
void page_fault_handler(struct Trapframe *tf) { uint32_t fault_va; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // Handle kernel-mode page faults. // LAB 3: Your code here. if ((tf->tf_cs&3) == 0) panic("Kernel page fault!"); // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. if( curenv->env_pgfault_upcall ) { //cprintf("in trap.c: page_fault_handler\n"); //the curenv->env_pgfault_upcall is set. struct UTrapframe *utf; uintptr_t utf_addr; //check if the tf->tf_esp is on the exception stack if (UXSTACKTOP-PGSIZE<=tf->tf_esp && tf->tf_esp<=UXSTACKTOP-1) utf_addr = tf->tf_esp - sizeof(struct UTrapframe) - 4; else utf_addr = UXSTACKTOP - sizeof(struct UTrapframe); user_mem_assert(curenv, (void*)utf_addr, 1, PTE_W); utf = (struct UTrapframe *) utf_addr; utf->utf_fault_va = fault_va; utf->utf_err = tf->tf_err; utf->utf_regs = tf->tf_regs; utf->utf_eip = tf->tf_eip; utf->utf_eflags = tf->tf_eflags; utf->utf_esp = tf->tf_esp; // curenv->env_tf.env_tf //set the function running curenv->env_tf.tf_eip = (uintptr_t)curenv->env_pgfault_upcall; curenv->env_tf.tf_esp = utf_addr; env_run(curenv); } // Destroy the environment that caused the fault. cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_eip); print_trapframe(tf); env_destroy(curenv); }
void page_fault_handler(struct Trapframe *tf) { uint64_t fault_va; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // Handle kernel-mode page faults. // cprintf("entering page fault\n"); // LAB 3: Your code here. if((tf->tf_cs & 3) == 0) { panic("pagefault occurs in kernel mode"); } // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. struct UTrapframe *new_utrap; if((curenv->env_pgfault_upcall)!=NULL) { int perm=PTE_P|PTE_U|PTE_W; if((tf->tf_rsp>=UXSTACKTOP-PGSIZE)&&(tf->tf_rsp<=UXSTACKTOP-1)) { cprintf("case 1\n"); new_utrap=(struct UTrapframe *)(tf->tf_rsp-sizeof(struct UTrapframe)-8); } else new_utrap=(struct UTrapframe *)(UXSTACKTOP-sizeof(struct UTrapframe)); // Destroy the environment that caused the fault. // cprintf("check user mem envid=%08x\n",curenv->env_id); user_mem_assert(curenv,(void *)new_utrap,sizeof(struct UTrapframe),perm); //memmove((void *)recurs,(void *)&new_utrap,sizeof(new_utrap)); // cprintf("user mem ok utf_fault_va=%08x\n",fault_va); new_utrap->utf_fault_va=fault_va; new_utrap->utf_err=tf->tf_err; new_utrap->utf_regs=tf->tf_regs; new_utrap->utf_rip=tf->tf_rip; new_utrap->utf_rsp=tf->tf_rsp; new_utrap->utf_eflags=tf->tf_eflags; tf->tf_rip=(uint64_t)curenv->env_pgfault_upcall; tf->tf_rsp=(uint64_t)new_utrap; env_run(curenv); } // cprintf("check page fault 2\n"); cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_rip); print_trapframe(tf); env_destroy(curenv); }
// Choose a user environment to run and run it. void sched_yield(void) { struct Env *idle; int i; // Implement simple round-robin scheduling. // // Search through 'envs' for an ENV_RUNNABLE environment in // circular fashion starting just after the env this CPU was // last running. Switch to the first such environment found. // // If no envs are runnable, but the environment previously // running on this CPU is still ENV_RUNNING, it's okay to // choose that environment. // // Never choose an environment that's currently running on // another CPU (env_status == ENV_RUNNING) and never choose an // idle environment (env_type == ENV_TYPE_IDLE). If there are // no runnable environments, simply drop through to the code // below to switch to this CPU's idle environment. // LAB 4: Your code here. if(thiscpu->cpu_env) { i = thiscpu->cpu_env-envs; } else { i = 1; } int k = i+1; int j = 1; for (j = 1; j<NENV; j++) { if ((envs[k].env_status == ENV_RUNNABLE) && (envs[k].env_type != ENV_TYPE_IDLE)) { env_run(&envs[k]); } k++; if (k==NENV) { k = 0; } } if (thiscpu->cpu_env) { if (j==NENV && thiscpu->cpu_env->env_status == ENV_RUNNING) { env_run(thiscpu->cpu_env); } } // For debugging and testing purposes, if there are no // runnable environments other than the idle environments, // drop into the kernel monitor. // For debugging and testing purposes, if there are no // runnable environments other than the idle environments, // drop into the kernel monitor. for (i = 0; i < NENV; i++) { if (envs[i].env_type != ENV_TYPE_IDLE && (envs[i].env_status == ENV_RUNNABLE || envs[i].env_status == ENV_RUNNING)) break; } if (i == NENV) { cprintf("No more runnable environments!\n"); while (1) monitor(NULL); } // Run this CPU's idle environment when nothing else is runnable. idle = &envs[cpunum()]; if (!(idle->env_status == ENV_RUNNABLE || idle->env_status == ENV_RUNNING)) panic("CPU %d: No idle environment!", cpunum()); env_run(idle); }
void page_fault_handler(struct Trapframe *tf) { uint32_t fault_va; void *va; int rc; struct UTrapframe utf; // Read processor's CR2 register to find the faulting address fault_va = rcr2(); // Handle kernel-mode page faults. // LAB 3: Your code here. if ((tf->tf_cs & 0x3) == RPL_K) { panic("Oops! Page fault in kernel: %p", fault_va); } // We've already handled kernel-mode exceptions, so if we get here, // the page fault happened in user mode. // Call the environment's page fault upcall, if one exists. Set up a // page fault stack frame on the user exception stack (below // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. // // The page fault upcall might cause another page fault, in which case // we branch to the page fault upcall recursively, pushing another // page fault stack frame on top of the user exception stack. // // The trap handler needs one word of scratch space at the top of the // trap-time stack in order to return. In the non-recursive case, we // don't have to worry about this because the top of the regular user // stack is free. In the recursive case, this means we have to leave // an extra word between the current top of the exception stack and // the new stack frame because the exception stack _is_ the trap-time // stack. // // If there's no page fault upcall, the environment didn't allocate a // page for its exception stack or can't write to it, or the exception // stack overflows, then destroy the environment that caused the fault. // Note that the grade script assumes you will first check for the page // fault upcall and print the "user fault va" message below if there is // none. The remaining three checks can be combined into a single test. // // Hints: // user_mem_assert() and env_run() are useful here. // To change what the user environment runs, modify 'curenv->env_tf' // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. if (curenv->env_pgfault_upcall != NULL) { utf.utf_fault_va = fault_va; utf.utf_err = tf->tf_err; utf.utf_regs = tf->tf_regs; utf.utf_eip = tf->tf_eip; utf.utf_eflags = tf->tf_eflags; utf.utf_esp = tf->tf_esp; // NOTE: since PF happened in user mode, CR3 should already have the // corres. env's PD loaded, hence no need to do explicit lcr3(). if ( ((UXSTACKTOP - PGSIZE) <= tf->tf_esp) && (tf->tf_esp < UXSTACKTOP) ) { va = (void *) (tf->tf_esp - sizeof(utf) - 4); //clog("wp1: va = %p, fault_va = %p, err = 0x%x, esp = %p, eip = %p", // va, fault_va, tf->tf_err, tf->tf_esp, tf->tf_eip); user_mem_assert(curenv, va, sizeof(utf) + 4, PTE_W | PTE_U); //lcr3(curenv->env_cr3); memset(va + sizeof(utf), 0, 4); } else { va = (void *) (UXSTACKTOP - sizeof(utf)); //clog("wp2: va = %p, fault_va = %p, err = 0x%x, esp = %p, eip = %p", // va, fault_va, tf->tf_err, tf->tf_esp, tf->tf_eip); user_mem_assert(curenv, va, sizeof(utf), PTE_W | PTE_U); //lcr3(curenv->env_cr3); } memmove(va, &utf, sizeof(utf)); tf->tf_esp = (uintptr_t) va; tf->tf_eip = (uintptr_t) curenv->env_pgfault_upcall; env_run(curenv); } // Destroy the environment that caused the fault. cprintf("[%08x] user fault va %08x ip %08x err %08x\n", curenv->env_id, fault_va, tf->tf_eip, tf->tf_err); print_trapframe(tf); //mon_backtrace(0, 0, tf); env_destroy(curenv); }