diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-05-24 16:10:39 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-05-29 16:27:32 +0200 |
commit | 791af8c861f4537ad29c34df14fb81701e04596f (patch) | |
tree | 79a3e97b084340de0c41954e834b797cf31936ac | |
parent | a649b9168cb9169b41532b168b94294e2be32e50 (diff) |
memory: propagate errors on I/O dispatch
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | exec.c | 21 | ||||
-rw-r--r-- | include/exec/exec-all.h | 6 | ||||
-rw-r--r-- | include/exec/softmmu_template.h | 4 | ||||
-rw-r--r-- | memory.c | 35 |
4 files changed, 36 insertions, 30 deletions
@@ -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 6362074e9c..17fde25c74 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 292ca02bc5..8584902cbe 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 */ @@ -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; |