Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3012 → Rev 3013

/branches/tracing/kernel/generic/src/mm/as.c
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.