From nobody Sat Jul 25 14:10:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=oss.qualcomm.com ARC-Seal: i=1; a=rsa-sha256; t=1784299562; cv=none; d=zohomail.com; s=zohoarc; b=KRcD/aiUaccD5CZgNnRQybnwnaynLosUzpXTizApSTSDbsSiqYjA48yD4IR4Z4Q4yDJk93UUlNp3kXGv8gKCbbS5UoEGSbAQ42VYDagyfyDPiVUwMXe3hKnSlcNQDniGd+PlTYSLfDZBIvJM7NUYwOykQnShsLL7adepbdMZgYQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1784299562; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=BvRoZwGnPxP1MvFPCRipUS24Heo1YSkKkPwHV9QMs2Q=; b=PDcS3lPQ9cJFldgimUdwgSvxA1Tr7GVs6zZ1ZqurqBajg0tVyRP2Z28xoM0RprbDGW1JVVuiNgcOPRjtswO4FsSW6xhPBcRy5iIGcQmoaFOAKb90o/rlanriOJBW+RDxqF/L0K0NulB+Pok4UNt8037MR9pliuhdcf2hPdAIXjY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1784299562048528.1096062781983; Fri, 17 Jul 2026 07:46:02 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wkjor-0006Xo-HS; Fri, 17 Jul 2026 10:45:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wkjok-0006X3-Hs for qemu-devel@nongnu.org; Fri, 17 Jul 2026 10:45:34 -0400 Received: from mx0b-0031df01.pphosted.com ([205.220.180.131]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wkjoi-0001e3-A9 for qemu-devel@nongnu.org; Fri, 17 Jul 2026 10:45:34 -0400 Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 66HE7qDa1875183 for ; Fri, 17 Jul 2026 14:45:31 GMT Received: from mail-qt1-f198.google.com (mail-qt1-f198.google.com [209.85.160.198]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4fff9p9twk-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Fri, 17 Jul 2026 14:45:31 +0000 (GMT) Received: by mail-qt1-f198.google.com with SMTP id d75a77b69052e-51c110a3b6aso72398371cf.1 for ; Fri, 17 Jul 2026 07:45:30 -0700 (PDT) Received: from localhost (85-207-54-79.static.bluetone.cz. [85.207.54.79]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5b291e0ea1dsm374475e87.43.2026.07.17.07.45.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jul 2026 07:45:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:message-id:mime-version :subject:to; s=qcppdkim1; bh=BvRoZwGnPxP1MvFPCRipUS24Heo1YSkKkPw HV9QMs2Q=; b=am35V1kYuwzZShP8s9cCdBxN0ebaJ2PlrE8DCthPLCEYHuv5PX/ sklY/ZMfgQ1BQvxgGd2vu5snAGZTu7kPbpvnmzeUfny5buFJ/7lex6DMV6FTmXjh 04PbIolGCOJhNxPgtwBUwpZ3kHuz1Nn+SSygdElU2OMW47a2cYEa8gG4QEBq5A+g 0Snr6GylgqmOHQnpbd5P7JuHaImvLm0SEd0b/IdzrTiFZRD+BtSEcaU/k+QrxSOK ZWS1H605QvB18aVT/b4caWw1u67QMpY+l+2jkwRLSvNfEdtNDqyn4FSuZlnqjXPW gHocvT1J0NnZqU97yO+VsOV8R+4OqgU0I3A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1784299530; x=1784904330; darn=nongnu.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=BvRoZwGnPxP1MvFPCRipUS24Heo1YSkKkPwHV9QMs2Q=; b=OewlvtH08Pz0Nca6yyDujyrPLoyLycNzJxuWqZpQ6e1n2+9w0mteo7MMmkSK2jkOWU LD5IasZyPHqexsY5AIyMCFdooAs9/nfQZE1mrNSU1sCb4keBGEBxIqqeeRwiSothep+i BluRzRQORC7ABjxw03MJuG8TjdIWv/bOASCOr5pOdHlwsgbHs3f3OumaVJquY5tCrc7T vztanrBR+XESA3rPgXFTtpetvHp79JwfIu3qT3LeY7cJU+lsf6SbsEqI81J3+sAMNpy/ 95/IwR1DRl8rfrRuJrPjDqfKalH/2VZslAi4RiGkgus3CypqrX2EXPMjfchXU73jl4WP 9Kgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784299530; x=1784904330; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=BvRoZwGnPxP1MvFPCRipUS24Heo1YSkKkPwHV9QMs2Q=; b=QlJT9IACIM902geAm8JW/rljb2vo7gOeKay9+xcyEzZTxR0MTyeuRcns3PIXX87Vyj cqWk3+uXzj5NOnH6HHj7jbnv98jAZkUz4bT1F1gSEG15QeTcs0wuEZDFZn2u2YlMnvU2 13fZlIne3ssZTQnXKF+lHT1Q6jViwfl4gZ1d1QlOu1HP697wdVXu4SZaTFORZ2oCauHW xjU8mg13wi4F2oSFj8LWlJwmdU+LGdIy51g6xyWiqTWf78kXwu0enl7rNFOyYw84BnF6 6jg1OrT4ThyfWYg6arYREDXbKoV6vFA1DOWKJvmB7bVUb55KjWoVfThCoha9gr/fT9k6 1L8g== X-Forwarded-Encrypted: i=1; AHgh+RoohX79eH4wp/vchui+lQiQDIQ7lBciUhJ2WG6IoeNTl1xpfs79DQgU/cYpNdAdwjAsBA4AAGduvnQK@nongnu.org X-Gm-Message-State: AOJu0YyIvEiatuWLxAdfqOhINS3CxfUN7lpN988oDqbyJ/RVvgWTh1q6 HKsXyn7FFaWwkrr8+F83U59ql7rodtnBwTEsYHMFY7zwvMxYGcAH293Pdpb1McUpaBzFxv26B/6 pkDU1uAZr4rh2cg6jNbFnWSlW0B5z33uNc6wGVvcBhwDCPbzTldjkMQt/7g== X-Gm-Gg: AfdE7cnXLG1BRdKYDTFHkMcu8hQSrXPquhCnLguYOGLwBsGdwE5nnVmtUpyvEcnVDQO TK1+aPnGjDKr8z8AY6bXMhLeq7aC5zDBOjbdvJKDIDYB17OxeT8kaRTOUZ2l+BguATpeJBsdi+D ohy8YesB0aayd2aM56zoFyziXf8RVQowjZZUBRdfe4aqvaF/MYGqBB8mi9NiDyMKNdkwASUuert PJIOOCJ3HIz11j1PNLImmyATIEaOqoj9WbE2TFmOKq5j8BXU/LAAOpFut5xpGxY7jvrC+P/M+0j ZG2F7d4uqveIkJblh4sjrCrEd51LuC8GUxw8Ezku0qp1Emw7bf32m/J28eOID2RHe024Gz5R+ly XUmhV8/z/+8ds9cWP/cjkbMXYBIZIBIim5J5KmCI/ X-Received: by 2002:a05:622a:4012:b0:51c:c29:d4c7 with SMTP id d75a77b69052e-5213fc54d38mr27413041cf.62.1784299530230; Fri, 17 Jul 2026 07:45:30 -0700 (PDT) X-Received: by 2002:a05:622a:4012:b0:51c:c29:d4c7 with SMTP id d75a77b69052e-5213fc54d38mr27411291cf.62.1784299528677; Fri, 17 Jul 2026 07:45:28 -0700 (PDT) From: Andrew Jones To: qemu-riscv@nongnu.org, qemu-devel@nongnu.org Cc: alistair.francis@wdc.com, palmer@dabbelt.com, daniel.barboza@oss.qualcomm.com Subject: [PATCH] hw/riscv/riscv-iommu: preserve requested perm in spa_fetch() Date: Fri, 17 Jul 2026 16:45:25 +0200 Message-ID: <20260717144525.1154204-1-andrew.jones@oss.qualcomm.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: bmNDeUoHD7KQSsL3a0y3HvIDwIcV9Bt0 X-Proofpoint-ORIG-GUID: bmNDeUoHD7KQSsL3a0y3HvIDwIcV9Bt0 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNzE3MDE1MCBTYWx0ZWRfXxeYNngJ9eqIx B5hq4xnelSjYril38QgaO3A6eQr95jyJNVk8SUlo9YdBU04ixmHAE+Bk+8xVX2LBuGSwualFOfP FZOhPD+kXU9l16ds/BUQBL33nUFGnwkzG65Pg+2KoqqDUeny/H18d7zgtXbZEOJfvzryjzfgD5q 5OQrKRgKMbh5LHaOeE6L9xdMcwnNxpzLVq+ZHLMT0S6LZNSohIVH+7+FuTvswz6uPhQ51duqMoz uk5YydLqTdyD3U2vLcoEDWxk9e00wAarCuuEKMp72EDiFZfHYSRzuqnioLH01r1R8Hp9kcykaya 5RmWc/9QRBwBVCkoZ1EmAr6OfD+gAnA5Ku/6Hw31kMW+zkcAJX0cbQcn7qnwjNnCV9C3Wz2izk+ UmJNpfPAkyg98WxPOH4+n1/yuVttfVszAUCifMw6H2ma1/tti2zvJcup/TK2vY6Gf72JVe4Eym4 f8mBjZothoYv/ehZ5jg== X-Authority-Analysis: v=2.4 cv=TaqmcxQh c=1 sm=1 tr=0 ts=6a5a400b cx=c_pps a=mPf7EqFMSY9/WdsSgAYMbA==:117 a=sMQditckXvAul1hrnTxjdA==:17 a=RAioF0-LDSMA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yx91gb_oNiZeI1HMLzn7:22 a=EUspDBNiAAAA:8 a=fpZ6B_ekHF_c09mJ6V8A:9 a=dawVfQjAaf238kedN5IG:22 X-Proofpoint-Spam-Info: AW1haW4tMjYwNzE3MDE1MCBTYWx0ZWRfX02acaoAgol1u fCF++WV395ebT2L/5WgmS5E3KGWqURTwDpLdvPSwi4rKeeS0y5M6Ex3Q8QuyzKWDNBFg8vUW2CQ M+5GwpbhUh8SvnQsp8/X//tG3DnJDQc= X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-07-17_04,2026-07-17_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 impostorscore=0 suspectscore=0 lowpriorityscore=0 phishscore=0 adultscore=0 spamscore=0 bulkscore=0 priorityscore=1501 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2607170150 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=205.220.180.131; envelope-from=andrew.jones@oss.qualcomm.com; helo=mx0b-0031df01.pphosted.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @qualcomm.com) X-ZM-MESSAGEID: 1784299562876158500 Content-Type: text/plain; charset="utf-8" b18e3f0e2d0f fixed spa_fetch() faults whose TTYP used the leaf PTE permission instead of the original request permission. However, it kept that request-narrowed value in iotlb->perm after a successful walk, and riscv_iommu_translate() caches iotlb->perm for later accesses to the same IOVA. That means a write to an RW mapping can cache the entry as write-only. A later read then hits the cache and faults even though the mapping allows it, which showed up in NVMe testing as bogus completions and controller timeouts. Keep the requested permission in a separate req_perm and use it for all permission checks and fault-type decisions. Accumulate the leaf permissions separately and copy them to iotlb->perm only after the full walk succeeds, so cached entries describe the mapping rather than the current request. Since faults leave iotlb->perm as the original request, the S-stage and G-stage TTYP fixes remain intact. Fixes: b18e3f0e2d0f ("hw/riscv/riscv-iommu.c: fix fault type for spa_fetch(= ) faults") Signed-off-by: Andrew Jones Reviewed-by: Daniel Henrique Barboza --- hw/riscv/riscv-iommu.c | 50 ++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index ed9fb09f8bc7..323a041b4a55 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -281,7 +281,7 @@ static hwaddr riscv_iommu_napot_page_mask(hwaddr ppn, h= waddr addr, hwaddr *out) static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ct= x, IOMMUTLBEntry *iotlb) { - IOMMUAccessFlags pte_perm; + IOMMUAccessFlags trans_perm =3D IOMMU_NONE; dma_addr_t addr, base; uint64_t satp, gatp, pte; bool en_s, en_g; @@ -298,6 +298,14 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, R= ISCVIOMMUContext *ctx, } pass; MemTxResult ret; bool pv =3D !!ctx->process_id; + /* + * Keep the request permission separate from iotlb->perm. G-stage + * walks translate S-stage PTE addresses before the real leaf is + * reached, but permission checks and fault types must still use the + * original request. A successful walk leaves iotlb->perm with the + * effective leaf permission for the translation cache. + */ + const IOMMUAccessFlags req_perm =3D iotlb->perm; =20 satp =3D get_field(ctx->satp, RISCV_IOMMU_ATP_MODE_FIELD); gatp =3D get_field(ctx->gatp, RISCV_IOMMU_ATP_MODE_FIELD); @@ -316,7 +324,7 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RI= SCVIOMMUContext *ctx, * means we can't do an early MSI check unless we have * strictly !en_s. */ - if (!en_s && (iotlb->perm & IOMMU_WO) && + if (!en_s && (req_perm & IOMMU_WO) && riscv_iommu_msi_check(s, ctx, iotlb->iova)) { iotlb->target_as =3D &s->trap_as; iotlb->translated_addr =3D iotlb->iova; @@ -434,13 +442,13 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, = RISCVIOMMUContext *ctx, masked_msbs =3D (addr >> (va_len - 1)) & mask; =20 if (masked_msbs !=3D 0 && masked_msbs !=3D mask) { - return (iotlb->perm & IOMMU_WO) ? + return (req_perm & IOMMU_WO) ? RISCV_IOMMU_FQ_CAUSE_WR_FAULT_S : RISCV_IOMMU_FQ_CAUSE_RD_FAULT_S; } } else { if ((addr & va_mask) !=3D addr) { - return (iotlb->perm & IOMMU_WO) ? + return (req_perm & IOMMU_WO) ? RISCV_IOMMU_FQ_CAUSE_WR_FAULT_VS : RISCV_IOMMU_FQ_CAUSE_RD_FAULT_VS; } @@ -465,8 +473,8 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RI= SCVIOMMUContext *ctx, MEMTXATTRS_UNSPECIFIED); } if (ret !=3D MEMTX_OK) { - return (iotlb->perm & IOMMU_WO) ? RISCV_IOMMU_FQ_CAUSE_WR_FAULT - : RISCV_IOMMU_FQ_CAUSE_RD_FAUL= T; + return (req_perm & IOMMU_WO) ? RISCV_IOMMU_FQ_CAUSE_WR_FAULT + : RISCV_IOMMU_FQ_CAUSE_RD_FAULT; } =20 sc[pass].step++; @@ -491,13 +499,13 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, = RISCVIOMMUContext *ctx, * non-user mode leaf PTE and !pv we need to fault. */ break; - } else if ((iotlb->perm & IOMMU_RO) && !(pte & PTE_R)) { + } else if ((req_perm & IOMMU_RO) && !(pte & PTE_R)) { break; /* Read access check failed */ - } else if ((iotlb->perm & IOMMU_WO) && !(pte & PTE_W)) { + } else if ((req_perm & IOMMU_WO) && !(pte & PTE_W)) { break; /* Write access check failed */ } else if (!ade && !(pte & PTE_A)) { break; /* Access bit not set */ - } else if ((iotlb->perm & IOMMU_WO) && !ade && !(pte & PTE_D)) { + } else if ((req_perm & IOMMU_WO) && !ade && !(pte & PTE_D)) { break; /* Dirty bit not set */ } else if (pass =3D=3D G_STAGE && !(pte & PTE_U)) { /* @@ -532,21 +540,20 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, = RISCVIOMMUContext *ctx, addr =3D iotlb->iova; continue; } + + /* Cache the effective permission, not this request's subset. = */ + IOMMUAccessFlags leaf_perm =3D (pte & PTE_W) ? + ((pte & PTE_R) ? IOMMU_RW : IOMMU= _WO) : + IOMMU_RO; + + trans_perm =3D trans_perm =3D=3D IOMMU_NONE ? + leaf_perm : trans_perm & leaf_perm; + /* Translation phase completed (GPA or SPA) */ iotlb->translated_addr =3D base; =20 - /* - * Do a bit_and between the PTE bits and the original - * request flags to determine the exact permission we - * need, i.e. if the original request is RO and the - * PTE has RW flags the actual perm is RO. - */ - pte_perm =3D (pte & PTE_W) ? ((pte & PTE_R) ? IOMMU_RW : IOMMU= _WO) - : IOMMU_RO; - iotlb->perm &=3D pte_perm; - /* Check MSI GPA address match */ - if (pass =3D=3D S_STAGE && (iotlb->perm & IOMMU_WO) && + if (pass =3D=3D S_STAGE && (req_perm & IOMMU_WO) && riscv_iommu_msi_check(s, ctx, base)) { /* Trap MSI writes and return GPA address. */ iotlb->target_as =3D &s->trap_as; @@ -563,6 +570,7 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RI= SCVIOMMUContext *ctx, continue; } =20 + iotlb->perm =3D trans_perm; return 0; } =20 @@ -587,7 +595,7 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RI= SCVIOMMUContext *ctx, */ iotlb->translated_addr =3D addr; =20 - return (iotlb->perm & IOMMU_WO) ? + return (req_perm & IOMMU_WO) ? (pass ? RISCV_IOMMU_FQ_CAUSE_WR_FAULT_VS : RISCV_IOMMU_FQ_CAUSE_WR_FAULT_S) : (pass ? RISCV_IOMMU_FQ_CAUSE_RD_FAULT_VS : --=20 2.43.0