775,6 → 775,100 |
return true; |
} |
|
/** Change adress area flags. |
* |
* The idea is to have the same data, but with a different access mode. |
* This is needed e.g. for writing code into memory and then executing it. |
* In order for this to work properly, this may copy the data |
* into private anonymous memory (unless it's already there). |
* |
* @param as Address space. |
* @param flags Flags of the area memory. |
* @param address Address withing the area to be changed. |
* |
* @return Zero on success or a value from @ref errno.h on failure. |
*/ |
int as_area_change_flags(as_t *as, int flags, uintptr_t address) |
{ |
as_area_t *area; |
uintptr_t base; |
link_t *cur; |
ipl_t ipl; |
|
ipl = interrupts_disable(); |
mutex_lock(&as->lock); |
|
area = find_area_and_lock(as, address); |
if (!area) { |
mutex_unlock(&as->lock); |
interrupts_restore(ipl); |
return ENOENT; |
} |
|
if (area->sh_info || area->backend != &anon_backend) { |
/* Copying shared areas not supported yet */ |
/* Copying non-anonymous memory not supported yet */ |
mutex_unlock(&as->lock); |
interrupts_restore(ipl); |
return ENOTSUP; |
} |
|
base = area->base; |
|
/* |
* 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. |
*/ |
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; |
pte_t *pte; |
|
for (j = 0; j < (count_t) node->value[i]; j++) { |
page_table_lock(as, false); |
pte = page_mapping_find(as, b + j * PAGE_SIZE); |
ASSERT(pte && PTE_VALID(pte) && |
PTE_PRESENT(pte)); |
|
/* Remove old mapping and insert the new one */ |
page_mapping_remove(as, b + j * PAGE_SIZE); |
page_mapping_insert(as, b + j * PAGE_SIZE, |
PTE_GET_FRAME(pte), flags); |
page_table_unlock(as, false); |
} |
} |
} |
|
/* |
* Finish TLB shootdown sequence. |
*/ |
|
tlb_invalidate_pages(as->asid, area->base, area->pages); |
/* |
* Invalidate potential software translation caches (e.g. TSB on |
* sparc64). |
*/ |
as_invalidate_translation_cache(as, area->base, area->pages); |
tlb_shootdown_finalize(); |
|
mutex_unlock(&area->lock); |
mutex_unlock(&as->lock); |
interrupts_restore(ipl); |
|
return 0; |
} |
|
|
/** Handle page fault within the current address space. |
* |
* This is the high-level page fault handler. It decides |
1770,6 → 1864,12 |
return (unative_t) as_area_resize(AS, address, size, 0); |
} |
|
/** Wrapper for as_area_change_flags(). */ |
unative_t sys_as_area_change_flags(uintptr_t address, int flags) |
{ |
return (unative_t) as_area_change_flags(AS, flags, address); |
} |
|
/** Wrapper for as_area_destroy(). */ |
unative_t sys_as_area_destroy(uintptr_t address) |
{ |