diff --git a/arch/x86/include/asm/string.h b/arch/x86/include/asm/string.h index 0eba11ae..206563b4 100644 --- a/arch/x86/include/asm/string.h +++ b/arch/x86/include/asm/string.h @@ -18,8 +18,13 @@ extern "C" { #endif +/* + * This function copies a physical page to its new physical destination. + */ +void copy_page_physical(void* dest, const void * src); + #ifdef HAVE_ARCH_MEMCPY -inline static void *memcpy(void *dest, const void *src, size_t count) +inline static void *memcpy(void* dest, const void *src, size_t count) { int32_t i, j, k; @@ -39,7 +44,7 @@ inline static void *memcpy(void *dest, const void *src, size_t count) #endif #ifdef HAVE_ARCH_MEMSET -inline static void *memset(void *dest, int val, size_t count) +inline static void *memset(void* dest, int val, size_t count) { int32_t i, j; @@ -55,7 +60,7 @@ inline static void *memset(void *dest, int val, size_t count) #endif #ifdef HAVE_ARCH_STRLEN -inline static size_t strlen(const char *str) +inline static size_t strlen(const char* str) { size_t len = 0; uint32_t i, j; @@ -73,11 +78,11 @@ inline static size_t strlen(const char *str) #endif #ifdef HAVE_ARCH_STRNCPY -char* strncpy(char *dest, const char *src, size_t n); +char* strncpy(char* dest, const char* src, size_t n); #endif #ifdef HAVE_ARCH_STRCPY -char* strcpy(char *dest, const char *src); +char* strcpy(char* dest, const char* src); #endif #ifdef __cplusplus diff --git a/arch/x86/kernel/string.asm b/arch/x86/kernel/string.asm index 59ba9e40..62f0d853 100644 --- a/arch/x86/kernel/string.asm +++ b/arch/x86/kernel/string.asm @@ -60,4 +60,39 @@ L3: pop ebp ret +; The following function based on JamesM's kernel development tutorials +; (http://www.jamesmolloy.co.uk/tutorial_html/) +global copy_page_physical +copy_page_physical: + push ebx ; According to __cdecl, we must preserve the contents of EBX. + pushf ; push EFLAGS, so we can pop it and reenable interrupts + ; later, if they were enabled anyway. + cli ; Disable interrupts, so we aren't interrupted. + ; Load these in BEFORE we disable paging! + + mov ebx, [esp+16] ; Source address + mov ecx, [esp+12] ; Destination address + + mov edx, cr0 ; Get the control register... + and edx, 0x7fffffff ; and... + mov cr0, edx ; Disable paging. + + mov edx, 1024 ; 1024*4bytes = 4096 bytes + +.loop: + mov eax, [ebx] ; Get the word at the source address + mov [ecx], eax ; Store it at the dest address + add ebx, 4 ; Source address += sizeof(word) + add ecx, 4 ; Dest address += sizeof(word) + dec edx ; One less word to do + jnz .loop + + mov edx, cr0 ; Get the control register again + or edx, 0x80000000 ; and... + mov cr0, edx ; Enable paging. + + popf ; Pop EFLAGS back. + pop ebx ; Get the original value of EBX back. + ret + SECTION .note.GNU-stack noalloc noexec nowrite progbits diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index 9f8f3c0c..6dd698b7 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -84,27 +84,19 @@ inline static size_t copy_page_table(uint32_t pgd_index, page_table_t* pgt, int* (*counter)++; for(i=0; i<1024; i++) { - if (pgt->entries[i]) { + if (pgt->entries[i] & 0xFFFFF000) { phyaddr = get_page(); if (!phyaddr) continue; if (counter) (*counter)++; - viraddr = map_region(0, phyaddr, 1, MAP_KERNEL_SPACE); - if (!viraddr) { - put_page(phyaddr); - continue; - } - - memcpy((void*) viraddr, (void*) ((pgd_index << 22) | (i << 12)), PAGE_SIZE); + copy_page_physical((void*)phyaddr, (void*) (pgt->entries[i] & 0xFFFFF000)); new_pgt->entries[i] = phyaddr | (pgt->entries[i] & 0xFFF); - // only the child use the copy => unmap copy - if (!vm_free(viraddr, 1)) - atomic_int32_sub(&curr_task->mem_usage, 1); - + // only the child use the copy + atomic_int32_sub(&curr_task->mem_usage, 1); } }