From nobody Wed Apr 9 00:56:28 2025 Return-Path: qemu-devel-bounces+famz=redhat.com@nongnu.org Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.81.9) by zmail26.collab.prod.int.phx2.redhat.com with LMTP; Mon, 4 Sep 2017 08:45:08 -0400 (EDT) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3E4DE122B73 for ; Mon, 4 Sep 2017 08:45:08 -0400 (EDT) Received: by smtp.corp.redhat.com (Postfix) id 384309AD3A; Mon, 4 Sep 2017 12:45:08 +0000 (UTC) Delivered-To: famz@redhat.com Received: from mx1.redhat.com (ext-mx01.extmail.prod.ext.phx2.redhat.com [10.5.110.25]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 2B7C29AD15 for ; Mon, 4 Sep 2017 12:45:03 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F1B7990122 for ; Mon, 4 Sep 2017 12:45:01 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com F1B7990122 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=qemu-devel-bounces+famz=redhat.com@nongnu.org DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com F1B7990122 Received: from localhost ([::1]:59635 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1doqkP-0002OX-5D for famz@redhat.com; Mon, 04 Sep 2017 08:45:01 -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> 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+famz=redhat.com@nongnu.org Sender: "Qemu-devel" X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 205 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 04 Sep 2017 12:45:02 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 04 Sep 2017 12:45:02 +0000 (UTC) for IP:'208.118.235.17' DOMAIN:'lists.gnu.org' HELO:'lists.gnu.org' FROM:'redhat.com@nongnu.org' RCPT:'' X-RedHat-Spam-Score: -5.02 (HEADER_FROM_DIFFERENT_DOMAINS,RCVD_IN_DNSWL_HI,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_PASS) 208.118.235.17 lists.gnu.org 208.118.235.17 lists.gnu.org X-Scanned-By: MIMEDefang 2.78 on 10.5.110.25 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Content-Length: 6096 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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(-) 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)(CPUArchSt= ate *env, uintptr_t retaddr) { CPUIOTLBEntry *iotlbentry =3D &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 =20 @@ -262,7 +262,7 @@ static inline void glue(io_write, SUFFIX)(CPUArchState = *env, uintptr_t retaddr) { CPUIOTLBEntry *iotlbentry =3D &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_SI= ZE); } =20 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) } =20 static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, + int mmu_idx, target_ulong addr, uintptr_t retaddr, int size) { CPUState *cpu =3D ENV_GET_CPU(env); @@ -754,6 +755,7 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEnt= ry *iotlbentry, MemoryRegion *mr =3D iotlb_to_region(cpu, physaddr, iotlbentry->attrs); uint64_t val; bool locked =3D false; + MemTxResult r; =20 physaddr =3D (physaddr & TARGET_PAGE_MASK) + addr; cpu->mem_io_pc =3D retaddr; @@ -767,7 +769,12 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEn= try *iotlbentry, qemu_mutex_lock_iothread(); locked =3D true; } - memory_region_dispatch_read(mr, physaddr, &val, size, iotlbentry->attr= s); + r =3D memory_region_dispatch_read(mr, physaddr, + &val, size, iotlbentry->attrs); + if (r !=3D 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, CPUIOTLBEnt= ry *iotlbentry, } =20 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 =3D iotlbentry->addr; MemoryRegion *mr =3D iotlb_to_region(cpu, physaddr, iotlbentry->attrs); bool locked =3D false; + MemTxResult r; =20 physaddr =3D (physaddr & TARGET_PAGE_MASK) + addr; if (mr !=3D &io_mem_rom && mr !=3D &io_mem_notdirty && !cpu->can_do_io= ) { @@ -795,7 +804,12 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry= *iotlbentry, qemu_mutex_lock_iothread(); locked =3D true; } - memory_region_dispatch_write(mr, physaddr, val, size, iotlbentry->attr= s); + r =3D memory_region_dispatch_write(mr, physaddr, + val, size, iotlbentry->attrs); + if (r !=3D 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, ta= rget_ulong addr) MemoryRegion *mr; CPUState *cpu =3D ENV_GET_CPU(env); CPUIOTLBEntry *iotlbentry; + hwaddr physaddr; =20 index =3D (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); mmu_idx =3D cpu_mmu_index(env, true); @@ -868,6 +883,19 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, t= arget_ulong addr) } qemu_mutex_unlock_iothread(); =20 + /* 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 =3D (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 --=20 2.7.4