Direct dispatch through MemoryRegion

Now that all mmio goes through MemoryRegions, we can convert
io_mem_opaque to be a MemoryRegion pointer, and remove the thunks
that convert from old-style CPU{Read,Write}MemoryFunc to MemoryRegionOps.

Signed-off-by: Avi Kivity <avi@redhat.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
master
Avi Kivity 2012-01-02 13:12:08 +02:00
parent 1ec9b909ff
commit a621f38de8
4 changed files with 53 additions and 118 deletions

View File

@ -302,9 +302,7 @@ extern void *tci_tb_ptr;
uint64_t io_mem_read(int index, target_phys_addr_t addr, unsigned size); uint64_t io_mem_read(int index, target_phys_addr_t addr, unsigned size);
void io_mem_write(int index, target_phys_addr_t addr, uint64_t value, void io_mem_write(int index, target_phys_addr_t addr, uint64_t value,
unsigned size); unsigned size);
extern CPUWriteMemoryFunc *_io_mem_write[IO_MEM_NB_ENTRIES][4]; extern struct MemoryRegion *io_mem_region[IO_MEM_NB_ENTRIES];
extern CPUReadMemoryFunc *_io_mem_read[IO_MEM_NB_ENTRIES][4];
extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx, void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
void *retaddr); void *retaddr);

View File

@ -31,9 +31,8 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr);
void qemu_ram_free(ram_addr_t addr); void qemu_ram_free(ram_addr_t addr);
void qemu_ram_free_from_ptr(ram_addr_t addr); void qemu_ram_free_from_ptr(ram_addr_t addr);
int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read, struct MemoryRegion;
CPUWriteMemoryFunc * const *mem_write, int cpu_register_io_memory(MemoryRegion *mr);
void *opaque);
void cpu_unregister_io_memory(int table_address); void cpu_unregister_io_memory(int table_address);
struct MemoryRegionSection; struct MemoryRegionSection;

40
exec.c
View File

@ -208,9 +208,7 @@ static void io_mem_init(void);
static void memory_map_init(void); static void memory_map_init(void);
/* io memory support */ /* io memory support */
CPUWriteMemoryFunc *_io_mem_write[IO_MEM_NB_ENTRIES][4]; MemoryRegion *io_mem_region[IO_MEM_NB_ENTRIES];
CPUReadMemoryFunc *_io_mem_read[IO_MEM_NB_ENTRIES][4];
void *io_mem_opaque[IO_MEM_NB_ENTRIES];
static char io_mem_used[IO_MEM_NB_ENTRIES]; static char io_mem_used[IO_MEM_NB_ENTRIES];
static MemoryRegion io_mem_watch; static MemoryRegion io_mem_watch;
#endif #endif
@ -2563,8 +2561,10 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
&p->phys_offset, orig_memory, &p->phys_offset, orig_memory,
p->region_offset); p->region_offset);
} else { } else {
subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK) MemoryRegion *mr
>> IO_MEM_SHIFT]; = io_mem_region[(orig_memory & ~TARGET_PAGE_MASK)
>> IO_MEM_SHIFT];
subpage = container_of(mr, subpage_t, iomem);
} }
subpage_register(subpage, start_addr2, end_addr2, phys_offset, subpage_register(subpage, start_addr2, end_addr2, phys_offset,
region_offset); region_offset);
@ -3427,13 +3427,8 @@ static int get_free_io_mem_idx(void)
modified. If it is zero, a new io zone is allocated. The return modified. If it is zero, a new io zone is allocated. The return
value can be used with cpu_register_physical_memory(). (-1) is value can be used with cpu_register_physical_memory(). (-1) is
returned if error. */ returned if error. */
static int cpu_register_io_memory_fixed(int io_index, static int cpu_register_io_memory_fixed(int io_index, MemoryRegion *mr)
CPUReadMemoryFunc * const *mem_read,
CPUWriteMemoryFunc * const *mem_write,
void *opaque)
{ {
int i;
if (io_index <= 0) { if (io_index <= 0) {
io_index = get_free_io_mem_idx(); io_index = get_free_io_mem_idx();
if (io_index == -1) if (io_index == -1)
@ -3444,36 +3439,21 @@ static int cpu_register_io_memory_fixed(int io_index,
return -1; return -1;
} }
for (i = 0; i < 3; ++i) { io_mem_region[io_index] = mr;
assert(mem_read[i]);
_io_mem_read[io_index][i] = mem_read[i];
}
for (i = 0; i < 3; ++i) {
assert(mem_write[i]);
_io_mem_write[io_index][i] = mem_write[i];
}
io_mem_opaque[io_index] = opaque;
return (io_index << IO_MEM_SHIFT); return (io_index << IO_MEM_SHIFT);
} }
int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read, int cpu_register_io_memory(MemoryRegion *mr)
CPUWriteMemoryFunc * const *mem_write,
void *opaque)
{ {
return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque); return cpu_register_io_memory_fixed(0, mr);
} }
void cpu_unregister_io_memory(int io_table_address) void cpu_unregister_io_memory(int io_table_address)
{ {
int i;
int io_index = io_table_address >> IO_MEM_SHIFT; int io_index = io_table_address >> IO_MEM_SHIFT;
for (i=0;i < 3; i++) { io_mem_region[io_index] = NULL;
_io_mem_read[io_index][i] = NULL;
_io_mem_write[io_index][i] = NULL;
}
io_mem_opaque[io_index] = NULL;
io_mem_used[io_index] = 0; io_mem_used[io_index] = 0;
} }

