From patchwork Tue Apr 20 20:22:02 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 50577 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 2E82AB7D0B for ; Wed, 21 Apr 2010 07:22:03 +1000 (EST) Received: from localhost ([127.0.0.1]:36048 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O4Krr-0001Yn-5y for incoming@patchwork.ozlabs.org; Tue, 20 Apr 2010 17:20:27 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O4Ki0-00078C-1n for qemu-devel@nongnu.org; Tue, 20 Apr 2010 17:10:16 -0400 Received: from [140.186.70.92] (port=37275 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O4Khw-00076l-Ld for qemu-devel@nongnu.org; Tue, 20 Apr 2010 17:10:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O4Khn-0003ua-F4 for qemu-devel@nongnu.org; Tue, 20 Apr 2010 17:10:12 -0400 Received: from are.twiddle.net ([75.149.56.221]:37434) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O4Khm-0003u0-Th for qemu-devel@nongnu.org; Tue, 20 Apr 2010 17:10:03 -0400 Received: by are.twiddle.net (Postfix, from userid 5000) id D8732D50; Tue, 20 Apr 2010 14:10:01 -0700 (PDT) Message-Id: <34811c00b8b37655d9955f6f21224709bc6ce004.1271795219.git.rth@twiddle.net> In-Reply-To: References: From: Richard Henderson Date: Tue, 20 Apr 2010 13:22:02 -0700 To: qemu-devel@nongnu.org X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: paul@codesourcery.com, agraf@suse.de Subject: [Qemu-devel] [PATCH 2/2] io: Add readq/writeq hooks and use them. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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;