implemented copy_page_map() (more testing needed)

This commit is contained in:
Steffen Vogel 2013-11-14 13:08:56 +01:00
parent cdcd9e7d20
commit 92b2badf71

View file

@ -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; i<PAGE_MAP_ENTRIES; i++) {
if (!(src->entries[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;