791,7 → 791,9 |
link_t *cur; |
ipl_t ipl; |
int page_flags; |
uintptr_t old_frame; |
uintptr_t *old_frame; |
index_t frame_idx; |
count_t used_pages; |
|
/* Flags for the new memory mapping */ |
page_flags = area_flags_to_page_flags(flags); |
818,13 → 820,35 |
base = area->base; |
|
/* |
* Compute total number of used pages in the used_space B+tree |
*/ |
used_pages = 0; |
|
for (cur = area->used_space.leaf_head.next; |
cur != &area->used_space.leaf_head; cur = cur->next) { |
btree_node_t *node; |
unsigned int i; |
|
node = list_get_instance(cur, btree_node_t, leaf_link); |
for (i = 0; i < node->keys; i++) { |
used_pages += (count_t) node->value[i]; |
} |
} |
|
/* An array for storing frame numbers */ |
old_frame = malloc(used_pages * sizeof(uintptr_t), 0); |
|
/* |
* Start TLB shootdown sequence. |
*/ |
tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages); |
|
/* |
* Visit only the pages mapped by used_space B+tree. |
* Remove used pages from page tables and remember their frame |
* numbers. |
*/ |
frame_idx = 0; |
|
for (cur = area->used_space.leaf_head.next; |
cur != &area->used_space.leaf_head; cur = cur->next) { |
btree_node_t *node; |
841,13 → 865,10 |
pte = page_mapping_find(as, b + j * PAGE_SIZE); |
ASSERT(pte && PTE_VALID(pte) && |
PTE_PRESENT(pte)); |
old_frame = PTE_GET_FRAME(pte); |
old_frame[frame_idx++] = PTE_GET_FRAME(pte); |
|
/* Remove old mapping and insert the new one */ |
/* Remove old mapping */ |
page_mapping_remove(as, b + j * PAGE_SIZE); |
page_mapping_insert(as, b + j * PAGE_SIZE, |
old_frame, page_flags); |
|
page_table_unlock(as, false); |
} |
} |
864,7 → 885,38 |
*/ |
as_invalidate_translation_cache(as, area->base, area->pages); |
tlb_shootdown_finalize(); |
|
|
/* |
* Map pages back in with new flags. This step is kept separate |
* so that there's no instant when the memory area could be |
* accesed with both the old and the new flags at once. |
*/ |
frame_idx = 0; |
|
for (cur = area->used_space.leaf_head.next; |
cur != &area->used_space.leaf_head; cur = cur->next) { |
btree_node_t *node; |
unsigned int i; |
|
node = list_get_instance(cur, btree_node_t, leaf_link); |
for (i = 0; i < node->keys; i++) { |
uintptr_t b = node->key[i]; |
count_t j; |
|
for (j = 0; j < (count_t) node->value[i]; j++) { |
page_table_lock(as, false); |
|
/* Insert the new mapping */ |
page_mapping_insert(as, b + j * PAGE_SIZE, |
old_frame[frame_idx++], page_flags); |
|
page_table_unlock(as, false); |
} |
} |
} |
|
free(old_frame); |
|
mutex_unlock(&area->lock); |
mutex_unlock(&as->lock); |
interrupts_restore(ipl); |