mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
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: Richard Henderson <rth@twiddle.net> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
bf8d516639
commit
b018ddf633
2 changed files with 38 additions and 26 deletions
36
exec.c
36
exec.c
|
@ -1383,32 +1383,14 @@ ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
|
|||
return ram_addr;
|
||||
}
|
||||
|
||||
static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
static bool unassigned_mem_accepts(void *opaque, hwaddr addr,
|
||||
unsigned size, bool is_write)
|
||||
{
|
||||
#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;
|
||||
return false;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.read = unassigned_mem_read,
|
||||
.write = unassigned_mem_write,
|
||||
const MemoryRegionOps unassigned_mem_ops = {
|
||||
.valid.accepts = unassigned_mem_accepts,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
static bool notdirty_mem_accepts(void *opaque, hwaddr addr,
|
||||
unsigned size, bool is_write)
|
||||
{
|
||||
return is_write;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps notdirty_mem_ops = {
|
||||
.read = unassigned_mem_read,
|
||||
.write = notdirty_mem_write,
|
||||
.valid.accepts = notdirty_mem_accepts,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
|
|
28
memory.c
28
memory.c
|
@ -814,6 +814,29 @@ void memory_region_init(MemoryRegion *mr,
|
|||
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,
|
||||
hwaddr addr,
|
||||
unsigned size,
|
||||
|
@ -847,7 +870,7 @@ static uint64_t memory_region_dispatch_read1(MemoryRegion *mr,
|
|||
uint64_t data = 0;
|
||||
|
||||
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) {
|
||||
|
@ -898,7 +921,8 @@ static void memory_region_dispatch_write(MemoryRegion *mr,
|
|||
unsigned size)
|
||||
{
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue