diff mbox

[21/22] memory: propagate errors on I/O dispatch

Message ID 1369947836-2638-22-git-send-email-pbonzini@redhat.com
State New
Headers show

Commit Message

Paolo Bonzini May 30, 2013, 9:03 p.m. UTC
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c                          |   21 ++++++++++++---------
 include/exec/exec-all.h         |    6 +++---
 include/exec/softmmu_template.h |    4 +++-
 memory.c                        |   35 ++++++++++++++++++-----------------
 4 files changed, 36 insertions(+), 30 deletions(-)
diff mbox

Patch

diff --git a/exec.c b/exec.c
index 878f021..520d4c4 100644
--- a/exec.c
+++ b/exec.c
@@ -1526,6 +1526,8 @@  static uint64_t subpage_read(void *opaque, hwaddr addr,
 {
     subpage_t *mmio = opaque;
     unsigned int idx = SUBPAGE_IDX(addr);
+    uint64_t val;
+
     MemoryRegionSection *section;
 #if defined(DEBUG_SUBPAGE)
     printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
@@ -1536,7 +1538,8 @@  static uint64_t subpage_read(void *opaque, hwaddr addr,
     addr += mmio->base;
     addr -= section->offset_within_address_space;
     addr += section->offset_within_region;
-    return io_mem_read(section->mr, addr, len);
+    io_mem_read(section->mr, addr, &val, len);
+    return val;
 }
 
 static void subpage_write(void *opaque, hwaddr addr,
@@ -1904,7 +1907,7 @@  void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
 {
     hwaddr l;
     uint8_t *ptr;
-    uint32_t val;
+    uint64_t val;
     hwaddr addr1;
     MemoryRegionSection *section;
 
@@ -1943,15 +1946,15 @@  void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
                 l = memory_access_size(l, addr1);
                 if (l == 4) {
                     /* 32 bit read access */
-                    val = io_mem_read(section->mr, addr1, 4);
+                    io_mem_read(section->mr, addr1, &val, 4);
                     stl_p(buf, val);
                 } else if (l == 2) {
                     /* 16 bit read access */
-                    val = io_mem_read(section->mr, addr1, 2);
+                    io_mem_read(section->mr, addr1, &val, 2);
                     stw_p(buf, val);
                 } else {
                     /* 8 bit read access */
-                    val = io_mem_read(section->mr, addr1, 1);
+                    io_mem_read(section->mr, addr1, &val, 1);
                     stb_p(buf, val);
                 }
             } else {
@@ -2195,7 +2198,7 @@  static inline uint32_t ldl_phys_internal(hwaddr addr,
                                          enum device_endian endian)
 {
     uint8_t *ptr;
-    uint32_t val;
+    uint64_t val;
     MemoryRegionSection *section;
     hwaddr l = 4;
     hwaddr addr1;
@@ -2204,7 +2207,7 @@  static inline uint32_t ldl_phys_internal(hwaddr addr,
                                       false);
     if (l < 4 || !memory_access_is_direct(section->mr, false)) {
         /* I/O case */
-        val = io_mem_read(section->mr, addr1, 4);
+        io_mem_read(section->mr, addr1, &val, 4);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap32(val);
@@ -2263,7 +2266,7 @@  static inline uint64_t ldq_phys_internal(hwaddr addr,
                                       false);
     if (l < 8 || !memory_access_is_direct(section->mr, false)) {
         /* I/O case */
-        val = io_mem_read(section->mr, addr1, 8);
+        io_mem_read(section->mr, addr1, &val, 8);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap64(val);
@@ -2330,7 +2333,7 @@  static inline uint32_t lduw_phys_internal(hwaddr addr,
                                       false);
     if (l < 2 || !memory_access_is_direct(section->mr, false)) {
         /* I/O case */
-        val = io_mem_read(section->mr, addr1, 2);
+        io_mem_read(section->mr, addr1, &val, 2);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap16(val);
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 6362074..17fde25 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -367,9 +367,9 @@  bool is_tcg_gen_code(uintptr_t pc_ptr);
 #if !defined(CONFIG_USER_ONLY)
 
 struct MemoryRegion *iotlb_to_region(hwaddr index);
-uint64_t io_mem_read(struct MemoryRegion *mr, hwaddr addr,
-                     unsigned size);
-void io_mem_write(struct MemoryRegion *mr, hwaddr addr,
+bool io_mem_read(struct MemoryRegion *mr, hwaddr addr,
+                 uint64_t *pvalue, unsigned size);
+bool io_mem_write(struct MemoryRegion *mr, hwaddr addr,
                   uint64_t value, unsigned size);
 
 void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx,
diff --git a/include/exec/softmmu_template.h b/include/exec/softmmu_template.h
index 292ca02..8584902 100644
--- a/include/exec/softmmu_template.h
+++ b/include/exec/softmmu_template.h
@@ -63,6 +63,7 @@  static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
                                               target_ulong addr,
                                               uintptr_t retaddr)
 {
+    uint64_t val;
     MemoryRegion *mr = iotlb_to_region(physaddr);
 
     physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
@@ -72,7 +73,8 @@  static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
     }
 
     env->mem_io_vaddr = addr;
-    return io_mem_read(mr, physaddr, 1 << SHIFT);
+    io_mem_read(mr, physaddr, &val, 1 << SHIFT);
+    return val;
 }
 
 /* handle all cases except unaligned access which span two pages */
diff --git a/memory.c b/memory.c
index f84fc53..5cb8f4a 100644
--- a/memory.c
+++ b/memory.c
@@ -928,10 +928,6 @@  static uint64_t memory_region_dispatch_read1(MemoryRegion *mr,
 {
     uint64_t data = 0;
 
-    if (!memory_region_access_valid(mr, addr, size, false)) {
-        return unassigned_mem_read(mr, addr, size);
-    }
-
     if (mr->ops->read) {
         access_with_adjusted_size(addr, &data, size,
                                   mr->ops->impl.min_access_size,
@@ -966,25 +962,29 @@  static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
     }
 }
 
-static uint64_t memory_region_dispatch_read(MemoryRegion *mr,
-                                            hwaddr addr,
-                                            unsigned size)
+static bool memory_region_dispatch_read(MemoryRegion *mr,
+                                        hwaddr addr,
+                                        uint64_t *pval,
+                                        unsigned size)
 {
-    uint64_t ret;
+    if (!memory_region_access_valid(mr, addr, size, false)) {
+        *pval = unassigned_mem_read(mr, addr, size);
+        return true;
+    }
 
-    ret = memory_region_dispatch_read1(mr, addr, size);
-    adjust_endianness(mr, &ret, size);
-    return ret;
+    *pval = memory_region_dispatch_read1(mr, addr, size);
+    adjust_endianness(mr, pval, size);
+    return false;
 }
 
-static void memory_region_dispatch_write(MemoryRegion *mr,
+static bool memory_region_dispatch_write(MemoryRegion *mr,
                                          hwaddr addr,
                                          uint64_t data,
                                          unsigned size)
 {
     if (!memory_region_access_valid(mr, addr, size, true)) {
         unassigned_mem_write(mr, addr, data, size);
-        return;
+        return true;
     }
 
     adjust_endianness(mr, &data, size);
@@ -998,6 +998,7 @@  static void memory_region_dispatch_write(MemoryRegion *mr,
         access_with_adjusted_size(addr, &data, size, 1, 4,
                                   memory_region_oldmmio_write_accessor, mr);
     }
+    return false;
 }
 
 void memory_region_init_io(MemoryRegion *mr,
@@ -1650,15 +1651,15 @@  void address_space_destroy(AddressSpace *as)
     g_free(as->ioeventfds);
 }
 
-uint64_t io_mem_read(MemoryRegion *mr, hwaddr addr, unsigned size)
+bool io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, unsigned size)
 {
-    return memory_region_dispatch_read(mr, addr, size);
+    return memory_region_dispatch_read(mr, addr, pval, size);
 }
 
-void io_mem_write(MemoryRegion *mr, hwaddr addr,
+bool io_mem_write(MemoryRegion *mr, hwaddr addr,
                   uint64_t val, unsigned size)
 {
-    memory_region_dispatch_write(mr, addr, val, size);
+    return memory_region_dispatch_write(mr, addr, val, size);
 }
 
 typedef struct MemoryRegionList MemoryRegionList;