提交 791af8c8 编写于 作者: P Paolo Bonzini

memory: propagate errors on I/O dispatch

Reviewed-by: NRichard Henderson <rth@twiddle.net>
Signed-off-by: NPaolo Bonzini <pbonzini@redhat.com>
上级 a649b916
...@@ -1526,6 +1526,8 @@ static uint64_t subpage_read(void *opaque, hwaddr addr, ...@@ -1526,6 +1526,8 @@ static uint64_t subpage_read(void *opaque, hwaddr addr,
{ {
subpage_t *mmio = opaque; subpage_t *mmio = opaque;
unsigned int idx = SUBPAGE_IDX(addr); unsigned int idx = SUBPAGE_IDX(addr);
uint64_t val;
MemoryRegionSection *section; MemoryRegionSection *section;
#if defined(DEBUG_SUBPAGE) #if defined(DEBUG_SUBPAGE)
printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__, 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, ...@@ -1536,7 +1538,8 @@ static uint64_t subpage_read(void *opaque, hwaddr addr,
addr += mmio->base; addr += mmio->base;
addr -= section->offset_within_address_space; addr -= section->offset_within_address_space;
addr += section->offset_within_region; 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, static void subpage_write(void *opaque, hwaddr addr,
...@@ -1904,7 +1907,7 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, ...@@ -1904,7 +1907,7 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
{ {
hwaddr l; hwaddr l;
uint8_t *ptr; uint8_t *ptr;
uint32_t val; uint64_t val;
hwaddr addr1; hwaddr addr1;
MemoryRegionSection *section; MemoryRegionSection *section;
...@@ -1943,15 +1946,15 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, ...@@ -1943,15 +1946,15 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
l = memory_access_size(l, addr1); l = memory_access_size(l, addr1);
if (l == 4) { if (l == 4) {
/* 32 bit read access */ /* 32 bit read access */
val = io_mem_read(section->mr, addr1, 4); io_mem_read(section->mr, addr1, &val, 4);
stl_p(buf, val); stl_p(buf, val);
} else if (l == 2) { } else if (l == 2) {
/* 16 bit read access */ /* 16 bit read access */
val = io_mem_read(section->mr, addr1, 2); io_mem_read(section->mr, addr1, &val, 2);
stw_p(buf, val); stw_p(buf, val);
} else { } else {
/* 8 bit read access */ /* 8 bit read access */
val = io_mem_read(section->mr, addr1, 1); io_mem_read(section->mr, addr1, &val, 1);
stb_p(buf, val); stb_p(buf, val);
} }
} else { } else {
...@@ -2195,7 +2198,7 @@ static inline uint32_t ldl_phys_internal(hwaddr addr, ...@@ -2195,7 +2198,7 @@ static inline uint32_t ldl_phys_internal(hwaddr addr,
enum device_endian endian) enum device_endian endian)
{ {
uint8_t *ptr; uint8_t *ptr;
uint32_t val; uint64_t val;
MemoryRegionSection *section; MemoryRegionSection *section;
hwaddr l = 4; hwaddr l = 4;
hwaddr addr1; hwaddr addr1;
...@@ -2204,7 +2207,7 @@ static inline uint32_t ldl_phys_internal(hwaddr addr, ...@@ -2204,7 +2207,7 @@ static inline uint32_t ldl_phys_internal(hwaddr addr,
false); false);
if (l < 4 || !memory_access_is_direct(section->mr, false)) { if (l < 4 || !memory_access_is_direct(section->mr, false)) {
/* I/O case */ /* 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 defined(TARGET_WORDS_BIGENDIAN)
if (endian == DEVICE_LITTLE_ENDIAN) { if (endian == DEVICE_LITTLE_ENDIAN) {
val = bswap32(val); val = bswap32(val);
...@@ -2263,7 +2266,7 @@ static inline uint64_t ldq_phys_internal(hwaddr addr, ...@@ -2263,7 +2266,7 @@ static inline uint64_t ldq_phys_internal(hwaddr addr,
false); false);
if (l < 8 || !memory_access_is_direct(section->mr, false)) { if (l < 8 || !memory_access_is_direct(section->mr, false)) {
/* I/O case */ /* 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 defined(TARGET_WORDS_BIGENDIAN)
if (endian == DEVICE_LITTLE_ENDIAN) { if (endian == DEVICE_LITTLE_ENDIAN) {
val = bswap64(val); val = bswap64(val);
...@@ -2330,7 +2333,7 @@ static inline uint32_t lduw_phys_internal(hwaddr addr, ...@@ -2330,7 +2333,7 @@ static inline uint32_t lduw_phys_internal(hwaddr addr,
false); false);
if (l < 2 || !memory_access_is_direct(section->mr, false)) { if (l < 2 || !memory_access_is_direct(section->mr, false)) {
/* I/O case */ /* 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 defined(TARGET_WORDS_BIGENDIAN)
if (endian == DEVICE_LITTLE_ENDIAN) { if (endian == DEVICE_LITTLE_ENDIAN) {
val = bswap16(val); val = bswap16(val);
......
...@@ -367,9 +367,9 @@ bool is_tcg_gen_code(uintptr_t pc_ptr); ...@@ -367,9 +367,9 @@ bool is_tcg_gen_code(uintptr_t pc_ptr);
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
struct MemoryRegion *iotlb_to_region(hwaddr index); struct MemoryRegion *iotlb_to_region(hwaddr index);
uint64_t io_mem_read(struct MemoryRegion *mr, hwaddr addr, bool io_mem_read(struct MemoryRegion *mr, hwaddr addr,
unsigned size); uint64_t *pvalue, unsigned size);
void io_mem_write(struct MemoryRegion *mr, hwaddr addr, bool io_mem_write(struct MemoryRegion *mr, hwaddr addr,
uint64_t value, unsigned size); uint64_t value, unsigned size);
void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx, void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx,
......
...@@ -63,6 +63,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env, ...@@ -63,6 +63,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
target_ulong addr, target_ulong addr,
uintptr_t retaddr) uintptr_t retaddr)
{ {
uint64_t val;
MemoryRegion *mr = iotlb_to_region(physaddr); MemoryRegion *mr = iotlb_to_region(physaddr);
physaddr = (physaddr & TARGET_PAGE_MASK) + addr; physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
...@@ -72,7 +73,8 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env, ...@@ -72,7 +73,8 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
} }
env->mem_io_vaddr = addr; 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 */ /* handle all cases except unaligned access which span two pages */
......
...@@ -928,10 +928,6 @@ static uint64_t memory_region_dispatch_read1(MemoryRegion *mr, ...@@ -928,10 +928,6 @@ static uint64_t memory_region_dispatch_read1(MemoryRegion *mr,
{ {
uint64_t data = 0; uint64_t data = 0;
if (!memory_region_access_valid(mr, addr, size, false)) {
return unassigned_mem_read(mr, addr, size);
}
if (mr->ops->read) { if (mr->ops->read) {
access_with_adjusted_size(addr, &data, size, access_with_adjusted_size(addr, &data, size,
mr->ops->impl.min_access_size, mr->ops->impl.min_access_size,
...@@ -966,25 +962,29 @@ static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned 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, static bool memory_region_dispatch_read(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
unsigned size) 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); *pval = memory_region_dispatch_read1(mr, addr, size);
adjust_endianness(mr, &ret, size); adjust_endianness(mr, pval, size);
return ret; return false;
} }
static void memory_region_dispatch_write(MemoryRegion *mr, static bool memory_region_dispatch_write(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
uint64_t data, uint64_t data,
unsigned size) unsigned size)
{ {
if (!memory_region_access_valid(mr, addr, size, true)) { if (!memory_region_access_valid(mr, addr, size, true)) {
unassigned_mem_write(mr, addr, data, size); unassigned_mem_write(mr, addr, data, size);
return; return true;
} }
adjust_endianness(mr, &data, size); adjust_endianness(mr, &data, size);
...@@ -998,6 +998,7 @@ static void memory_region_dispatch_write(MemoryRegion *mr, ...@@ -998,6 +998,7 @@ static void memory_region_dispatch_write(MemoryRegion *mr,
access_with_adjusted_size(addr, &data, size, 1, 4, access_with_adjusted_size(addr, &data, size, 1, 4,
memory_region_oldmmio_write_accessor, mr); memory_region_oldmmio_write_accessor, mr);
} }
return false;
} }
void memory_region_init_io(MemoryRegion *mr, void memory_region_init_io(MemoryRegion *mr,
...@@ -1650,15 +1651,15 @@ void address_space_destroy(AddressSpace *as) ...@@ -1650,15 +1651,15 @@ void address_space_destroy(AddressSpace *as)
g_free(as->ioeventfds); 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) 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; typedef struct MemoryRegionList MemoryRegionList;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册