Commit b018ddf6 authored by Paolo Bonzini's avatar Paolo Bonzini

memory: dispatch unassigned accesses based on .valid.accepts

This provides the basics for detecting accesses to unassigned memory
as soon as they happen, and also for a simple implementation of
address_space_access_valid.
Reviewed-by: default avatarRichard Henderson <rth@twiddle.net>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent bf8d5166
...@@ -1383,32 +1383,14 @@ ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr) ...@@ -1383,32 +1383,14 @@ ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
return ram_addr; return ram_addr;
} }
static uint64_t unassigned_mem_read(void *opaque, hwaddr addr, static bool unassigned_mem_accepts(void *opaque, hwaddr addr,
unsigned size) unsigned size, bool is_write)
{ {
#ifdef DEBUG_UNASSIGNED return false;
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
#endif
return 0;
}
static void unassigned_mem_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val);
#endif
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
#endif
} }
static const MemoryRegionOps unassigned_mem_ops = { const MemoryRegionOps unassigned_mem_ops = {
.read = unassigned_mem_read, .valid.accepts = unassigned_mem_accepts,
.write = unassigned_mem_write,
.endianness = DEVICE_NATIVE_ENDIAN, .endianness = DEVICE_NATIVE_ENDIAN,
}; };
...@@ -1442,9 +1424,15 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr, ...@@ -1442,9 +1424,15 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr); tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
} }
static bool notdirty_mem_accepts(void *opaque, hwaddr addr,
unsigned size, bool is_write)
{
return is_write;
}
static const MemoryRegionOps notdirty_mem_ops = { static const MemoryRegionOps notdirty_mem_ops = {
.read = unassigned_mem_read,
.write = notdirty_mem_write, .write = notdirty_mem_write,
.valid.accepts = notdirty_mem_accepts,
.endianness = DEVICE_NATIVE_ENDIAN, .endianness = DEVICE_NATIVE_ENDIAN,
}; };
......
...@@ -814,6 +814,29 @@ void memory_region_init(MemoryRegion *mr, ...@@ -814,6 +814,29 @@ void memory_region_init(MemoryRegion *mr,
mr->flush_coalesced_mmio = false; mr->flush_coalesced_mmio = false;
} }
static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
unsigned size)
{
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
#endif
return 0;
}
static void unassigned_mem_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val);
#endif
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
#endif
}
static bool memory_region_access_valid(MemoryRegion *mr, static bool memory_region_access_valid(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
unsigned size, unsigned size,
...@@ -847,7 +870,7 @@ static uint64_t memory_region_dispatch_read1(MemoryRegion *mr, ...@@ -847,7 +870,7 @@ 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)) { if (!memory_region_access_valid(mr, addr, size, false)) {
return -1U; /* FIXME: better signalling */ return unassigned_mem_read(mr, addr, size);
} }
if (!mr->ops->read) { if (!mr->ops->read) {
...@@ -898,7 +921,8 @@ static void memory_region_dispatch_write(MemoryRegion *mr, ...@@ -898,7 +921,8 @@ static void memory_region_dispatch_write(MemoryRegion *mr,
unsigned size) unsigned size)
{ {
if (!memory_region_access_valid(mr, addr, size, true)) { if (!memory_region_access_valid(mr, addr, size, true)) {
return; /* FIXME: better signalling */ unassigned_mem_write(mr, addr, data, size);
return;
} }
adjust_endianness(mr, &data, size); adjust_endianness(mr, &data, size);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment