pd_entry* vmmngr_pdirectory_lookup_entry(pdirectory* p, virtual_addr addr) { if (p) return &p->entries[PAGE_DIR_INDEX(addr)]; set_last_error(EINVAL, VMEM_BAD_ARGUMENT, EO_VMMNGR); return 0; }
void do_page_fault (process_t *proc, unsigned int linear_addr, long error_code) { page_frame_t *new_page, *page_frame; unsigned int phys_frame_addr; pagetable_entry_t *pte; int pf_ok; //Only handle usermode writes to present pages (not present ones later (pagein)) //if ((error_code & PAGE_FAULT_P) && // (error_code & PAGE_FAULT_RW) && // (error_code & PAGE_FAULT_US)) if (error_code & PAGE_FAULT_P) { // // CHECK IF WE REALLY SHOULD COPY THIS // (with vm_blocks) // pf_ok = 0; //Only write pagefaults handled if (error_code & PAGE_FAULT_RW) { if ((linear_addr >= proc->vm_data.vm_start) && (linear_addr < proc->vm_data.vm_end) && (proc->vm_data.vm_flags & VM_READWRITE)) pf_ok = 1; if ((linear_addr >= proc->vm_stack.vm_start) && (linear_addr < proc->vm_stack.vm_end) && (proc->vm_stack.vm_flags & VM_READWRITE)) pf_ok = 1; if ((linear_addr >= proc->vm_kernel_stack.vm_start) && (linear_addr < proc->vm_kernel_stack.vm_end) && (proc->vm_kernel_stack.vm_flags & VM_READWRITE)) pf_ok = 1; } if (!pf_ok) { printf ("*real* page fault (out of bounds), should terminate task!\n"); printf ("present=%s, write=%s, usermode=%s, address=0x%x, dir=0x%x\n", ((int) error_code & PAGE_FAULT_P) ? "true" : "false", ((int) error_code & PAGE_FAULT_RW) ? "true" : "false", ((int) error_code & PAGE_FAULT_US) ? "true" : "false", linear_addr, (int) (proc->tss.cr3)); printf ("data start 0x%x, data end 0x%x, flags 0x%x\n", (int) proc->vm_data.vm_start, (int) proc->vm_data.vm_end, (int) proc->vm_data.vm_flags); printf ("stack start 0x%x, stack end 0x%x, flags 0x%x\n", (int) proc->vm_stack.vm_start, (int) proc->vm_stack.vm_end, (int) proc->vm_stack.vm_flags); while(1); } //Get dir pte = (pagetable_entry_t *) proc->tss.cr3; //Get table from dir pte = (pagetable_entry_t *) PTE_TO_PHYSICAL(pte[PAGE_DIR_INDEX(linear_addr)]); //Get page from table phys_frame_addr = PTE_TO_PHYSICAL(pte[PAGE_TABLE_INDEX(linear_addr)]); //Check use count of this page frame page_frame = &page_frames[PHYS_TO_FRAME_NR (phys_frame_addr)]; if (page_frame->count > 1) { //Page in use by others, we need to copy new_page = get_free_page(); if (new_page == NULL) panic ("Can't COW, no free pages!"); //Copy page //printf ("COW(copy, 0x%x->0x%x)\n", phys_frame_addr, new_page->page_frame_nr * PAGE_SIZE); copy_page (phys_frame_addr, new_page->page_frame_nr * PAGE_SIZE); //Remap pagetable map_page (proc, new_page->page_frame_nr * PAGE_SIZE, linear_addr & PHYS_PAGE_MASK, PAGE_PRESENT | PAGE_USER | PAGE_WRITEABLE); //Decrease use count page_frame->count--; } else if (page_frame->count == 1) { //The page is not in use by others, just remap //printf ("COW(remap, 0x%x)\n", linear_addr); //Remap pagetable map_page (proc, phys_frame_addr, linear_addr & PHYS_PAGE_MASK, PAGE_PRESENT | PAGE_USER | PAGE_WRITEABLE); } else { printf ("Page frame has invalid use count!\n"); while (1); } //Schedule next process schedule(); } else { printf ("*real* page fault (page not present), should terminate task!\n"); printf ("present=%s, write=%s, usermode=%s, address=0x%x, dir=0x%x\n", ((int) error_code & PAGE_FAULT_P) ? "true" : "false", ((int) error_code & PAGE_FAULT_RW) ? "true" : "false", ((int) error_code & PAGE_FAULT_US) ? "true" : "false", linear_addr, (int) (proc->tss.cr3)); printf ("data start 0x%x, data end 0x%x, flags 0x%x\n", (int) proc->vm_data.vm_start, (int) proc->vm_data.vm_end, (int) proc->vm_data.vm_flags); printf ("stack start 0x%x, stack end 0x%x, flags 0x%x\n", (int) proc->vm_stack.vm_start, (int) proc->vm_stack.vm_end, (int) proc->vm_stack.vm_flags); while(1); } }