inline static void *malloc_pages(size_t len, size_t alignment) { void *p; CHECK_USED_AGAINST_MAX(len); p = smemalign(alignment, len); memset(p, 0, len); ACTUALLY_ALLOCATING_PAGES(len); LOGICALLY_ALLOCATING_PAGES(len); return p; }
/** @brief Function deals with the page fault * * This is an amazing function. * * @param void * @return void */ void page_fault_handler(void){ int fault_addr = get_cr2(); mutex_lock(&cur_task->pcb_mutex); uint32_t align_addr = fault_addr & PGALIGN_MASK; uint32_t *ptep = NULL; Page *phy_page = NULL; phy_page = page_lookup(cur_task->task_pgdir, align_addr, &ptep); uint32_t pte = *ptep; /** Catch COW page fualt */ if((ptep != NULL) &&(pte & PTE_P) && (pte & PTE_COW)) { mutex_lock(&mtx_m.frame_mutex); if(phy_page->pp_ref == 1) { *ptep = (pte | PTE_W) &(~PTE_COW); mutex_unlock(&mtx_m.frame_mutex); } else{ mutex_unlock(&mtx_m.frame_mutex); if(pte & PTE_RWMARK){ lprintf("ERROR: Cannot access TXT or ro_data area!"); mutex_unlock(&cur_task->pcb_mutex); sys_vanish(); return; } Page *new_page = page_alloc(); if(new_page == NULL){ lprintf("ERROR: No pages for COW in page_fault_handler"); mutex_unlock(&cur_task->pcb_mutex); sys_vanish(); return; } uint32_t *temp_page = smemalign(PAGE_SIZE, PAGE_SIZE); if (temp_page == NULL){ lprintf("ERROR: No memory for temp_page in page_fault_handler!"); mutex_unlock(&cur_task->pcb_mutex); sys_vanish(); return; } /* Copy the physical page to a temporary page in kernel space */ memcpy((void*)temp_page, (void*)align_addr, PAGE_SIZE); if(page_insert(cur_task->task_pgdir, new_page, align_addr, PTE_P | PTE_U | PTE_W) < 0) { lprintf("ERROR: No memory for COW in page_fault_handler"); mutex_unlock(&cur_task->pcb_mutex); sys_vanish(); return; } /* Copy the content to the new mapped physical page */ memcpy((void*)align_addr, (void*)temp_page, PAGE_SIZE); /* Free the temp physical page */ sfree(temp_page, PAGE_SIZE); mutex_lock(&mtx_m.frame_mutex); phy_page->pp_ref--; mutex_unlock(&mtx_m.frame_mutex); } } /** Catch the ZFOD */ else if ((ptep != NULL) &&(pte & PTE_P) && (pte & PTE_ZFOD)) { Page *pg = page_alloc(); if(pg == NULL){ lprintf("ERROR: No pages for ZFOD in page_fault_handler"); mutex_unlock(&cur_task->pcb_mutex); sys_vanish(); return; } uint32_t perm = PTE_P | PTE_U | PTE_W; if(page_insert(cur_task->task_pgdir, pg, align_addr, perm) < 0) { lprintf("ERROR: No memory for ZFOD in page_fault_handler"); mutex_unlock(&cur_task->pcb_mutex); sys_vanish(); return; } bzero((void*)align_addr, PAGE_SIZE); } /* Check if installed swexn handler can fix this up */ else if(cur_thread->swexn_eip != NULL) { mutex_unlock(&cur_task->pcb_mutex); swexn_handler(HAS_ERROR_CODE, SWEXN_CAUSE_PAGEFAULT); return; } else{ mutex_unlock(&cur_task->pcb_mutex); sys_vanish(); return; } mutex_unlock(&cur_task->pcb_mutex); return; }