122
memory.c
View File

@ -906,11 +906,10 @@ static bool memory_region_access_valid(MemoryRegion *mr,
return true; return true;
} }
static uint32_t memory_region_read_thunk_n(void *_mr, static uint64_t memory_region_dispatch_read1(MemoryRegion *mr,
target_phys_addr_t addr, target_phys_addr_t addr,
unsigned size) unsigned size)
{ {
MemoryRegion *mr = _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)) {
@ -930,17 +929,45 @@ static uint32_t memory_region_read_thunk_n(void *_mr,
return data; return data;
} }
static void memory_region_write_thunk_n(void *_mr, static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
target_phys_addr_t addr,
unsigned size,
uint64_t data)
{ {
MemoryRegion *mr = _mr; if (memory_region_wrong_endianness(mr)) {
switch (size) {
case 1:
break;
case 2:
*data = bswap16(*data);
break;
case 4:
*data = bswap32(*data);
default:
abort();
}
}
}
static uint64_t memory_region_dispatch_read(MemoryRegion *mr,
target_phys_addr_t addr,
unsigned size)
{
uint64_t ret;
ret = memory_region_dispatch_read1(mr, addr, size);
adjust_endianness(mr, &ret, size);
return ret;
}
static void memory_region_dispatch_write(MemoryRegion *mr,
target_phys_addr_t addr,
uint64_t data,
unsigned size)
{
if (!memory_region_access_valid(mr, addr, size, true)) { if (!memory_region_access_valid(mr, addr, size, true)) {
return; /* FIXME: better signalling */ return; /* FIXME: better signalling */
} }
adjust_endianness(mr, &data, size);
if (!mr->ops->write) { if (!mr->ops->write) {
mr->ops->old_mmio.write[bitops_ffsl(size)](mr->opaque, addr, data); mr->ops->old_mmio.write[bitops_ffsl(size)](mr->opaque, addr, data);
return; return;
@ -953,69 +980,6 @@ static void memory_region_write_thunk_n(void *_mr,
memory_region_write_accessor, mr); memory_region_write_accessor, mr);
} }
static uint32_t memory_region_read_thunk_b(void *mr, target_phys_addr_t addr)
{
return memory_region_read_thunk_n(mr, addr, 1);
}
static uint32_t memory_region_read_thunk_w(void *mr, target_phys_addr_t addr)
{
uint32_t data;
data = memory_region_read_thunk_n(mr, addr, 2);
if (memory_region_wrong_endianness(mr)) {
data = bswap16(data);
}
return data;
}
static uint32_t memory_region_read_thunk_l(void *mr, target_phys_addr_t addr)
{
uint32_t data;
data = memory_region_read_thunk_n(mr, addr, 4);
if (memory_region_wrong_endianness(mr)) {
data = bswap32(data);
}
return data;
}
static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
uint32_t data)
{
memory_region_write_thunk_n(mr, addr, 1, data);
}
static void memory_region_write_thunk_w(void *mr, target_phys_addr_t addr,
uint32_t data)
{
if (memory_region_wrong_endianness(mr)) {
data = bswap16(data);
}
memory_region_write_thunk_n(mr, addr, 2, data);
}
static void memory_region_write_thunk_l(void *mr, target_phys_addr_t addr,
uint32_t data)
{
if (memory_region_wrong_endianness(mr)) {
data = bswap32(data);
}
memory_region_write_thunk_n(mr, addr, 4, data);
}
static CPUReadMemoryFunc * const memory_region_read_thunk[] = {
memory_region_read_thunk_b,
memory_region_read_thunk_w,
memory_region_read_thunk_l,
};
static CPUWriteMemoryFunc * const memory_region_write_thunk[] = {
memory_region_write_thunk_b,
memory_region_write_thunk_w,
memory_region_write_thunk_l,
};
void memory_region_init_io(MemoryRegion *mr, void memory_region_init_io(MemoryRegion *mr,
const MemoryRegionOps *ops, const MemoryRegionOps *ops,
void *opaque, void *opaque,
@ -1027,9 +991,7 @@ void memory_region_init_io(MemoryRegion *mr,
mr->opaque = opaque; mr->opaque = opaque;
mr->terminates = true; mr->terminates = true;
mr->destructor = memory_region_destructor_iomem; mr->destructor = memory_region_destructor_iomem;
mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk, mr->ram_addr = cpu_register_io_memory(mr);
memory_region_write_thunk,
mr);
} }
void memory_region_init_ram(MemoryRegion *mr, void memory_region_init_ram(MemoryRegion *mr,
@ -1078,9 +1040,7 @@ void memory_region_init_rom_device(MemoryRegion *mr,
mr->terminates = true; mr->terminates = true;
mr->destructor = memory_region_destructor_rom_device; mr->destructor = memory_region_destructor_rom_device;
mr->ram_addr = qemu_ram_alloc(size, mr); mr->ram_addr = qemu_ram_alloc(size, mr);
mr->ram_addr |= cpu_register_io_memory(memory_region_read_thunk, mr->ram_addr |= cpu_register_io_memory(mr);
memory_region_write_thunk,
mr);
mr->ram_addr |= IO_MEM_ROMD; mr->ram_addr |= IO_MEM_ROMD;
} }
@ -1552,15 +1512,13 @@ void set_system_io_map(MemoryRegion *mr)
uint64_t io_mem_read(int io_index, target_phys_addr_t addr, unsigned size) uint64_t io_mem_read(int io_index, target_phys_addr_t addr, unsigned size)
{ {
return _io_mem_read[io_index][bitops_ffsl(size)](io_mem_opaque[io_index], return memory_region_dispatch_read(io_mem_region[io_index], addr, size);
addr);
} }
void io_mem_write(int io_index, target_phys_addr_t addr, void io_mem_write(int io_index, target_phys_addr_t addr,
uint64_t val, unsigned size) uint64_t val, unsigned size)
{ {
_io_mem_write[io_index][bitops_ffsl(size)](io_mem_opaque[io_index], memory_region_dispatch_write(io_mem_region[io_index], addr, val, size);
addr, val);
} }
typedef struct MemoryRegionList MemoryRegionList; typedef struct MemoryRegionList MemoryRegionList;