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