diff --git a/arch/x86/include/asm/string.h b/arch/x86/include/asm/string.h index ee39ff4a..ad9c0520 100644 --- a/arch/x86/include/asm/string.h +++ b/arch/x86/include/asm/string.h @@ -26,13 +26,6 @@ extern "C" { #endif -/** @brief Copy a physical page to another physical destination - * - * @param dest Destination address - * @param src Source address - */ -void copy_page_physical(void* dest, const void * src); - #ifdef HAVE_ARCH_MEMCPY #ifdef CONFIG_ROCKCREEK diff --git a/include/metalsvm/mmu.h b/include/metalsvm/mmu.h index 71cfab64..15284900 100644 --- a/include/metalsvm/mmu.h +++ b/include/metalsvm/mmu.h @@ -71,9 +71,7 @@ static inline size_t get_page(void) { return get_pages(1); } * @param phyaddr Physical address of the first page * @param npages Number of pages * - * @return - * - 0 on success - * - -EINVAL (-22) on failure + * @return number of pages which were marked as used before calling */ int put_pages(size_t phyaddr, size_t npages); @@ -83,6 +81,23 @@ int put_pages(size_t phyaddr, size_t npages); */ static inline int put_page(size_t phyaddr) { return put_pages(phyaddr, 1); } +/** @brief Copy a physical page frames + * + * @param psrc physical address of source page frames + * @param pdest physical address of source page frames + * @param npages number of pages + * @return + * - 0 on success + * - -1 on failure + */ +int copy_pages(size_t pdest, size_t psrc, size_t npages); + +/** @brief Copy a single page + * + * Convenience function: uses copy_pages(pdest, psrc, 1); + */ +static inline int copy_page(size_t pdest, size_t psrc) { return copy_pages(pdest, psrc, 1); } + #ifdef __cplusplus } #endif diff --git a/mm/memory.c b/mm/memory.c index 82155ef5..464ffa2b 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -167,6 +167,36 @@ int put_pages(size_t phyaddr, size_t npages) return ret; } +int copy_pages(size_t pdest, size_t psrc, size_t npages) +{ + size_t viraddr; + size_t vdest, vsrc; + + // allocate virtual memory areas + viraddr = vma_alloc(2*npages*PAGE_SIZE, VMA_HEAP); + if (BUILTIN_EXPECT(!viraddr, 0)) + return -ENOMEM; + + // map pages + vsrc = map_region(viraddr, psrc, npages, MAP_KERNEL_SPACE); + vdest = map_region(viraddr+npages*PAGE_SIZE, pdest, npages, MAP_KERNEL_SPACE); + if (BUILTIN_EXPECT(!vsrc || !vdest, 0)) { + unmap_region(viraddr, 2*npages); + return -ENOMEM; + } + + kprintf("copy_pages: copy %u pages from: %#lx (%#lx) to %#lx (%#lx)\n", npages, vsrc, psrc, vdest, pdest); // TODO remove + + // copy the whole page + memcpy((void*) vdest, (void*) vsrc, npages*PAGE_SIZE); + + // householding + unmap_region(viraddr, 2*npages); + vma_free(viraddr, viraddr+2*npages*PAGE_SIZE); + + return pdest; +} + int mmu_init(void) { unsigned int i;