/** * temp_phys_page - väliaikainen käyttökelpoinen osoitin fyysiseen sivuun * @page: virtuaalisivun numero (ei oikea sivunumero vaan tämän funktion asia) * @phys_page: fyysinen sivu, johon virtuaalinen sivu pannaan osoittamaan, tai 0 poistoa varten **/ void * temp_phys_page(uint_t page, uint_t phys_page) { static uint32_t used[1 + (TEMP_PAGES_COUNT - 1) / 32]; uint_t used_n, used_b, skip_check = 1; if (page < TEMP_PAGES_COUNT) { used_n = page / 32; used_b = page % 32; page += TEMP_PAGES_START; } else if (page == TEMPORARY_PAGE_DIRECTORY || page == TEMPORARY_PAGE_TABLE) { used_n = 0; used_b = 32; } else { panic("temp_phys_page abuse!\n"); return 0; } void *address = PAGE_TO_ADDR(page); if (phys_page == 0) { KERNEL_PT_ADDR[page].pagenum = page; asm_invlpg(address); if (!skip_check) { used[used_n] &= ~(1 << used_b); } return 0; } if (!skip_check) { if (used[used_n] & (1 << used_b)) { panic("temp_phys_page IN USE!\n"); return 0; } used[used_n] |= (1 << used_b); } KERNEL_PT_ADDR[page].pagenum = phys_page; asm_invlpg(address); return address; }
union gdt_entry gdt[32]; struct gdt_ptr gdt_ptr; struct kernel_tasks kernel_tasks = { .tss_for_hw_int = { .cs = KERNEL_CS_SEL, .eip = (uintptr_t) irq_task, .ds = KERNEL_DS_SEL, .es = KERNEL_DS_SEL, .fs = KERNEL_DS_SEL, .gs = KERNEL_DS_SEL, .ss = KERNEL_DS_SEL, .esp = (uintptr_t) &stack_for_hw_int_task, .ebp = (uintptr_t) &stack_for_hw_int_task, .cr3 = (uintptr_t) PAGE_TO_ADDR(KERNEL_PAGE_DIRECTORY), .eflags = 0x02, }, .tss_for_page_fault = { .cs = KERNEL_CS_SEL, .eip = (uintptr_t) asm_page_fault_handler, .ds = KERNEL_DS_SEL, .es = KERNEL_DS_SEL, .fs = KERNEL_DS_SEL, .gs = KERNEL_DS_SEL, .ss = KERNEL_DS_SEL, .esp = (uintptr_t) &stack_for_page_fault, .ebp = (uintptr_t) &stack_for_page_fault, .cr3 = (uintptr_t) PAGE_TO_ADDR(KERNEL_PAGE_DIRECTORY), .eflags = 0x02, },
/** * Allocate a memory block. * * On a memory request, the allocator returns the head of a free-list of the * matching size (i.e., smallest block that satisfies the request). If the * free-list of the matching block size is empty, then a larger block size will * be selected. The selected (large) block is then splitted into two smaller * blocks. Among the two blocks, left block will be used for allocation or be * further splitted while the right block will be added to the appropriate * free-list. * * @param size size in bytes * @return memory block address */ void *buddy_alloc(int size) { if(size > (1<<MAX_ORDER)) { printf("Size too big for memory space\n"); return NULL; } int newOrder = MIN_ORDER; while(size > (1<<newOrder)) { newOrder++; } // printf("Received request of order: %d\n", newOrder); int splits = 0; Node* temp = find_order(newOrder); while(temp == 0) { newOrder++; temp = find_order(newOrder); splits++; } if(splits == 0) { temp->free = 0; return PAGE_TO_ADDR(temp->pageIndex); } while(splits > 0) { // printf("Splitting node of order: %d\n", temp->order); Node* tempLeft = init_node(temp, temp->pageIndex); int pageRight = ADDR_TO_PAGE(BUDDY_ADDR(PAGE_TO_ADDR((unsigned long)temp->pageIndex), (temp->order-1))); Node* tempRight = init_node(temp, pageRight); temp->left = tempLeft; temp->right = tempRight; temp->free = 0; temp = temp->left; splits--; } temp->free = 0; return PAGE_TO_ADDR(temp->pageIndex); /*old code int index = MIN_ORDER; while(size > (1<<index)) { index++; } struct list_head head = free_area[index]; if(!list_empty(&head)) { page_t* page = list_entry(head.next, page_t, list); page->order = index; return PAGE_TO_ADDR((unsigned long) (g_pages - page)); } else { int splits = 1; index++; while(index <= MAX_ORDER && list_empty(&(free_area[index]))) { splits++; index++; } head = free_area[index]; page_t* page = list_entry(head.next, page_t, list); while(splits > 0) { page_t buddy = g_pages[ADDR_TO_PAGE(BUDDY_ADDR(PAGE_TO_ADDR((unsigned long) (page - g_pages)), (index-1)))]; buddy.order = index - 1; list_add(&buddy.list, &free_area[index-1]); splits--; index--; } page->order = index; return PAGE_TO_ADDR((unsigned long) (g_pages - page)); }*/ return NULL; }
int handle_user_pagefault(void) { phys_pagedir = active_process->mem.phys_pd; cr2 = asm_get_cr2(); dpage = ADDR_TO_PAGE(cr2); doffset = eip - (char*) PAGE_TO_ADDR(dpage); dpde = dpage / MEMORY_PE_COUNT; dpte = dpage % MEMORY_PE_COUNT; eip = (void*) kernel_tasks.tss_for_active_thread.eip; cpage = ADDR_TO_PAGE(eip); coffset = eip - (char*) PAGE_TO_ADDR(cpage); cpde = cpage / MEMORY_PE_COUNT; cpte = cpage % MEMORY_PE_COUNT; const char *panic_msg; uint_t new_location; page_entry_t *pd, *pt; if (!(pd = temp_page_directory(phys_pagedir))) { goto no_pd_got; } if (!pd[dpde].pagenum) { goto no_pt_page; } if ((dpde >= KMEM_PDE_END) && !pd[dpde].user) { printf("User process = %d, thread = %d\n", active_pid, active_tid); printf("Trying to access address %p (page %d).\n", asm_get_cr2(), ADDR_TO_PAGE(asm_get_cr2())); printf("(!pd[dpde].user)\n"); panic("Bug in memory handling!"); } if (!pd[dpde].present) { new_location = swap_in(phys_pagedir, pd[dpde].pagenum); if (!new_location) { goto no_pt_page_swapped; } pd[dpde].pagenum = new_location; pd[dpde].present = 1; } if (!(pt = temp_page_table(pd[dpde].pagenum))) { goto no_pt_got; } if (dpde && dpte && !pt[dpte].pagenum) { goto no_cr2_page; } if (!pt[dpte].user) { return user_tries_kernel(); } if (dpde < KMEM_PDE_END) { printf("User process = %d, thread = %d\n", active_pid, active_tid); printf("Trying to access address %p (page %d).\n", asm_get_cr2(), ADDR_TO_PAGE(asm_get_cr2())); printf("(dpde < KMEM_PDE_END) && pt[dpte].user)\n"); panic("Bug in memory handling!"); return user_tries_kernel(); } if (!pt[dpte].present) { new_location = swap_in(phys_pagedir, pt[dpte].pagenum); if (!new_location) { goto no_cr2_page_swapped; } pt[dpte].pagenum = new_location; pt[dpte].present = 1; } return 0; // Ratkaistu. :) no_pd_got: panic_msg = "Page fault: failed getting PD from RAM!"; goto fail; no_pt_page: panic_msg = "Page fault; page missing from PD!"; goto fail; no_pt_page_swapped: panic_msg = "Page fault; failed swapping PT to RAM!"; goto fail; no_pt_got: panic_msg = "Page fault; failed getting PT from RAM!"; goto fail; no_cr2_page: panic_msg = "Page fault; page missing from PT!"; goto fail; no_cr2_page_swapped: panic_msg = "Page fault; failed swapping page to RAM!"; goto fail; fail: printf("Page Fault!\nThread %i, process %i\n", active_tid, active_pid); printf("Trying to access address %p (page %d).\n", cr2, dpage); printf("%s\n", panic_msg); return -1; }