From 92b2badf717f74bb1c0ded6721ef85eaeb4b619c Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 14 Nov 2013 13:08:56 +0100 Subject: [PATCH] implemented copy_page_map() (more testing needed) --- arch/x86/mm/page64.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/arch/x86/mm/page64.c b/arch/x86/mm/page64.c index 25efb01a..76489afe 100644 --- a/arch/x86/mm/page64.c +++ b/arch/x86/mm/page64.c @@ -101,6 +101,63 @@ static inline size_t map_to_virt(size_t addr) { return canonicalize(addr << (map_to_level(addr) * PAGE_MAP_SHIFT)); } + +/* + * Copy page maps using recursion + * + * @param from pointer to virtual address of source page tables + * @param to pointer to virtual address of destination page tables + * @param copy flags what should be copied (see #define COPY_*) + * @return number of new allocated page frames (for tables only) + */ +static int copy_page_map(page_map_t *src, page_map_t *dest, int copy) +{ + page_map_t* next_src, * next_dest; + + int ret = 0; + uint32_t i; + for(i=0; ientries[i] & PG_PRESENT)) + // skip empty entries + dest->entries[i] = 0; + else if (src->entries[i] & PG_USER) { + size_t phys; + kprintf("d:%p (%s: 0x%012lx) -> %p\n", &src->entries[i], map_to_lvlname((size_t) &src->entries[i]), map_to_virt((size_t) &src->entries[i]), &dest->entries[i]); + + // deep copy user tables + if ((size_t) src >= PAGE_PGT) { + phys = get_page(); + if (BUILTIN_EXPECT(!phys, 0)) + return -ENOMEM; + + dest->entries[i] = phys|(src->entries[i] & ~PAGE_MASK); + + // reuse pointers to next lower page map tables + next_src = (page_map_t*) ((size_t) &src->entries[i] << 9); + next_dest = (page_map_t*) ((size_t) &dest->entries[i] << 9); + + ret += 1 + copy_page_map(next_src, next_dest, copy); + } + // deep copy page frame + else { + if (copy) { + phys = copy_page_frame((size_t*) src->entries[i]); + dest->entries[i] = phys|(src->entries[i] & ~PAGE_MASK); + } + kprintf("c: %p (%lx)\n", &src->entries[i], src->entries[i]); + } + } + // shallow copy kernel only tables + else { + kprintf("s:%p (%s: 0x%012lx) -> %p\n", &src->entries[i], map_to_lvlname((size_t) &src->entries[i]), map_to_virt((size_t) &src->entries[i]), &dest->entries[i]); + dest->entries[i] = src->entries[i]; + } + } + + kputs("r\n"); + return ret; +} + int create_page_map(task_t* task, int copy) { size_t phys;