From patchwork Mon Sep 4 12:25:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 111576 Delivered-To: patch@linaro.org Received: by 10.140.94.166 with SMTP id g35csp1480414qge; Mon, 4 Sep 2017 05:45:09 -0700 (PDT) X-Google-Smtp-Source: ADKCNb5Uh86tv82Si/2QhDznsfFzH7LO/s7snfIi9N4QFRbL6F+6ql3Sb2r3s4LKrWYjwzCux5hz X-Received: by 10.200.34.232 with SMTP id g37mr383157qta.217.1504529109161; Mon, 04 Sep 2017 05:45:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1504529109; cv=none; d=google.com; s=arc-20160816; b=YIhff7WNGI9BMzQWjQRkzzbpKhCskOrB2FKWN+UANs2W7pSus7ZFFjOas+Hqs+v/9/ mxVB/ASp0NN20SJYk6Uig7R8wvpzDCysr4uG+VYn1eUn7o9IE/YNkfrPt30w+HnG3j1X RFUAb+8kYNC/+u+YUf+eh8Vl9/33qqp3OhGZ7huYDbifEH7c/3pVTnbCU4M1nZnDEhpA yIHlwgz4SfqZFNkf1hcKug48/A7SWTnoKxulWi/qHGXP4uNRzhzJtqFTlrrz/mhXn352 2iBMqeHhDl4i11B/LhcW8yY6sjaefPBA+gxsUkZrYwNNPpRyVaaWZJO/U5q3c3Cfb1OE 0wZQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:arc-authentication-results; bh=WuqpqY79FraI/VIruzzq69jObXCBSjJx2TwxCdeEU/0=; b=lOBOqCwPXCtZ8RnnEAPTW9kOEWJtEnXW6eEUJTxZ651PnzeD/8B+5jDWGYTu9lKGdA d9qysE9rFO1BCKtPhvkTvtrhckHM17BRT3miLwKufDNR90QBNG9W2/9WcwRHJPfpYddR CYB4xwlCNo8VQK42/6QKbUSRRXZ8SF42KGe+fasbKtqJVJ7XoAusKSaggGiAqc3tGqez gHbxDmGcJuxNV8Bu3pSDWFCSpo8xmEd7QZ5ubj5aoMcEaRl+I7T/KC/SFPB8ANmYd9xu GSN36DhWI+AGGeC5NEd4DYEmoJ/i7VlIOCBkjQCsvNJx6GojbSzP/HdvMKQczonTpZhf tFqw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 11si6853797qtp.509.2017.09.04.05.45.08 for (version=TLS1 cipher=AES128-SHA bits=128/128); Mon, 04 Sep 2017 05:45:09 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:59635 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1doqkV-0002OX-1M for patch@linaro.org; Mon, 04 Sep 2017 08:45:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52863) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1doqSg-0005DX-3f for qemu-devel@nongnu.org; Mon, 04 Sep 2017 08:26:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1doqSQ-0004vs-UD for qemu-devel@nongnu.org; Mon, 04 Sep 2017 08:26:42 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:37132) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1doqSQ-0004v8-N6 for qemu-devel@nongnu.org; Mon, 04 Sep 2017 08:26:26 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1doqSP-0005aw-Mz for qemu-devel@nongnu.org; Mon, 04 Sep 2017 13:26:25 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 4 Sep 2017 13:25:58 +0100 Message-Id: <1504527967-29248-28-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1504527967-29248-1-git-send-email-peter.maydell@linaro.org> References: <1504527967-29248-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PULL 27/36] cputlb: Support generating CPU exceptions on memory transaction failures X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Call the new cpu_transaction_failed() hook at the places where CPU generated code interacts with the memory system: io_readx() io_writex() get_page_addr_code() Any access from C code (eg via cpu_physical_memory_rw(), address_space_rw(), ld/st_*_phys()) will *not* trigger CPU exceptions via cpu_transaction_failed(). Handling for transactions failures for this kind of call should be done by using a function which returns a MemTxResult and treating the failure case appropriately in the calling code. In an ideal world we would not generate CPU exceptions for instruction fetch failures in get_page_addr_code() but instead wait until the code translation process tried a load and it failed; however that change would require too great a restructuring and redesign to attempt at this point. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias --- softmmu_template.h | 4 ++-- accel/tcg/cputlb.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) -- 2.7.4 diff --git a/softmmu_template.h b/softmmu_template.h index 4a2b665..d756329 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -101,7 +101,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env, uintptr_t retaddr) { CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index]; - return io_readx(env, iotlbentry, addr, retaddr, DATA_SIZE); + return io_readx(env, iotlbentry, mmu_idx, addr, retaddr, DATA_SIZE); } #endif @@ -262,7 +262,7 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env, uintptr_t retaddr) { CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index]; - return io_writex(env, iotlbentry, val, addr, retaddr, DATA_SIZE); + return io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr, DATA_SIZE); } void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 85635ae..e72415a 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -747,6 +747,7 @@ static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr) } static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, + int mmu_idx, target_ulong addr, uintptr_t retaddr, int size) { CPUState *cpu = ENV_GET_CPU(env); @@ -754,6 +755,7 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, MemoryRegion *mr = iotlb_to_region(cpu, physaddr, iotlbentry->attrs); uint64_t val; bool locked = false; + MemTxResult r; physaddr = (physaddr & TARGET_PAGE_MASK) + addr; cpu->mem_io_pc = retaddr; @@ -767,7 +769,12 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, qemu_mutex_lock_iothread(); locked = true; } - memory_region_dispatch_read(mr, physaddr, &val, size, iotlbentry->attrs); + r = memory_region_dispatch_read(mr, physaddr, + &val, size, iotlbentry->attrs); + if (r != MEMTX_OK) { + cpu_transaction_failed(cpu, physaddr, addr, size, MMU_DATA_LOAD, + mmu_idx, iotlbentry->attrs, r, retaddr); + } if (locked) { qemu_mutex_unlock_iothread(); } @@ -776,6 +783,7 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, } static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry, + int mmu_idx, uint64_t val, target_ulong addr, uintptr_t retaddr, int size) { @@ -783,6 +791,7 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry, hwaddr physaddr = iotlbentry->addr; MemoryRegion *mr = iotlb_to_region(cpu, physaddr, iotlbentry->attrs); bool locked = false; + MemTxResult r; physaddr = (physaddr & TARGET_PAGE_MASK) + addr; if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) { @@ -795,7 +804,12 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry, qemu_mutex_lock_iothread(); locked = true; } - memory_region_dispatch_write(mr, physaddr, val, size, iotlbentry->attrs); + r = memory_region_dispatch_write(mr, physaddr, + val, size, iotlbentry->attrs); + if (r != MEMTX_OK) { + cpu_transaction_failed(cpu, physaddr, addr, size, MMU_DATA_STORE, + mmu_idx, iotlbentry->attrs, r, retaddr); + } if (locked) { qemu_mutex_unlock_iothread(); } @@ -845,6 +859,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr) MemoryRegion *mr; CPUState *cpu = ENV_GET_CPU(env); CPUIOTLBEntry *iotlbentry; + hwaddr physaddr; index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); mmu_idx = cpu_mmu_index(env, true); @@ -868,6 +883,19 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr) } qemu_mutex_unlock_iothread(); + /* Give the new-style cpu_transaction_failed() hook first chance + * to handle this. + * This is not the ideal place to detect and generate CPU + * exceptions for instruction fetch failure (for instance + * we don't know the length of the access that the CPU would + * use, and it would be better to go ahead and try the access + * and use the MemTXResult it produced). However it is the + * simplest place we have currently available for the check. + */ + physaddr = (iotlbentry->addr & TARGET_PAGE_MASK) + addr; + cpu_transaction_failed(cpu, physaddr, addr, 0, MMU_INST_FETCH, mmu_idx, + iotlbentry->attrs, MEMTX_DECODE_ERROR, 0); + cpu_unassigned_access(cpu, addr, false, true, 0, 4); /* The CPU's unassigned access hook might have longjumped out * with an exception. If it didn't (or there was no hook) then