#include <inc/mmu.h>
#include <inc/x86.h>
#include <inc/assert.h>
#include <kern/memory_manager.h>
#include <kern/trap.h>
#include <kern/console.h>
#include <kern/command_prompt.h>
#include <kern/user_environment.h>
#include <kern/file_manager.h>
#include <kern/syscall.h>
#include <kern/sched.h>
#include <kern/kclock.h>
#include <kern/trap.h>
static struct Taskstate ts;
/// Interrupt descriptor table. (Must be built at run time because
/// shifted function addresses can't be represented in relocation records.)
///
struct Gatedesc idt[256] = { { 0 } };
struct Pseudodesc idt_pd = {
sizeof(idt) - 1, (uint32) idt
};
extern void (*PAGE_FAULT)();
extern void (*SYSCALL_HANDLER)();
extern void (*DBL_FAULT)();
extern void (*ALL_FAULTS0)();
extern void (*ALL_FAULTS1)();
extern void (*ALL_FAULTS2)();
extern void (*ALL_FAULTS3)();
extern void (*ALL_FAULTS4)();
extern void (*ALL_FAULTS5)();
extern void (*ALL_FAULTS6)();
extern void (*ALL_FAULTS7)();
//extern void (*ALL_FAULTS8)();
//extern void (*ALL_FAULTS9)();
extern void (*ALL_FAULTS10)();
extern void (*ALL_FAULTS11)();
extern void (*ALL_FAULTS12)();
extern void (*ALL_FAULTS13)();
//extern void (*ALL_FAULTS14)();
//extern void (*ALL_FAULTS15)();
extern void (*ALL_FAULTS16)();
extern void (*ALL_FAULTS17)();
extern void (*ALL_FAULTS18)();
extern void (*ALL_FAULTS19)();
extern void (*ALL_FAULTS32)();
extern void (*ALL_FAULTS33)();
extern void (*ALL_FAULTS34)();
extern void (*ALL_FAULTS35)();
extern void (*ALL_FAULTS36)();
extern void (*ALL_FAULTS37)();
extern void (*ALL_FAULTS38)();
extern void (*ALL_FAULTS39)();
extern void (*ALL_FAULTS40)();
extern void (*ALL_FAULTS41)();
extern void (*ALL_FAULTS42)();
extern void (*ALL_FAULTS43)();
extern void (*ALL_FAULTS44)();
extern void (*ALL_FAULTS45)();
extern void (*ALL_FAULTS46)();
extern void (*ALL_FAULTS47)();
static const char *trapname(int trapno)
{
static const char * const excnames[] = {
"Divide error",
"Debug",
"Non-Maskable Interrupt",
"Breakpoint",
"Overflow",
"BOUND Range Exceeded",
"Invalid Opcode",
"Device Not Available",
"Double Fault",
"Coprocessor Segment Overrun",
"Invalid TSS",
"Segment Not Present",
"Stack Fault",
"General Protection",
"Page Fault",
"(unknown trap)",
"x87 FPU Floating-Point Error",
"Alignment Check",
"Machine-Check",
"SIMD Floating-Point Exception"
};
if (trapno < sizeof(excnames)/sizeof(excnames[0]))
return excnames[trapno];
if (trapno == T_SYSCALL)
return "System call";
return "(unknown trap)";
}
void
idt_init(void)
{
extern struct Segdesc gdt[];
// LAB 3: Your code here.
//initialize idt
SETGATE(idt[T_PGFLT], 0, GD_KT , &PAGE_FAULT, 0) ;
SETGATE(idt[T_SYSCALL], 0, GD_KT , &SYSCALL_HANDLER, 3) ;
SETGATE(idt[T_DBLFLT], 0, GD_KT , &DBL_FAULT, 0) ;
SETGATE(idt[T_DIVIDE ], 0, GD_KT , &ALL_FAULTS0, 3) ;
SETGATE(idt[T_DEBUG ], 1, GD_KT , &ALL_FAULTS1, 3) ;
SETGATE(idt[T_NMI ], 0, GD_KT , &ALL_FAULTS2, 3) ;
SETGATE(idt[T_BRKPT ], 1, GD_KT , &ALL_FAULTS3, 3) ;
SETGATE(idt[T_OFLOW ], 1, GD_KT , &ALL_FAULTS4, 3) ;
SETGATE(idt[T_BOUND ], 0, GD_KT , &ALL_FAULTS5, 3) ;
SETGATE(idt[T_ILLOP ], 0, GD_KT , &ALL_FAULTS6, 3) ;
SETGATE(idt[T_DEVICE ], 0, GD_KT , &ALL_FAULTS7, 3) ;
//SETGATE(idt[T_DBLFLT ], 0, GD_KT , &ALL_FAULTS, 3) ;
//SETGATE(idt[], 0, GD_KT , &ALL_FAULTS, 3) ;
SETGATE(idt[T_TSS ], 0, GD_KT , &ALL_FAULTS10, 3) ;
SETGATE(idt[T_SEGNP ], 0, GD_KT , &ALL_FAULTS11, 3) ;
SETGATE(idt[T_STACK ], 0, GD_KT , &ALL_FAULTS12, 3) ;
SETGATE(idt[T_GPFLT ], 0, GD_KT , &ALL_FAULTS13, 3) ;
//SETGATE(idt[T_PGFLT ], 0, GD_KT , &ALL_FAULTS, 3) ;
//SETGATE(idt[ne T_RES ], 0, GD_KT , &ALL_FAULTS, 3) ;
SETGATE(idt[T_FPERR ], 0, GD_KT , &ALL_FAULTS16, 3) ;
SETGATE(idt[T_ALIGN ], 0, GD_KT , &ALL_FAULTS17, 3) ;
SETGATE(idt[T_MCHK ], 0, GD_KT , &ALL_FAULTS18, 3) ;
SETGATE(idt[T_SIMDERR ], 0, GD_KT , &ALL_FAULTS19, 3) ;
SETGATE(idt[IRQ0_Clock], 0, GD_KT , &ALL_FAULTS32, 3) ;
SETGATE(idt[33], 0, GD_KT , &ALL_FAULTS33, 3) ;
SETGATE(idt[34], 0, GD_KT , &ALL_FAULTS34, 3) ;
SETGATE(idt[35], 0, GD_KT , &ALL_FAULTS35, 3) ;
SETGATE(idt[36], 0, GD_KT , &ALL_FAULTS36, 3) ;
SETGATE(idt[37], 0, GD_KT , &ALL_FAULTS37, 3) ;
SETGATE(idt[38], 0, GD_KT , &ALL_FAULTS38, 3) ;
SETGATE(idt[39], 0, GD_KT , &ALL_FAULTS39, 3) ;
SETGATE(idt[40], 0, GD_KT , &ALL_FAULTS40, 3) ;
SETGATE(idt[41], 0, GD_KT , &ALL_FAULTS41, 3) ;
SETGATE(idt[42], 0, GD_KT , &ALL_FAULTS42, 3) ;
SETGATE(idt[43], 0, GD_KT , &ALL_FAULTS43, 3) ;
SETGATE(idt[44], 0, GD_KT , &ALL_FAULTS44, 3) ;
SETGATE(idt[45], 0, GD_KT , &ALL_FAULTS45, 3) ;
SETGATE(idt[46], 0, GD_KT , &ALL_FAULTS46, 3) ;
SETGATE(idt[47], 0, GD_KT , &ALL_FAULTS47, 3) ;
// Setup a TSS so that we get the right stack
// when we trap to the kernel.
ts.ts_esp0 = KERNEL_STACK_TOP;
ts.ts_ss0 = GD_KD;
// Initialize the TSS field of the gdt.
gdt[GD_TSS >> 3] = SEG16(STS_T32A, (uint32) (&ts),
sizeof(struct Taskstate), 0);
gdt[GD_TSS >> 3].sd_s = 0;
// Load the TSS
ltr(GD_TSS);
// Load the IDT
asm volatile("lidt idt_pd");
}
void print_trapframe(struct Trapframe *tf)
{
cprintf("TRAP frame at %p\n", tf);
print_regs(&tf->tf_regs);
cprintf(" es 0x----%04x\n", tf->tf_es);
cprintf(" ds 0x----%04x\n", tf->tf_ds);
cprintf(" trap 0x%08x %s - %d\n", tf->tf_trapno, trapname(tf->tf_trapno), tf->tf_trapno);
cprintf(" err 0x%08x\n", tf->tf_err);
cprintf(" eip 0x%08x\n", tf->tf_eip);
cprintf(" cs 0x----%04x\n", tf->tf_cs);
cprintf(" flag 0x%08x\n", tf->tf_eflags);
cprintf(" esp 0x%08x\n", tf->tf_esp);
cprintf(" ss 0x----%04x\n", tf->tf_ss);
}
void print_regs(struct PushRegs *regs)
{
cprintf(" edi 0x%08x\n", regs->reg_edi);
cprintf(" esi 0x%08x\n", regs->reg_esi);
cprintf(" ebp 0x%08x\n", regs->reg_ebp);
cprintf(" oesp 0x%08x\n", regs->reg_oesp);
cprintf(" ebx 0x%08x\n", regs->reg_ebx);
cprintf(" edx 0x%08x\n", regs->reg_edx);
cprintf(" ecx 0x%08x\n", regs->reg_ecx);
cprintf(" eax 0x%08x\n", regs->reg_eax);
}
static void trap_dispatch(struct Trapframe *tf)
{
// Handle processor exceptions.
// LAB 3: Your code here.
if(tf->tf_trapno == T_PGFLT)
{
if(isPageReplacmentAlgorithmLRU()){
update_WS_time_stamps();
}
fault_handler(tf);
}
else if (tf->tf_trapno == T_SYSCALL)
{
uint32 ret = syscall(tf->tf_regs.reg_eax
,tf->tf_regs.reg_edx
,tf->tf_regs.reg_ecx
,tf->tf_regs.reg_ebx
,tf->tf_regs.reg_edi
,tf->tf_regs.reg_esi);
tf->tf_regs.reg_eax = ret;
}
else if(tf->tf_trapno == T_DBLFLT)
{
cprintf("aywa ya basha\n");
}
else if (tf->tf_trapno == IRQ0_Clock)
{
clock_interrupt_handler() ;
}
else
{
// Unexpected trap: The user process or the kernel has a bug.
//print_trapframe(tf);
if (tf->tf_cs == GD_KT)
panic("unhandled trap in kernel");
else {
//env_destroy(curenv);
return;
}
}
return;
}
void trap(struct Trapframe *tf)
{
kclock_stop();
//struct Trapframe* old_tf = 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);
}
// cprintf("================================================================\n");
// cprintf("kernel: trap to be dispatched: %s # = %d, IP = %x\n", trapname(tf->tf_trapno), tf->tf_trapno, tf->tf_eip) ;
if(tf->tf_trapno == IRQ0_Clock)
{
// cprintf("Clock INT: EIP = %x, ECX = %x, EFlags = %x, SP = %x\n", tf->tf_eip, tf->tf_regs.reg_ecx, tf->tf_eflags, tf->tf_esp);
//uint32 time_bef = time ;
//cprintf("timenow bef lag in trap = %d\n", time);
// int cc=0; int ccc=0;
// for(;cc<35000; cc++)
// {
// ccc++;
// }
//cprintf("timenow aft lag in trap= %d\n", time);
}
// Dispatch based on what type of trap occurred
trap_dispatch(tf);
// Return to the current environment, which should be runnable.
assert(curenv && curenv->env_status == ENV_RUNNABLE);
/// Mahmoud added code: I am here checking to see to where should
/// the trap routine exit, to kernel code or to user code ?
/// refer to : Intel 80386 Reference Programmer's Manual/s09_08.htm
/// chapter 9.8.14
{
if((tf->tf_err & 0x4) == 0)
{
//cprintf("Last trap [%s] came from kernel mode, returning to kernel eip = %x\n",trapname(tf->tf_trapno), tf->tf_eip);
//the Trap came from supervisor mode
//LOG_STATMENT(cprintf("Last trap came from kernel mode, returning to kernel eip = %x",tf->tf_eip));
}
else
{
//cprintf("Last trap [%s] came from USER mode, returning to user eip = %x\n",trapname(tf->tf_trapno), tf->tf_eip);
//the Trap came from user mode
//LOG_STATMENT(cprintf("Last trap came from user mode, returning to user eip = %x",tf->tf_eip));
}
}
// tf = curenv->env_tf ;
env_run(curenv);
}
void setPageReplacmentAlgorithmLRU(){_PageRepAlgoType = PG_REP_LRU;}
void setPageReplacmentAlgorithmCLOCK(){_PageRepAlgoType = PG_REP_CLOCK;}
void setPageReplacmentAlgorithmFIFO(){_PageRepAlgoType = PG_REP_FIFO;}
uint32 isPageReplacmentAlgorithmLRU(){if(_PageRepAlgoType == PG_REP_LRU) return 1; return 0;}
uint32 isPageReplacmentAlgorithmCLOCK(){if(_PageRepAlgoType == PG_REP_CLOCK) return 1; return 0;}
uint32 isPageReplacmentAlgorithmFIFO(){if(_PageRepAlgoType == PG_REP_FIFO) return 1; return 0;}
void detect_modified_loop()
{
struct Frame_Info * slowPtr = LIST_FIRST(&modified_frame_list);
struct Frame_Info * fastPtr = LIST_FIRST(&modified_frame_list);
while (slowPtr && fastPtr) {
fastPtr = LIST_NEXT(fastPtr); // advance the fast pointer
if (fastPtr == slowPtr) // and check if its equal to the slow pointer
{
cprintf("loop detected in modiflist\n");
break;
}
if (fastPtr == NULL) {
break; // since fastPtr is NULL we reached the tail
}
fastPtr = LIST_NEXT(fastPtr); //advance and check again
if (fastPtr == slowPtr) {
cprintf("loop detected in modiflist\n");
break;
}
slowPtr = LIST_NEXT(slowPtr); // advance the slow pointer only once
}
cprintf("finished modi loop detection\n");
}
void fault_handler(struct Trapframe *tf)
{
uint32 fault_va;
// Read processor's CR2 register to find the faulting address
fault_va = rcr2();
//get a pointer to the environment that caused the fault at runtime
struct Env* faulted_env = curenv;
//check the faulted address, is it a table or not ?
//If the directory entry of the faulted address is NOT PRESENT then
if ( (curenv->env_pgdir[PDX(fault_va)] & PERM_PRESENT) != PERM_PRESENT)
{
/* we have a table fault ============================================================= */
//cprintf("[%s] user TABLE fault va %08x\n", curenv->prog_name, fault_va);
faulted_env->tableFaultsCounter ++ ;
table_fault_handler(faulted_env, fault_va);
}
else
{
/* we have normal page fault ============================================================= */
//cprintf("[%08s] user PAGE fault va %08x\n", curenv->prog_name, fault_va);
faulted_env->pageFaultsCounter ++ ;
page_fault_handler(faulted_env, fault_va);
}
/*************************************************************/
//Refresh the TLB cache
tlbflush();
/*************************************************************/
}
//Handle the table fault
void table_fault_handler(struct Env * curenv, uint32 fault_va)
{
cprintf("\nTable fault\n");
uint32 tableWorkingSetSize= env_table_ws_get_size(curenv);
cprintf("Table Working Set Size %u - Max Size: %u\n", tableWorkingSetSize, TABLE_WS_MAX_SIZE);
if(tableWorkingSetSize == TABLE_WS_MAX_SIZE)
{
int Victim_index;
if (isPageReplacmentAlgorithmCLOCK())
{
cprintf("Clock table replacement: \n");
Victim_index=getTableVictimCLOCK(curenv);
}
else if(isPageReplacmentAlgorithmLRU())
{
Victim_index=getTableVictimLRU(curenv);
}
else if(isPageReplacmentAlgorithmFIFO())
panic("FIFO page replacement isn't implemented yet!!");
removeTableVictim(curenv,Victim_index);
placeFaultedTable(curenv,fault_va,Victim_index);
}
else
{
int index=0;
for(;index<TABLE_WS_MAX_SIZE;index ++)
{
if(curenv->tableWorkingSet[index].empty==1)
break;
}
placeFaultedTable(curenv,fault_va,index);
}
}
//Handle the page fault
void page_fault_handler(struct Env * curenv, uint32 fault_va)
{
cprintf("\nPage Fault!!\n");
uint32 pageWorkingSetSize= env_page_ws_get_size(curenv);
cprintf("Page Working Set Size %u - Max Size: %u\n", pageWorkingSetSize, PAGE_WS_MAX_SIZE);
if(pageWorkingSetSize == PAGE_WS_MAX_SIZE )
{
int Victim_index;
if (isPageReplacmentAlgorithmCLOCK())
{
cprintf("Clock page replacement: \n");
Victim_index = getPageVictimCLOCK(curenv);
}
else if(isPageReplacmentAlgorithmLRU())
{
Victim_index = getPageVictimLRU(curenv);
}
else if(isPageReplacmentAlgorithmFIFO())
panic("FIFO page replacement isn't implemented yet!!");
removePageVictim(curenv,Victim_index);
placeFaultedPage(curenv,fault_va,Victim_index);
}
else
{
int index=0;
for(;index<PAGE_WS_MAX_SIZE;index ++)
{
if(curenv->pageWorkingSet[index].empty==1)
break;
}
placeFaultedPage(curenv,fault_va,index);
}
}
int getTableVictimLRU(struct Env* env)
{
return _getVictimLRU(env->tableWorkingSet, env_table_ws_get_size(env));
}
int getPageVictimLRU(struct Env* env)
{
return _getVictimLRU(env->pageWorkingSet, env_page_ws_get_size(env));
}
int getTableVictimCLOCK(struct Env* env)
{
//cprintf("\t[Table]before get victim: %u - ", env->table_last_WS_index);
int vic = _getVictimTableCLOCK(env->tableWorkingSet,env_table_ws_get_size(env), &env->table_last_WS_index, env->env_pgdir);
//cprintf("after get victim: %u\n", env->table_last_WS_index);
return vic;
}
int getPageVictimCLOCK(struct Env* env)
{
return _getVictimPageCLOCK(env->pageWorkingSet, env_page_ws_get_size(env), &env->page_last_WS_index, env->env_pgdir);
}
int _getVictimPageCLOCK(struct WorkingSetElement* ws, int wsSize, uint32* lastWSIndex, uint32* pgDir)
{
int cur_index, currentWSIndex;
currentWSIndex = *lastWSIndex;
//cprintf("CLOCK index: %d\n", currentWSIndex);
uint32* ptr_pageTable;
// Iterate over WS to get the victim page
while(1)
{
// Get the page table corresponding to the current WS Virtual Address
assert(get_page_table(pgDir, (void *)ws[currentWSIndex].virtual_address, &ptr_pageTable) != TABLE_NOT_EXIST);
// If the accessed bit is set to 0, this is the victim
if( (ptr_pageTable[PTX(ws[currentWSIndex].virtual_address)] & PERM_USED) != PERM_USED)
break;
// Wasn't the victim, clear its accessed bit
ptr_pageTable[PTX(ws[currentWSIndex].virtual_address)] &= ~PERM_USED;
currentWSIndex ++;
currentWSIndex %= wsSize;
}
// Update the lastWSIndex to the next WS element
*lastWSIndex = (currentWSIndex + 1)% wsSize;
return currentWSIndex;
}
int _getVictimTableCLOCK(struct WorkingSetElement* ws, int wsSize, uint32* lastWSIndex, uint32* pgDir)
{
int currentWSIndex;
currentWSIndex = *lastWSIndex;
while(1)
{
//cprintf("Table address : %x\n",pgDir[PDX(ws[currentWSIndex].virtual_address)]);
// If the accessed bit is set to 0, this is the victim
if ((pgDir[PDX(ws[currentWSIndex].virtual_address)] & PERM_USED) != PERM_USED)
break;
// Wasn't find victim, clear its accessed bit
pgDir[PDX(ws[currentWSIndex].virtual_address)] &= ~PERM_USED;
currentWSIndex++;
currentWSIndex %= wsSize;
}
// Update the lastWSIndex to the next WS element
*lastWSIndex = (currentWSIndex + 1) % wsSize;
return currentWSIndex;
}
int _getVictimLRU(struct WorkingSetElement* ws, int wsSize)
{
int cur_index, lru_index;
uint32 lru_timestamp = 0xFFFFFFFF;
lru_index = -1;
for(cur_index = 0; cur_index < wsSize; cur_index++)
{
if(lru_timestamp > ws[cur_index].time_stamp)
{
lru_index = cur_index;
lru_timestamp = ws[cur_index].time_stamp;
}
}
assert(lru_index != -1);
return lru_index;
}
void removePageVictim(struct Env* env, int victimIndex)
{
uint32 VA = env->pageWorkingSet[victimIndex].virtual_address;
uint32* ptrTable;
get_page_table(env->env_pgdir, (void*) VA, &ptrTable);
uint32 victimPA = ptrTable[PTX(VA)];
struct Frame_Info* ptrVictimFrame = to_frame_info(EXTRACT_ADDRESS(victimPA));
ptrVictimFrame ->isBuffered = 1;
ptrVictimFrame ->environment = env;
ptrVictimFrame ->va = VA;
pt_set_page_permissions(env, VA, PERM_BUFFERED, PERM_PRESENT);
if ((victimPA & PERM_MODIFIED) != PERM_MODIFIED)
bufferList_add_page(&free_frame_list, ptrVictimFrame);
else
{
bufferList_add_page(&modified_frame_list, ptrVictimFrame);
if (modified_frame_list.size == MAX_MODIFIED_LIST_COUNT)
{
struct Frame_Info* curPtrFrameInfo;
LIST_FOREACH(curPtrFrameInfo,&modified_frame_list)
{
if (curPtrFrameInfo->environment == env)
{
pf_update_env_page(env,(uint32*)curPtrFrameInfo->va,curPtrFrameInfo);
pt_set_page_permissions(env,curPtrFrameInfo->va,0,PERM_MODIFIED);
bufferlist_remove_page(&modified_frame_list,curPtrFrameInfo);
bufferList_add_page(&free_frame_list,curPtrFrameInfo);
}
}
}
}
}
void removeTableVictim(struct Env* env , int victimIndex)
{
uint32* ptrTable;
uint32* VA=(uint32*)env->pageWorkingSet[victimIndex].virtual_address;
pf_write_env_table(env,env->pageWorkingSet[victimIndex].virtual_address,ptrTable);
env->env_pgdir[PDX(ptrTable)] &= ~PERM_PRESENT;
struct Frame_Info* ptr_TableFrameinfo= to_frame_info(K_PHYSICAL_ADDRESS(ptrTable));
free_frame(ptr_TableFrameinfo);
ptr_TableFrameinfo ->references=0;
env_table_ws_clear_entry(env,victimIndex);
}
int placeFaultedPage(struct Env* env,uint32 fault_va,int Index)
{
//cprintf("placeFaultedPage\n");
//uint32 VA = env->pageWorkingSet[Index].virtual_address;
uint32* ptrTable;
uint32 PA;
get_page_table(env->env_pgdir,(void*)fault_va,&ptrTable);
PA = ptrTable[PTX(fault_va)];
if((PA & PERM_BUFFERED ) == PERM_BUFFERED)
{
pt_set_page_permissions(env,fault_va,PERM_PRESENT,PERM_BUFFERED);
struct Frame_Info* ptrBufferedPageFrameInfo= to_frame_info(EXTRACT_ADDRESS(PA));
ptrBufferedPageFrameInfo->isBuffered=0;
if( (PA & PERM_MODIFIED ) == PERM_MODIFIED)
bufferlist_remove_page(&modified_frame_list,ptrBufferedPageFrameInfo);
else
bufferlist_remove_page(&free_frame_list,ptrBufferedPageFrameInfo);
}
else
{
struct Frame_Info* ptrPlacedPageFrameinfo ;
allocate_frame(&ptrPlacedPageFrameinfo);
map_frame(env->env_pgdir,ptrPlacedPageFrameinfo,(void*)fault_va,PERM_PRESENT | PERM_USER | PERM_WRITEABLE | PERM_USED);
int ret = pf_read_env_page(env,(void*)fault_va);
if(ret == E_PAGE_NOT_EXIST_IN_PF)
{
if(fault_va >= USER_HEAP_MAX && fault_va <= USTACKTOP)
pf_add_empty_env_page(env,fault_va);
}
}
env_page_ws_set_entry(env,Index,fault_va);
env->page_last_WS_index = (Index + 1) % PAGE_WS_MAX_SIZE;
return 0;
}
int placeFaultedTable(struct Env* env,uint32 fault_va,int Index)
{
//cprintf("placeFaultedTable , %x\n",env->env_pgdir[PDX(fault_va)]);
uint32* ptrNewTable;
//uint32 directory_entry = env->env_pgdir[PDX(fault_va)];
cprintf("dir index : %u\n",PDX(fault_va));
if(env->env_pgdir[PDX(fault_va)] == 0)
create_page_table(env->env_pgdir,fault_va,&ptrNewTable);
else
{
pf_read_env_table(env,fault_va,ptrNewTable);
pf_remove_env_table(env,fault_va);
}
env_table_ws_set_entry(env,Index,fault_va);
env->table_last_WS_index = (Index + 1) % TABLE_WS_MAX_SIZE;
return 0;
}