961,6 → 961,78 |
AS = new_as; |
} |
|
/** Write directly into a page, bypassing area flags. |
* |
* This allows a debugger to write into a page that is mapped read-only |
* (such as the text segment). Naturally, this is only possible if the |
* correspoinding area is not shared and anonymous. |
* |
* FIXME: doesn't take into account that it isn't a good idea to write |
* into the frame if the area is shared or isn't anonymous |
*/ |
static int debug_write_inside_page(uintptr_t va, void *data, size_t n) |
{ |
uintptr_t page; |
pte_t *pte; |
as_area_t *area; |
uintptr_t frame; |
ipl_t ipl; |
int rc; |
|
page = ALIGN_DOWN(va, PAGE_SIZE); |
ASSERT(ALIGN_DOWN(va + n - 1, PAGE_SIZE) == page); |
|
restart: |
mutex_lock(&AS->lock); |
ipl = interrupts_disable(); |
area = find_area_and_lock(AS, page); |
|
pte = page_mapping_find(AS, page); |
if (! (pte && PTE_VALID(pte) && PTE_PRESENT(pte)) ) { |
mutex_unlock(&area->lock); |
mutex_unlock(&AS->lock); |
interrupts_restore(ipl); |
|
rc = as_page_fault(page, PF_ACCESS_WRITE, NULL); |
if (rc == AS_PF_FAULT) return EINVAL; |
|
goto restart; |
} |
|
frame = PTE_GET_FRAME(pte); |
memcpy((void *)(PA2KA(frame) + (va - page)), data, n); |
|
mutex_unlock(&area->lock); |
mutex_unlock(&AS->lock); |
interrupts_restore(ipl); |
|
return EOK; |
} |
|
/** Write data bypassing area flags. |
* |
* See debug_write_inside_page(). |
*/ |
int as_debug_write(uintptr_t va, void *data, size_t n) |
{ |
size_t now; |
int rc; |
|
while (n > 0) { |
now = ALIGN_UP(va, PAGE_SIZE) - va; |
if (now > n) now = n; |
|
rc = debug_write_inside_page(va, data, now); |
if (rc != EOK) return rc; |
|
va += now; |
data += now; |
n -= now; |
} |
|
return EOK; |
} |
|
/** Convert address space area flags to page flags. |
* |
* @param aflags Flags of some address space area. |