memory: propagate errors on I/O dispatch
Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
a649b9168c
commit
791af8c861
21
exec.c
21
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);
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
35
memory.c
35
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;
|
||||
|
Loading…
Reference in New Issue
Block a user