Commit e3127ae0 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

exec: reorganize address_space_map



First of all, rename "todo" to "done".

Second, clearly separate the case of done == 0 with the case of done != 0.
This will help handling reference counting in the next patch.

Third, this test:

             if (memory_region_get_ram_addr(mr) + xlat != raddr + todo) {

does not guarantee that the memory region is the same across two iterations
of the while loop.  For example, you could have two blocks:

A) size 640 K, mapped at physical address 0, ram_addr_t 0
B) size 64 K, mapped at physical address 0xa0000, ram_addr_t 0xa0000

then mapping 1 M starting at physical address zero will erroneously treat
B as the continuation of block A.  qemu_ram_ptr_length ensures that no
invalid memory is accessed, but it is still a pointless complication of
the algorithm.  The patch makes the logic clearer with an explicit test
that the memory region is the same.

Reviewed-by: default avatarJan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 1b5ec234
Loading
Loading
Loading
Loading
+38 −33
Original line number Diff line number Diff line
@@ -2065,20 +2065,20 @@ void *address_space_map(AddressSpace *as,
                        bool is_write)
{
    hwaddr len = *plen;
    hwaddr todo = 0;
    hwaddr l, xlat;
    MemoryRegion *mr;
    ram_addr_t raddr = RAM_ADDR_MAX;
    ram_addr_t rlen;
    void *ret;
    hwaddr done = 0;
    hwaddr l, xlat, base;
    MemoryRegion *mr, *this_mr;
    ram_addr_t raddr;

    if (len == 0) {
        return NULL;
    }

    while (len > 0) {
    l = len;
    mr = address_space_translate(as, addr, &xlat, &l, is_write);

    if (!memory_access_is_direct(mr, is_write)) {
            if (todo || bounce.buffer) {
                break;
        if (bounce.buffer) {
            return NULL;
        }
        bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
        bounce.addr = addr;
@@ -2090,22 +2090,27 @@ void *address_space_map(AddressSpace *as,
        *plen = l;
        return bounce.buffer;
    }
        if (!todo) {
            raddr = memory_region_get_ram_addr(mr) + xlat;
        } else {
            if (memory_region_get_ram_addr(mr) + xlat != raddr + todo) {
                break;
            }
        }

    base = xlat;
    raddr = memory_region_get_ram_addr(mr);

    for (;;) {
        len -= l;
        addr += l;
        todo += l;
        done += l;
        if (len == 0) {
            break;
        }
    rlen = todo;
    ret = qemu_ram_ptr_length(raddr, &rlen);
    *plen = rlen;
    return ret;

        l = len;
        this_mr = address_space_translate(as, addr, &xlat, &l, is_write);
        if (this_mr != mr || xlat != base + done) {
            break;
        }
    }

    *plen = done;
    return qemu_ram_ptr_length(raddr + base, plen);
}

/* Unmaps a memory region previously mapped by address_space_map().