If the device provides full 64-bit i/o routines, use them instead of forcing the i/o to be split into two 32-bit i/o calls.
Signed-off-by: Richard Henderson <r...@twiddle.net> --- cpu-common.h | 5 ++ exec.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++------ softmmu_template.h | 8 ++- 3 files changed, 139 insertions(+), 18 deletions(-) diff --git a/cpu-common.h b/cpu-common.h index 0566654..df5ad32 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -28,13 +28,18 @@ typedef unsigned long ram_addr_t; typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t, uint32_t); typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t); +typedef void CPUWriteMemory64Func(void *opaque, target_phys_addr_t, uint64_t); +typedef uint64_t CPUReadMemory64Func(void *opaque, target_phys_addr_t); + typedef struct CPUIOMemoryOps { CPUReadMemoryFunc *readb; CPUReadMemoryFunc *readw; CPUReadMemoryFunc *readl; + CPUReadMemory64Func *readq; CPUWriteMemoryFunc *writeb; CPUWriteMemoryFunc *writew; CPUWriteMemoryFunc *writel; + CPUWriteMemory64Func *writeq; } CPUIOMemoryOps; void cpu_register_physical_memory_offset(target_phys_addr_t start_addr, diff --git a/exec.c b/exec.c index d8691c9..596e2e4 100644 --- a/exec.c +++ b/exec.c @@ -2930,6 +2930,17 @@ static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr) return 0; } +static uint64_t unassigned_mem_readq(void *opaque, target_phys_addr_t addr) +{ +#ifdef DEBUG_UNASSIGNED + printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); +#endif +#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) + do_unassigned_access(addr, 0, 0, 0, 8); +#endif + return 0; +} + static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) { #ifdef DEBUG_UNASSIGNED @@ -2960,13 +2971,26 @@ static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_ #endif } +static void unassigned_mem_writeq(void *opaque, target_phys_addr_t addr, uint64_t val) +{ +#ifdef DEBUG_UNASSIGNED + printf("Unassigned mem write " TARGET_FMT_plx " = 0x" PRIx64 "\n", + addr, val); +#endif +#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) + do_unassigned_access(addr, 1, 0, 0, 8); +#endif +} + static const CPUIOMemoryOps unassigned_mem_ops = { .readb = unassigned_mem_readb, .readw = unassigned_mem_readw, .readl = unassigned_mem_readl, + .readq = unassigned_mem_readq, .writeb = unassigned_mem_writeb, .writew = unassigned_mem_writew, .writel = unassigned_mem_writel, + .writeq = unassigned_mem_writeq, }; static const CPUIOMemoryOps rom_mem_ops = { @@ -2974,6 +2998,7 @@ static const CPUIOMemoryOps rom_mem_ops = { .writeb = unassigned_mem_writeb, .writew = unassigned_mem_writew, .writel = unassigned_mem_writel, + .writeq = unassigned_mem_writeq, }; static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr, @@ -3036,11 +3061,32 @@ static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr, tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr); } +static void notdirty_mem_writeq(void *opaque, target_phys_addr_t ram_addr, + uint64_t val) +{ + int dirty_flags; + dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr); + if (!(dirty_flags & CODE_DIRTY_FLAG)) { +#if !defined(CONFIG_USER_ONLY) + tb_invalidate_phys_page_fast(ram_addr, 8); + dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr); +#endif + } + stq_p(qemu_get_ram_ptr(ram_addr), val); + dirty_flags |= (0xff & ~CODE_DIRTY_FLAG); + cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags); + /* we remove the notdirty callback only if the code has been flushed */ + if (dirty_flags == 0xff) { + tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr); + } +} + static const CPUIOMemoryOps notdirty_mem_ops = { /* Read functions never used. */ .writeb = notdirty_mem_writeb, .writew = notdirty_mem_writew, .writel = notdirty_mem_writel, + .writeq = notdirty_mem_writeq, }; /* Generate a debug exception if a watchpoint has been hit. */ @@ -3109,6 +3155,12 @@ static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr) return ldl_phys(addr); } +static uint64_t watch_mem_readq(void *opaque, target_phys_addr_t addr) +{ + check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x7, BP_MEM_READ); + return ldq_phys(addr); +} + static void watch_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) { @@ -3130,13 +3182,22 @@ static void watch_mem_writel(void *opaque, target_phys_addr_t addr, stl_phys(addr, val); } +static void watch_mem_writeq(void *opaque, target_phys_addr_t addr, + uint64_t val) +{ + check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x7, BP_MEM_WRITE); + stq_phys(addr, val); +} + static const CPUIOMemoryOps watch_mem_ops = { .readb = watch_mem_readb, .readw = watch_mem_readw, .readl = watch_mem_readl, + .readq = watch_mem_readq, .writeb = watch_mem_writeb, .writew = watch_mem_writew, .writel = watch_mem_writel, + .writeq = watch_mem_writeq, }; static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr) @@ -3226,13 +3287,44 @@ static void subpage_writel (void *opaque, addr + mmio->region_offset[idx], value); } +static uint64_t subpage_readq (void *opaque, target_phys_addr_t addr) +{ + subpage_t *mmio = opaque; + unsigned int idx = SUBPAGE_IDX(addr); + +#if defined(DEBUG_SUBPAGE) + printf("%s: subpage %p addr " TARGET_FMT_plx " idx %d\n", + __func__, mmio, addr, idx); +#endif + + return mmio->mem_ops[idx].readq(mmio->opaque[idx], + addr + mmio->region_offset[idx]); +} + +static void subpage_writeq (void *opaque, + target_phys_addr_t addr, uint64_t value) +{ + subpage_t *mmio = opaque; + unsigned int idx = SUBPAGE_IDX(addr); + +#if defined(DEBUG_SUBPAGE) + printf("%s: subpage %p addr " TARGET_FMT_plx " idx %d\n", + __func__, mmio, addr, idx); +#endif + + return mmio->mem_ops[idx].writeq(mmio->opaque[idx], + addr + mmio->region_offset[idx], value); +} + static const CPUIOMemoryOps subpage_ops = { .readb = subpage_readb, .readw = subpage_readw, .readl = subpage_readl, + .readq = subpage_readq, .writeb = subpage_writeb, .writew = subpage_writew, .writel = subpage_writel, + .writeq = subpage_writeq, }; static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, @@ -3342,9 +3434,11 @@ int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read, ops.readb = mem_read[0]; ops.readw = mem_read[1]; ops.readl = mem_read[2]; + ops.readq = NULL; ops.writeb = mem_write[0]; ops.writew = mem_write[1]; ops.writel = mem_write[2]; + ops.writeq = NULL; return cpu_register_io_memory_fixed(0, &ops, opaque); } @@ -3447,7 +3541,11 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset; /* XXX: could force cpu_single_env to NULL to avoid potential bugs */ - if (l >= 4 && ((addr1 & 3) == 0)) { + if (l >= 8 && (addr1 & 7) == 0 && io_mem_ops[io_index].writeq) { + uint64_t v64 = ldq_p(buf); + io_mem_ops[io_index].writeq(opaque, addr1, v64); + l = 8; + } else if (l >= 4 && ((addr1 & 3) == 0)) { /* 32 bit write access */ val = ldl_p(buf); io_mem_ops[io_index].writel(opaque, addr1, val); @@ -3486,7 +3584,12 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, void *opaque = io_mem_opaque[io_index]; if (p) addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset; - if (l >= 4 && ((addr1 & 3) == 0)) { + if (l >= 8 && (addr1 & 7) == 0 && io_mem_ops[io_index].readq) { + uint64_t v64; + v64 = io_mem_ops[io_index].readq(opaque, addr1); + stq_p(buf, val); + l = 8; + } else if (l >= 4 && ((addr1 & 3) == 0)) { /* 32 bit read access */ val = io_mem_ops[io_index].readl(opaque, addr1); stl_p(buf, val); @@ -3750,21 +3853,25 @@ uint64_t ldq_phys(target_phys_addr_t addr) /* I/O case */ int io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); void *opaque = io_mem_opaque[io_index]; - CPUReadMemoryFunc *readl; - uint32_t v1, v2; if (p) addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset; - readl = io_mem_ops[io_index].readl; - v1 = readl(opaque, addr); - v2 = readl(opaque, addr + 4); + if (io_mem_ops[io_index].readq) { + val = io_mem_ops[io_index].readq(opaque, addr); + } else { + CPUReadMemoryFunc *readl = io_mem_ops[io_index].readl; + uint32_t v1, v2; + + v1 = readl(opaque, addr); + v2 = readl(opaque, addr + 4); #ifdef TARGET_WORDS_BIGENDIAN - val = ((uint64_t)v1 << 32) | v2; + val = ((uint64_t)v1 << 32) | v2; #else - val = ((uint64_t)v2 << 32) | v1; + val = ((uint64_t)v2 << 32) | v1; #endif + } } else { /* RAM case */ ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) + @@ -3845,20 +3952,25 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val) if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { int io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); void *opaque = io_mem_opaque[io_index]; - CPUWriteMemoryFunc *writel; - uint32_t v1, v2; if (p) addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset; + + if (io_mem_ops[io_index].writeq) { + io_mem_ops[io_index].writeq(opaque, addr, val); + } else { + CPUWriteMemoryFunc *writel = io_mem_ops[io_index].writel; + uint32_t v1, v2; + #ifdef TARGET_WORDS_BIGENDIAN - v1 = val >> 32, v2 = val; + v1 = val >> 32, v2 = val; #else - v1 = val, v2 = val >> 32; + v1 = val, v2 = val >> 32; #endif - writel = io_mem_ops[io_index].writel; - writel(opaque, addr, v1); - writel(opaque, addr + 4, v2); + writel(opaque, addr, v1); + writel(opaque, addr + 4, v2); + } } else { ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); diff --git a/softmmu_template.h b/softmmu_template.h index 27e23c9..37992e0 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -72,7 +72,9 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr, #if SHIFT <= 2 res = io_mem_ops[index].glue(read,SUFFIX)(opaque, physaddr); #else - { + if (io_mem_ops[index].readq) { + res = io_mem_ops[index].readq(opaque, physaddr); + } else { CPUReadMemoryFunc *readl = io_mem_ops[index].readl; uint32_t v1 = readl(opaque, physaddr); uint32_t v2 = readl(opaque, physaddr + 4); @@ -222,7 +224,9 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr, #if SHIFT <= 2 io_mem_ops[index].glue(write,SUFFIX)(opaque, physaddr, val); #else - { + if (io_mem_ops[index].writeq) { + io_mem_ops[index].writeq(opaque, physaddr, val); + } else { CPUWriteMemoryFunc *writel = io_mem_ops[index].writel; uint32_t v1, v2; -- 1.6.6.1