Beispiel #1
0
static void handler(enum exception_type type, int subtype, void *vaddr,
        arch_registers_state_t *regs, arch_registers_fpu_state_t *fpuregs)
{
    debug_printf("got exception %d(%d) on %p\n", type, subtype, vaddr);
    assert(type == EXCEPT_PAGEFAULT);
    assert(subtype == PAGEFLT_WRITE);
    uintptr_t addr = (uintptr_t) vaddr;
    uintptr_t faddr = addr & ~BASE_PAGE_MASK;
    uintptr_t base = (uintptr_t) cow_vbuf;
    if (addr < base || addr >= base + BUFSIZE) {
        debug_printf("unexpected write pagefault on %p\n", vaddr);
        exit(1);
    }
    assert(cow_frame_count);
    debug_printf("got expected write pagefault on %p, creating copy of page\n", vaddr);
    // get and map copy of page
    size_t frame_id = (addr - base) / BASE_PAGE_SIZE;
    debug_printf("remapping frame %zu\n", frame_id);
    struct memobj *m = vregion_get_memobj(cow_vregion);
    assert(m);
    errval_t err;
    struct capref retframe;
    struct capref f = (struct capref) { .cnode = cow_frames, .slot = frame_id };
    size_t retoff;
    struct vregion *vr;
    void *buf;
    // copy data from faulting page to new page
    err = vspace_map_one_frame(&buf, BASE_PAGE_SIZE, f, NULL, &vr);
    assert(err_is_ok(err));
    memcpy(buf, (void *)faddr, BASE_PAGE_SIZE);
    vregion_destroy(vr);
    err = m->f.unfill(m, frame_id * BASE_PAGE_SIZE, &retframe, &retoff);
    assert(err_is_ok(err));
    err = m->f.fill(m, frame_id * BASE_PAGE_SIZE, f, BASE_PAGE_SIZE);
    assert(err_is_ok(err));
    err = m->f.pagefault(m, cow_vregion, frame_id * BASE_PAGE_SIZE, 0);
    assert(err_is_ok(err));
    err = m->f.protect(m, cow_vregion, frame_id * BASE_PAGE_SIZE,
            BASE_PAGE_SIZE, VREGION_FLAGS_READ_WRITE);
    assert(err_is_ok(err));
}
Beispiel #2
0
/**
 * \brief Destroy the given region
 *
 * \return SYS_ERR_OK on success, error code on failure
 *
 * \bug This only works if the memobj type is memobj_one_frame.
 */
errval_t vregion_destroy(struct vregion *vregion)
{
    errval_t err;

    struct vspace *vspace = vregion_get_vspace(vregion);
    if (vspace != NULL) {
        err = vspace_remove_vregion(vspace, vregion);
        if (err_is_fail(err)) {
            return err_push(err, LIB_ERR_VSPACE_REMOVE_REGION);
        }
    }

    struct memobj *memobj = vregion_get_memobj(vregion);
    if (memobj != NULL) {
        err = memobj->f.unmap_region(memobj, vregion);
        if (err_is_fail(err)) {
            return err_push(err, LIB_ERR_MEMOBJ_UNMAP_REGION);
        }
    }

    return SYS_ERR_OK;
}