memory: propagate errors on I/O dispatch
authorPaolo Bonzini <pbonzini@redhat.com>
Fri, 24 May 2013 14:10:39 +0000 (16:10 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 29 May 2013 14:27:32 +0000 (16:27 +0200)
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
exec.c
include/exec/exec-all.h
include/exec/softmmu_template.h
memory.c

diff --git a/exec.c b/exec.c
index 878f021953cb4a6d6954f9bd0ac95b7ed44e1990..520d4c4d882dc48db98eb686766f427879071624 100644 (file)
--- 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);
index 6362074e9c4f61317031bf9c286939c7155a0266..17fde25c74be9c6b8f22ea9a2155642e2b489c72 100644 (file)
@@ -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,
index 292ca02bc527f745064e706c412fddb4e4452ef8..8584902cbee2011f042db2a73436a4e932116e1a 100644 (file)
@@ -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 */
index f84fc53d4aa70a3fa43c0b10670b411a61189c49..5cb8f4a8b2e098a27623ee1fae82af2f1f5cbce1 100644 (file)
--- 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;