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>
			
			
This commit is contained in:
		
							parent
							
								
									1ec9b909ff
								
							
						
					
					
						commit
						a621f38de8
					
				@ -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);
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										38
									
								
								exec.c
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								exec.c
									
									
									
									
									
								
							@ -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_region[(orig_memory & ~TARGET_PAGE_MASK)
 | 
				
			||||||
                                        >> IO_MEM_SHIFT];
 | 
					                                        >> 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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										118
									
								
								memory.c
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								memory.c
									
									
									
									
									
								
							@ -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;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user