Revision e3127ae0

b/exec.c
2065 2065
                        bool is_write)
2066 2066
{
2067 2067
    hwaddr len = *plen;
2068
    hwaddr todo = 0;
2069
    hwaddr l, xlat;
2070
    MemoryRegion *mr;
2071
    ram_addr_t raddr = RAM_ADDR_MAX;
2072
    ram_addr_t rlen;
2073
    void *ret;
2068
    hwaddr done = 0;
2069
    hwaddr l, xlat, base;
2070
    MemoryRegion *mr, *this_mr;
2071
    ram_addr_t raddr;
2074 2072

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

  
2079
        if (!memory_access_is_direct(mr, is_write)) {
2080
            if (todo || bounce.buffer) {
2081
                break;
2082
            }
2083
            bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
2084
            bounce.addr = addr;
2085
            bounce.len = l;
2086
            if (!is_write) {
2087
                address_space_read(as, addr, bounce.buffer, l);
2088
            }
2073
    if (len == 0) {
2074
        return NULL;
2075
    }
2089 2076

  
2090
            *plen = l;
2091
            return bounce.buffer;
2077
    l = len;
2078
    mr = address_space_translate(as, addr, &xlat, &l, is_write);
2079
    if (!memory_access_is_direct(mr, is_write)) {
2080
        if (bounce.buffer) {
2081
            return NULL;
2092 2082
        }
2093
        if (!todo) {
2094
            raddr = memory_region_get_ram_addr(mr) + xlat;
2095
        } else {
2096
            if (memory_region_get_ram_addr(mr) + xlat != raddr + todo) {
2097
                break;
2098
            }
2083
        bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
2084
        bounce.addr = addr;
2085
        bounce.len = l;
2086
        if (!is_write) {
2087
            address_space_read(as, addr, bounce.buffer, l);
2099 2088
        }
2100 2089

  
2090
        *plen = l;
2091
        return bounce.buffer;
2092
    }
2093

  
2094
    base = xlat;
2095
    raddr = memory_region_get_ram_addr(mr);
2096

  
2097
    for (;;) {
2101 2098
        len -= l;
2102 2099
        addr += l;
2103
        todo += l;
2100
        done += l;
2101
        if (len == 0) {
2102
            break;
2103
        }
2104

  
2105
        l = len;
2106
        this_mr = address_space_translate(as, addr, &xlat, &l, is_write);
2107
        if (this_mr != mr || xlat != base + done) {
2108
            break;
2109
        }
2104 2110
    }
2105
    rlen = todo;
2106
    ret = qemu_ram_ptr_length(raddr, &rlen);
2107
    *plen = rlen;
2108
    return ret;
2111

  
2112
    *plen = done;
2113
    return qemu_ram_ptr_length(raddr + base, plen);
2109 2114
}
2110 2115

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

Also available in: Unified diff