|
@@ -2681,53 +2681,69 @@ static bool flatview_access_allowed(MemoryRegion *mr, MemTxAttrs attrs,
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static MemTxResult flatview_write_continue_step(MemTxAttrs attrs,
|
|
|
|
+ const uint8_t *buf,
|
|
|
|
+ hwaddr len, hwaddr mr_addr,
|
|
|
|
+ hwaddr *l, MemoryRegion *mr)
|
|
|
|
+{
|
|
|
|
+ if (!flatview_access_allowed(mr, attrs, mr_addr, *l)) {
|
|
|
|
+ return MEMTX_ACCESS_ERROR;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!memory_access_is_direct(mr, true)) {
|
|
|
|
+ uint64_t val;
|
|
|
|
+ MemTxResult result;
|
|
|
|
+ bool release_lock = prepare_mmio_access(mr);
|
|
|
|
+
|
|
|
|
+ *l = memory_access_size(mr, *l, mr_addr);
|
|
|
|
+ /*
|
|
|
|
+ * XXX: could force current_cpu to NULL to avoid
|
|
|
|
+ * potential bugs
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Assure Coverity (and ourselves) that we are not going to OVERRUN
|
|
|
|
+ * the buffer by following ldn_he_p().
|
|
|
|
+ */
|
|
|
|
+#ifdef QEMU_STATIC_ANALYSIS
|
|
|
|
+ assert((*l == 1 && len >= 1) ||
|
|
|
|
+ (*l == 2 && len >= 2) ||
|
|
|
|
+ (*l == 4 && len >= 4) ||
|
|
|
|
+ (*l == 8 && len >= 8));
|
|
|
|
+#endif
|
|
|
|
+ val = ldn_he_p(buf, *l);
|
|
|
|
+ result = memory_region_dispatch_write(mr, mr_addr, val,
|
|
|
|
+ size_memop(*l), attrs);
|
|
|
|
+ if (release_lock) {
|
|
|
|
+ bql_unlock();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return result;
|
|
|
|
+ } else {
|
|
|
|
+ /* RAM case */
|
|
|
|
+ uint8_t *ram_ptr = qemu_ram_ptr_length(mr->ram_block, mr_addr, l,
|
|
|
|
+ false);
|
|
|
|
+
|
|
|
|
+ memmove(ram_ptr, buf, *l);
|
|
|
|
+ invalidate_and_set_dirty(mr, mr_addr, *l);
|
|
|
|
+
|
|
|
|
+ return MEMTX_OK;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
/* Called within RCU critical section. */
|
|
/* Called within RCU critical section. */
|
|
static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr,
|
|
static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr,
|
|
MemTxAttrs attrs,
|
|
MemTxAttrs attrs,
|
|
const void *ptr,
|
|
const void *ptr,
|
|
- hwaddr len, hwaddr addr1,
|
|
|
|
|
|
+ hwaddr len, hwaddr mr_addr,
|
|
hwaddr l, MemoryRegion *mr)
|
|
hwaddr l, MemoryRegion *mr)
|
|
{
|
|
{
|
|
- uint8_t *ram_ptr;
|
|
|
|
- uint64_t val;
|
|
|
|
MemTxResult result = MEMTX_OK;
|
|
MemTxResult result = MEMTX_OK;
|
|
- bool release_lock = false;
|
|
|
|
const uint8_t *buf = ptr;
|
|
const uint8_t *buf = ptr;
|
|
|
|
|
|
for (;;) {
|
|
for (;;) {
|
|
- if (!flatview_access_allowed(mr, attrs, addr1, l)) {
|
|
|
|
- result |= MEMTX_ACCESS_ERROR;
|
|
|
|
- /* Keep going. */
|
|
|
|
- } else if (!memory_access_is_direct(mr, true)) {
|
|
|
|
- release_lock |= prepare_mmio_access(mr);
|
|
|
|
- l = memory_access_size(mr, l, addr1);
|
|
|
|
- /* XXX: could force current_cpu to NULL to avoid
|
|
|
|
- potential bugs */
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Assure Coverity (and ourselves) that we are not going to OVERRUN
|
|
|
|
- * the buffer by following ldn_he_p().
|
|
|
|
- */
|
|
|
|
-#ifdef QEMU_STATIC_ANALYSIS
|
|
|
|
- assert((l == 1 && len >= 1) ||
|
|
|
|
- (l == 2 && len >= 2) ||
|
|
|
|
- (l == 4 && len >= 4) ||
|
|
|
|
- (l == 8 && len >= 8));
|
|
|
|
-#endif
|
|
|
|
- val = ldn_he_p(buf, l);
|
|
|
|
- result |= memory_region_dispatch_write(mr, addr1, val,
|
|
|
|
- size_memop(l), attrs);
|
|
|
|
- } else {
|
|
|
|
- /* RAM case */
|
|
|
|
- ram_ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
|
|
|
|
- memmove(ram_ptr, buf, l);
|
|
|
|
- invalidate_and_set_dirty(mr, addr1, l);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (release_lock) {
|
|
|
|
- bql_unlock();
|
|
|
|
- release_lock = false;
|
|
|
|
- }
|
|
|
|
|
|
+ result |= flatview_write_continue_step(attrs, buf, len, mr_addr, &l,
|
|
|
|
+ mr);
|
|
|
|
|
|
len -= l;
|
|
len -= l;
|
|
buf += l;
|
|
buf += l;
|
|
@@ -2738,7 +2754,7 @@ static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr,
|
|
}
|
|
}
|
|
|
|
|
|
l = len;
|
|
l = len;
|
|
- mr = flatview_translate(fv, addr, &addr1, &l, true, attrs);
|
|
|
|
|
|
+ mr = flatview_translate(fv, addr, &mr_addr, &l, true, attrs);
|
|
}
|
|
}
|
|
|
|
|
|
return result;
|
|
return result;
|
|
@@ -2749,63 +2765,76 @@ static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
|
|
const void *buf, hwaddr len)
|
|
const void *buf, hwaddr len)
|
|
{
|
|
{
|
|
hwaddr l;
|
|
hwaddr l;
|
|
- hwaddr addr1;
|
|
|
|
|
|
+ hwaddr mr_addr;
|
|
MemoryRegion *mr;
|
|
MemoryRegion *mr;
|
|
|
|
|
|
l = len;
|
|
l = len;
|
|
- mr = flatview_translate(fv, addr, &addr1, &l, true, attrs);
|
|
|
|
|
|
+ mr = flatview_translate(fv, addr, &mr_addr, &l, true, attrs);
|
|
if (!flatview_access_allowed(mr, attrs, addr, len)) {
|
|
if (!flatview_access_allowed(mr, attrs, addr, len)) {
|
|
return MEMTX_ACCESS_ERROR;
|
|
return MEMTX_ACCESS_ERROR;
|
|
}
|
|
}
|
|
return flatview_write_continue(fv, addr, attrs, buf, len,
|
|
return flatview_write_continue(fv, addr, attrs, buf, len,
|
|
- addr1, l, mr);
|
|
|
|
|
|
+ mr_addr, l, mr);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static MemTxResult flatview_read_continue_step(MemTxAttrs attrs, uint8_t *buf,
|
|
|
|
+ hwaddr len, hwaddr mr_addr,
|
|
|
|
+ hwaddr *l,
|
|
|
|
+ MemoryRegion *mr)
|
|
|
|
+{
|
|
|
|
+ if (!flatview_access_allowed(mr, attrs, mr_addr, *l)) {
|
|
|
|
+ return MEMTX_ACCESS_ERROR;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!memory_access_is_direct(mr, false)) {
|
|
|
|
+ /* I/O case */
|
|
|
|
+ uint64_t val;
|
|
|
|
+ MemTxResult result;
|
|
|
|
+ bool release_lock = prepare_mmio_access(mr);
|
|
|
|
+
|
|
|
|
+ *l = memory_access_size(mr, *l, mr_addr);
|
|
|
|
+ result = memory_region_dispatch_read(mr, mr_addr, &val, size_memop(*l),
|
|
|
|
+ attrs);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Assure Coverity (and ourselves) that we are not going to OVERRUN
|
|
|
|
+ * the buffer by following stn_he_p().
|
|
|
|
+ */
|
|
|
|
+#ifdef QEMU_STATIC_ANALYSIS
|
|
|
|
+ assert((*l == 1 && len >= 1) ||
|
|
|
|
+ (*l == 2 && len >= 2) ||
|
|
|
|
+ (*l == 4 && len >= 4) ||
|
|
|
|
+ (*l == 8 && len >= 8));
|
|
|
|
+#endif
|
|
|
|
+ stn_he_p(buf, *l, val);
|
|
|
|
+
|
|
|
|
+ if (release_lock) {
|
|
|
|
+ bql_unlock();
|
|
|
|
+ }
|
|
|
|
+ return result;
|
|
|
|
+ } else {
|
|
|
|
+ /* RAM case */
|
|
|
|
+ uint8_t *ram_ptr = qemu_ram_ptr_length(mr->ram_block, mr_addr, l,
|
|
|
|
+ false);
|
|
|
|
+
|
|
|
|
+ memcpy(buf, ram_ptr, *l);
|
|
|
|
+
|
|
|
|
+ return MEMTX_OK;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/* Called within RCU critical section. */
|
|
/* Called within RCU critical section. */
|
|
MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
|
|
MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
|
|
MemTxAttrs attrs, void *ptr,
|
|
MemTxAttrs attrs, void *ptr,
|
|
- hwaddr len, hwaddr addr1, hwaddr l,
|
|
|
|
|
|
+ hwaddr len, hwaddr mr_addr, hwaddr l,
|
|
MemoryRegion *mr)
|
|
MemoryRegion *mr)
|
|
{
|
|
{
|
|
- uint8_t *ram_ptr;
|
|
|
|
- uint64_t val;
|
|
|
|
MemTxResult result = MEMTX_OK;
|
|
MemTxResult result = MEMTX_OK;
|
|
- bool release_lock = false;
|
|
|
|
uint8_t *buf = ptr;
|
|
uint8_t *buf = ptr;
|
|
|
|
|
|
fuzz_dma_read_cb(addr, len, mr);
|
|
fuzz_dma_read_cb(addr, len, mr);
|
|
for (;;) {
|
|
for (;;) {
|
|
- if (!flatview_access_allowed(mr, attrs, addr1, l)) {
|
|
|
|
- result |= MEMTX_ACCESS_ERROR;
|
|
|
|
- /* Keep going. */
|
|
|
|
- } else if (!memory_access_is_direct(mr, false)) {
|
|
|
|
- /* I/O case */
|
|
|
|
- release_lock |= prepare_mmio_access(mr);
|
|
|
|
- l = memory_access_size(mr, l, addr1);
|
|
|
|
- result |= memory_region_dispatch_read(mr, addr1, &val,
|
|
|
|
- size_memop(l), attrs);
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Assure Coverity (and ourselves) that we are not going to OVERRUN
|
|
|
|
- * the buffer by following stn_he_p().
|
|
|
|
- */
|
|
|
|
-#ifdef QEMU_STATIC_ANALYSIS
|
|
|
|
- assert((l == 1 && len >= 1) ||
|
|
|
|
- (l == 2 && len >= 2) ||
|
|
|
|
- (l == 4 && len >= 4) ||
|
|
|
|
- (l == 8 && len >= 8));
|
|
|
|
-#endif
|
|
|
|
- stn_he_p(buf, l, val);
|
|
|
|
- } else {
|
|
|
|
- /* RAM case */
|
|
|
|
- ram_ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
|
|
|
|
- memcpy(buf, ram_ptr, l);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (release_lock) {
|
|
|
|
- bql_unlock();
|
|
|
|
- release_lock = false;
|
|
|
|
- }
|
|
|
|
|
|
+ result |= flatview_read_continue_step(attrs, buf, len, mr_addr, &l, mr);
|
|
|
|
|
|
len -= l;
|
|
len -= l;
|
|
buf += l;
|
|
buf += l;
|
|
@@ -2816,7 +2845,7 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
|
|
}
|
|
}
|
|
|
|
|
|
l = len;
|
|
l = len;
|
|
- mr = flatview_translate(fv, addr, &addr1, &l, false, attrs);
|
|
|
|
|
|
+ mr = flatview_translate(fv, addr, &mr_addr, &l, false, attrs);
|
|
}
|
|
}
|
|
|
|
|
|
return result;
|
|
return result;
|
|
@@ -2827,16 +2856,16 @@ static MemTxResult flatview_read(FlatView *fv, hwaddr addr,
|
|
MemTxAttrs attrs, void *buf, hwaddr len)
|
|
MemTxAttrs attrs, void *buf, hwaddr len)
|
|
{
|
|
{
|
|
hwaddr l;
|
|
hwaddr l;
|
|
- hwaddr addr1;
|
|
|
|
|
|
+ hwaddr mr_addr;
|
|
MemoryRegion *mr;
|
|
MemoryRegion *mr;
|
|
|
|
|
|
l = len;
|
|
l = len;
|
|
- mr = flatview_translate(fv, addr, &addr1, &l, false, attrs);
|
|
|
|
|
|
+ mr = flatview_translate(fv, addr, &mr_addr, &l, false, attrs);
|
|
if (!flatview_access_allowed(mr, attrs, addr, len)) {
|
|
if (!flatview_access_allowed(mr, attrs, addr, len)) {
|
|
return MEMTX_ACCESS_ERROR;
|
|
return MEMTX_ACCESS_ERROR;
|
|
}
|
|
}
|
|
return flatview_read_continue(fv, addr, attrs, buf, len,
|
|
return flatview_read_continue(fv, addr, attrs, buf, len,
|
|
- addr1, l, mr);
|
|
|
|
|
|
+ mr_addr, l, mr);
|
|
}
|
|
}
|
|
|
|
|
|
MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr,
|
|
MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr,
|
|
@@ -3341,6 +3370,59 @@ static inline MemoryRegion *address_space_translate_cached(
|
|
return section.mr;
|
|
return section.mr;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Called within RCU critical section. */
|
|
|
|
+static MemTxResult address_space_write_continue_cached(MemTxAttrs attrs,
|
|
|
|
+ const void *ptr,
|
|
|
|
+ hwaddr len,
|
|
|
|
+ hwaddr mr_addr,
|
|
|
|
+ hwaddr l,
|
|
|
|
+ MemoryRegion *mr)
|
|
|
|
+{
|
|
|
|
+ MemTxResult result = MEMTX_OK;
|
|
|
|
+ const uint8_t *buf = ptr;
|
|
|
|
+
|
|
|
|
+ for (;;) {
|
|
|
|
+ result |= flatview_write_continue_step(attrs, buf, len, mr_addr, &l,
|
|
|
|
+ mr);
|
|
|
|
+
|
|
|
|
+ len -= l;
|
|
|
|
+ buf += l;
|
|
|
|
+ mr_addr += l;
|
|
|
|
+
|
|
|
|
+ if (!len) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ l = len;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Called within RCU critical section. */
|
|
|
|
+static MemTxResult address_space_read_continue_cached(MemTxAttrs attrs,
|
|
|
|
+ void *ptr, hwaddr len,
|
|
|
|
+ hwaddr mr_addr, hwaddr l,
|
|
|
|
+ MemoryRegion *mr)
|
|
|
|
+{
|
|
|
|
+ MemTxResult result = MEMTX_OK;
|
|
|
|
+ uint8_t *buf = ptr;
|
|
|
|
+
|
|
|
|
+ for (;;) {
|
|
|
|
+ result |= flatview_read_continue_step(attrs, buf, len, mr_addr, &l, mr);
|
|
|
|
+ len -= l;
|
|
|
|
+ buf += l;
|
|
|
|
+ mr_addr += l;
|
|
|
|
+
|
|
|
|
+ if (!len) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ l = len;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+
|
|
/* Called from RCU critical section. address_space_read_cached uses this
|
|
/* Called from RCU critical section. address_space_read_cached uses this
|
|
* out of line function when the target is an MMIO or IOMMU region.
|
|
* out of line function when the target is an MMIO or IOMMU region.
|
|
*/
|
|
*/
|
|
@@ -3348,15 +3430,14 @@ MemTxResult
|
|
address_space_read_cached_slow(MemoryRegionCache *cache, hwaddr addr,
|
|
address_space_read_cached_slow(MemoryRegionCache *cache, hwaddr addr,
|
|
void *buf, hwaddr len)
|
|
void *buf, hwaddr len)
|
|
{
|
|
{
|
|
- hwaddr addr1, l;
|
|
|
|
|
|
+ hwaddr mr_addr, l;
|
|
MemoryRegion *mr;
|
|
MemoryRegion *mr;
|
|
|
|
|
|
l = len;
|
|
l = len;
|
|
- mr = address_space_translate_cached(cache, addr, &addr1, &l, false,
|
|
|
|
|
|
+ mr = address_space_translate_cached(cache, addr, &mr_addr, &l, false,
|
|
MEMTXATTRS_UNSPECIFIED);
|
|
MEMTXATTRS_UNSPECIFIED);
|
|
- return flatview_read_continue(cache->fv,
|
|
|
|
- addr, MEMTXATTRS_UNSPECIFIED, buf, len,
|
|
|
|
- addr1, l, mr);
|
|
|
|
|
|
+ return address_space_read_continue_cached(MEMTXATTRS_UNSPECIFIED,
|
|
|
|
+ buf, len, mr_addr, l, mr);
|
|
}
|
|
}
|
|
|
|
|
|
/* Called from RCU critical section. address_space_write_cached uses this
|
|
/* Called from RCU critical section. address_space_write_cached uses this
|
|
@@ -3366,15 +3447,14 @@ MemTxResult
|
|
address_space_write_cached_slow(MemoryRegionCache *cache, hwaddr addr,
|
|
address_space_write_cached_slow(MemoryRegionCache *cache, hwaddr addr,
|
|
const void *buf, hwaddr len)
|
|
const void *buf, hwaddr len)
|
|
{
|
|
{
|
|
- hwaddr addr1, l;
|
|
|
|
|
|
+ hwaddr mr_addr, l;
|
|
MemoryRegion *mr;
|
|
MemoryRegion *mr;
|
|
|
|
|
|
l = len;
|
|
l = len;
|
|
- mr = address_space_translate_cached(cache, addr, &addr1, &l, true,
|
|
|
|
|
|
+ mr = address_space_translate_cached(cache, addr, &mr_addr, &l, true,
|
|
MEMTXATTRS_UNSPECIFIED);
|
|
MEMTXATTRS_UNSPECIFIED);
|
|
- return flatview_write_continue(cache->fv,
|
|
|
|
- addr, MEMTXATTRS_UNSPECIFIED, buf, len,
|
|
|
|
- addr1, l, mr);
|
|
|
|
|
|
+ return address_space_write_continue_cached(MEMTXATTRS_UNSPECIFIED,
|
|
|
|
+ buf, len, mr_addr, l, mr);
|
|
}
|
|
}
|
|
|
|
|
|
#define ARG1_DECL MemoryRegionCache *cache
|
|
#define ARG1_DECL MemoryRegionCache *cache
|