From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758817887028805.4167132044988; Thu, 25 Sep 2025 09:31:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1ooN-0006ZH-J5; Thu, 25 Sep 2025 12:27:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1ony-0006L1-QO; Thu, 25 Sep 2025 12:26:52 -0400 Received: from sgoci-sdnproxy-4.icoremail.net ([129.150.39.64]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1ong-0004jd-Uh; Thu, 25 Sep 2025 12:26:48 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-6 (Coremail) with SMTP id AQAAfwB3DWEubdVofjN6Bw--.1716S2; Fri, 26 Sep 2025 00:26:22 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwDHLestbdVoW_MeAA--.7120S4; Fri, 26 Sep 2025 00:26:22 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , pierrick.bouvier@linaro.org, philmd@linaro.org, jean-philippe@linaro.org, smostafa@google.com, Tao Tang Subject: [PATCH v2 01/14] hw/arm/smmuv3: Fix incorrect reserved mask for SMMU CR0 register Date: Fri, 26 Sep 2025 00:26:05 +0800 Message-Id: <20250925162618.191242-2-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwDHLestbdVoW_MeAA--.7120S4 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAEBWjUSMIHrwAAse Authentication-Results: hzbj-icmmx-6; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvdXoWrZry5Ar43ZFW5GryDXw17GFg_yoWDKrcEkF Z7Xay8Wr4UKFWDX3W8KFWSyry09w45WrZ5XF1xtF1DtF98Xa45XFs7Z3s5X34fGFy8uFya kanFyrWag39rWjkaLaAFLSUrUUUUbb8apTn2vfkv8UJUUUU8wcxFpf9Il3svdxBIdaVrnU Uv73VFW2AGmfu7jjvjm3AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUU UUUU= 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=lists.gnu.org; Received-SPF: pass client-ip=129.150.39.64; envelope-from=tangtao1634@phytium.com.cn; helo=sgoci-sdnproxy-4.icoremail.net X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 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: 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-ZM-MESSAGEID: 1758817888806116600 Content-Type: text/plain; charset="utf-8" The current definition of the SMMU_CR0_RESERVED mask is incorrect. It mistakenly treats bit 10 (DPT_WALK_EN) as a reserved bit while treating bit 9 (RES0) as an implemented bit. According to the SMMU architecture specification, the layout for CR0 is: | 31:11| RES0 | | 10 | DPT_WALK_EN | | 9 | RES0 | | 8:6 | VMW | | 5 | RES0 | | 4 | ATSCHK | | 3 | CMDQEN | | 2 | EVENTQEN | | 1 | PRIQEN | | 0 | SMMUEN | Signed-off-by: Tao Tang Reviewed-by: Eric Auger Link: https://lists.gnu.org/archive/html/qemu-arm/2025-06/msg00088.html --- hw/arm/smmuv3-internal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index b6b7399347..516f2ffa75 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -120,7 +120,8 @@ REG32(CR0, 0x20) FIELD(CR0, EVENTQEN, 2, 1) FIELD(CR0, CMDQEN, 3, 1) =20 -#define SMMU_CR0_RESERVED 0xFFFFFC20 +#define SMMU_CR0_RESERVED 0xFFFFFA20 + =20 REG32(CR0ACK, 0x24) REG32(CR1, 0x28) --=20 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758817877635583.9551885482372; Thu, 25 Sep 2025 09:31:17 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1oo6-0006R8-64; Thu, 25 Sep 2025 12:27:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1onq-0006Iw-4y; Thu, 25 Sep 2025 12:26:42 -0400 Received: from zg8tmja5ljk3lje4ms43mwaa.icoremail.net ([209.97.181.73]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1onf-0004jP-SH; Thu, 25 Sep 2025 12:26:40 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-6 (Coremail) with SMTP id AQAAfwBnblIvbdVogjN6Bw--.50551S2; Fri, 26 Sep 2025 00:26:23 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwDHLestbdVoW_MeAA--.7120S5; Fri, 26 Sep 2025 00:26:22 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , pierrick.bouvier@linaro.org, philmd@linaro.org, jean-philippe@linaro.org, smostafa@google.com, Tao Tang Subject: [PATCH v2 02/14] hw/arm/smmuv3: Correct SMMUEN field name in CR0 Date: Fri, 26 Sep 2025 00:26:06 +0800 Message-Id: <20250925162618.191242-3-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwDHLestbdVoW_MeAA--.7120S5 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAEBWjUSMIHsQAAsA Authentication-Results: hzbj-icmmx-6; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvdXoW7Jr47Xr1xXw4furyxury7GFg_yoWkJFb_Cw 48ZrWkWr129FZ3Xr1FkFy2yryFkwsrJw4kXay0va4jyF9xWFy7Xw4kAr1rZw4xXr15CryS yanFvrWS9rnrWjkaLaAFLSUrUUUUbb8apTn2vfkv8UJUUUU8wcxFpf9Il3svdxBIdaVrnU Uv73VFW2AGmfu7jjvjm3AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUU UUUU= 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=lists.gnu.org; Received-SPF: pass client-ip=209.97.181.73; envelope-from=tangtao1634@phytium.com.cn; helo=zg8tmja5ljk3lje4ms43mwaa.icoremail.net X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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: 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-ZM-MESSAGEID: 1758817878624116600 Content-Type: text/plain; charset="utf-8" The FIELD macro for the SMMU enable bit in the CR0 register was incorrectly named SMMU_ENABLE. The ARM SMMUv3 Architecture Specification (both older IHI 0070.E.a and newer IHI 0070.G.b) consistently refers to the SMMU enable bit as SMMUEN. This change makes our implementation consistent with the manual. Signed-off-by: Tao Tang Reviewed-by: Eric Auger --- hw/arm/smmuv3-internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 516f2ffa75..71a3c0c02c 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -116,7 +116,7 @@ REG32(IDR5, 0x14) REG32(IIDR, 0x18) REG32(AIDR, 0x1c) REG32(CR0, 0x20) - FIELD(CR0, SMMU_ENABLE, 0, 1) + FIELD(CR0, SMMUEN, 0, 1) FIELD(CR0, EVENTQEN, 2, 1) FIELD(CR0, CMDQEN, 3, 1) =20 @@ -182,7 +182,7 @@ REG32(EVENTQ_IRQ_CFG2, 0xbc) =20 static inline int smmu_enabled(SMMUv3State *s) { - return FIELD_EX32(s->cr[0], CR0, SMMU_ENABLE); + return FIELD_EX32(s->cr[0], CR0, SMMUEN); } =20 /* Command Queue Entry */ --=20 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758817992213980.5924207560354; Thu, 25 Sep 2025 09:33:12 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1ons-0006JC-PN; Thu, 25 Sep 2025 12:26:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1onp-0006IT-M4; Thu, 25 Sep 2025 12:26:41 -0400 Received: from sgoci-sdnproxy-4.icoremail.net ([129.150.39.64]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1onj-0004kI-14; Thu, 25 Sep 2025 12:26:41 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-7 (Coremail) with SMTP id AQAAfwDX3bUybdVoYwo6CQ--.582S2; Fri, 26 Sep 2025 00:26:26 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwDHLestbdVoW_MeAA--.7120S6; Fri, 26 Sep 2025 00:26:23 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , pierrick.bouvier@linaro.org, philmd@linaro.org, jean-philippe@linaro.org, smostafa@google.com, Tao Tang Subject: [PATCH v2 03/14] hw/arm/smmuv3: Introduce secure registers and commands Date: Fri, 26 Sep 2025 00:26:07 +0800 Message-Id: <20250925162618.191242-4-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwDHLestbdVoW_MeAA--.7120S6 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAEBWjUSMIHswAAsC Authentication-Results: hzbj-icmmx-7; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvJXoWxWr4rJF4rWr4xXrWUtF4xZwb_yoW5Zw48pr 40yFyrC3yDJF4xWw1fGa1UAF13Crs5A34UGFZFkr1ava4rWryfArW8Ka4fGrykWF1rZF1D J3Wqv34F93ySyr7anT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj DUYxn0WfASr-VFAU7a7-sFnT9fnUUIcSsGvfJ3UbIYCTnIWIevJa73UjIFyTuYvj4RJUUU UUUUU 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=lists.gnu.org; Received-SPF: pass client-ip=129.150.39.64; envelope-from=tangtao1634@phytium.com.cn; helo=sgoci-sdnproxy-4.icoremail.net X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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: 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-ZM-MESSAGEID: 1758817994277116600 Content-Type: text/plain; charset="utf-8" The Arm SMMUv3 architecture defines a set of registers and commands for managing secure transactions and context. This patch introduces the definitions for these secure registers and commands within the SMMUv3 device model internal header. Signed-off-by: Tao Tang --- hw/arm/smmuv3-internal.h | 72 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 71a3c0c02c..3820157eaa 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -38,7 +38,7 @@ typedef enum SMMUTranslationClass { SMMU_CLASS_IN, } SMMUTranslationClass; =20 -/* MMIO Registers */ +/* MMIO Registers. The offsets are shared by Non-secure/Realm/Root states.= */ =20 REG32(IDR0, 0x0) FIELD(IDR0, S2P, 0 , 1) @@ -121,6 +121,7 @@ REG32(CR0, 0x20) FIELD(CR0, CMDQEN, 3, 1) =20 #define SMMU_CR0_RESERVED 0xFFFFFA20 +#define SMMU_S_CR0_RESERVED 0xFFFFFC12 =20 =20 REG32(CR0ACK, 0x24) @@ -180,6 +181,75 @@ REG32(EVENTQ_IRQ_CFG2, 0xbc) =20 #define A_IDREGS 0xfd0 =20 +/* Secure registers. The offsets are begin with SMMU_SECURE_BASE_OFFSET */ +#define SMMU_SECURE_BASE_OFFSET 0x8000 + +REG32(S_IDR0, 0x8000) +REG32(S_IDR1, 0x8004) + FIELD(S_IDR1, S_SIDSIZE, 0 , 6) + FIELD(S_IDR1, SEL2, 29, 1) + FIELD(S_IDR1, SECURE_IMPL, 31, 1) + +REG32(S_IDR2, 0x8008) +REG32(S_IDR3, 0x800c) +REG32(S_IDR4, 0x8010) + +REG32(S_CR0, 0x8020) + FIELD(S_CR0, SMMUEN, 0, 1) + FIELD(S_CR0, EVENTQEN, 2, 1) + FIELD(S_CR0, CMDQEN, 3, 1) + +REG32(S_CR0ACK, 0x8024) +REG32(S_CR1, 0x8028) +REG32(S_CR2, 0x802c) + +REG32(S_INIT, 0x803c) + FIELD(S_INIT, INV_ALL, 0, 1) +/* Alias for the S_INIT offset to match in the dispatcher switch */ +#define A_S_INIT_ALIAS 0x3c + +REG32(S_GBPA, 0x8044) + FIELD(S_GBPA, ABORT, 20, 1) + FIELD(S_GBPA, UPDATE, 31, 1) + +REG32(S_IRQ_CTRL, 0x8050) + FIELD(S_IRQ_CTRL, GERROR_IRQEN, 0, 1) + FIELD(S_IRQ_CTRL, EVENTQ_IRQEN, 2, 1) + +REG32(S_IRQ_CTRLACK, 0x8054) + +REG32(S_GERROR, 0x8060) + FIELD(S_GERROR, CMDQ_ERR, 0, 1) + +#define SMMU_GERROR_IRQ_CFG0_RESERVED 0x00FFFFFFFFFFFFFC +#define SMMU_GERROR_IRQ_CFG2_RESERVED 0x000000000000003F + +#define SMMU_STRTAB_BASE_RESERVED 0x40FFFFFFFFFFFFC0 +#define SMMU_QUEUE_BASE_RESERVED 0x40FFFFFFFFFFFFFF +#define SMMU_EVENTQ_IRQ_CFG0_RESERVED 0x00FFFFFFFFFFFFFC + +REG32(S_GERRORN, 0x8064) +REG64(S_GERROR_IRQ_CFG0, 0x8068) +REG32(S_GERROR_IRQ_CFG1, 0x8070) +REG32(S_GERROR_IRQ_CFG2, 0x8074) +REG64(S_STRTAB_BASE, 0x8080) +REG32(S_STRTAB_BASE_CFG, 0x8088) + FIELD(S_STRTAB_BASE_CFG, LOG2SIZE, 0, 6) + FIELD(S_STRTAB_BASE_CFG, SPLIT, 6, 5) + FIELD(S_STRTAB_BASE_CFG, FMT, 16, 2) + +REG64(S_CMDQ_BASE, 0x8090) +REG32(S_CMDQ_PROD, 0x8098) +REG32(S_CMDQ_CONS, 0x809c) + FIELD(S_CMDQ_CONS, ERR, 24, 7) + +REG64(S_EVENTQ_BASE, 0x80a0) +REG32(S_EVENTQ_PROD, 0x80a8) +REG32(S_EVENTQ_CONS, 0x80ac) +REG64(S_EVENTQ_IRQ_CFG0, 0x80b0) +REG32(S_EVENTQ_IRQ_CFG1, 0x80b8) +REG32(S_EVENTQ_IRQ_CFG2, 0x80bc) + static inline int smmu_enabled(SMMUv3State *s) { return FIELD_EX32(s->cr[0], CR0, SMMUEN); --=20 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758818001330597.0393692888085; Thu, 25 Sep 2025 09:33:21 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1oox-00076f-RG; Thu, 25 Sep 2025 12:27:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1oo6-0006Rp-7p; Thu, 25 Sep 2025 12:27:00 -0400 Received: from zg8tmtu5ljy1ljeznc42.icoremail.net ([159.65.134.6]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1onm-0004kv-AY; Thu, 25 Sep 2025 12:26:56 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-7 (Coremail) with SMTP id AQAAfwDHzrYzbdVoawo6CQ--.511S2; Fri, 26 Sep 2025 00:26:27 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwDHLestbdVoW_MeAA--.7120S7; Fri, 26 Sep 2025 00:26:23 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , pierrick.bouvier@linaro.org, philmd@linaro.org, jean-philippe@linaro.org, smostafa@google.com, Tao Tang Subject: [PATCH v2 04/14] refactor: Move ARMSecuritySpace to a common header Date: Fri, 26 Sep 2025 00:26:08 +0800 Message-Id: <20250925162618.191242-5-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwDHLestbdVoW_MeAA--.7120S7 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAEBWjUSMIHtQAAsE Authentication-Results: hzbj-icmmx-7; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvJXoWxXF45CF1xJr1fJF4kJryDAwb_yoWrur15pF 4Yyas3Gw48Gay3Gas3ZFsrWF1rK395WF47KFyxWr4kXFnrur18Cr4vyF1Yka45GrWYv3WF vr17Zw4rKF1kXrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj DUYxn0WfASr-VFAU7a7-sFnT9fnUUIcSsGvfJ3UbIYCTnIWIevJa73UjIFyTuYvj4RJUUU UUUUU 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=lists.gnu.org; Received-SPF: pass client-ip=159.65.134.6; envelope-from=tangtao1634@phytium.com.cn; helo=zg8tmtu5ljy1ljeznc42.icoremail.net X-Spam_score_int: 41 X-Spam_score: 4.1 X-Spam_bar: ++++ X-Spam_report: (4.1 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_PBL=3.335, RCVD_IN_SBL_CSS=3.335, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_PASS=-0.001, T_SPF_HELO_TEMPERROR=0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: 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-ZM-MESSAGEID: 1758818002358116600 Content-Type: text/plain; charset="utf-8" The ARMSecuritySpace enum and its related helpers were defined in the target-specific header target/arm/cpu.h. This prevented common, target-agnostic code like the SMMU model from using these definitions without triggering "cpu.h included from common code" errors. To resolve this, this commit introduces a new, lightweight header, include/hw/arm/arm-security.h, which is safe for inclusion by common code. The following changes were made: - The ARMSecuritySpace enum and the arm_space_is_secure() and arm_secure_to_space() helpers have been moved from target/arm/cpu.h to the new hw/arm/arm-security.h header. - Headers for common devices like the SMMU (smmu-common.h) have been updated to include the new lightweight header instead of cpu.h. This refactoring decouples the security state definitions from the core CPU implementation, allowing common hardware models to correctly handle security states without pulling in heavyweight, target-specific headers. Signed-off-by: Tao Tang Reviewed-by: Eric Auger --- include/hw/arm/arm-security.h | 54 +++++++++++++++++++++++++++++++++++ target/arm/cpu.h | 25 +--------------- 2 files changed, 55 insertions(+), 24 deletions(-) create mode 100644 include/hw/arm/arm-security.h diff --git a/include/hw/arm/arm-security.h b/include/hw/arm/arm-security.h new file mode 100644 index 0000000000..9664c0f95e --- /dev/null +++ b/include/hw/arm/arm-security.h @@ -0,0 +1,54 @@ +/* + * ARM security space helpers + * + * Provide ARMSecuritySpace and helpers for code that is not tied to CPU. + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef HW_ARM_ARM_SECURITY_H +#define HW_ARM_ARM_SECURITY_H + +#include + +/* + * ARM v9 security states. + * The ordering of the enumeration corresponds to the low 2 bits + * of the GPI value, and (except for Root) the concat of NSE:NS. + */ + + typedef enum ARMSecuritySpace { + ARMSS_Secure =3D 0, + ARMSS_NonSecure =3D 1, + ARMSS_Root =3D 2, + ARMSS_Realm =3D 3, +} ARMSecuritySpace; + +/* Return true if @space is secure, in the pre-v9 sense. */ +static inline bool arm_space_is_secure(ARMSecuritySpace space) +{ + return space =3D=3D ARMSS_Secure || space =3D=3D ARMSS_Root; +} + +/* Return the ARMSecuritySpace for @secure, assuming !RME or EL[0-2]. */ +static inline ARMSecuritySpace arm_secure_to_space(bool secure) +{ + return secure ? ARMSS_Secure : ARMSS_NonSecure; +} + +#endif /* HW_ARM_ARM_SECURITY_H */ + + diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 1c0deb723d..2ff9343d0b 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -31,6 +31,7 @@ #include "exec/page-protection.h" #include "qapi/qapi-types-common.h" #include "target/arm/multiprocessing.h" +#include "hw/arm/arm-security.h" #include "target/arm/gtimer.h" #include "target/arm/cpu-sysregs.h" =20 @@ -2477,30 +2478,6 @@ static inline int arm_feature(CPUARMState *env, int = feature) =20 void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp); =20 -/* - * ARM v9 security states. - * The ordering of the enumeration corresponds to the low 2 bits - * of the GPI value, and (except for Root) the concat of NSE:NS. - */ - -typedef enum ARMSecuritySpace { - ARMSS_Secure =3D 0, - ARMSS_NonSecure =3D 1, - ARMSS_Root =3D 2, - ARMSS_Realm =3D 3, -} ARMSecuritySpace; - -/* Return true if @space is secure, in the pre-v9 sense. */ -static inline bool arm_space_is_secure(ARMSecuritySpace space) -{ - return space =3D=3D ARMSS_Secure || space =3D=3D ARMSS_Root; -} - -/* Return the ARMSecuritySpace for @secure, assuming !RME or EL[0-2]. */ -static inline ARMSecuritySpace arm_secure_to_space(bool secure) -{ - return secure ? ARMSS_Secure : ARMSS_NonSecure; -} =20 #if !defined(CONFIG_USER_ONLY) /** --=20 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758817784873854.2669092709868; Thu, 25 Sep 2025 09:29:44 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1oog-0006t2-2h; Thu, 25 Sep 2025 12:27:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1onw-0006Kx-OT; Thu, 25 Sep 2025 12:26:50 -0400 Received: from zg8tmtyylji0my4xnjqumte4.icoremail.net ([162.243.164.118]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1onk-0004kh-UA; Thu, 25 Sep 2025 12:26:47 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-6 (Coremail) with SMTP id AQAAfwD3jWE0bdVoljN6Bw--.50241S2; Fri, 26 Sep 2025 00:26:28 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwDHLestbdVoW_MeAA--.7120S8; Fri, 26 Sep 2025 00:26:27 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , pierrick.bouvier@linaro.org, philmd@linaro.org, jean-philippe@linaro.org, smostafa@google.com, Tao Tang Subject: [PATCH v2 05/14] hw/arm/smmuv3: Introduce banked registers for SMMUv3 state Date: Fri, 26 Sep 2025 00:26:09 +0800 Message-Id: <20250925162618.191242-6-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwDHLestbdVoW_MeAA--.7120S8 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAEBWjUSMIHtwAAsG Authentication-Results: hzbj-icmmx-6; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvAXoWDCry3Wr1DZF1DGrWkWw45Jrb_yoWrCw48Co WfKF4qqw18Wr1kCFykuF1fJFsxAFZ5K39Iva1FqrsI9FZrJr4UJryIkr43Ca9Igr45XFWD Ar4xu3yxXF48AF18n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3UbIjqfuFe4nvWSU8nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UU UUUUUUU== 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=lists.gnu.org; Received-SPF: pass client-ip=162.243.164.118; envelope-from=tangtao1634@phytium.com.cn; helo=zg8tmtyylji0my4xnjqumte4.icoremail.net X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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: 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-ZM-MESSAGEID: 1758817787532116600 Content-Type: text/plain; charset="utf-8" Refactor the SMMUv3 state management by introducing a banked register structure. This change is foundational for supporting multiple security states (Non-secure, Secure, etc.) in a clean and scalable way. A new structure, SMMUv3RegBank, is defined to hold the state for a single security context. The main SMMUv3State now contains an array of these structures. This avoids having separate fields for secure and non-secure registers (e.g., s->cr and s->secure_cr). The primary benefits of this refactoring are: - Significant reduction in code duplication for MMIO handlers. - Improved code readability and long-term maintainability. Additionally, a new enum SMMUSecurityIndex is introduced to represent the security state of a stream. This enum will be used as the index for the register banks in subsequent patches. Signed-off-by: Tao Tang --- hw/arm/smmuv3-internal.h | 33 ++- hw/arm/smmuv3.c | 484 ++++++++++++++++++++--------------- hw/arm/trace-events | 6 +- include/hw/arm/smmu-common.h | 14 + include/hw/arm/smmuv3.h | 34 ++- 5 files changed, 336 insertions(+), 235 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 3820157eaa..cf17c405de 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -250,9 +250,9 @@ REG64(S_EVENTQ_IRQ_CFG0, 0x80b0) REG32(S_EVENTQ_IRQ_CFG1, 0x80b8) REG32(S_EVENTQ_IRQ_CFG2, 0x80bc) =20 -static inline int smmu_enabled(SMMUv3State *s) +static inline int smmu_enabled(SMMUv3State *s, SMMUSecurityIndex sec_idx) { - return FIELD_EX32(s->cr[0], CR0, SMMUEN); + return FIELD_EX32(s->bank[sec_idx].cr[0], CR0, SMMUEN); } =20 /* Command Queue Entry */ @@ -278,14 +278,16 @@ static inline uint32_t smmuv3_idreg(int regoffset) return smmuv3_ids[regoffset / 4]; } =20 -static inline bool smmuv3_eventq_irq_enabled(SMMUv3State *s) +static inline bool smmuv3_eventq_irq_enabled(SMMUv3State *s, + SMMUSecurityIndex sec_idx) { - return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, EVENTQ_IRQEN); + return FIELD_EX32(s->bank[sec_idx].irq_ctrl, IRQ_CTRL, EVENTQ_IRQEN); } =20 -static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s) +static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s, + SMMUSecurityIndex sec_idx) { - return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN); + return FIELD_EX32(s->bank[sec_idx].irq_ctrl, IRQ_CTRL, GERROR_IRQEN); } =20 /* Queue Handling */ @@ -328,19 +330,23 @@ static inline void queue_cons_incr(SMMUQueue *q) q->cons =3D deposit32(q->cons, 0, q->log2size + 1, q->cons + 1); } =20 -static inline bool smmuv3_cmdq_enabled(SMMUv3State *s) +static inline bool smmuv3_cmdq_enabled(SMMUv3State *s, + SMMUSecurityIndex sec_idx) { - return FIELD_EX32(s->cr[0], CR0, CMDQEN); + return FIELD_EX32(s->bank[sec_idx].cr[0], CR0, CMDQEN); } =20 -static inline bool smmuv3_eventq_enabled(SMMUv3State *s) +static inline bool smmuv3_eventq_enabled(SMMUv3State *s, + SMMUSecurityIndex sec_idx) { - return FIELD_EX32(s->cr[0], CR0, EVENTQEN); + return FIELD_EX32(s->bank[sec_idx].cr[0], CR0, EVENTQEN); } =20 -static inline void smmu_write_cmdq_err(SMMUv3State *s, uint32_t err_type) +static inline void smmu_write_cmdq_err(SMMUv3State *s, uint32_t err_type, + SMMUSecurityIndex sec_idx) { - s->cmdq.cons =3D FIELD_DP32(s->cmdq.cons, CMDQ_CONS, ERR, err_type); + s->bank[sec_idx].cmdq.cons =3D FIELD_DP32(s->bank[sec_idx].cmdq.cons, + CMDQ_CONS, ERR, err_type); } =20 /* Commands */ @@ -511,6 +517,7 @@ typedef struct SMMUEventInfo { uint32_t sid; bool recorded; bool inval_ste_allowed; + SMMUSecurityIndex sec_idx; union { struct { uint32_t ssid; @@ -594,7 +601,7 @@ typedef struct SMMUEventInfo { (x)->word[6] =3D (uint32_t)(addr & 0xffffffff); \ } while (0) =20 -void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event); +void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *info); =20 /* Configuration Data */ =20 diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index bcf8af8dc7..2efa39b78c 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -48,14 +48,14 @@ * @gerror_mask: mask of gerrors to toggle (relevant if @irq is GERROR) */ static void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, - uint32_t gerror_mask) + uint32_t gerror_mask, SMMUSecurityIndex sec= _idx) { =20 bool pulse =3D false; =20 switch (irq) { case SMMU_IRQ_EVTQ: - pulse =3D smmuv3_eventq_irq_enabled(s); + pulse =3D smmuv3_eventq_irq_enabled(s, sec_idx); break; case SMMU_IRQ_PRIQ: qemu_log_mask(LOG_UNIMP, "PRI not yet supported\n"); @@ -65,17 +65,17 @@ static void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq = irq, break; case SMMU_IRQ_GERROR: { - uint32_t pending =3D s->gerror ^ s->gerrorn; + uint32_t pending =3D s->bank[sec_idx].gerror ^ s->bank[sec_idx].ge= rrorn; uint32_t new_gerrors =3D ~pending & gerror_mask; =20 if (!new_gerrors) { /* only toggle non pending errors */ return; } - s->gerror ^=3D new_gerrors; - trace_smmuv3_write_gerror(new_gerrors, s->gerror); + s->bank[sec_idx].gerror ^=3D new_gerrors; + trace_smmuv3_write_gerror(new_gerrors, s->bank[sec_idx].gerror); =20 - pulse =3D smmuv3_gerror_irq_enabled(s); + pulse =3D smmuv3_gerror_irq_enabled(s, sec_idx); break; } } @@ -85,24 +85,25 @@ static void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq = irq, } } =20 -static void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn) +static void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn, + SMMUSecurityIndex sec_idx) { - uint32_t pending =3D s->gerror ^ s->gerrorn; - uint32_t toggled =3D s->gerrorn ^ new_gerrorn; + uint32_t pending =3D s->bank[sec_idx].gerror ^ s->bank[sec_idx].gerror= n; + uint32_t toggled =3D s->bank[sec_idx].gerrorn ^ new_gerrorn; =20 if (toggled & ~pending) { qemu_log_mask(LOG_GUEST_ERROR, - "guest toggles non pending errors =3D 0x%x\n", - toggled & ~pending); + "guest toggles non pending errors =3D 0x%x sec_idx= =3D%d\n", + toggled & ~pending, sec_idx); } =20 /* * We do not raise any error in case guest toggles bits corresponding * to not active IRQs (CONSTRAINED UNPREDICTABLE) */ - s->gerrorn =3D new_gerrorn; + s->bank[sec_idx].gerrorn =3D new_gerrorn; =20 - trace_smmuv3_write_gerrorn(toggled & pending, s->gerrorn); + trace_smmuv3_write_gerrorn(toggled & pending, s->bank[sec_idx].gerrorn= ); } =20 static inline MemTxResult queue_read(SMMUQueue *q, Cmd *cmd) @@ -142,12 +143,13 @@ static MemTxResult queue_write(SMMUQueue *q, Evt *evt= _in) return MEMTX_OK; } =20 -static MemTxResult smmuv3_write_eventq(SMMUv3State *s, Evt *evt) +static MemTxResult smmuv3_write_eventq(SMMUv3State *s, Evt *evt, + SMMUSecurityIndex sec_idx) { - SMMUQueue *q =3D &s->eventq; + SMMUQueue *q =3D &s->bank[sec_idx].eventq; MemTxResult r; =20 - if (!smmuv3_eventq_enabled(s)) { + if (!smmuv3_eventq_enabled(s, sec_idx)) { return MEMTX_ERROR; } =20 @@ -161,7 +163,7 @@ static MemTxResult smmuv3_write_eventq(SMMUv3State *s, = Evt *evt) } =20 if (!smmuv3_q_empty(q)) { - smmuv3_trigger_irq(s, SMMU_IRQ_EVTQ, 0); + smmuv3_trigger_irq(s, SMMU_IRQ_EVTQ, 0, sec_idx); } return MEMTX_OK; } @@ -171,7 +173,7 @@ void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo = *info) Evt evt =3D {}; MemTxResult r; =20 - if (!smmuv3_eventq_enabled(s)) { + if (!smmuv3_eventq_enabled(s, info->sec_idx)) { return; } =20 @@ -249,74 +251,104 @@ void smmuv3_record_event(SMMUv3State *s, SMMUEventIn= fo *info) g_assert_not_reached(); } =20 - trace_smmuv3_record_event(smmu_event_string(info->type), info->sid); - r =3D smmuv3_write_eventq(s, &evt); + trace_smmuv3_record_event(smmu_event_string(info->type), + info->sid, info->sec_idx); + r =3D smmuv3_write_eventq(s, &evt, info->sec_idx); if (r !=3D MEMTX_OK) { - smmuv3_trigger_irq(s, SMMU_IRQ_GERROR, R_GERROR_EVENTQ_ABT_ERR_MAS= K); + smmuv3_trigger_irq(s, SMMU_IRQ_GERROR, R_GERROR_EVENTQ_ABT_ERR_MAS= K, + info->sec_idx); } info->recorded =3D true; } =20 static void smmuv3_init_regs(SMMUv3State *s) { + /* Initialize Non-secure bank (SMMU_SEC_IDX_NS) */ /* Based on sys property, the stages supported in smmu will be adverti= sed.*/ if (s->stage && !strcmp("2", s->stage)) { - s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, S2P, 1); + s->bank[SMMU_SEC_IDX_NS].idr[0] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, S2P, 1); } else if (s->stage && !strcmp("nested", s->stage)) { - s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, S1P, 1); - s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, S2P, 1); + s->bank[SMMU_SEC_IDX_NS].idr[0] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, S1P, 1); + s->bank[SMMU_SEC_IDX_NS].idr[0] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, S2P, 1); } else { - s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, S1P, 1); - } - - s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, TTF, 2); /* AArch64 PTW only= */ - s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, COHACC, 1); /* IO coherent */ - s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, ASID16, 1); /* 16-bit ASID */ - s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, VMID16, 1); /* 16-bit VMID */ - s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, TTENDIAN, 2); /* little endi= an */ - s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, STALL_MODEL, 1); /* No stall= */ + s->bank[SMMU_SEC_IDX_NS].idr[0] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, S1P, 1); + } + + s->bank[SMMU_SEC_IDX_NS].idr[0] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, TTF, 2); /* AArch64 PTW onl= y */ + s->bank[SMMU_SEC_IDX_NS].idr[0] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, COHACC, 1); /* IO coherent = */ + s->bank[SMMU_SEC_IDX_NS].idr[0] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, ASID16, 1); /* 16-bit ASID = */ + s->bank[SMMU_SEC_IDX_NS].idr[0] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, VMID16, 1); /* 16-bit VMID = */ + s->bank[SMMU_SEC_IDX_NS].idr[0] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, TTENDIAN, 2); /* little end= ian */ + s->bank[SMMU_SEC_IDX_NS].idr[0] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, STALL_MODEL, 1); /* No stal= l */ /* terminated transaction will always be aborted/error returned */ - s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, TERM_MODEL, 1); + s->bank[SMMU_SEC_IDX_NS].idr[0] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, TERM_MODEL, 1); /* 2-level stream table supported */ - s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, STLEVEL, 1); - - s->idr[1] =3D FIELD_DP32(s->idr[1], IDR1, SIDSIZE, SMMU_IDR1_SIDSIZE); - s->idr[1] =3D FIELD_DP32(s->idr[1], IDR1, EVENTQS, SMMU_EVENTQS); - s->idr[1] =3D FIELD_DP32(s->idr[1], IDR1, CMDQS, SMMU_CMDQS); - - s->idr[3] =3D FIELD_DP32(s->idr[3], IDR3, HAD, 1); - if (FIELD_EX32(s->idr[0], IDR0, S2P)) { + s->bank[SMMU_SEC_IDX_NS].idr[0] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, STLEVEL, 1); + + s->bank[SMMU_SEC_IDX_NS].idr[1] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[1], IDR1, SIDSIZE, SMMU_IDR1_SIDSIZE); + s->bank[SMMU_SEC_IDX_NS].idr[1] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[1], IDR1, EVENTQS, SMMU_EVENTQS); + s->bank[SMMU_SEC_IDX_NS].idr[1] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[1], IDR1, CMDQS, SMMU_CMDQS); + + s->bank[SMMU_SEC_IDX_NS].idr[3] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[3], IDR3, HAD, 1); + if (FIELD_EX32(s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, S2P)) { /* XNX is a stage-2-specific feature */ - s->idr[3] =3D FIELD_DP32(s->idr[3], IDR3, XNX, 1); + s->bank[SMMU_SEC_IDX_NS].idr[3] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[3], IDR3, XNX, 1); } - s->idr[3] =3D FIELD_DP32(s->idr[3], IDR3, RIL, 1); - s->idr[3] =3D FIELD_DP32(s->idr[3], IDR3, BBML, 2); + s->bank[SMMU_SEC_IDX_NS].idr[3] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[3], IDR3, RIL, 1); + s->bank[SMMU_SEC_IDX_NS].idr[3] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[3], IDR3, BBML, 2); =20 - s->idr[5] =3D FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS); /* 44 b= its */ + /* 44 bits */ + s->bank[SMMU_SEC_IDX_NS].idr[5] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[5], IDR5, OAS, SMMU_IDR5_OAS); /* 4K, 16K and 64K granule support */ - s->idr[5] =3D FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1); - s->idr[5] =3D FIELD_DP32(s->idr[5], IDR5, GRAN16K, 1); - s->idr[5] =3D FIELD_DP32(s->idr[5], IDR5, GRAN64K, 1); - - s->cmdq.base =3D deposit64(s->cmdq.base, 0, 5, SMMU_CMDQS); - s->cmdq.prod =3D 0; - s->cmdq.cons =3D 0; - s->cmdq.entry_size =3D sizeof(struct Cmd); - s->eventq.base =3D deposit64(s->eventq.base, 0, 5, SMMU_EVENTQS); - s->eventq.prod =3D 0; - s->eventq.cons =3D 0; - s->eventq.entry_size =3D sizeof(struct Evt); - - s->features =3D 0; - s->sid_split =3D 0; + s->bank[SMMU_SEC_IDX_NS].idr[5] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[5], IDR5, GRAN4K, 1); + s->bank[SMMU_SEC_IDX_NS].idr[5] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[5], IDR5, GRAN16K, 1); + s->bank[SMMU_SEC_IDX_NS].idr[5] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_NS].idr[5], IDR5, GRAN64K, 1); + + /* Initialize Non-secure command and event queues */ + s->bank[SMMU_SEC_IDX_NS].cmdq.base =3D + deposit64(s->bank[SMMU_SEC_IDX_NS].cmdq.base, 0, 5, SMMU_CMDQS); + s->bank[SMMU_SEC_IDX_NS].cmdq.prod =3D 0; + s->bank[SMMU_SEC_IDX_NS].cmdq.cons =3D 0; + s->bank[SMMU_SEC_IDX_NS].cmdq.entry_size =3D sizeof(struct Cmd); + s->bank[SMMU_SEC_IDX_NS].eventq.base =3D + deposit64(s->bank[SMMU_SEC_IDX_NS].eventq.base, 0, 5, SMMU_EVENTQS= ); + s->bank[SMMU_SEC_IDX_NS].eventq.prod =3D 0; + s->bank[SMMU_SEC_IDX_NS].eventq.cons =3D 0; + s->bank[SMMU_SEC_IDX_NS].eventq.entry_size =3D sizeof(struct Evt); + s->bank[SMMU_SEC_IDX_NS].features =3D 0; + s->bank[SMMU_SEC_IDX_NS].sid_split =3D 0; s->aidr =3D 0x1; - s->cr[0] =3D 0; - s->cr0ack =3D 0; - s->irq_ctrl =3D 0; - s->gerror =3D 0; - s->gerrorn =3D 0; + s->bank[SMMU_SEC_IDX_NS].cr[0] =3D 0; + s->bank[SMMU_SEC_IDX_NS].cr0ack =3D 0; + s->bank[SMMU_SEC_IDX_NS].irq_ctrl =3D 0; + s->bank[SMMU_SEC_IDX_NS].gerror =3D 0; + s->bank[SMMU_SEC_IDX_NS].gerrorn =3D 0; s->statusr =3D 0; - s->gbpa =3D SMMU_GBPA_RESET_VAL; + s->bank[SMMU_SEC_IDX_NS].gbpa =3D SMMU_GBPA_RESET_VAL; + } =20 static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf, @@ -430,7 +462,7 @@ static bool s2_pgtable_config_valid(uint8_t sl0, uint8_= t t0sz, uint8_t gran) static int decode_ste_s2_cfg(SMMUv3State *s, SMMUTransCfg *cfg, STE *ste) { - uint8_t oas =3D FIELD_EX32(s->idr[5], IDR5, OAS); + uint8_t oas =3D FIELD_EX32(s->bank[SMMU_SEC_IDX_NS].idr[5], IDR5, OAS); =20 if (STE_S2AA64(ste) =3D=3D 0x0) { qemu_log_mask(LOG_UNIMP, @@ -548,7 +580,7 @@ static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg, STE *ste, SMMUEventInfo *event) { uint32_t config; - uint8_t oas =3D FIELD_EX32(s->idr[5], IDR5, OAS); + uint8_t oas =3D FIELD_EX32(s->bank[SMMU_SEC_IDX_NS].idr[5], IDR5, OAS); int ret; =20 if (!STE_VALID(ste)) { @@ -625,20 +657,25 @@ bad_ste: * @sid: stream ID * @ste: returned stream table entry * @event: handle to an event info + * @cfg: translation configuration * * Supports linear and 2-level stream table * Return 0 on success, -EINVAL otherwise */ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, - SMMUEventInfo *event) + SMMUEventInfo *event, SMMUTransCfg *cfg) { - dma_addr_t addr, strtab_base; + dma_addr_t addr; uint32_t log2size; int strtab_size_shift; int ret; + uint32_t features =3D s->bank[cfg->sec_idx].features; + dma_addr_t strtab_base =3D s->bank[cfg->sec_idx].strtab_base; + uint8_t sid_split =3D s->bank[cfg->sec_idx].sid_split; =20 - trace_smmuv3_find_ste(sid, s->features, s->sid_split); - log2size =3D FIELD_EX32(s->strtab_base_cfg, STRTAB_BASE_CFG, LOG2SIZE); + trace_smmuv3_find_ste(sid, features, sid_split, cfg->sec_idx); + log2size =3D FIELD_EX32(s->bank[cfg->sec_idx].strtab_base_cfg, + STRTAB_BASE_CFG, LOG2SIZE); /* * Check SID range against both guest-configured and implementation li= mits */ @@ -646,7 +683,7 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, = STE *ste, event->type =3D SMMU_EVT_C_BAD_STREAMID; return -EINVAL; } - if (s->features & SMMU_FEATURE_2LVL_STE) { + if (features & SMMU_FEATURE_2LVL_STE) { int l1_ste_offset, l2_ste_offset, max_l2_ste, span, i; dma_addr_t l1ptr, l2ptr; STEDesc l1std; @@ -655,11 +692,11 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid= , STE *ste, * Align strtab base address to table size. For this purpose, assu= me it * is not bounded by SMMU_IDR1_SIDSIZE. */ - strtab_size_shift =3D MAX(5, (int)log2size - s->sid_split - 1 + 3); - strtab_base =3D s->strtab_base & SMMU_BASE_ADDR_MASK & + strtab_size_shift =3D MAX(5, (int)log2size - sid_split - 1 + 3); + strtab_base =3D strtab_base & SMMU_BASE_ADDR_MASK & ~MAKE_64BIT_MASK(0, strtab_size_shift); - l1_ste_offset =3D sid >> s->sid_split; - l2_ste_offset =3D sid & ((1 << s->sid_split) - 1); + l1_ste_offset =3D sid >> sid_split; + l2_ste_offset =3D sid & ((1 << sid_split) - 1); l1ptr =3D (dma_addr_t)(strtab_base + l1_ste_offset * sizeof(l1std)= ); /* TODO: guarantee 64-bit single-copy atomicity */ ret =3D dma_memory_read(&address_space_memory, l1ptr, &l1std, @@ -688,7 +725,7 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, = STE *ste, } max_l2_ste =3D (1 << span) - 1; l2ptr =3D l1std_l2ptr(&l1std); - trace_smmuv3_find_ste_2lvl(s->strtab_base, l1ptr, l1_ste_offset, + trace_smmuv3_find_ste_2lvl(strtab_base, l1ptr, l1_ste_offset, l2ptr, l2_ste_offset, max_l2_ste); if (l2_ste_offset > max_l2_ste) { qemu_log_mask(LOG_GUEST_ERROR, @@ -700,7 +737,7 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, = STE *ste, addr =3D l2ptr + l2_ste_offset * sizeof(*ste); } else { strtab_size_shift =3D log2size + 5; - strtab_base =3D s->strtab_base & SMMU_BASE_ADDR_MASK & + strtab_base =3D strtab_base & SMMU_BASE_ADDR_MASK & ~MAKE_64BIT_MASK(0, strtab_size_shift); addr =3D strtab_base + sid * sizeof(*ste); } @@ -719,7 +756,7 @@ static int decode_cd(SMMUv3State *s, SMMUTransCfg *cfg, int i; SMMUTranslationStatus status; SMMUTLBEntry *entry; - uint8_t oas =3D FIELD_EX32(s->idr[5], IDR5, OAS); + uint8_t oas =3D FIELD_EX32(s->bank[SMMU_SEC_IDX_NS].idr[5], IDR5, OAS); =20 if (!CD_VALID(cd) || !CD_AARCH64(cd)) { goto bad_cd; @@ -834,7 +871,7 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, = SMMUTransCfg *cfg, /* ASID defaults to -1 (if s1 is not supported). */ cfg->asid =3D -1; =20 - ret =3D smmu_find_ste(s, sid, &ste, event); + ret =3D smmu_find_ste(s, sid, &ste, event, cfg); if (ret) { return ret; } @@ -964,6 +1001,7 @@ static SMMUTranslationStatus smmuv3_do_translate(SMMUv= 3State *s, hwaddr addr, * - s2 translation =3D> CLASS_IN (input to function) */ class =3D ptw_info.is_ipa_descriptor ? SMMU_CLASS_TT : class; + event->sec_idx =3D cfg->sec_idx; switch (ptw_info.type) { case SMMU_PTW_ERR_WALK_EABT: event->type =3D SMMU_EVT_F_WALK_EABT; @@ -1046,6 +1084,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegi= on *mr, hwaddr addr, .inval_ste_allowed =3D false}; SMMUTranslationStatus status; SMMUTransCfg *cfg =3D NULL; + SMMUSecurityIndex sec_idx =3D SMMU_SEC_IDX_NS; IOMMUTLBEntry entry =3D { .target_as =3D &address_space_memory, .iova =3D addr, @@ -1057,12 +1096,9 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryReg= ion *mr, hwaddr addr, =20 qemu_mutex_lock(&s->mutex); =20 - if (!smmu_enabled(s)) { - if (FIELD_EX32(s->gbpa, GBPA, ABORT)) { - status =3D SMMU_TRANS_ABORT; - } else { - status =3D SMMU_TRANS_DISABLE; - } + if (!smmu_enabled(s, sec_idx)) { + bool abort_flag =3D FIELD_EX32(s->bank[sec_idx].gbpa, GBPA, ABORT); + status =3D abort_flag ? SMMU_TRANS_ABORT : SMMU_TRANS_DISABLE; goto epilogue; } =20 @@ -1278,14 +1314,14 @@ static void smmuv3_range_inval(SMMUState *s, Cmd *c= md, SMMUStage stage) } } =20 -static int smmuv3_cmdq_consume(SMMUv3State *s) +static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUSecurityIndex sec_idx) { SMMUState *bs =3D ARM_SMMU(s); SMMUCmdError cmd_error =3D SMMU_CERROR_NONE; - SMMUQueue *q =3D &s->cmdq; + SMMUQueue *q =3D &s->bank[sec_idx].cmdq; SMMUCommandType type =3D 0; =20 - if (!smmuv3_cmdq_enabled(s)) { + if (!smmuv3_cmdq_enabled(s, sec_idx)) { return 0; } /* @@ -1296,11 +1332,12 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) */ =20 while (!smmuv3_q_empty(q)) { - uint32_t pending =3D s->gerror ^ s->gerrorn; + uint32_t pending =3D s->bank[sec_idx].gerror ^ s->bank[sec_idx].ge= rrorn; Cmd cmd; =20 trace_smmuv3_cmdq_consume(Q_PROD(q), Q_CONS(q), - Q_PROD_WRAP(q), Q_CONS_WRAP(q)); + Q_PROD_WRAP(q), Q_CONS_WRAP(q), + sec_idx); =20 if (FIELD_EX32(pending, GERROR, CMDQ_ERR)) { break; @@ -1319,7 +1356,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) switch (type) { case SMMU_CMD_SYNC: if (CMD_SYNC_CS(&cmd) & CMD_SYNC_SIG_IRQ) { - smmuv3_trigger_irq(s, SMMU_IRQ_CMD_SYNC, 0); + smmuv3_trigger_irq(s, SMMU_IRQ_CMD_SYNC, 0, sec_idx); } break; case SMMU_CMD_PREFETCH_CONFIG: @@ -1498,8 +1535,9 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) =20 if (cmd_error) { trace_smmuv3_cmdq_consume_error(smmu_cmd_string(type), cmd_error); - smmu_write_cmdq_err(s, cmd_error); - smmuv3_trigger_irq(s, SMMU_IRQ_GERROR, R_GERROR_CMDQ_ERR_MASK); + smmu_write_cmdq_err(s, cmd_error, sec_idx); + smmuv3_trigger_irq(s, SMMU_IRQ_GERROR, + R_GERROR_CMDQ_ERR_MASK, sec_idx); } =20 trace_smmuv3_cmdq_consume_out(Q_PROD(q), Q_CONS(q), @@ -1509,31 +1547,33 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) } =20 static MemTxResult smmu_writell(SMMUv3State *s, hwaddr offset, - uint64_t data, MemTxAttrs attrs) + uint64_t data, MemTxAttrs attrs, + SMMUSecurityIndex reg_sec_idx) { - switch (offset) { - case A_GERROR_IRQ_CFG0: - s->gerror_irq_cfg0 =3D data; - return MEMTX_OK; + uint32_t reg_offset =3D offset & 0xfff; + switch (reg_offset) { case A_STRTAB_BASE: - s->strtab_base =3D data; + /* Clear reserved bits according to spec */ + s->bank[reg_sec_idx].strtab_base =3D data & SMMU_STRTAB_BASE_RESER= VED; return MEMTX_OK; case A_CMDQ_BASE: - s->cmdq.base =3D data; - s->cmdq.log2size =3D extract64(s->cmdq.base, 0, 5); - if (s->cmdq.log2size > SMMU_CMDQS) { - s->cmdq.log2size =3D SMMU_CMDQS; + s->bank[reg_sec_idx].cmdq.base =3D data; + s->bank[reg_sec_idx].cmdq.log2size =3D extract64( + s->bank[reg_sec_idx].cmdq.base, 0, 5); + if (s->bank[reg_sec_idx].cmdq.log2size > SMMU_CMDQS) { + s->bank[reg_sec_idx].cmdq.log2size =3D SMMU_CMDQS; } return MEMTX_OK; case A_EVENTQ_BASE: - s->eventq.base =3D data; - s->eventq.log2size =3D extract64(s->eventq.base, 0, 5); - if (s->eventq.log2size > SMMU_EVENTQS) { - s->eventq.log2size =3D SMMU_EVENTQS; + s->bank[reg_sec_idx].eventq.base =3D data; + s->bank[reg_sec_idx].eventq.log2size =3D extract64( + s->bank[reg_sec_idx].eventq.base, 0, 5); + if (s->bank[reg_sec_idx].eventq.log2size > SMMU_EVENTQS) { + s->bank[reg_sec_idx].eventq.log2size =3D SMMU_EVENTQS; } return MEMTX_OK; case A_EVENTQ_IRQ_CFG0: - s->eventq_irq_cfg0 =3D data; + s->bank[reg_sec_idx].eventq_irq_cfg0 =3D data; return MEMTX_OK; default: qemu_log_mask(LOG_UNIMP, @@ -1544,43 +1584,47 @@ static MemTxResult smmu_writell(SMMUv3State *s, hwa= ddr offset, } =20 static MemTxResult smmu_writel(SMMUv3State *s, hwaddr offset, - uint64_t data, MemTxAttrs attrs) + uint64_t data, MemTxAttrs attrs, + SMMUSecurityIndex reg_sec_idx) { - switch (offset) { + uint32_t reg_offset =3D offset & 0xfff; + switch (reg_offset) { case A_CR0: - s->cr[0] =3D data; - s->cr0ack =3D data & ~SMMU_CR0_RESERVED; + s->bank[reg_sec_idx].cr[0] =3D data; + s->bank[reg_sec_idx].cr0ack =3D data; /* in case the command queue has been enabled */ - smmuv3_cmdq_consume(s); + smmuv3_cmdq_consume(s, reg_sec_idx); return MEMTX_OK; case A_CR1: - s->cr[1] =3D data; + s->bank[reg_sec_idx].cr[1] =3D data; return MEMTX_OK; case A_CR2: - s->cr[2] =3D data; + s->bank[reg_sec_idx].cr[2] =3D data; return MEMTX_OK; case A_IRQ_CTRL: - s->irq_ctrl =3D data; + s->bank[reg_sec_idx].irq_ctrl =3D data; return MEMTX_OK; case A_GERRORN: - smmuv3_write_gerrorn(s, data); + smmuv3_write_gerrorn(s, data, reg_sec_idx); /* * By acknowledging the CMDQ_ERR, SW may notify cmds can * be processed again */ - smmuv3_cmdq_consume(s); + smmuv3_cmdq_consume(s, reg_sec_idx); return MEMTX_OK; case A_GERROR_IRQ_CFG0: /* 64b */ - s->gerror_irq_cfg0 =3D deposit64(s->gerror_irq_cfg0, 0, 32, data); + s->bank[reg_sec_idx].gerror_irq_cfg0 =3D + deposit64(s->bank[reg_sec_idx].gerror_irq_cfg0, 0, 32, data); return MEMTX_OK; case A_GERROR_IRQ_CFG0 + 4: - s->gerror_irq_cfg0 =3D deposit64(s->gerror_irq_cfg0, 32, 32, data); + s->bank[reg_sec_idx].gerror_irq_cfg0 =3D + deposit64(s->bank[reg_sec_idx].gerror_irq_cfg0, 32, 32, data); return MEMTX_OK; case A_GERROR_IRQ_CFG1: - s->gerror_irq_cfg1 =3D data; + s->bank[reg_sec_idx].gerror_irq_cfg1 =3D data; return MEMTX_OK; case A_GERROR_IRQ_CFG2: - s->gerror_irq_cfg2 =3D data; + s->bank[reg_sec_idx].gerror_irq_cfg2 =3D data; return MEMTX_OK; case A_GBPA: /* @@ -1589,66 +1633,81 @@ static MemTxResult smmu_writel(SMMUv3State *s, hwad= dr offset, */ if (data & R_GBPA_UPDATE_MASK) { /* Ignore update bit as write is synchronous. */ - s->gbpa =3D data & ~R_GBPA_UPDATE_MASK; + s->bank[reg_sec_idx].gbpa =3D data & ~R_GBPA_UPDATE_MASK; } return MEMTX_OK; case A_STRTAB_BASE: /* 64b */ - s->strtab_base =3D deposit64(s->strtab_base, 0, 32, data); + s->bank[reg_sec_idx].strtab_base =3D + deposit64(s->bank[reg_sec_idx].strtab_base, 0, 32, data); return MEMTX_OK; case A_STRTAB_BASE + 4: - s->strtab_base =3D deposit64(s->strtab_base, 32, 32, data); + s->bank[reg_sec_idx].strtab_base =3D + deposit64(s->bank[reg_sec_idx].strtab_base, 32, 32, data); return MEMTX_OK; case A_STRTAB_BASE_CFG: - s->strtab_base_cfg =3D data; + s->bank[reg_sec_idx].strtab_base_cfg =3D data; if (FIELD_EX32(data, STRTAB_BASE_CFG, FMT) =3D=3D 1) { - s->sid_split =3D FIELD_EX32(data, STRTAB_BASE_CFG, SPLIT); - s->features |=3D SMMU_FEATURE_2LVL_STE; + s->bank[reg_sec_idx].sid_split =3D + FIELD_EX32(data, STRTAB_BASE_CFG, SPLIT); + s->bank[reg_sec_idx].features |=3D SMMU_FEATURE_2LVL_STE; } return MEMTX_OK; case A_CMDQ_BASE: /* 64b */ - s->cmdq.base =3D deposit64(s->cmdq.base, 0, 32, data); - s->cmdq.log2size =3D extract64(s->cmdq.base, 0, 5); - if (s->cmdq.log2size > SMMU_CMDQS) { - s->cmdq.log2size =3D SMMU_CMDQS; + s->bank[reg_sec_idx].cmdq.base =3D + deposit64(s->bank[reg_sec_idx].cmdq.base, 0, 32, data); + s->bank[reg_sec_idx].cmdq.log2size =3D + extract64(s->bank[reg_sec_idx].cmdq.base, 0, 5); + if (s->bank[reg_sec_idx].cmdq.log2size > SMMU_CMDQS) { + s->bank[reg_sec_idx].cmdq.log2size =3D SMMU_CMDQS; } return MEMTX_OK; case A_CMDQ_BASE + 4: /* 64b */ - s->cmdq.base =3D deposit64(s->cmdq.base, 32, 32, data); + s->bank[reg_sec_idx].cmdq.base =3D + deposit64(s->bank[reg_sec_idx].cmdq.base, 32, 32, data); + return MEMTX_OK; return MEMTX_OK; case A_CMDQ_PROD: - s->cmdq.prod =3D data; - smmuv3_cmdq_consume(s); + s->bank[reg_sec_idx].cmdq.prod =3D data; + smmuv3_cmdq_consume(s, reg_sec_idx); return MEMTX_OK; case A_CMDQ_CONS: - s->cmdq.cons =3D data; + s->bank[reg_sec_idx].cmdq.cons =3D data; return MEMTX_OK; case A_EVENTQ_BASE: /* 64b */ - s->eventq.base =3D deposit64(s->eventq.base, 0, 32, data); - s->eventq.log2size =3D extract64(s->eventq.base, 0, 5); - if (s->eventq.log2size > SMMU_EVENTQS) { - s->eventq.log2size =3D SMMU_EVENTQS; + s->bank[reg_sec_idx].eventq.base =3D + deposit64(s->bank[reg_sec_idx].eventq.base, 0, 32, data); + s->bank[reg_sec_idx].eventq.log2size =3D + extract64(s->bank[reg_sec_idx].eventq.base, 0, 5); + if (s->bank[reg_sec_idx].eventq.log2size > SMMU_EVENTQS) { + s->bank[reg_sec_idx].eventq.log2size =3D SMMU_EVENTQS; } + s->bank[reg_sec_idx].eventq.cons =3D data; return MEMTX_OK; case A_EVENTQ_BASE + 4: - s->eventq.base =3D deposit64(s->eventq.base, 32, 32, data); + s->bank[reg_sec_idx].eventq.base =3D + deposit64(s->bank[reg_sec_idx].eventq.base, 32, 32, data); + return MEMTX_OK; return MEMTX_OK; case A_EVENTQ_PROD: - s->eventq.prod =3D data; + s->bank[reg_sec_idx].eventq.prod =3D data; return MEMTX_OK; case A_EVENTQ_CONS: - s->eventq.cons =3D data; + s->bank[reg_sec_idx].eventq.cons =3D data; return MEMTX_OK; case A_EVENTQ_IRQ_CFG0: /* 64b */ - s->eventq_irq_cfg0 =3D deposit64(s->eventq_irq_cfg0, 0, 32, data); + s->bank[reg_sec_idx].eventq_irq_cfg0 =3D + deposit64(s->bank[reg_sec_idx].eventq_irq_cfg0, 0, 32, data); return MEMTX_OK; case A_EVENTQ_IRQ_CFG0 + 4: - s->eventq_irq_cfg0 =3D deposit64(s->eventq_irq_cfg0, 32, 32, data); + s->bank[reg_sec_idx].eventq_irq_cfg0 =3D + deposit64(s->bank[reg_sec_idx].eventq_irq_cfg0, 32, 32, data); + return MEMTX_OK; return MEMTX_OK; case A_EVENTQ_IRQ_CFG1: - s->eventq_irq_cfg1 =3D data; + s->bank[reg_sec_idx].eventq_irq_cfg1 =3D data; return MEMTX_OK; case A_EVENTQ_IRQ_CFG2: - s->eventq_irq_cfg2 =3D data; + s->bank[reg_sec_idx].eventq_irq_cfg2 =3D data; return MEMTX_OK; default: qemu_log_mask(LOG_UNIMP, @@ -1667,13 +1726,14 @@ static MemTxResult smmu_write_mmio(void *opaque, hw= addr offset, uint64_t data, =20 /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */ offset &=3D ~0x10000; + SMMUSecurityIndex reg_sec_idx =3D SMMU_SEC_IDX_NS; =20 switch (size) { case 8: - r =3D smmu_writell(s, offset, data, attrs); + r =3D smmu_writell(s, offset, data, attrs, reg_sec_idx); break; case 4: - r =3D smmu_writel(s, offset, data, attrs); + r =3D smmu_writel(s, offset, data, attrs, reg_sec_idx); break; default: r =3D MEMTX_ERROR; @@ -1685,20 +1745,24 @@ static MemTxResult smmu_write_mmio(void *opaque, hw= addr offset, uint64_t data, } =20 static MemTxResult smmu_readll(SMMUv3State *s, hwaddr offset, - uint64_t *data, MemTxAttrs attrs) + uint64_t *data, MemTxAttrs attrs, + SMMUSecurityIndex reg_sec_idx) { - switch (offset) { + uint32_t reg_offset =3D offset & 0xfff; + switch (reg_offset) { case A_GERROR_IRQ_CFG0: - *data =3D s->gerror_irq_cfg0; + *data =3D s->bank[reg_sec_idx].gerror_irq_cfg0; return MEMTX_OK; case A_STRTAB_BASE: - *data =3D s->strtab_base; + *data =3D s->bank[reg_sec_idx].strtab_base; return MEMTX_OK; case A_CMDQ_BASE: - *data =3D s->cmdq.base; + *data =3D s->bank[reg_sec_idx].cmdq.base; return MEMTX_OK; case A_EVENTQ_BASE: - *data =3D s->eventq.base; + *data =3D s->bank[reg_sec_idx].eventq.base; + return MEMTX_OK; + *data =3D s->bank[reg_sec_idx].eventq_irq_cfg0; return MEMTX_OK; default: *data =3D 0; @@ -1710,14 +1774,16 @@ static MemTxResult smmu_readll(SMMUv3State *s, hwad= dr offset, } =20 static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset, - uint64_t *data, MemTxAttrs attrs) + uint64_t *data, MemTxAttrs attrs, + SMMUSecurityIndex reg_sec_idx) { - switch (offset) { + uint32_t reg_offset =3D offset & 0xfff; + switch (reg_offset) { case A_IDREGS ... A_IDREGS + 0x2f: *data =3D smmuv3_idreg(offset - A_IDREGS); return MEMTX_OK; case A_IDR0 ... A_IDR5: - *data =3D s->idr[(offset - A_IDR0) / 4]; + *data =3D s->bank[reg_sec_idx].idr[(reg_offset - A_IDR0) / 4]; return MEMTX_OK; case A_IIDR: *data =3D s->iidr; @@ -1726,77 +1792,79 @@ static MemTxResult smmu_readl(SMMUv3State *s, hwadd= r offset, *data =3D s->aidr; return MEMTX_OK; case A_CR0: - *data =3D s->cr[0]; + *data =3D s->bank[reg_sec_idx].cr[0]; return MEMTX_OK; case A_CR0ACK: - *data =3D s->cr0ack; + *data =3D s->bank[reg_sec_idx].cr0ack; return MEMTX_OK; case A_CR1: - *data =3D s->cr[1]; + *data =3D s->bank[reg_sec_idx].cr[1]; return MEMTX_OK; case A_CR2: - *data =3D s->cr[2]; + *data =3D s->bank[reg_sec_idx].cr[2]; return MEMTX_OK; case A_STATUSR: *data =3D s->statusr; return MEMTX_OK; case A_GBPA: - *data =3D s->gbpa; + *data =3D s->bank[reg_sec_idx].gbpa; return MEMTX_OK; case A_IRQ_CTRL: case A_IRQ_CTRL_ACK: - *data =3D s->irq_ctrl; + *data =3D s->bank[reg_sec_idx].irq_ctrl; return MEMTX_OK; case A_GERROR: - *data =3D s->gerror; + *data =3D s->bank[reg_sec_idx].gerror; return MEMTX_OK; case A_GERRORN: - *data =3D s->gerrorn; + *data =3D s->bank[reg_sec_idx].gerrorn; return MEMTX_OK; case A_GERROR_IRQ_CFG0: /* 64b */ - *data =3D extract64(s->gerror_irq_cfg0, 0, 32); + *data =3D extract64(s->bank[reg_sec_idx].gerror_irq_cfg0, 0, 32); return MEMTX_OK; case A_GERROR_IRQ_CFG0 + 4: - *data =3D extract64(s->gerror_irq_cfg0, 32, 32); + *data =3D extract64(s->bank[reg_sec_idx].gerror_irq_cfg0, 32, 32); + return MEMTX_OK; return MEMTX_OK; case A_GERROR_IRQ_CFG1: - *data =3D s->gerror_irq_cfg1; + *data =3D s->bank[reg_sec_idx].gerror_irq_cfg1; return MEMTX_OK; case A_GERROR_IRQ_CFG2: - *data =3D s->gerror_irq_cfg2; + *data =3D s->bank[reg_sec_idx].gerror_irq_cfg2; return MEMTX_OK; case A_STRTAB_BASE: /* 64b */ - *data =3D extract64(s->strtab_base, 0, 32); + *data =3D extract64(s->bank[reg_sec_idx].strtab_base, 0, 32); return MEMTX_OK; case A_STRTAB_BASE + 4: /* 64b */ - *data =3D extract64(s->strtab_base, 32, 32); + *data =3D extract64(s->bank[reg_sec_idx].strtab_base, 32, 32); return MEMTX_OK; case A_STRTAB_BASE_CFG: - *data =3D s->strtab_base_cfg; + *data =3D s->bank[reg_sec_idx].strtab_base_cfg; return MEMTX_OK; case A_CMDQ_BASE: /* 64b */ - *data =3D extract64(s->cmdq.base, 0, 32); + *data =3D extract64(s->bank[reg_sec_idx].cmdq.base, 0, 32); return MEMTX_OK; case A_CMDQ_BASE + 4: - *data =3D extract64(s->cmdq.base, 32, 32); + *data =3D extract64(s->bank[reg_sec_idx].cmdq.base, 32, 32); return MEMTX_OK; case A_CMDQ_PROD: - *data =3D s->cmdq.prod; + *data =3D s->bank[reg_sec_idx].cmdq.prod; return MEMTX_OK; case A_CMDQ_CONS: - *data =3D s->cmdq.cons; + *data =3D s->bank[reg_sec_idx].cmdq.cons; return MEMTX_OK; case A_EVENTQ_BASE: /* 64b */ - *data =3D extract64(s->eventq.base, 0, 32); + *data =3D extract64(s->bank[reg_sec_idx].eventq.base, 0, 32); return MEMTX_OK; case A_EVENTQ_BASE + 4: /* 64b */ - *data =3D extract64(s->eventq.base, 32, 32); + *data =3D extract64(s->bank[reg_sec_idx].eventq.base, 32, 32); return MEMTX_OK; case A_EVENTQ_PROD: - *data =3D s->eventq.prod; + *data =3D s->bank[reg_sec_idx].eventq.prod; return MEMTX_OK; case A_EVENTQ_CONS: - *data =3D s->eventq.cons; + *data =3D s->bank[reg_sec_idx].eventq.cons; + return MEMTX_OK; return MEMTX_OK; default: *data =3D 0; @@ -1816,13 +1884,14 @@ static MemTxResult smmu_read_mmio(void *opaque, hwa= ddr offset, uint64_t *data, =20 /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */ offset &=3D ~0x10000; + SMMUSecurityIndex reg_sec_idx =3D SMMU_SEC_IDX_NS; =20 switch (size) { case 8: - r =3D smmu_readll(s, offset, data, attrs); + r =3D smmu_readll(s, offset, data, attrs, reg_sec_idx); break; case 4: - r =3D smmu_readl(s, offset, data, attrs); + r =3D smmu_readl(s, offset, data, attrs, reg_sec_idx); break; default: r =3D MEMTX_ERROR; @@ -1918,7 +1987,7 @@ static bool smmuv3_gbpa_needed(void *opaque) SMMUv3State *s =3D opaque; =20 /* Only migrate GBPA if it has different reset value. */ - return s->gbpa !=3D SMMU_GBPA_RESET_VAL; + return s->bank[SMMU_SEC_IDX_NS].gbpa !=3D SMMU_GBPA_RESET_VAL; } =20 static const VMStateDescription vmstate_gbpa =3D { @@ -1927,7 +1996,7 @@ static const VMStateDescription vmstate_gbpa =3D { .minimum_version_id =3D 1, .needed =3D smmuv3_gbpa_needed, .fields =3D (const VMStateField[]) { - VMSTATE_UINT32(gbpa, SMMUv3State), + VMSTATE_UINT32(bank[SMMU_SEC_IDX_NS].gbpa, SMMUv3State), VMSTATE_END_OF_LIST() } }; @@ -1938,28 +2007,29 @@ static const VMStateDescription vmstate_smmuv3 =3D { .minimum_version_id =3D 1, .priority =3D MIG_PRI_IOMMU, .fields =3D (const VMStateField[]) { - VMSTATE_UINT32(features, SMMUv3State), + VMSTATE_UINT32(bank[SMMU_SEC_IDX_NS].features, SMMUv3State), VMSTATE_UINT8(sid_size, SMMUv3State), - VMSTATE_UINT8(sid_split, SMMUv3State), + VMSTATE_UINT8(bank[SMMU_SEC_IDX_NS].sid_split, SMMUv3State), =20 - VMSTATE_UINT32_ARRAY(cr, SMMUv3State, 3), - VMSTATE_UINT32(cr0ack, SMMUv3State), + VMSTATE_UINT32_ARRAY(bank[SMMU_SEC_IDX_NS].cr, SMMUv3State, 3), + VMSTATE_UINT32(bank[SMMU_SEC_IDX_NS].cr0ack, SMMUv3State), VMSTATE_UINT32(statusr, SMMUv3State), - VMSTATE_UINT32(irq_ctrl, SMMUv3State), - VMSTATE_UINT32(gerror, SMMUv3State), - VMSTATE_UINT32(gerrorn, SMMUv3State), - VMSTATE_UINT64(gerror_irq_cfg0, SMMUv3State), - VMSTATE_UINT32(gerror_irq_cfg1, SMMUv3State), - VMSTATE_UINT32(gerror_irq_cfg2, SMMUv3State), - VMSTATE_UINT64(strtab_base, SMMUv3State), - VMSTATE_UINT32(strtab_base_cfg, SMMUv3State), - VMSTATE_UINT64(eventq_irq_cfg0, SMMUv3State), - VMSTATE_UINT32(eventq_irq_cfg1, SMMUv3State), - VMSTATE_UINT32(eventq_irq_cfg2, SMMUv3State), - - VMSTATE_STRUCT(cmdq, SMMUv3State, 0, vmstate_smmuv3_queue, SMMUQue= ue), - VMSTATE_STRUCT(eventq, SMMUv3State, 0, vmstate_smmuv3_queue, SMMUQ= ueue), - + VMSTATE_UINT32(bank[SMMU_SEC_IDX_NS].irq_ctrl, SMMUv3State), + VMSTATE_UINT32(bank[SMMU_SEC_IDX_NS].gerror, SMMUv3State), + VMSTATE_UINT32(bank[SMMU_SEC_IDX_NS].gerrorn, SMMUv3State), + VMSTATE_UINT64(bank[SMMU_SEC_IDX_NS].gerror_irq_cfg0, SMMUv3State), + VMSTATE_UINT32(bank[SMMU_SEC_IDX_NS].gerror_irq_cfg1, SMMUv3State), + VMSTATE_UINT32(bank[SMMU_SEC_IDX_NS].gerror_irq_cfg2, SMMUv3State), + VMSTATE_UINT64(bank[SMMU_SEC_IDX_NS].strtab_base, SMMUv3State), + VMSTATE_UINT32(bank[SMMU_SEC_IDX_NS].strtab_base_cfg, SMMUv3State), + VMSTATE_UINT64(bank[SMMU_SEC_IDX_NS].eventq_irq_cfg0, SMMUv3State), + VMSTATE_UINT32(bank[SMMU_SEC_IDX_NS].eventq_irq_cfg1, SMMUv3State), + VMSTATE_UINT32(bank[SMMU_SEC_IDX_NS].eventq_irq_cfg2, SMMUv3State), + + VMSTATE_STRUCT(bank[SMMU_SEC_IDX_NS].cmdq, SMMUv3State, 0, + vmstate_smmuv3_queue, SMMUQueue), + VMSTATE_STRUCT(bank[SMMU_SEC_IDX_NS].eventq, SMMUv3State, 0, + vmstate_smmuv3_queue, SMMUQueue), VMSTATE_END_OF_LIST(), }, .subsections =3D (const VMStateDescription * const []) { diff --git a/hw/arm/trace-events b/hw/arm/trace-events index f3386bd7ae..80cb4d6b04 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -35,13 +35,13 @@ smmuv3_trigger_irq(int irq) "irq=3D%d" smmuv3_write_gerror(uint32_t toggled, uint32_t gerror) "toggled=3D0x%x, ne= w GERROR=3D0x%x" smmuv3_write_gerrorn(uint32_t acked, uint32_t gerrorn) "acked=3D0x%x, new = GERRORN=3D0x%x" smmuv3_unhandled_cmd(uint32_t type) "Unhandled command type=3D%d" -smmuv3_cmdq_consume(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8= _t cons_wrap) "prod=3D%d cons=3D%d prod.wrap=3D%d cons.wrap=3D%d" +smmuv3_cmdq_consume(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8= _t cons_wrap, int sec_idx) "prod=3D%d cons=3D%d prod.wrap=3D%d cons.wrap=3D= %d sec_idx=3D%d" smmuv3_cmdq_opcode(const char *opcode) "<--- %s" smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, u= int8_t cons_wrap) "prod:%d, cons:%d, prod_wrap:%d, cons_wrap:%d " smmuv3_cmdq_consume_error(const char *cmd_name, uint8_t cmd_error) "Error = on %s command execution: %d" smmuv3_write_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) = "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)" -smmuv3_record_event(const char *type, uint32_t sid) "%s sid=3D0x%x" -smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "sid= =3D0x%x features:0x%x, sid_split:0x%x" +smmuv3_record_event(const char *type, uint32_t sid, int sec_idx) "%s sid= =3D0x%x sec_idx=3D%d" +smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split, int s= ec_idx) "sid=3D0x%x features:0x%x, sid_split:0x%x sec_idx=3D%d" smmuv3_find_ste_2lvl(uint64_t strtab_base, uint64_t l1ptr, int l1_ste_offs= et, uint64_t l2ptr, int l2_ste_offset, int max_l2_ste) "strtab_base:0x%"PRI= x64" l1ptr:0x%"PRIx64" l1_off:0x%x, l2ptr:0x%"PRIx64" l2_off:0x%x max_l2_st= e:%d" smmuv3_get_ste(uint64_t addr) "STE addr: 0x%"PRIx64 smmuv3_translate_disable(const char *n, uint16_t sid, uint64_t addr, bool = is_write) "%s sid=3D0x%x bypass (smmu disabled) iova:0x%"PRIx64" is_write= =3D%d" diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 80d0fecfde..3df82b83eb 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -40,6 +40,19 @@ #define CACHED_ENTRY_TO_ADDR(ent, addr) ((ent)->entry.translated_addr= + \ ((addr) & (ent)->entry.addr_m= ask)) =20 +/* + * SMMU Security state index + * + * The values of this enumeration are identical to the SEC_SID signal + * encoding defined in the ARM SMMUv3 Architecture Specification. It is us= ed + * to select the appropriate programming interface for a given transaction. + */ +typedef enum SMMUSecurityIndex { + SMMU_SEC_IDX_NS =3D 0, + SMMU_SEC_IDX_S =3D 1, + SMMU_SEC_IDX_NUM, +} SMMUSecurityIndex; + /* * Page table walk error types */ @@ -116,6 +129,7 @@ typedef struct SMMUTransCfg { SMMUTransTableInfo tt[2]; /* Used by stage-2 only. */ struct SMMUS2Cfg s2cfg; + SMMUSecurityIndex sec_idx; /* cached security index */ } SMMUTransCfg; =20 typedef struct SMMUDevice { diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h index d183a62766..572f15251e 100644 --- a/include/hw/arm/smmuv3.h +++ b/include/hw/arm/smmuv3.h @@ -32,19 +32,11 @@ typedef struct SMMUQueue { uint8_t log2size; } SMMUQueue; =20 -struct SMMUv3State { - SMMUState smmu_state; - - uint32_t features; - uint8_t sid_size; - uint8_t sid_split; - +/* Structure for register bank */ +typedef struct SMMUv3RegBank { uint32_t idr[6]; - uint32_t iidr; - uint32_t aidr; uint32_t cr[3]; uint32_t cr0ack; - uint32_t statusr; uint32_t gbpa; uint32_t irq_ctrl; uint32_t gerror; @@ -57,12 +49,28 @@ struct SMMUv3State { uint64_t eventq_irq_cfg0; uint32_t eventq_irq_cfg1; uint32_t eventq_irq_cfg2; + uint32_t features; + uint8_t sid_split; =20 SMMUQueue eventq, cmdq; +} SMMUv3RegBank; + +struct SMMUv3State { + SMMUState smmu_state; + + /* Shared (non-banked) registers and state */ + uint8_t sid_size; + uint32_t iidr; + uint32_t aidr; + uint32_t statusr; + + /* Banked registers for all access */ + SMMUv3RegBank bank[SMMU_SEC_IDX_NUM]; =20 qemu_irq irq[4]; QemuMutex mutex; char *stage; + bool secure_impl; }; =20 typedef enum { @@ -84,7 +92,9 @@ struct SMMUv3Class { #define TYPE_ARM_SMMUV3 "arm-smmuv3" OBJECT_DECLARE_TYPE(SMMUv3State, SMMUv3Class, ARM_SMMUV3) =20 -#define STAGE1_SUPPORTED(s) FIELD_EX32(s->idr[0], IDR0, S1P) -#define STAGE2_SUPPORTED(s) FIELD_EX32(s->idr[0], IDR0, S2P) +#define STAGE1_SUPPORTED(s) \ + FIELD_EX32(s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, S1P) +#define STAGE2_SUPPORTED(s) \ + FIELD_EX32(s->bank[SMMU_SEC_IDX_NS].idr[0], IDR0, S2P) =20 #endif --=20 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758817715380731.9270708732711; Thu, 25 Sep 2025 09:28:35 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1op0-0007Du-HU; Thu, 25 Sep 2025 12:27:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1oo6-0006S5-Nj; Thu, 25 Sep 2025 12:27:00 -0400 Received: from zg8tmtu5ljy1ljeznc42.icoremail.net ([159.65.134.6]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1onl-0004l9-Q5; Thu, 25 Sep 2025 12:26:58 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-6 (Coremail) with SMTP id AQAAfwA3PVE1bdVooDN6Bw--.49908S2; Fri, 26 Sep 2025 00:26:29 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwDHLestbdVoW_MeAA--.7120S9; Fri, 26 Sep 2025 00:26:28 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , pierrick.bouvier@linaro.org, philmd@linaro.org, jean-philippe@linaro.org, smostafa@google.com, Tao Tang Subject: [PATCH v2 06/14] hw/arm/smmuv3: Add separate address space for secure SMMU accesses Date: Fri, 26 Sep 2025 00:26:10 +0800 Message-Id: <20250925162618.191242-7-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwDHLestbdVoW_MeAA--.7120S9 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAEBWjUSMIHuQAAsI Authentication-Results: hzbj-icmmx-6; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvJXoWxWr43Jw47Jw1rCw48XF1kKrg_yoW5ZrW5pF Z3AFZxt3yjk3W7ZrZ7XrnruFy8Wa95WF4UGr47Cwn5ZF13tr1ayw4qk3W5KFyDCr45Ja17 ZF17Zr4xXF4jqrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj DUYxn0WfASr-VFAU7a7-sFnT9fnUUIcSsGvfJ3UbIYCTnIWIevJa73UjIFyTuYvj4RJUUU UUUUU 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=lists.gnu.org; Received-SPF: pass client-ip=159.65.134.6; envelope-from=tangtao1634@phytium.com.cn; helo=zg8tmtu5ljy1ljeznc42.icoremail.net X-Spam_score_int: 41 X-Spam_score: 4.1 X-Spam_bar: ++++ X-Spam_report: (4.1 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_PBL=3.335, RCVD_IN_SBL_CSS=3.335, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_PASS=-0.001, T_SPF_HELO_TEMPERROR=0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: 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-ZM-MESSAGEID: 1758817719061116600 Content-Type: text/plain; charset="utf-8" According to the Arm architecture, SMMU-originated memory accesses, such as fetching commands or writing events for a secure stream, must target the Secure Physical Address (PA) space. The existing model sends all DMA to the global address_space_memory. This patch introduces the infrastructure to differentiate between secure and non-secure memory accesses. A weak global symbol, arm_secure_address_space, is added, which can be provided by the machine model to represent the Secure PA space. A new helper, smmu_get_address_space(), selects the target address space based on the is_secure context. All internal DMA calls (dma_memory_read/write) are updated to use this helper. Additionally, the attrs.secure bit is set on transactions targeting the secure address space. Signed-off-by: Tao Tang --- hw/arm/smmu-common.c | 8 ++++++++ hw/arm/virt.c | 5 +++++ include/hw/arm/smmu-common.h | 20 ++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 62a7612184..24db448683 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -30,6 +30,14 @@ #include "hw/arm/smmu-common.h" #include "smmu-internal.h" =20 +/* Global state for secure address space availability */ +bool arm_secure_as_available; + +void smmu_enable_secure_address_space(void) +{ + arm_secure_as_available =3D true; +} + /* IOTLB Management */ =20 static guint smmu_iotlb_key_hash(gconstpointer v) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 02209fadcf..805d9aadb7 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -92,6 +92,8 @@ #include "hw/cxl/cxl_host.h" #include "qemu/guest-random.h" =20 +AddressSpace arm_secure_address_space; + static GlobalProperty arm_virt_compat[] =3D { { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" }, }; @@ -2243,6 +2245,9 @@ static void machvirt_init(MachineState *machine) memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory", UINT64_MAX); memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1); + address_space_init(&arm_secure_address_space, secure_sysmem, + "secure-memory-space"); + smmu_enable_secure_address_space(); } =20 firmware_loaded =3D virt_firmware_init(vms, sysmem, diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 3df82b83eb..cd61c5e126 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -53,6 +53,26 @@ typedef enum SMMUSecurityIndex { SMMU_SEC_IDX_NUM, } SMMUSecurityIndex; =20 +extern AddressSpace __attribute__((weak)) arm_secure_address_space; +extern bool arm_secure_as_available; +void smmu_enable_secure_address_space(void); + +static inline AddressSpace *smmu_get_address_space(SMMUSecurityIndex sec_s= id) +{ + switch (sec_sid) { + case SMMU_SEC_IDX_S: + { + if (arm_secure_as_available) { + return &arm_secure_address_space; + } + } + QEMU_FALLTHROUGH; + case SMMU_SEC_IDX_NS: + default: + return &address_space_memory; + } +} + /* * Page table walk error types */ --=20 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758817646478976.6505464024559; Thu, 25 Sep 2025 09:27:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1onv-0006K5-7L; Thu, 25 Sep 2025 12:26:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1onp-0006IV-Mj; Thu, 25 Sep 2025 12:26:41 -0400 Received: from zg8tmja5ljk3lje4ms43mwaa.icoremail.net ([209.97.181.73]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1oni-0004kw-N0; Thu, 25 Sep 2025 12:26:41 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-6 (Coremail) with SMTP id AQAAfwCHj1M2bdVoozN6Bw--.50399S2; Fri, 26 Sep 2025 00:26:30 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwDHLestbdVoW_MeAA--.7120S10; Fri, 26 Sep 2025 00:26:29 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , pierrick.bouvier@linaro.org, philmd@linaro.org, jean-philippe@linaro.org, smostafa@google.com, Tao Tang Subject: [PATCH v2 07/14] hw/arm/smmuv3: Make Configuration Cache security-state aware Date: Fri, 26 Sep 2025 00:26:11 +0800 Message-Id: <20250925162618.191242-8-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwDHLestbdVoW_MeAA--.7120S10 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAEBWjUSMIHuwAAsK Authentication-Results: hzbj-icmmx-6; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvAXoWfJryUKr47Jr4UuFyDXw47Arb_yoW8Gw17to WrKr47X3W8WrnruFyvvr1fJa1aqrZYk3y3Kr4Yv3yYganxtF15JFyIyrZxZrn09F45Jr1x Ar1fCrWxXF4UAr1rn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3UbIjqfuFe4nvWSU8nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UU UUUUUUU== 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=lists.gnu.org; Received-SPF: pass client-ip=209.97.181.73; envelope-from=tangtao1634@phytium.com.cn; helo=zg8tmja5ljk3lje4ms43mwaa.icoremail.net X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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: 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-ZM-MESSAGEID: 1758817649370116600 Content-Type: text/plain; charset="utf-8" This patch adapts the Configuration Cache (STE/CD caches) to support multiple security states. The cache key, previously just the SMMUDevice, is now a composite key of the SMMUDevice and the security index (sec_idx). This allows for separate cache entries for the same device when operating in different security states, preventing aliasing between secure and non-secure configurations. The configuration cache invalidation functions have been refactored to correctly handle multiple security states, ensuring that invalidation commands operate on the appropriate cache entries. Finally, checks have been added to the stream table's MMIO read/write logic to verify if the stream table is writable. This ensures that the Configuration Cache management is compliant with the architecture. Signed-off-by: Tao Tang --- hw/arm/smmu-common.c | 63 ++++++++++++++++++++++- hw/arm/smmuv3.c | 98 ++++++++++++++++++++++++++++-------- include/hw/arm/smmu-common.h | 14 ++++++ 3 files changed, 153 insertions(+), 22 deletions(-) diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 24db448683..bc13b00f1d 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -30,6 +30,43 @@ #include "hw/arm/smmu-common.h" #include "smmu-internal.h" =20 +/* Configuration Cache Management */ +static guint smmu_config_key_hash(gconstpointer key) +{ + const SMMUConfigKey *k =3D key; + return g_direct_hash(k->sdev) ^ (guint)k->sec_idx; +} + +static gboolean smmu_config_key_equal(gconstpointer a, gconstpointer b) +{ + const SMMUConfigKey *ka =3D a; + const SMMUConfigKey *kb =3D b; + return ka->sdev =3D=3D kb->sdev && ka->sec_idx =3D=3D kb->sec_idx; +} + +SMMUConfigKey smmu_get_config_key(SMMUDevice *sdev, SMMUSecurityIndex sec_= idx) +{ + SMMUConfigKey key =3D {.sdev =3D sdev, .sec_idx =3D sec_idx}; + return key; +} + +ARMSecuritySpace smmu_get_security_space(SMMUSecurityIndex sec_idx) +{ + switch (sec_idx) { + case SMMU_SEC_IDX_S: + return ARMSS_Secure; + case SMMU_SEC_IDX_NS: + default: + return ARMSS_NonSecure; + } +} + +MemTxAttrs smmu_get_txattrs(SMMUSecurityIndex sec_idx) +{ + return (MemTxAttrs) { .secure =3D sec_idx > SMMU_SEC_IDX_NS ? 1 : 0, + .space =3D smmu_get_security_space(sec_idx) }; +} + /* Global state for secure address space availability */ bool arm_secure_as_available; =20 @@ -237,7 +274,8 @@ static gboolean smmu_hash_remove_by_vmid_ipa(gpointer k= ey, gpointer value, static gboolean smmu_hash_remove_by_sid_range(gpointer key, gpointer value, gpointer user_= data) { - SMMUDevice *sdev =3D (SMMUDevice *)key; + SMMUConfigKey *config_key =3D (SMMUConfigKey *)key; + SMMUDevice *sdev =3D config_key->sdev; uint32_t sid =3D smmu_get_sid(sdev); SMMUSIDRange *sid_range =3D (SMMUSIDRange *)user_data; =20 @@ -255,6 +293,25 @@ void smmu_configs_inv_sid_range(SMMUState *s, SMMUSIDR= ange sid_range) &sid_range); } =20 +/* Remove all cached configs for a specific device, regardless of security= . */ +static gboolean smmu_hash_remove_by_sdev(gpointer key, gpointer value, + gpointer user_data) +{ + SMMUConfigKey *config_key =3D (SMMUConfigKey *)key; + SMMUDevice *target =3D (SMMUDevice *)user_data; + + if (config_key->sdev !=3D target) { + return false; + } + trace_smmu_config_cache_inv(smmu_get_sid(target)); + return true; +} + +void smmu_configs_inv_sdev(SMMUState *s, SMMUDevice *sdev) +{ + g_hash_table_foreach_remove(s->configs, smmu_hash_remove_by_sdev, sdev= ); +} + void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova, uint8_t tg, uint64_t num_pages, uint8_t ttl) { @@ -942,7 +999,9 @@ static void smmu_base_realize(DeviceState *dev, Error *= *errp) error_propagate(errp, local_err); return; } - s->configs =3D g_hash_table_new_full(NULL, NULL, NULL, g_free); + s->configs =3D g_hash_table_new_full(smmu_config_key_hash, + smmu_config_key_equal, + g_free, g_free); s->iotlb =3D g_hash_table_new_full(smmu_iotlb_key_hash, smmu_iotlb_key= _equal, g_free, g_free); s->smmu_pcibus_by_busptr =3D g_hash_table_new(NULL, NULL); diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 2efa39b78c..eba709ae2b 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -352,14 +352,13 @@ static void smmuv3_init_regs(SMMUv3State *s) } =20 static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf, - SMMUEventInfo *event) + SMMUEventInfo *event, SMMUTransCfg *cfg) { int ret, i; =20 trace_smmuv3_get_ste(addr); /* TODO: guarantee 64-bit single-copy atomicity */ - ret =3D dma_memory_read(&address_space_memory, addr, buf, sizeof(*buf), - MEMTXATTRS_UNSPECIFIED); + ret =3D dma_memory_read(cfg->as, addr, buf, sizeof(*buf), cfg->txattrs= ); if (ret !=3D MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "Cannot fetch pte at address=3D0x%"PRIx64"\n", addr); @@ -404,8 +403,7 @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, SMMUTr= ansCfg *cfg, } =20 /* TODO: guarantee 64-bit single-copy atomicity */ - ret =3D dma_memory_read(&address_space_memory, addr, buf, sizeof(*buf), - MEMTXATTRS_UNSPECIFIED); + ret =3D dma_memory_read(cfg->as, addr, buf, sizeof(*buf), cfg->txattrs= ); if (ret !=3D MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "Cannot fetch pte at address=3D0x%"PRIx64"\n", addr); @@ -699,8 +697,8 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, = STE *ste, l2_ste_offset =3D sid & ((1 << sid_split) - 1); l1ptr =3D (dma_addr_t)(strtab_base + l1_ste_offset * sizeof(l1std)= ); /* TODO: guarantee 64-bit single-copy atomicity */ - ret =3D dma_memory_read(&address_space_memory, l1ptr, &l1std, - sizeof(l1std), MEMTXATTRS_UNSPECIFIED); + ret =3D dma_memory_read(cfg->as, l1ptr, + &l1std, sizeof(l1std), cfg->txattrs); if (ret !=3D MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "Could not read L1PTR at 0X%"PRIx64"\n", l1ptr); @@ -742,7 +740,7 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, = STE *ste, addr =3D strtab_base + sid * sizeof(*ste); } =20 - if (smmu_get_ste(s, addr, ste, event)) { + if (smmu_get_ste(s, addr, ste, event, cfg)) { return -EINVAL; } =20 @@ -900,18 +898,21 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr= , SMMUTransCfg *cfg, * * @sdev: SMMUDevice handle * @event: output event info + * @sec_idx: security index * * The configuration cache contains data resulting from both STE and CD * decoding under the form of an SMMUTransCfg struct. The hash table is in= dexed * by the SMMUDevice handle. */ -static SMMUTransCfg *smmuv3_get_config(SMMUDevice *sdev, SMMUEventInfo *ev= ent) +static SMMUTransCfg *smmuv3_get_config(SMMUDevice *sdev, SMMUEventInfo *ev= ent, + SMMUSecurityIndex sec_idx) { SMMUv3State *s =3D sdev->smmu; SMMUState *bc =3D &s->smmu_state; SMMUTransCfg *cfg; + SMMUConfigKey lookup_key =3D smmu_get_config_key(sdev, sec_idx); =20 - cfg =3D g_hash_table_lookup(bc->configs, sdev); + cfg =3D g_hash_table_lookup(bc->configs, &lookup_key); if (cfg) { sdev->cfg_cache_hits++; trace_smmuv3_config_cache_hit(smmu_get_sid(sdev), @@ -925,9 +926,14 @@ static SMMUTransCfg *smmuv3_get_config(SMMUDevice *sde= v, SMMUEventInfo *event) 100 * sdev->cfg_cache_hits / (sdev->cfg_cache_hits + sdev->cfg_cache_misses= )); cfg =3D g_new0(SMMUTransCfg, 1); + cfg->sec_idx =3D sec_idx; + cfg->txattrs =3D smmu_get_txattrs(sec_idx); + cfg->as =3D smmu_get_address_space(sec_idx); =20 if (!smmuv3_decode_config(&sdev->iommu, cfg, event)) { - g_hash_table_insert(bc->configs, sdev, cfg); + SMMUConfigKey *persistent_key =3D g_new(SMMUConfigKey, 1); + *persistent_key =3D smmu_get_config_key(sdev, sec_idx); + g_hash_table_insert(bc->configs, persistent_key, cfg); } else { g_free(cfg); cfg =3D NULL; @@ -941,8 +947,8 @@ static void smmuv3_flush_config(SMMUDevice *sdev) SMMUv3State *s =3D sdev->smmu; SMMUState *bc =3D &s->smmu_state; =20 - trace_smmu_config_cache_inv(smmu_get_sid(sdev)); - g_hash_table_remove(bc->configs, sdev); + /* Remove all security-indexed configs for this device */ + smmu_configs_inv_sdev(bc, sdev); } =20 /* Do translation with TLB lookup. */ @@ -1102,7 +1108,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegi= on *mr, hwaddr addr, goto epilogue; } =20 - cfg =3D smmuv3_get_config(sdev, &event); + cfg =3D smmuv3_get_config(sdev, &event, sec_idx); if (!cfg) { status =3D SMMU_TRANS_ERROR; goto epilogue; @@ -1182,7 +1188,7 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, { SMMUDevice *sdev =3D container_of(mr, SMMUDevice, iommu); SMMUEventInfo eventinfo =3D {.inval_ste_allowed =3D true}; - SMMUTransCfg *cfg =3D smmuv3_get_config(sdev, &eventinfo); + SMMUTransCfg *cfg =3D smmuv3_get_config(sdev, &eventinfo, SMMU_SEC_IDX= _NS); IOMMUTLBEvent event; uint8_t granule; =20 @@ -1314,6 +1320,38 @@ static void smmuv3_range_inval(SMMUState *s, Cmd *cm= d, SMMUStage stage) } } =20 +static inline int smmuv3_get_cr0_smmuen(SMMUv3State *s, + SMMUSecurityIndex sec_idx) +{ + return smmu_enabled(s, sec_idx); +} + +static inline int smmuv3_get_cr0ack_smmuen(SMMUv3State *s, + SMMUSecurityIndex sec_idx) +{ + return FIELD_EX32(s->bank[sec_idx].cr0ack, CR0, SMMUEN); +} + +static inline bool smmuv3_is_smmu_enabled(SMMUv3State *s, + SMMUSecurityIndex sec_idx) +{ + int cr0_smmuen =3D smmuv3_get_cr0_smmuen(s, sec_idx); + int cr0ack_smmuen =3D smmuv3_get_cr0ack_smmuen(s, sec_idx); + return (cr0_smmuen =3D=3D 0 && cr0ack_smmuen =3D=3D 0); +} + +/* Check if STRTAB_BASE register is writable */ +static bool smmu_strtab_base_writable(SMMUv3State *s, SMMUSecurityIndex se= c_idx) +{ + /* Check TABLES_PRESET - use NS bank as it's the global setting */ + if (FIELD_EX32(s->bank[SMMU_SEC_IDX_NS].idr[1], IDR1, TABLES_PRESET)) { + return false; + } + + /* Check SMMUEN conditions for the specific security domain */ + return smmuv3_is_smmu_enabled(s, sec_idx); +} + static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUSecurityIndex sec_idx) { SMMUState *bs =3D ARM_SMMU(s); @@ -1553,6 +1591,11 @@ static MemTxResult smmu_writell(SMMUv3State *s, hwad= dr offset, uint32_t reg_offset =3D offset & 0xfff; switch (reg_offset) { case A_STRTAB_BASE: + if (!smmu_strtab_base_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "STRTAB_BASE write ignored: register is RO\n"); + return MEMTX_OK; + } /* Clear reserved bits according to spec */ s->bank[reg_sec_idx].strtab_base =3D data & SMMU_STRTAB_BASE_RESER= VED; return MEMTX_OK; @@ -1637,14 +1680,29 @@ static MemTxResult smmu_writel(SMMUv3State *s, hwad= dr offset, } return MEMTX_OK; case A_STRTAB_BASE: /* 64b */ - s->bank[reg_sec_idx].strtab_base =3D - deposit64(s->bank[reg_sec_idx].strtab_base, 0, 32, data); - return MEMTX_OK; case A_STRTAB_BASE + 4: - s->bank[reg_sec_idx].strtab_base =3D - deposit64(s->bank[reg_sec_idx].strtab_base, 32, 32, data); + if (!smmu_strtab_base_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "STRTAB_BASE write ignored: register is RO\n"); + return MEMTX_OK; + } + + data &=3D SMMU_STRTAB_BASE_RESERVED; + if (reg_offset =3D=3D A_STRTAB_BASE) { + s->bank[reg_sec_idx].strtab_base =3D deposit64( + s->bank[reg_sec_idx].strtab_base, 0, 32, data); + } else { + s->bank[reg_sec_idx].strtab_base =3D deposit64( + s->bank[reg_sec_idx].strtab_base, 32, 32, data); + } return MEMTX_OK; case A_STRTAB_BASE_CFG: + if (!smmu_strtab_base_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "STRTAB_BASE_CFG write ignored: register is RO\n= "); + return MEMTX_OK; + } + s->bank[reg_sec_idx].strtab_base_cfg =3D data; if (FIELD_EX32(data, STRTAB_BASE_CFG, FMT) =3D=3D 1) { s->bank[reg_sec_idx].sid_split =3D diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index cd61c5e126..ed21db7728 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -22,6 +22,7 @@ #include "hw/sysbus.h" #include "hw/pci/pci.h" #include "qom/object.h" +#include "hw/arm/arm-security.h" =20 #define SMMU_PCI_BUS_MAX 256 #define SMMU_PCI_DEVFN_MAX 256 @@ -53,6 +54,9 @@ typedef enum SMMUSecurityIndex { SMMU_SEC_IDX_NUM, } SMMUSecurityIndex; =20 +MemTxAttrs smmu_get_txattrs(SMMUSecurityIndex sec_idx); +ARMSecuritySpace smmu_get_security_space(SMMUSecurityIndex sec_idx); + extern AddressSpace __attribute__((weak)) arm_secure_address_space; extern bool arm_secure_as_available; void smmu_enable_secure_address_space(void); @@ -150,6 +154,8 @@ typedef struct SMMUTransCfg { /* Used by stage-2 only. */ struct SMMUS2Cfg s2cfg; SMMUSecurityIndex sec_idx; /* cached security index */ + MemTxAttrs txattrs; /* cached transaction attributes */ + AddressSpace *as; /* cached address space */ } SMMUTransCfg; =20 typedef struct SMMUDevice { @@ -176,6 +182,11 @@ typedef struct SMMUIOTLBKey { uint8_t level; } SMMUIOTLBKey; =20 +typedef struct SMMUConfigKey { + SMMUDevice *sdev; + SMMUSecurityIndex sec_idx; +} SMMUConfigKey; + typedef struct SMMUSIDRange { uint32_t start; uint32_t end; @@ -251,6 +262,7 @@ SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTran= sCfg *cfg, void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *ent= ry); SMMUIOTLBKey smmu_get_iotlb_key(int asid, int vmid, uint64_t iova, uint8_t tg, uint8_t level); +SMMUConfigKey smmu_get_config_key(SMMUDevice *sdev, SMMUSecurityIndex sec_= idx); void smmu_iotlb_inv_all(SMMUState *s); void smmu_iotlb_inv_asid_vmid(SMMUState *s, int asid, int vmid); void smmu_iotlb_inv_vmid(SMMUState *s, int vmid); @@ -260,6 +272,8 @@ void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vm= id, dma_addr_t iova, void smmu_iotlb_inv_ipa(SMMUState *s, int vmid, dma_addr_t ipa, uint8_t tg, uint64_t num_pages, uint8_t ttl); void smmu_configs_inv_sid_range(SMMUState *s, SMMUSIDRange sid_range); +/* Invalidate all cached configs for a given device across all security id= x */ +void smmu_configs_inv_sdev(SMMUState *s, SMMUDevice *sdev); /* Unmap the range of all the notifiers registered to any IOMMU mr */ void smmu_inv_notifiers_all(SMMUState *s); =20 --=20 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758817765932482.92822760116246; Thu, 25 Sep 2025 09:29:25 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1op1-0007Do-8J; Thu, 25 Sep 2025 12:27:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1oo6-0006S2-DZ; Thu, 25 Sep 2025 12:27:00 -0400 Received: from sgoci-sdnproxy-4.icoremail.net ([129.150.39.64]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1ons-0004l7-8I; Thu, 25 Sep 2025 12:26:57 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-6 (Coremail) with SMTP id AQAAfwDHXWE3bdVopzN6Bw--.5704S2; Fri, 26 Sep 2025 00:26:31 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwDHLestbdVoW_MeAA--.7120S11; Fri, 26 Sep 2025 00:26:30 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , pierrick.bouvier@linaro.org, philmd@linaro.org, jean-philippe@linaro.org, smostafa@google.com, Tao Tang Subject: [PATCH v2 08/14] hw/arm/smmuv3: Add security-state handling for page table walks Date: Fri, 26 Sep 2025 00:26:12 +0800 Message-Id: <20250925162618.191242-9-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwDHLestbdVoW_MeAA--.7120S11 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAEBWjUSMIHvQAAsM Authentication-Results: hzbj-icmmx-6; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvJXoWxtFW3XrWDtw45XF4DuryDKFg_yoWDGF43p3 yxGrnxtr4rtF1SvrWkAr42v3Z3G34vgF4DKryDCr9akayYqry8AF1DKFy5CFZ0gr15J39r Zr1vgr4xZrnrXrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj DUYxn0WfASr-VFAU7a7-sFnT9fnUUIcSsGvfJ3UbIYCTnIWIevJa73UjIFyTuYvj4RJUUU UUUUU 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=lists.gnu.org; Received-SPF: pass client-ip=129.150.39.64; envelope-from=tangtao1634@phytium.com.cn; helo=sgoci-sdnproxy-4.icoremail.net X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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: 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-ZM-MESSAGEID: 1758817773593116600 Content-Type: text/plain; charset="utf-8" This patch introduces the necessary logic to handle security states during the page table translation process. Support for the NS (Non-secure) attribute bit is added to the parsing of various translation structures, including CD and PTEs. This allows the SMMU model to correctly determine the security properties of memory during a translation. With this change, a new translation stage is added: - Secure Stage 1 translation Note that this commit does not include support for Secure Stage 2 translation, which will be addressed in the future. Signed-off-by: Tao Tang --- hw/arm/smmu-common.c | 55 ++++++++++++++++++++++++++++++++---- hw/arm/smmu-internal.h | 7 +++++ hw/arm/smmuv3-internal.h | 2 ++ hw/arm/smmuv3.c | 2 ++ hw/arm/trace-events | 2 +- include/hw/arm/smmu-common.h | 4 +++ 6 files changed, 66 insertions(+), 6 deletions(-) diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index bc13b00f1d..f563cba023 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -398,20 +398,25 @@ void smmu_iotlb_inv_vmid_s1(SMMUState *s, int vmid) * @base_addr[@index] */ static int get_pte(dma_addr_t baseaddr, uint32_t index, uint64_t *pte, - SMMUPTWEventInfo *info) + SMMUPTWEventInfo *info, SMMUTransCfg *cfg, int walk_ns) { int ret; dma_addr_t addr =3D baseaddr + index * sizeof(*pte); + /* Only support Secure PA Space as RME isn't implemented yet */ + MemTxAttrs attrs =3D + smmu_get_txattrs(walk_ns ? SMMU_SEC_IDX_NS : SMMU_SEC_IDX_S); + AddressSpace *as =3D + smmu_get_address_space(walk_ns ? SMMU_SEC_IDX_NS : SMMU_SEC_IDX_S); =20 /* TODO: guarantee 64-bit single-copy atomicity */ - ret =3D ldq_le_dma(&address_space_memory, addr, pte, MEMTXATTRS_UNSPEC= IFIED); + ret =3D ldq_le_dma(as, addr, pte, attrs); =20 if (ret !=3D MEMTX_OK) { info->type =3D SMMU_PTW_ERR_WALK_EABT; info->addr =3D addr; return -EINVAL; } - trace_smmu_get_pte(baseaddr, index, addr, *pte); + trace_smmu_get_pte(baseaddr, index, addr, *pte, walk_ns); return 0; } =20 @@ -542,6 +547,8 @@ static int smmu_ptw_64_s1(SMMUState *bs, SMMUTransCfg *= cfg, =20 baseaddr =3D extract64(tt->ttb, 0, cfg->oas); baseaddr &=3D ~indexmask; + int nscfg =3D tt->nscfg; + bool forced_ns =3D false; /* Track if NSTable=3D1 forced NS mode */ =20 while (level < VMSA_LEVELS) { uint64_t subpage_size =3D 1ULL << level_shift(level, granule_sz); @@ -551,7 +558,9 @@ static int smmu_ptw_64_s1(SMMUState *bs, SMMUTransCfg *= cfg, dma_addr_t pte_addr =3D baseaddr + offset * sizeof(pte); uint8_t ap; =20 - if (get_pte(baseaddr, offset, &pte, info)) { + /* Use NS if forced by previous NSTable=3D1 or current nscfg */ + int current_ns =3D forced_ns || nscfg; + if (get_pte(baseaddr, offset, &pte, info, cfg, current_ns)) { goto error; } trace_smmu_ptw_level(stage, level, iova, subpage_size, @@ -576,6 +585,26 @@ static int smmu_ptw_64_s1(SMMUState *bs, SMMUTransCfg = *cfg, goto error; } } + + /* + * Hierarchical control of Secure/Non-secure accesses: + * If NSTable=3D1 from Secure space, force all subsequent look= ups to + * Non-secure space and ignore future NSTable according to + * (IHI 0070G.b) 13.4.1 Stage 1 page permissions and + * (DDI 0487H.a)D8.4.2 Control of Secure or Non-secure memory = access + */ + if (!forced_ns) { + int new_nstable =3D PTE_NSTABLE(pte); + if (!current_ns && new_nstable) { + /* First transition from Secure to Non-secure */ + forced_ns =3D true; + nscfg =3D 1; + } else if (!forced_ns) { + /* Still in original mode, update nscfg normally */ + nscfg =3D new_nstable; + } + /* If forced_ns is already true, ignore NSTable bit */ + } level++; continue; } else if (is_page_pte(pte, level)) { @@ -618,6 +647,8 @@ static int smmu_ptw_64_s1(SMMUState *bs, SMMUTransCfg *= cfg, goto error; } =20 + tlbe->sec_idx =3D PTE_NS(pte) ? SMMU_SEC_IDX_NS : SMMU_SEC_IDX_S; + tlbe->entry.target_as =3D smmu_get_address_space(tlbe->sec_idx); tlbe->entry.translated_addr =3D gpa; tlbe->entry.iova =3D iova & ~mask; tlbe->entry.addr_mask =3D mask; @@ -687,7 +718,8 @@ static int smmu_ptw_64_s2(SMMUTransCfg *cfg, dma_addr_t pte_addr =3D baseaddr + offset * sizeof(pte); uint8_t s2ap; =20 - if (get_pte(baseaddr, offset, &pte, info)) { + /* Use NS as Secure Stage 2 is not implemented (SMMU_S_IDR1.SEL2 = =3D=3D 0)*/ + if (get_pte(baseaddr, offset, &pte, info, cfg, 1)) { goto error; } trace_smmu_ptw_level(stage, level, ipa, subpage_size, @@ -740,6 +772,8 @@ static int smmu_ptw_64_s2(SMMUTransCfg *cfg, goto error_ipa; } =20 + tlbe->sec_idx =3D SMMU_SEC_IDX_NS; + tlbe->entry.target_as =3D &address_space_memory; tlbe->entry.translated_addr =3D gpa; tlbe->entry.iova =3D ipa & ~mask; tlbe->entry.addr_mask =3D mask; @@ -824,6 +858,17 @@ int smmu_ptw(SMMUState *bs, SMMUTransCfg *cfg, dma_add= r_t iova, return ret; } =20 + if (!cfg->sel2 && tlbe->sec_idx > SMMU_SEC_IDX_NS) { + /* + * Nested translation with Secure IPA output is not supported if + * Secure Stage 2 is not implemented. + */ + info->type =3D SMMU_PTW_ERR_TRANSLATION; + info->stage =3D SMMU_STAGE_1; + tlbe->entry.perm =3D IOMMU_NONE; + return -EINVAL; + } + ipa =3D CACHED_ENTRY_TO_ADDR(tlbe, iova); ret =3D smmu_ptw_64_s2(cfg, ipa, perm, &tlbe_s2, info); if (ret) { diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h index d143d296f3..cb3a6eb8d1 100644 --- a/hw/arm/smmu-internal.h +++ b/hw/arm/smmu-internal.h @@ -58,6 +58,10 @@ ((level =3D=3D 3) && = \ ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_L3_PTE_TYPE_PAGE)) =20 +/* Non-secure bit */ +#define PTE_NS(pte) \ + (extract64(pte, 5, 1)) + /* access permissions */ =20 #define PTE_AP(pte) \ @@ -66,6 +70,9 @@ #define PTE_APTABLE(pte) \ (extract64(pte, 61, 2)) =20 +#define PTE_NSTABLE(pte) \ + (extract64(pte, 63, 1)) + #define PTE_AF(pte) \ (extract64(pte, 10, 1)) /* diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index cf17c405de..af2936cf16 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -704,6 +704,8 @@ static inline int oas2bits(int oas_field) #define CD_R(x) extract32((x)->word[1], 13, 1) #define CD_A(x) extract32((x)->word[1], 14, 1) #define CD_AARCH64(x) extract32((x)->word[1], 9 , 1) +#define CD_NSCFG0(x) extract32((x)->word[2], 0, 1) +#define CD_NSCFG1(x) extract32((x)->word[4], 0, 1) =20 /** * tg2granule - Decodes the CD translation granule size field according diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index eba709ae2b..2f8494c346 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -832,6 +832,7 @@ static int decode_cd(SMMUv3State *s, SMMUTransCfg *cfg, tt->ttb =3D CACHED_ENTRY_TO_ADDR(entry, tt->ttb); } =20 + tt->nscfg =3D i ? CD_NSCFG1(cd) : CD_NSCFG0(cd); tt->had =3D CD_HAD(cd, i); trace_smmuv3_decode_cd_tt(i, tt->tsz, tt->ttb, tt->granule_sz, tt-= >had); } @@ -929,6 +930,7 @@ static SMMUTransCfg *smmuv3_get_config(SMMUDevice *sdev= , SMMUEventInfo *event, cfg->sec_idx =3D sec_idx; cfg->txattrs =3D smmu_get_txattrs(sec_idx); cfg->as =3D smmu_get_address_space(sec_idx); + cfg->sel2 =3D s->bank[SMMU_SEC_IDX_S].idr[1]; =20 if (!smmuv3_decode_config(&sdev->iommu, cfg, event)) { SMMUConfigKey *persistent_key =3D g_new(SMMUConfigKey, 1); diff --git a/hw/arm/trace-events b/hw/arm/trace-events index 80cb4d6b04..f99de78655 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -16,7 +16,7 @@ smmu_ptw_level(int stage, int level, uint64_t iova, size_= t subpage_size, uint64_ smmu_ptw_invalid_pte(int stage, int level, uint64_t baseaddr, uint64_t pte= addr, uint32_t offset, uint64_t pte) "stage=3D%d level=3D%d base@=3D0x%"PRI= x64" pte@=3D0x%"PRIx64" offset=3D%d pte=3D0x%"PRIx64 smmu_ptw_page_pte(int stage, int level, uint64_t iova, uint64_t baseaddr,= uint64_t pteaddr, uint64_t pte, uint64_t address) "stage=3D%d level=3D%d i= ova=3D0x%"PRIx64" base@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D0x%"PRIx64" = page address =3D 0x%"PRIx64 smmu_ptw_block_pte(int stage, int level, uint64_t baseaddr, uint64_t ptead= dr, uint64_t pte, uint64_t iova, uint64_t gpa, int bsize_mb) "stage=3D%d le= vel=3D%d base@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D0x%"PRIx64" iova=3D0x= %"PRIx64" block address =3D 0x%"PRIx64" block size =3D %d MiB" -smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte)= "baseaddr=3D0x%"PRIx64" index=3D0x%x, pteaddr=3D0x%"PRIx64", pte=3D0x%"PRI= x64 +smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte,= bool ns_walk) "baseaddr=3D0x%"PRIx64" index=3D0x%x, pteaddr=3D0x%"PRIx64",= pte=3D0x%"PRIx64" ns_walk=3D%d" smmu_iotlb_inv_all(void) "IOTLB invalidate all" smmu_iotlb_inv_asid_vmid(int asid, int vmid) "IOTLB invalidate asid=3D%d v= mid=3D%d" smmu_iotlb_inv_vmid(int vmid) "IOTLB invalidate vmid=3D%d" diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index ed21db7728..c27aec8bd4 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -109,6 +109,7 @@ typedef struct SMMUTransTableInfo { uint8_t tsz; /* input range, ie. 2^(64 -tsz)*/ uint8_t granule_sz; /* granule page shift */ bool had; /* hierarchical attribute disable */ + bool nscfg; /* Non-secure attribute of Starting-level T= T */ } SMMUTransTableInfo; =20 typedef struct SMMUTLBEntry { @@ -116,6 +117,7 @@ typedef struct SMMUTLBEntry { uint8_t level; uint8_t granule; IOMMUAccessFlags parent_perm; + SMMUSecurityIndex sec_idx; } SMMUTLBEntry; =20 /* Stage-2 configuration. */ @@ -156,6 +158,8 @@ typedef struct SMMUTransCfg { SMMUSecurityIndex sec_idx; /* cached security index */ MemTxAttrs txattrs; /* cached transaction attributes */ AddressSpace *as; /* cached address space */ + bool current_walk_ns; /* cached if the current walk is non-secure= */ + bool sel2; } SMMUTransCfg; =20 typedef struct SMMUDevice { --=20 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758817996174259.44691495800055; Thu, 25 Sep 2025 09:33:16 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1ooN-0006Zh-JV; Thu, 25 Sep 2025 12:27:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1onx-0006Kz-02; Thu, 25 Sep 2025 12:26:50 -0400 Received: from zg8tmja5ljk3lje4ms43mwaa.icoremail.net ([209.97.181.73]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1onl-0004la-Ad; Thu, 25 Sep 2025 12:26:48 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-7 (Coremail) with SMTP id AQAAfwA3PDw3bdVojgo6CQ--.544S2; Fri, 26 Sep 2025 00:26:32 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwDHLestbdVoW_MeAA--.7120S12; Fri, 26 Sep 2025 00:26:30 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , pierrick.bouvier@linaro.org, philmd@linaro.org, jean-philippe@linaro.org, smostafa@google.com, Tao Tang Subject: [PATCH v2 09/14] hw/arm/smmuv3: Add secure TLB entry management Date: Fri, 26 Sep 2025 00:26:13 +0800 Message-Id: <20250925162618.191242-10-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwDHLestbdVoW_MeAA--.7120S12 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAEBWjUSMIHvwAAsO Authentication-Results: hzbj-icmmx-7; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvAXoW3Zw4fXr4fuw1xCry8CFy3urg_yoW8JF47Co WFkw4UXa18WrnrXFyqkF4xJF42vFWUta15A3WFqrWYg3ZxKrn5KF1xtws3JF4rtr4UWr40 yr95CrW8Xr17Ar95n29KB7ZKAUJUUUU5529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3UbIjqfuFe4nvWSU8nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UU UUUUUUU== 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=lists.gnu.org; Received-SPF: pass client-ip=209.97.181.73; envelope-from=tangtao1634@phytium.com.cn; helo=zg8tmja5ljk3lje4ms43mwaa.icoremail.net X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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: 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-ZM-MESSAGEID: 1758817998348116601 Content-Type: text/plain; charset="utf-8" To prevent aliasing between secure and non-secure translations for the same address space, the IOTLB lookup key must incorporate the security state of the transaction. A secure parameter has been added to smmu_get_iotlb_key, ensuring that secure and non-secure TLB entries are treated as distinct entities within the cache. Building on this, this commit also implements the SMMU_S_INIT register. This secure-only register provides a mechanism for software to perform a global invalidation of all cached translations within the IOTLB. This is a critical feature for secure hypervisors like Hafnium, which use it as the final step of their SMMU initialization sequence to ensure a clean TLB state. Together, these changes provide robust management for secure TLB entries, preventing TLB pollution between security worlds and allowing for proper initialization by secure software. Signed-off-by: Tao Tang --- hw/arm/smmu-common.c | 25 ++++++++------ hw/arm/smmuv3.c | 67 ++++++++++++++++++++++++++++-------- hw/arm/trace-events | 1 + include/hw/arm/smmu-common.h | 10 ++++-- 4 files changed, 76 insertions(+), 27 deletions(-) diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index f563cba023..fdabcc4542 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -84,7 +84,7 @@ static guint smmu_iotlb_key_hash(gconstpointer v) =20 /* Jenkins hash */ a =3D b =3D c =3D JHASH_INITVAL + sizeof(*key); - a +=3D key->asid + key->vmid + key->level + key->tg; + a +=3D key->asid + key->vmid + key->level + key->tg + key->sec_idx; b +=3D extract64(key->iova, 0, 32); c +=3D extract64(key->iova, 32, 32); =20 @@ -100,14 +100,15 @@ static gboolean smmu_iotlb_key_equal(gconstpointer v1= , gconstpointer v2) =20 return (k1->asid =3D=3D k2->asid) && (k1->iova =3D=3D k2->iova) && (k1->level =3D=3D k2->level) && (k1->tg =3D=3D k2->tg) && - (k1->vmid =3D=3D k2->vmid); + (k1->vmid =3D=3D k2->vmid) && (k1->sec_idx =3D=3D k2->sec_idx); } =20 SMMUIOTLBKey smmu_get_iotlb_key(int asid, int vmid, uint64_t iova, - uint8_t tg, uint8_t level) + uint8_t tg, uint8_t level, + SMMUSecurityIndex sec_idx) { SMMUIOTLBKey key =3D {.asid =3D asid, .vmid =3D vmid, .iova =3D iova, - .tg =3D tg, .level =3D level}; + .tg =3D tg, .level =3D level, .sec_idx =3D sec_idx= }; =20 return key; } @@ -129,7 +130,7 @@ static SMMUTLBEntry *smmu_iotlb_lookup_all_levels(SMMUS= tate *bs, SMMUIOTLBKey key; =20 key =3D smmu_get_iotlb_key(cfg->asid, cfg->s2cfg.vmid, - iova & ~mask, tg, level); + iova & ~mask, tg, level, cfg->sec_idx); entry =3D g_hash_table_lookup(bs->iotlb, &key); if (entry) { break; @@ -193,7 +194,7 @@ void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg= , SMMUTLBEntry *new) } =20 *key =3D smmu_get_iotlb_key(cfg->asid, cfg->s2cfg.vmid, new->entry.iov= a, - tg, new->level); + tg, new->level, cfg->sec_idx); trace_smmu_iotlb_insert(cfg->asid, cfg->s2cfg.vmid, new->entry.iova, tg, new->level); g_hash_table_insert(bs->iotlb, key, new); @@ -313,13 +314,15 @@ void smmu_configs_inv_sdev(SMMUState *s, SMMUDevice *= sdev) } =20 void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova, - uint8_t tg, uint64_t num_pages, uint8_t ttl) + uint8_t tg, uint64_t num_pages, uint8_t ttl, + SMMUSecurityIndex sec_idx) { /* if tg is not set we use 4KB range invalidation */ uint8_t granule =3D tg ? tg * 2 + 10 : 12; =20 if (ttl && (num_pages =3D=3D 1) && (asid >=3D 0)) { - SMMUIOTLBKey key =3D smmu_get_iotlb_key(asid, vmid, iova, tg, ttl); + SMMUIOTLBKey key =3D smmu_get_iotlb_key(asid, vmid, iova, + tg, ttl, sec_idx); =20 if (g_hash_table_remove(s->iotlb, &key)) { return; @@ -345,13 +348,15 @@ void smmu_iotlb_inv_iova(SMMUState *s, int asid, int = vmid, dma_addr_t iova, * in Stage-1 invalidation ASID =3D -1, means don't care. */ void smmu_iotlb_inv_ipa(SMMUState *s, int vmid, dma_addr_t ipa, uint8_t tg, - uint64_t num_pages, uint8_t ttl) + uint64_t num_pages, uint8_t ttl, + SMMUSecurityIndex sec_idx) { uint8_t granule =3D tg ? tg * 2 + 10 : 12; int asid =3D -1; =20 if (ttl && (num_pages =3D=3D 1)) { - SMMUIOTLBKey key =3D smmu_get_iotlb_key(asid, vmid, ipa, tg, ttl); + SMMUIOTLBKey key =3D smmu_get_iotlb_key(asid, vmid, ipa, + tg, ttl, sec_idx); =20 if (g_hash_table_remove(s->iotlb, &key)) { return; diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 2f8494c346..3835b9e79f 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -953,6 +953,21 @@ static void smmuv3_flush_config(SMMUDevice *sdev) smmu_configs_inv_sdev(bc, sdev); } =20 +static void smmuv3_invalidate_all_caches(SMMUv3State *s) +{ + trace_smmuv3_invalidate_all_caches(); + SMMUState *bs =3D &s->smmu_state; + + /* Clear all cached configs including STE and CD */ + if (bs->configs) { + g_hash_table_remove_all(bs->configs); + } + + /* Invalidate all SMMU IOTLB entries */ + smmu_inv_notifiers_all(&s->smmu_state); + smmu_iotlb_inv_all(bs); +} + /* Do translation with TLB lookup. */ static SMMUTranslationStatus smmuv3_do_translate(SMMUv3State *s, hwaddr ad= dr, SMMUTransCfg *cfg, @@ -1181,16 +1196,18 @@ epilogue: * @tg: translation granule (if communicated through range invalidation) * @num_pages: number of @granule sized pages (if tg !=3D 0), otherwise 1 * @stage: Which stage(1 or 2) is used + * @sec_idx: security index */ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, IOMMUNotifier *n, int asid, int vmid, dma_addr_t iova, uint8_t tg, - uint64_t num_pages, int stage) + uint64_t num_pages, int stage, + SMMUSecurityIndex sec_idx) { SMMUDevice *sdev =3D container_of(mr, SMMUDevice, iommu); SMMUEventInfo eventinfo =3D {.inval_ste_allowed =3D true}; - SMMUTransCfg *cfg =3D smmuv3_get_config(sdev, &eventinfo, SMMU_SEC_IDX= _NS); + SMMUTransCfg *cfg =3D smmuv3_get_config(sdev, &eventinfo, sec_idx); IOMMUTLBEvent event; uint8_t granule; =20 @@ -1235,7 +1252,7 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, } =20 event.type =3D IOMMU_NOTIFIER_UNMAP; - event.entry.target_as =3D &address_space_memory; + event.entry.target_as =3D smmu_get_address_space(sec_idx); event.entry.iova =3D iova; event.entry.addr_mask =3D num_pages * (1 << granule) - 1; event.entry.perm =3D IOMMU_NONE; @@ -1246,7 +1263,8 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, /* invalidate an asid/vmid/iova range tuple in all mr's */ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova, uint8_t tg, - uint64_t num_pages, int stage) + uint64_t num_pages, int stage, + SMMUSecurityIndex sec_idx) { SMMUDevice *sdev; =20 @@ -1258,12 +1276,14 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s,= int asid, int vmid, iova, tg, num_pages, stage); =20 IOMMU_NOTIFIER_FOREACH(n, mr) { - smmuv3_notify_iova(mr, n, asid, vmid, iova, tg, num_pages, sta= ge); + smmuv3_notify_iova(mr, n, asid, vmid, iova, tg, + num_pages, stage, sec_idx); } } } =20 -static void smmuv3_range_inval(SMMUState *s, Cmd *cmd, SMMUStage stage) +static void smmuv3_range_inval(SMMUState *s, Cmd *cmd, SMMUStage stage, + SMMUSecurityIndex sec_idx) { dma_addr_t end, addr =3D CMD_ADDR(cmd); uint8_t type =3D CMD_TYPE(cmd); @@ -1289,11 +1309,11 @@ static void smmuv3_range_inval(SMMUState *s, Cmd *c= md, SMMUStage stage) =20 if (!tg) { trace_smmuv3_range_inval(vmid, asid, addr, tg, 1, ttl, leaf, stage= ); - smmuv3_inv_notifiers_iova(s, asid, vmid, addr, tg, 1, stage); + smmuv3_inv_notifiers_iova(s, asid, vmid, addr, tg, 1, stage, sec_i= dx); if (stage =3D=3D SMMU_STAGE_1) { - smmu_iotlb_inv_iova(s, asid, vmid, addr, tg, 1, ttl); + smmu_iotlb_inv_iova(s, asid, vmid, addr, tg, 1, ttl, sec_idx); } else { - smmu_iotlb_inv_ipa(s, vmid, addr, tg, 1, ttl); + smmu_iotlb_inv_ipa(s, vmid, addr, tg, 1, ttl, sec_idx); } return; } @@ -1312,11 +1332,13 @@ static void smmuv3_range_inval(SMMUState *s, Cmd *c= md, SMMUStage stage) num_pages =3D (mask + 1) >> granule; trace_smmuv3_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf, stage); - smmuv3_inv_notifiers_iova(s, asid, vmid, addr, tg, num_pages, stag= e); + smmuv3_inv_notifiers_iova(s, asid, vmid, addr, tg, + num_pages, stage, sec_idx); if (stage =3D=3D SMMU_STAGE_1) { - smmu_iotlb_inv_iova(s, asid, vmid, addr, tg, num_pages, ttl); + smmu_iotlb_inv_iova(s, asid, vmid, addr, tg, + num_pages, ttl, sec_idx); } else { - smmu_iotlb_inv_ipa(s, vmid, addr, tg, num_pages, ttl); + smmu_iotlb_inv_ipa(s, vmid, addr, tg, num_pages, ttl, sec_idx); } addr +=3D mask + 1; } @@ -1514,7 +1536,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUSe= curityIndex sec_idx) cmd_error =3D SMMU_CERROR_ILL; break; } - smmuv3_range_inval(bs, &cmd, SMMU_STAGE_1); + smmuv3_range_inval(bs, &cmd, SMMU_STAGE_1, sec_idx); break; case SMMU_CMD_TLBI_S12_VMALL: { @@ -1539,7 +1561,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUSe= curityIndex sec_idx) * As currently only either s1 or s2 are supported * we can reuse same function for s2. */ - smmuv3_range_inval(bs, &cmd, SMMU_STAGE_2); + smmuv3_range_inval(bs, &cmd, SMMU_STAGE_2, sec_idx); break; case SMMU_CMD_TLBI_EL3_ALL: case SMMU_CMD_TLBI_EL3_VA: @@ -1769,6 +1791,21 @@ static MemTxResult smmu_writel(SMMUv3State *s, hwadd= r offset, case A_EVENTQ_IRQ_CFG2: s->bank[reg_sec_idx].eventq_irq_cfg2 =3D data; return MEMTX_OK; + case A_S_INIT_ALIAS: + if (data & R_S_INIT_INV_ALL_MASK) { + int cr0_smmuen =3D smmuv3_get_cr0_smmuen(s, SMMU_SEC_IDX_NS); + int s_cr0_smmuen =3D smmuv3_get_cr0_smmuen(s, SMMU_SEC_IDX_S); + if (cr0_smmuen || s_cr0_smmuen) { + /* CONSTRAINED UNPREDICTABLE behavior: Ignore this write */ + qemu_log_mask(LOG_GUEST_ERROR, "S_INIT write ignored: " + "CR0.SMMUEN=3D%d or S_CR0.SMMUEN=3D%d is set= \n", + cr0_smmuen, s_cr0_smmuen); + return MEMTX_OK; + } + smmuv3_invalidate_all_caches(s); + } + /* Synchronous emulation: invalidation completed instantly. */ + return MEMTX_OK; default: qemu_log_mask(LOG_UNIMP, "%s Unexpected 32-bit access to 0x%"PRIx64" (WI)\n", @@ -1925,6 +1962,8 @@ static MemTxResult smmu_readl(SMMUv3State *s, hwaddr = offset, case A_EVENTQ_CONS: *data =3D s->bank[reg_sec_idx].eventq.cons; return MEMTX_OK; + case A_S_INIT_ALIAS: + *data =3D 0; return MEMTX_OK; default: *data =3D 0; diff --git a/hw/arm/trace-events b/hw/arm/trace-events index f99de78655..64e8659ae9 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -64,6 +64,7 @@ smmuv3_cmdq_tlbi_s12_vmid(int vmid) "vmid=3D%d" smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu= mr=3D%s" smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu= mr=3D%s" smmuv3_inv_notifiers_iova(const char *name, int asid, int vmid, uint64_t i= ova, uint8_t tg, uint64_t num_pages, int stage) "iommu mr=3D%s asid=3D%d vm= id=3D%d iova=3D0x%"PRIx64" tg=3D%d num_pages=3D0x%"PRIx64" stage=3D%d" +smmuv3_invalidate_all_caches(void) "Invalidate all SMMU caches and TLBs" smmu_reset_exit(void) "" =20 # strongarm.c diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index c27aec8bd4..b566f11b47 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -184,6 +184,7 @@ typedef struct SMMUIOTLBKey { int vmid; uint8_t tg; uint8_t level; + SMMUSecurityIndex sec_idx; } SMMUIOTLBKey; =20 typedef struct SMMUConfigKey { @@ -265,16 +266,19 @@ SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTr= ansCfg *cfg, SMMUTransTableInfo *tt, hwaddr iova); void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *ent= ry); SMMUIOTLBKey smmu_get_iotlb_key(int asid, int vmid, uint64_t iova, - uint8_t tg, uint8_t level); + uint8_t tg, uint8_t level, + SMMUSecurityIndex sec_idx); SMMUConfigKey smmu_get_config_key(SMMUDevice *sdev, SMMUSecurityIndex sec_= idx); void smmu_iotlb_inv_all(SMMUState *s); void smmu_iotlb_inv_asid_vmid(SMMUState *s, int asid, int vmid); void smmu_iotlb_inv_vmid(SMMUState *s, int vmid); void smmu_iotlb_inv_vmid_s1(SMMUState *s, int vmid); void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova, - uint8_t tg, uint64_t num_pages, uint8_t ttl); + uint8_t tg, uint64_t num_pages, uint8_t ttl, + SMMUSecurityIndex sec_idx); void smmu_iotlb_inv_ipa(SMMUState *s, int vmid, dma_addr_t ipa, uint8_t tg, - uint64_t num_pages, uint8_t ttl); + uint64_t num_pages, uint8_t ttl, + SMMUSecurityIndex sec_idx); void smmu_configs_inv_sid_range(SMMUState *s, SMMUSIDRange sid_range); /* Invalidate all cached configs for a given device across all security id= x */ void smmu_configs_inv_sdev(SMMUState *s, SMMUDevice *sdev); --=20 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758817758953149.2093789115744; Thu, 25 Sep 2025 09:29:18 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1ooy-00079T-8l; Thu, 25 Sep 2025 12:27:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1oo6-0006Ro-6p; Thu, 25 Sep 2025 12:27:00 -0400 Received: from zg8tmtyylji0my4xnjqumte4.icoremail.net ([162.243.164.118]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1ono-0004lg-Ds; Thu, 25 Sep 2025 12:26:56 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-6 (Coremail) with SMTP id AQAAfwD3jWE4bdVouTN6Bw--.50242S2; Fri, 26 Sep 2025 00:26:32 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwDHLestbdVoW_MeAA--.7120S13; Fri, 26 Sep 2025 00:26:31 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , pierrick.bouvier@linaro.org, philmd@linaro.org, jean-philippe@linaro.org, smostafa@google.com, Tao Tang Subject: [PATCH v2 10/14] hw/arm/smmuv3: Add banked support for queues and error handling Date: Fri, 26 Sep 2025 00:26:14 +0800 Message-Id: <20250925162618.191242-11-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwDHLestbdVoW_MeAA--.7120S13 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAEBWjUSMIHwQAAsw Authentication-Results: hzbj-icmmx-6; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvAXoWfZw17trW7Kw1DXFyxArWDurg_yoW8ZF17Jo WrKw4DZw4xWr1ku34q9Fn7JF43AFs3CwsIka4rZa1Du398Ar18Wr97CrW3u3yagr43XFyD tw109w4xXF4rArWrn29KB7ZKAUJUUUUr529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3UbIjqfuFe4nvWSU8nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UU UUUUUUU== 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=lists.gnu.org; Received-SPF: pass client-ip=162.243.164.118; envelope-from=tangtao1634@phytium.com.cn; helo=zg8tmtyylji0my4xnjqumte4.icoremail.net X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 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: 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-ZM-MESSAGEID: 1758817761590116600 Content-Type: text/plain; charset="utf-8" This commit extends the banked register model to the Command Queue (CMDQ), Event Queue (EVTQ), and global error handling logic. By leveraging the banked structure, the SMMUv3 model now supports separate, parallel queues and error status registers for the Secure and Non-secure states. This is essential for correctly modeling the parallel programming interfaces defined by the SMMUv3 architecture. Additionally, this patch hardens the MMIO implementation by adding several checks that were incomplete in the previous version. For instance, writes to the Command Queue registers are now correctly gated by the IDR1.QUEUES_PRESET bit, ensuring compliance with the architectural rules for pre-configured queues. Signed-off-by: Tao Tang --- hw/arm/smmuv3-internal.h | 2 + hw/arm/smmuv3.c | 374 +++++++++++++++++++++++++++++++++------ 2 files changed, 323 insertions(+), 53 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index af2936cf16..6bff504219 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -517,6 +517,8 @@ typedef struct SMMUEventInfo { uint32_t sid; bool recorded; bool inval_ste_allowed; + AddressSpace *as; + MemTxAttrs txattrs; SMMUSecurityIndex sec_idx; union { struct { diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 3835b9e79f..53c7eff0e3 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -106,14 +106,15 @@ static void smmuv3_write_gerrorn(SMMUv3State *s, uint= 32_t new_gerrorn, trace_smmuv3_write_gerrorn(toggled & pending, s->bank[sec_idx].gerrorn= ); } =20 -static inline MemTxResult queue_read(SMMUQueue *q, Cmd *cmd) +static inline MemTxResult queue_read(SMMUQueue *q, Cmd *cmd, + SMMUSecurityIndex sec_idx) { dma_addr_t addr =3D Q_CONS_ENTRY(q); MemTxResult ret; int i; =20 - ret =3D dma_memory_read(&address_space_memory, addr, cmd, sizeof(Cmd), - MEMTXATTRS_UNSPECIFIED); + ret =3D dma_memory_read(smmu_get_address_space(sec_idx), addr, cmd, + sizeof(Cmd), smmu_get_txattrs(sec_idx)); if (ret !=3D MEMTX_OK) { return ret; } @@ -123,7 +124,8 @@ static inline MemTxResult queue_read(SMMUQueue *q, Cmd = *cmd) return ret; } =20 -static MemTxResult queue_write(SMMUQueue *q, Evt *evt_in) +static MemTxResult queue_write(SMMUQueue *q, Evt *evt_in, + SMMUSecurityIndex sec_idx) { dma_addr_t addr =3D Q_PROD_ENTRY(q); MemTxResult ret; @@ -133,8 +135,8 @@ static MemTxResult queue_write(SMMUQueue *q, Evt *evt_i= n) for (i =3D 0; i < ARRAY_SIZE(evt.word); i++) { cpu_to_le32s(&evt.word[i]); } - ret =3D dma_memory_write(&address_space_memory, addr, &evt, sizeof(Evt= ), - MEMTXATTRS_UNSPECIFIED); + ret =3D dma_memory_write(smmu_get_address_space(sec_idx), addr, &evt, + sizeof(Evt), smmu_get_txattrs(sec_idx)); if (ret !=3D MEMTX_OK) { return ret; } @@ -157,7 +159,7 @@ static MemTxResult smmuv3_write_eventq(SMMUv3State *s, = Evt *evt, return MEMTX_ERROR; } =20 - r =3D queue_write(q, evt); + r =3D queue_write(q, evt, sec_idx); if (r !=3D MEMTX_OK) { return r; } @@ -1025,6 +1027,8 @@ static SMMUTranslationStatus smmuv3_do_translate(SMMU= v3State *s, hwaddr addr, */ class =3D ptw_info.is_ipa_descriptor ? SMMU_CLASS_TT : class; event->sec_idx =3D cfg->sec_idx; + event->txattrs =3D cfg->txattrs; + event->sec_idx =3D cfg->sec_idx; switch (ptw_info.type) { case SMMU_PTW_ERR_WALK_EABT: event->type =3D SMMU_EVT_F_WALK_EABT; @@ -1376,6 +1380,110 @@ static bool smmu_strtab_base_writable(SMMUv3State *= s, SMMUSecurityIndex sec_idx) return smmuv3_is_smmu_enabled(s, sec_idx); } =20 +static inline int smmuv3_get_cr0_cmdqen(SMMUv3State *s, + SMMUSecurityIndex sec_idx) +{ + return FIELD_EX32(s->bank[sec_idx].cr[0], CR0, CMDQEN); +} + +static inline int smmuv3_get_cr0ack_cmdqen(SMMUv3State *s, + SMMUSecurityIndex sec_idx) +{ + return FIELD_EX32(s->bank[sec_idx].cr0ack, CR0, CMDQEN); +} + +static inline int smmuv3_get_cr0_eventqen(SMMUv3State *s, + SMMUSecurityIndex sec_idx) +{ + return FIELD_EX32(s->bank[sec_idx].cr[0], CR0, EVENTQEN); +} + +static inline int smmuv3_get_cr0ack_eventqen(SMMUv3State *s, + SMMUSecurityIndex sec_idx) +{ + return FIELD_EX32(s->bank[sec_idx].cr0ack, CR0, EVENTQEN); +} + +/* Check if MSI is supported */ +static inline bool smmu_msi_supported(SMMUv3State *s, SMMUSecurityIndex se= c_idx) +{ + return FIELD_EX32(s->bank[sec_idx].idr[0], IDR0, MSI); +} + +/* Check if secure GERROR_IRQ_CFGx registers are writable */ +static inline bool smmu_gerror_irq_cfg_writable(SMMUv3State *s, + SMMUSecurityIndex sec_idx) +{ + if (!smmu_msi_supported(s, SMMU_SEC_IDX_NS)) { + return false; + } + + bool ctrl_en =3D FIELD_EX32(s->bank[sec_idx].irq_ctrl, + IRQ_CTRL, GERROR_IRQEN); + + return !ctrl_en; +} + +/* Check if CMDQEN is disabled */ +static bool smmu_cmdqen_disabled(SMMUv3State *s, SMMUSecurityIndex sec_idx) +{ + int cr0_cmdqen =3D smmuv3_get_cr0_cmdqen(s, sec_idx); + int cr0ack_cmdqen =3D smmuv3_get_cr0ack_cmdqen(s, sec_idx); + return (cr0_cmdqen =3D=3D 0 && cr0ack_cmdqen =3D=3D 0); +} + +/* Check if CMDQ_BASE register is writable */ +static bool smmu_cmdq_base_writable(SMMUv3State *s, SMMUSecurityIndex sec_= idx) +{ + /* Check TABLES_PRESET - use NS bank as it's the global setting */ + if (FIELD_EX32(s->bank[SMMU_SEC_IDX_NS].idr[1], IDR1, QUEUES_PRESET)) { + return false; + } + + return smmu_cmdqen_disabled(s, sec_idx); +} + +/* Check if EVENTQEN is disabled */ +static bool smmu_eventqen_disabled(SMMUv3State *s, SMMUSecurityIndex sec_i= dx) +{ + int cr0_eventqen =3D smmuv3_get_cr0_eventqen(s, sec_idx); + int cr0ack_eventqen =3D smmuv3_get_cr0ack_eventqen(s, sec_idx); + return (cr0_eventqen =3D=3D 0 && cr0ack_eventqen =3D=3D 0); +} + +static bool smmu_idr1_queue_preset(SMMUv3State *s, SMMUSecurityIndex sec_i= dx) +{ + return FIELD_EX32(s->bank[sec_idx].idr[1], IDR1, QUEUES_PRESET); +} + +/* Check if EVENTQ_BASE register is writable */ +static bool smmu_eventq_base_writable(SMMUv3State *s, SMMUSecurityIndex se= c_idx) +{ + /* Check TABLES_PRESET - use NS bank as it's the global setting */ + if (smmu_idr1_queue_preset(s, SMMU_SEC_IDX_NS)) { + return false; + } + + return smmu_eventqen_disabled(s, sec_idx); +} + +static bool smmu_irq_ctl_evtq_irqen_disabled(SMMUv3State *s, + SMMUSecurityIndex sec_idx) +{ + return FIELD_EX32(s->bank[sec_idx].irq_ctrl, IRQ_CTRL, EVENTQ_IRQEN); +} + +/* Check if EVENTQ_IRQ_CFGx is writable */ +static bool smmu_eventq_irq_cfg_writable(SMMUv3State *s, + SMMUSecurityIndex sec_idx) +{ + if (smmu_msi_supported(s, sec_idx)) { + return false; + } + + return smmu_irq_ctl_evtq_irqen_disabled(s, sec_idx); +} + static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUSecurityIndex sec_idx) { SMMUState *bs =3D ARM_SMMU(s); @@ -1405,7 +1513,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUSe= curityIndex sec_idx) break; } =20 - if (queue_read(q, &cmd) !=3D MEMTX_OK) { + if (queue_read(q, &cmd, sec_idx) !=3D MEMTX_OK) { cmd_error =3D SMMU_CERROR_ABT; break; } @@ -1430,8 +1538,11 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUS= ecurityIndex sec_idx) SMMUDevice *sdev =3D smmu_find_sdev(bs, sid); =20 if (CMD_SSEC(&cmd)) { - cmd_error =3D SMMU_CERROR_ILL; - break; + if (sec_idx !=3D SMMU_SEC_IDX_S) { + /* Secure Stream with Non-Secure command */ + cmd_error =3D SMMU_CERROR_ILL; + break; + } } =20 if (!sdev) { @@ -1450,8 +1561,10 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUS= ecurityIndex sec_idx) SMMUSIDRange sid_range; =20 if (CMD_SSEC(&cmd)) { - cmd_error =3D SMMU_CERROR_ILL; - break; + if (sec_idx !=3D SMMU_SEC_IDX_S) { + cmd_error =3D SMMU_CERROR_ILL; + break; + } } =20 mask =3D (1ULL << (range + 1)) - 1; @@ -1469,8 +1582,10 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUS= ecurityIndex sec_idx) SMMUDevice *sdev =3D smmu_find_sdev(bs, sid); =20 if (CMD_SSEC(&cmd)) { - cmd_error =3D SMMU_CERROR_ILL; - break; + if (sec_idx !=3D SMMU_SEC_IDX_S) { + cmd_error =3D SMMU_CERROR_ILL; + break; + } } =20 if (!sdev) { @@ -1624,6 +1739,13 @@ static MemTxResult smmu_writell(SMMUv3State *s, hwad= dr offset, s->bank[reg_sec_idx].strtab_base =3D data & SMMU_STRTAB_BASE_RESER= VED; return MEMTX_OK; case A_CMDQ_BASE: + if (!smmu_cmdq_base_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "CMDQ_BASE write ignored: register is RO\n"); + return MEMTX_OK; + } + + data &=3D SMMU_QUEUE_BASE_RESERVED; s->bank[reg_sec_idx].cmdq.base =3D data; s->bank[reg_sec_idx].cmdq.log2size =3D extract64( s->bank[reg_sec_idx].cmdq.base, 0, 5); @@ -1632,6 +1754,13 @@ static MemTxResult smmu_writell(SMMUv3State *s, hwad= dr offset, } return MEMTX_OK; case A_EVENTQ_BASE: + if (!smmu_eventq_base_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "EVENTQ_BASE write ignored: register is RO\n"); + return MEMTX_OK; + } + + data &=3D SMMU_QUEUE_BASE_RESERVED; s->bank[reg_sec_idx].eventq.base =3D data; s->bank[reg_sec_idx].eventq.log2size =3D extract64( s->bank[reg_sec_idx].eventq.base, 0, 5); @@ -1640,8 +1769,25 @@ static MemTxResult smmu_writell(SMMUv3State *s, hwad= dr offset, } return MEMTX_OK; case A_EVENTQ_IRQ_CFG0: + if (!smmu_eventq_irq_cfg_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "EVENTQ_IRQ_CFG0 write ignored: register is RO\n= "); + return MEMTX_OK; + } + + data &=3D SMMU_EVENTQ_IRQ_CFG0_RESERVED; s->bank[reg_sec_idx].eventq_irq_cfg0 =3D data; return MEMTX_OK; + case A_GERROR_IRQ_CFG0: + if (!smmu_gerror_irq_cfg_writable(s, reg_sec_idx)) { + /* SMMU_(*_)_IRQ_CTRL.GERROR_IRQEN =3D=3D 1: IGNORED this writ= e */ + qemu_log_mask(LOG_GUEST_ERROR, "GERROR_IRQ_CFG0 write ignored:= " + "register is RO when IRQ enabled\n"); + return MEMTX_OK; + } + s->bank[reg_sec_idx].gerror_irq_cfg0 =3D + data & SMMU_GERROR_IRQ_CFG0_RESERVED; + return MEMTX_OK; default: qemu_log_mask(LOG_UNIMP, "%s Unexpected 64-bit access to 0x%"PRIx64" (WI)\n", @@ -1666,7 +1812,15 @@ static MemTxResult smmu_writel(SMMUv3State *s, hwadd= r offset, s->bank[reg_sec_idx].cr[1] =3D data; return MEMTX_OK; case A_CR2: - s->bank[reg_sec_idx].cr[2] =3D data; + if (smmuv3_is_smmu_enabled(s, reg_sec_idx)) { + /* Allow write: SMMUEN is 0 in both CR0 and CR0ACK */ + s->bank[reg_sec_idx].cr[2] =3D data; + } else { + /* CONSTRAINED UNPREDICTABLE behavior: Ignore this write */ + qemu_log_mask(LOG_GUEST_ERROR, + "CR2 write ignored: register is read-only when " + "CR0.SMMUEN or CR0ACK.SMMUEN is set\n"); + } return MEMTX_OK; case A_IRQ_CTRL: s->bank[reg_sec_idx].irq_ctrl =3D data; @@ -1680,14 +1834,28 @@ static MemTxResult smmu_writel(SMMUv3State *s, hwad= dr offset, smmuv3_cmdq_consume(s, reg_sec_idx); return MEMTX_OK; case A_GERROR_IRQ_CFG0: /* 64b */ - s->bank[reg_sec_idx].gerror_irq_cfg0 =3D - deposit64(s->bank[reg_sec_idx].gerror_irq_cfg0, 0, 32, data); - return MEMTX_OK; case A_GERROR_IRQ_CFG0 + 4: - s->bank[reg_sec_idx].gerror_irq_cfg0 =3D - deposit64(s->bank[reg_sec_idx].gerror_irq_cfg0, 32, 32, data); + if (!smmu_gerror_irq_cfg_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, "GERROR_IRQ_CFG0 write ignored:= " + "register is RO when IRQ enabled\n"); + return MEMTX_OK; + } + + data &=3D SMMU_GERROR_IRQ_CFG0_RESERVED; + if (reg_offset =3D=3D A_GERROR_IRQ_CFG0) { + s->bank[reg_sec_idx].gerror_irq_cfg0 =3D deposit64( + s->bank[reg_sec_idx].gerror_irq_cfg0, 0, 32, data); + } else { + s->bank[reg_sec_idx].gerror_irq_cfg0 =3D deposit64( + s->bank[reg_sec_idx].gerror_irq_cfg0, 32, 32, data); + } return MEMTX_OK; case A_GERROR_IRQ_CFG1: + if (!smmu_gerror_irq_cfg_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, "GERROR_IRQ_CFG1 write ignored:= " + "register is RO when IRQ enabled\n"); + return MEMTX_OK; + } s->bank[reg_sec_idx].gerror_irq_cfg1 =3D data; return MEMTX_OK; case A_GERROR_IRQ_CFG2: @@ -1735,60 +1903,106 @@ static MemTxResult smmu_writel(SMMUv3State *s, hwa= ddr offset, } return MEMTX_OK; case A_CMDQ_BASE: /* 64b */ - s->bank[reg_sec_idx].cmdq.base =3D - deposit64(s->bank[reg_sec_idx].cmdq.base, 0, 32, data); - s->bank[reg_sec_idx].cmdq.log2size =3D - extract64(s->bank[reg_sec_idx].cmdq.base, 0, 5); - if (s->bank[reg_sec_idx].cmdq.log2size > SMMU_CMDQS) { - s->bank[reg_sec_idx].cmdq.log2size =3D SMMU_CMDQS; - } - return MEMTX_OK; case A_CMDQ_BASE + 4: /* 64b */ - s->bank[reg_sec_idx].cmdq.base =3D - deposit64(s->bank[reg_sec_idx].cmdq.base, 32, 32, data); - return MEMTX_OK; + if (!smmu_cmdq_base_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "CMDQ_BASE write ignored: register is RO\n"); + return MEMTX_OK; + } + + data &=3D SMMU_QUEUE_BASE_RESERVED; + if (reg_offset =3D=3D A_CMDQ_BASE) { + s->bank[reg_sec_idx].cmdq.base =3D deposit64( + s->bank[reg_sec_idx].cmdq.base, 0, 32, data); + + s->bank[reg_sec_idx].cmdq.log2size =3D extract64( + s->bank[reg_sec_idx].cmdq.base, 0, 5); + if (s->bank[reg_sec_idx].cmdq.log2size > SMMU_CMDQS) { + s->bank[reg_sec_idx].cmdq.log2size =3D SMMU_CMDQS; + } + } else { + s->bank[reg_sec_idx].cmdq.base =3D deposit64( + s->bank[reg_sec_idx].cmdq.base, 32, 32, data); + } + return MEMTX_OK; case A_CMDQ_PROD: s->bank[reg_sec_idx].cmdq.prod =3D data; smmuv3_cmdq_consume(s, reg_sec_idx); return MEMTX_OK; case A_CMDQ_CONS: + if (!smmu_cmdqen_disabled(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "CMDQ_CONS write ignored: register is RO\n"); + return MEMTX_OK; + } s->bank[reg_sec_idx].cmdq.cons =3D data; return MEMTX_OK; case A_EVENTQ_BASE: /* 64b */ - s->bank[reg_sec_idx].eventq.base =3D - deposit64(s->bank[reg_sec_idx].eventq.base, 0, 32, data); - s->bank[reg_sec_idx].eventq.log2size =3D - extract64(s->bank[reg_sec_idx].eventq.base, 0, 5); - if (s->bank[reg_sec_idx].eventq.log2size > SMMU_EVENTQS) { - s->bank[reg_sec_idx].eventq.log2size =3D SMMU_EVENTQS; - } - s->bank[reg_sec_idx].eventq.cons =3D data; - return MEMTX_OK; case A_EVENTQ_BASE + 4: - s->bank[reg_sec_idx].eventq.base =3D - deposit64(s->bank[reg_sec_idx].eventq.base, 32, 32, data); - return MEMTX_OK; + if (!smmu_eventq_base_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "EVENTQ_BASE write ignored: register is RO\n"); + return MEMTX_OK; + } + + data &=3D SMMU_QUEUE_BASE_RESERVED; + if (reg_offset =3D=3D A_EVENTQ_BASE) { + s->bank[reg_sec_idx].eventq.base =3D deposit64( + s->bank[reg_sec_idx].eventq.base, 0, 32, data); + + s->bank[reg_sec_idx].eventq.log2size =3D extract64( + s->bank[reg_sec_idx].eventq.base, 0, 5); + if (s->bank[reg_sec_idx].eventq.log2size > SMMU_EVENTQS) { + s->bank[reg_sec_idx].eventq.log2size =3D SMMU_EVENTQS; + } + } else { + s->bank[reg_sec_idx].eventq.base =3D deposit64( + s->bank[reg_sec_idx].eventq.base, 32, 32, data); + } return MEMTX_OK; case A_EVENTQ_PROD: + if (!smmu_eventqen_disabled(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "EVENTQ_PROD write ignored: register is RO\n"); + return MEMTX_OK; + } s->bank[reg_sec_idx].eventq.prod =3D data; return MEMTX_OK; case A_EVENTQ_CONS: s->bank[reg_sec_idx].eventq.cons =3D data; return MEMTX_OK; case A_EVENTQ_IRQ_CFG0: /* 64b */ - s->bank[reg_sec_idx].eventq_irq_cfg0 =3D - deposit64(s->bank[reg_sec_idx].eventq_irq_cfg0, 0, 32, data); - return MEMTX_OK; case A_EVENTQ_IRQ_CFG0 + 4: - s->bank[reg_sec_idx].eventq_irq_cfg0 =3D - deposit64(s->bank[reg_sec_idx].eventq_irq_cfg0, 32, 32, data); - return MEMTX_OK; + if (!smmu_eventq_irq_cfg_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "EVENTQ_IRQ_CFG0 write ignored: register is RO\n= "); + return MEMTX_OK; + } + + data &=3D SMMU_EVENTQ_IRQ_CFG0_RESERVED; + if (reg_offset =3D=3D A_EVENTQ_IRQ_CFG0) { + s->bank[reg_sec_idx].eventq_irq_cfg0 =3D deposit64( + s->bank[reg_sec_idx].eventq_irq_cfg0, 0, 32, data); + } else { + s->bank[reg_sec_idx].eventq_irq_cfg0 =3D deposit64( + s->bank[reg_sec_idx].eventq_irq_cfg0, 32, 32, data); + } return MEMTX_OK; case A_EVENTQ_IRQ_CFG1: + if (!smmu_eventq_irq_cfg_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "EVENTQ_IRQ_CFG1 write ignored: register is RO\n= "); + return MEMTX_OK; + } s->bank[reg_sec_idx].eventq_irq_cfg1 =3D data; return MEMTX_OK; case A_EVENTQ_IRQ_CFG2: + if (!smmu_eventq_irq_cfg_writable(s, reg_sec_idx)) { + qemu_log_mask(LOG_GUEST_ERROR, + "EVENTQ_IRQ_CFG2 write ignored: register is RO\n= "); + return MEMTX_OK; + } s->bank[reg_sec_idx].eventq_irq_cfg2 =3D data; return MEMTX_OK; case A_S_INIT_ALIAS: @@ -1848,6 +2062,11 @@ static MemTxResult smmu_readll(SMMUv3State *s, hwadd= r offset, uint32_t reg_offset =3D offset & 0xfff; switch (reg_offset) { case A_GERROR_IRQ_CFG0: + /* SMMU_(*_)GERROR_IRQ_CFG0 BOTH check SMMU_IDR0.MSI */ + if (!smmu_msi_supported(s, SMMU_SEC_IDX_NS)) { + *data =3D 0; /* RES0 */ + return MEMTX_OK; + } *data =3D s->bank[reg_sec_idx].gerror_irq_cfg0; return MEMTX_OK; case A_STRTAB_BASE: @@ -1859,6 +2078,13 @@ static MemTxResult smmu_readll(SMMUv3State *s, hwadd= r offset, case A_EVENTQ_BASE: *data =3D s->bank[reg_sec_idx].eventq.base; return MEMTX_OK; + case A_EVENTQ_IRQ_CFG0: + /* MSI support is depends on the register's security domain */ + if (!smmu_msi_supported(s, reg_sec_idx)) { + *data =3D 0; + return MEMTX_OK; + } + *data =3D s->bank[reg_sec_idx].eventq_irq_cfg0; return MEMTX_OK; default: @@ -1917,16 +2143,31 @@ static MemTxResult smmu_readl(SMMUv3State *s, hwadd= r offset, *data =3D s->bank[reg_sec_idx].gerrorn; return MEMTX_OK; case A_GERROR_IRQ_CFG0: /* 64b */ - *data =3D extract64(s->bank[reg_sec_idx].gerror_irq_cfg0, 0, 32); - return MEMTX_OK; case A_GERROR_IRQ_CFG0 + 4: - *data =3D extract64(s->bank[reg_sec_idx].gerror_irq_cfg0, 32, 32); - return MEMTX_OK; + /* SMMU_(*_)GERROR_IRQ_CFG0 BOTH check SMMU_IDR0.MSI */ + if (!smmu_msi_supported(s, SMMU_SEC_IDX_NS)) { + *data =3D 0; /* RES0 */ + return MEMTX_OK; + } + + if (reg_offset =3D=3D A_GERROR_IRQ_CFG0) { + *data =3D extract64(s->bank[reg_sec_idx].gerror_irq_cfg0, 0, 3= 2); + } else { + *data =3D extract64(s->bank[reg_sec_idx].gerror_irq_cfg0, 32, = 32); + } return MEMTX_OK; case A_GERROR_IRQ_CFG1: + if (!smmu_msi_supported(s, SMMU_SEC_IDX_NS)) { + *data =3D 0; /* RES0 */ + return MEMTX_OK; + } *data =3D s->bank[reg_sec_idx].gerror_irq_cfg1; return MEMTX_OK; case A_GERROR_IRQ_CFG2: + if (!smmu_msi_supported(s, SMMU_SEC_IDX_NS)) { + *data =3D 0; /* RES0 */ + return MEMTX_OK; + } *data =3D s->bank[reg_sec_idx].gerror_irq_cfg2; return MEMTX_OK; case A_STRTAB_BASE: /* 64b */ @@ -1962,6 +2203,33 @@ static MemTxResult smmu_readl(SMMUv3State *s, hwaddr= offset, case A_EVENTQ_CONS: *data =3D s->bank[reg_sec_idx].eventq.cons; return MEMTX_OK; + case A_EVENTQ_IRQ_CFG0: + case A_EVENTQ_IRQ_CFG0 + 4: + if (!smmu_msi_supported(s, reg_sec_idx)) { + *data =3D 0; + return MEMTX_OK; + } + + if (reg_offset =3D=3D A_EVENTQ_IRQ_CFG0) { + *data =3D extract64(s->bank[reg_sec_idx].eventq_irq_cfg0, 0, 3= 2); + } else { + *data =3D extract64(s->bank[reg_sec_idx].eventq_irq_cfg0, 32, = 32); + } + return MEMTX_OK; + case A_EVENTQ_IRQ_CFG1: + if (!smmu_msi_supported(s, reg_sec_idx)) { + *data =3D 0; + return MEMTX_OK; + } + *data =3D s->bank[reg_sec_idx].eventq_irq_cfg1; + return MEMTX_OK; + case A_EVENTQ_IRQ_CFG2: + if (!smmu_msi_supported(s, reg_sec_idx)) { + *data =3D 0; + return MEMTX_OK; + } + *data =3D s->bank[reg_sec_idx].eventq_irq_cfg2; + return MEMTX_OK; case A_S_INIT_ALIAS: *data =3D 0; return MEMTX_OK; --=20 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758817795848893.702467850711; Thu, 25 Sep 2025 09:29:55 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1oov-00074T-MH; Thu, 25 Sep 2025 12:27:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1ooF-0006U8-5Z; Thu, 25 Sep 2025 12:27:07 -0400 Received: from zg8tmtyylji0my4xnjqumte4.icoremail.net ([162.243.164.118]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1ons-0004mc-J1; Thu, 25 Sep 2025 12:27:04 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-7 (Coremail) with SMTP id AQAAfwAXHbU7bdVopAo6CQ--.561S2; Fri, 26 Sep 2025 00:26:35 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwDHLestbdVoW_MeAA--.7120S14; Fri, 26 Sep 2025 00:26:32 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , pierrick.bouvier@linaro.org, philmd@linaro.org, jean-philippe@linaro.org, smostafa@google.com, Tao Tang Subject: [PATCH v2 11/14] hw/arm/smmuv3: Harden security checks in MMIO handlers Date: Fri, 26 Sep 2025 00:26:15 +0800 Message-Id: <20250925162618.191242-12-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwDHLestbdVoW_MeAA--.7120S14 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAEBWjUSMIHwwAAsy Authentication-Results: hzbj-icmmx-7; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvJXoWxGFykuF15Gw4xWrW5AFWfAFb_yoWrXF18pr WvgryYgr4DGF13Xan3Jw1kCF1FkrWkWF9rGrZxGrW8Za4UJ3yrJ3W8Aa45Ka4DGFyUAws7 JFyfAF4fWF12y3DanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj DUYxn0WfASr-VFAU7a7-sFnT9fnUUIcSsGvfJ3UbIYCTnIWIevJa73UjIFyTuYvj4RJUUU UUUUU 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=lists.gnu.org; Received-SPF: pass client-ip=162.243.164.118; envelope-from=tangtao1634@phytium.com.cn; helo=zg8tmtyylji0my4xnjqumte4.icoremail.net X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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: 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-ZM-MESSAGEID: 1758817798434116600 Content-Type: text/plain; charset="utf-8" This patch hardens the security validation within the main MMIO dispatcher functions (smmu_read_mmio and smmu_write_mmio). First, accesses to the secure register space are now correctly gated by whether the SECURE_IMPL feature is enabled in the model. This prevents guest software from accessing the secure programming interface when it is disabled, though some registers are exempt from this check as per the architecture. Second, the check for the input stream's security is made more robust. It now validates not only the legacy MemTxAttrs.secure bit, but also the .space field. This brings the SMMU's handling of security spaces into full alignment with the PE. Signed-off-by: Tao Tang --- hw/arm/smmuv3.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 53c7eff0e3..eec36d5fd2 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -1484,6 +1484,12 @@ static bool smmu_eventq_irq_cfg_writable(SMMUv3State= *s, return smmu_irq_ctl_evtq_irqen_disabled(s, sec_idx); } =20 +/* Check if the SMMU hardware itself implements secure state features */ +static inline bool smmu_hw_secure_implemented(SMMUv3State *s) +{ + return FIELD_EX32(s->bank[SMMU_SEC_IDX_S].idr[1], S_IDR1, SECURE_IMPL); +} + static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUSecurityIndex sec_idx) { SMMUState *bs =3D ARM_SMMU(s); @@ -1723,6 +1729,43 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUS= ecurityIndex sec_idx) return 0; } =20 +static bool is_secure_impl_exempt_reg(hwaddr offset) +{ + switch (offset) { + case A_S_EVENTQ_IRQ_CFG0: + case A_S_EVENTQ_IRQ_CFG1: + case A_S_EVENTQ_IRQ_CFG2: + return true; + default: + return false; + } +} + +/* Helper function for Secure register access validation */ +static bool smmu_check_secure_access(SMMUv3State *s, MemTxAttrs attrs, + hwaddr offset, bool is_read) +{ /* Check if the access is secure */ + if (!(attrs.space =3D=3D ARMSS_Secure || attrs.space =3D=3D ARMSS_Root= || + attrs.secure =3D=3D 1)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Non-secure %s attempt at offset 0x%" PRIx64 " (%s)\n", + __func__, is_read ? "read" : "write", offset, + is_read ? "RAZ" : "WI"); + return false; + } + + /* Check if the secure state is implemented. Some registers are exempt= ed */ + /* from this check. */ + if (!is_secure_impl_exempt_reg(offset) && !smmu_hw_secure_implemented(= s)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Secure %s attempt at offset 0x%" PRIx64 ". But Secure sta= te " + "is not implemented (RES0)\n", + __func__, is_read ? "read" : "write", offset); + return false; + } + return true; +} + static MemTxResult smmu_writell(SMMUv3State *s, hwaddr offset, uint64_t data, MemTxAttrs attrs, SMMUSecurityIndex reg_sec_idx) @@ -2038,6 +2081,13 @@ static MemTxResult smmu_write_mmio(void *opaque, hwa= ddr offset, uint64_t data, /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */ offset &=3D ~0x10000; SMMUSecurityIndex reg_sec_idx =3D SMMU_SEC_IDX_NS; + if (offset >=3D SMMU_SECURE_BASE_OFFSET) { + if (!smmu_check_secure_access(s, attrs, offset, false)) { + trace_smmuv3_write_mmio(offset, data, size, MEMTX_OK); + return MEMTX_OK; + } + reg_sec_idx =3D SMMU_SEC_IDX_S; + } =20 switch (size) { case 8: @@ -2252,6 +2302,14 @@ static MemTxResult smmu_read_mmio(void *opaque, hwad= dr offset, uint64_t *data, /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */ offset &=3D ~0x10000; SMMUSecurityIndex reg_sec_idx =3D SMMU_SEC_IDX_NS; + if (offset >=3D SMMU_SECURE_BASE_OFFSET) { + if (!smmu_check_secure_access(s, attrs, offset, true)) { + *data =3D 0; + trace_smmuv3_read_mmio(offset, *data, size, MEMTX_OK); + return MEMTX_OK; + } + reg_sec_idx =3D SMMU_SEC_IDX_S; + } =20 switch (size) { case 8: --=20 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758856311001518.8410437662534; Thu, 25 Sep 2025 20:11:51 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1yq4-0006Su-Dd; Thu, 25 Sep 2025 23:09:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1yq1-0006Pl-5u; Thu, 25 Sep 2025 23:09:37 -0400 Received: from zg8tmtyylji0my4xnjqumte4.icoremail.net ([162.243.164.118]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1ypr-0003ir-AR; Thu, 25 Sep 2025 23:09:35 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-6 (Coremail) with SMTP id AQAAfwBX7mHPA9Zomkp8Bw--.7124S2; Fri, 26 Sep 2025 11:09:03 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwBXu+jKA9Zoee4gAA--.9761S3; Fri, 26 Sep 2025 11:08:58 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , Pierrick Bouvier , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Jean-Philippe Brucker , Mostafa Saleh , Tao Tang Subject: [PATCH v2 12/14] hw/arm/smmuv3: Use iommu_index to represent the security context Date: Fri, 26 Sep 2025 11:08:29 +0800 Message-Id: <20250926030831.1067440-1-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwBXu+jKA9Zoee4gAA--.9761S3 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAEBWjUSMIH0QAGsm Authentication-Results: hzbj-icmmx-6; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvJXoWxCr4Utr47Jw4fAw1DCr4kZwb_yoW5KF1fpF 4kGFZ5Kw4fJF13Ar1fJa1kZF4a93ykGFW7XFZxKws5Ar1kZr97XryvkFyYgryUCFWUCw42 qa10krWDW3WqyrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj DUYxn0WfASr-VFAU7a7-sFnT9fnUUIcSsGvfJ3UbIYCTnIWIevJa73UjIFyTuYvj4RJUUU UUUUU 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=lists.gnu.org; Received-SPF: pass client-ip=162.243.164.118; envelope-from=tangtao1634@phytium.com.cn; helo=zg8tmtyylji0my4xnjqumte4.icoremail.net X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 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: 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-ZM-MESSAGEID: 1758856315478116600 Resending patches 12=E2=80=9314/14 that were missing due to a send issue. S= orry for the noise. The Arm SMMUv3 architecture uses a SEC_SID (Secure StreamID) to select the programming interface. To support future extensions like RME, which defines four security states (Non-secure, Secure, Realm, and Root), the QEMU model must cleanly separate these contexts for all operations. This commit leverages the generic iommu_index to represent this security context. The core IOMMU layer now uses the SMMU's .attrs_to_index callback to map a transaction's ARMSecuritySpace attribute to the corresponding iommu_index. This index is then passed down to smmuv3_translate and used throughout the model to select the correct register bank and processing logic. This makes the iommu_index the clear QEMU equivalent of the architectural SEC_SID, cleanly separating the contexts for all subsequent lookups. Signed-off-by: Tao Tang --- hw/arm/smmuv3.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index eec36d5fd2..c92cc0f06a 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -1099,6 +1099,38 @@ static void smmuv3_fixup_event(SMMUEventInfo *event,= hwaddr iova) } } +static SMMUSecurityIndex smmuv3_attrs_to_security_index(MemTxAttrs attrs) +{ + switch (attrs.space) { + case ARMSS_Secure: + return SMMU_SEC_IDX_S; + case ARMSS_NonSecure: + default: + return SMMU_SEC_IDX_NS; + } +} + +/* + * ARM SMMU IOMMU index mapping (implements SEC_SID from ARM SMMU): + * iommu_idx =3D 0: Non-secure transactions + * iommu_idx =3D 1: Secure transactions + * + * The iommu_idx parameter effectively implements the SEC_SID + * (Security Stream ID) attribute from the ARM SMMU architecture + * specification, which allows the SMMU to differentiate between + * secure and non-secure transactions at the hardware level. + */ +static int smmuv3_attrs_to_index(IOMMUMemoryRegion *iommu, MemTxAttrs attr= s) +{ + return smmuv3_attrs_to_security_index(attrs); +} + +static int smmuv3_num_indexes(IOMMUMemoryRegion *iommu) +{ + /* Support 2 IOMMU indexes for now: NS/S */ + return SMMU_SEC_IDX_NUM; +} + /* Entry point to SMMU, does everything. */ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, IOMMUAccessFlags flag, int iommu_idx) @@ -1111,7 +1143,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegi= on *mr, hwaddr addr, .inval_ste_allowed =3D false}; SMMUTranslationStatus status; SMMUTransCfg *cfg =3D NULL; - SMMUSecurityIndex sec_idx =3D SMMU_SEC_IDX_NS; + SMMUSecurityIndex sec_idx =3D iommu_idx; IOMMUTLBEntry entry =3D { .target_as =3D &address_space_memory, .iova =3D addr, @@ -1155,6 +1187,7 @@ epilogue: entry.perm =3D cached_entry->entry.perm; entry.translated_addr =3D CACHED_ENTRY_TO_ADDR(cached_entry, addr); entry.addr_mask =3D cached_entry->entry.addr_mask; + entry.target_as =3D cached_entry->entry.target_as; trace_smmuv3_translate_success(mr->parent_obj.name, sid, addr, entry.translated_addr, entry.perm, cfg->stage); @@ -2534,6 +2567,8 @@ static void smmuv3_iommu_memory_region_class_init(Obj= ectClass *klass, imrc->translate =3D smmuv3_translate; imrc->notify_flag_changed =3D smmuv3_notify_flag_changed; + imrc->attrs_to_index =3D smmuv3_attrs_to_index; + imrc->num_indexes =3D smmuv3_num_indexes; } static const TypeInfo smmuv3_type_info =3D { -- 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758857180734176.2202620454418; Thu, 25 Sep 2025 20:26:20 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1z4W-0002jo-Cc; Thu, 25 Sep 2025 23:24:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1z4T-0002jP-Cw; Thu, 25 Sep 2025 23:24:33 -0400 Received: from sgoci-sdnproxy-4.icoremail.net ([129.150.39.64]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1z4C-0005Tl-T9; Thu, 25 Sep 2025 23:24:33 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-6 (Coremail) with SMTP id AQAAfwAnvWBNB9Zo9lt8Bw--.5833S2; Fri, 26 Sep 2025 11:23:57 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwAHa+hBB9Zoe_wgAA--.9731S3; Fri, 26 Sep 2025 11:23:45 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , Pierrick Bouvier , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Jean-Philippe Brucker , Mostafa Saleh , Tao Tang Subject: [PATCH v2 13/14] hw/arm/smmuv3: Add property to enable Secure SMMU support Date: Fri, 26 Sep 2025 11:23:39 +0800 Message-Id: <20250926032339.1089647-1-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwAHa+hBB9Zoe_wgAA--.9731S3 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAFBWjVmkcBvQAAsd Authentication-Results: hzbj-icmmx-6; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvJXoW7KrWktFyDKr15WFyDGFyDKFg_yoW5JFy5pF s3Ar1rKr45u3WfJay7Za18Zay2v3yvq3ZxurW8C3Wru3WDAryDXr4vkr48Ga98Xw1Yya1x WF48uF48CF42vrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj DUYxn0WfASr-VFAU7a7-sFnT9fnUUIcSsGvfJ3UbIYCTnIWIevJa73UjIFyTuYvj4RJUUU UUUUU 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=lists.gnu.org; Received-SPF: pass client-ip=129.150.39.64; envelope-from=tangtao1634@phytium.com.cn; helo=sgoci-sdnproxy-4.icoremail.net X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 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: 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-ZM-MESSAGEID: 1758857182413116600 Content-Type: text/plain; charset="utf-8" My apologies, resending patches 13-14/14 to fix a threading mistake from my previous attempt. This commit completes the initial implementation of the Secure SMMUv3 model by making the feature user-configurable. A new boolean property, "secure-impl", is introduced to the device. This property defaults to false, ensuring backward compatibility for existing machine types that do not expect the secure programming interface. When "secure-impl" is set to true, the smmuv3_init_regs function now initializes the secure register bank (bank[SMMU_SEC_IDX_S]). Crucially, the S_IDR1.SECURE_IMPL bit is set according to this property, correctly advertising the presence of the secure functionality to the guest. This patch ties together all the previous refactoring work. With this property enabled, the banked registers, security-aware queues, and other secure features become active, allowing a guest to probe and configure the Secure SMMU. Signed-off-by: Tao Tang --- hw/arm/smmuv3.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index c92cc0f06a..80fbc25cf5 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -351,6 +351,16 @@ static void smmuv3_init_regs(SMMUv3State *s) s->statusr =3D 0; s->bank[SMMU_SEC_IDX_NS].gbpa =3D SMMU_GBPA_RESET_VAL; + /* Initialize Secure bank (SMMU_SEC_IDX_S) */ + memset(s->bank[SMMU_SEC_IDX_S].idr, 0, sizeof(s->bank[SMMU_SEC_IDX_S].= idr)); + s->bank[SMMU_SEC_IDX_S].idr[1] =3D FIELD_DP32(s->bank[SMMU_SEC_IDX_S].= idr[1], + S_IDR1, SECURE_IMPL, + s->secure_impl); + s->bank[SMMU_SEC_IDX_S].idr[1] =3D FIELD_DP32( + s->bank[SMMU_SEC_IDX_S].idr[1], IDR1, SIDSIZE, SMMU_IDR1_SIDSIZE); + s->bank[SMMU_SEC_IDX_S].gbpa =3D SMMU_GBPA_RESET_VAL; + s->bank[SMMU_SEC_IDX_S].cmdq.entry_size =3D sizeof(struct Cmd); + s->bank[SMMU_SEC_IDX_S].eventq.entry_size =3D sizeof(struct Evt); } static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf, @@ -2505,6 +2515,12 @@ static const Property smmuv3_properties[] =3D { * Defaults to stage 1 */ DEFINE_PROP_STRING("stage", SMMUv3State, stage), + /* + * SECURE_IMPL field in S_IDR1 register. + * Indicates whether secure state is implemented. + * Defaults to false (0) + */ + DEFINE_PROP_BOOL("secure-impl", SMMUv3State, secure_impl, false), }; static void smmuv3_instance_init(Object *obj) -- 2.34.1 From nobody Sun Sep 28 16:32:16 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 175885755122725.08968242307685; Thu, 25 Sep 2025 20:32:31 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1zAf-00054u-Jt; Thu, 25 Sep 2025 23:30:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v1zAc-000532-DL; Thu, 25 Sep 2025 23:30:54 -0400 Received: from zg8tmja5ljk3lje4ms43mwaa.icoremail.net ([209.97.181.73]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v1zAH-0006r4-7m; Thu, 25 Sep 2025 23:30:43 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-7 (Coremail) with SMTP id AQAAfwAXWWzKCNZokH0_CQ--.1S2; Fri, 26 Sep 2025 11:30:18 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAfwB32ufGCNZoBAAhAA--.9828S3; Fri, 26 Sep 2025 11:30:14 +0800 (CST) From: Tao Tang To: Eric Auger , Peter Maydell Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Chen Baozi , Pierrick Bouvier , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Jean-Philippe Brucker , Mostafa Saleh , Tao Tang Subject: [PATCH v2 14/14] hw/arm/smmuv3: Optional Secure bank migration via subsections Date: Fri, 26 Sep 2025 11:30:13 +0800 Message-Id: <20250926033013.1099304-1-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250925162618.191242-1-tangtao1634@phytium.com.cn> References: <20250925162618.191242-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAfwB32ufGCNZoBAAhAA--.9828S3 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAFBWjVmkcBzQAAst Authentication-Results: hzbj-icmmx-7; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvJXoWxWF45uw4xXFy8Jw48Ww1kAFb_yoWruw4kpr s8G3Z8GryDGF4fZr4fJw4rCFs8CrWrGF4akrWDCa93ta1kJay2qrnFyFW8u3s5JrWjqa17 uF1xuFZrJr47ArJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj DUYxn0WfASr-VFAU7a7-sFnT9fnUUIcSsGvfJ3UbIYCTnIWIevJa73UjIFyTuYvj4RJUUU UUUUU 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=lists.gnu.org; Received-SPF: pass client-ip=209.97.181.73; envelope-from=tangtao1634@phytium.com.cn; helo=zg8tmja5ljk3lje4ms43mwaa.icoremail.net X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 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: 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-ZM-MESSAGEID: 1758857553830116600 Content-Type: text/plain; charset="utf-8" My apologies, resending patches 13-14/14 to fix a threading mistake from my previous attempt. Introduce a generic vmstate_smmuv3_bank that serializes a single SMMUv3 bank (registers and queues). Add a 'smmuv3/bank_s' subsection guarded by secure_impl and a new 'migrate-secure-bank' property; when enabled, the S bank is migrated. Add a 'smmuv3/gbpa_secure' subsection which is only sent when GBPA differs from its reset value. This keeps the existing migration stream unchanged by default and remains backward compatible: older QEMUs can ignore unknown subsections, and with 'migrate-secure-bank' defaulting to off, the stream is identical to before. This also prepares for future RME extensions (Realm/Root) by reusing the bank subsection pattern. Usage: -global arm-smmuv3,secure-impl=3Don,migrate-secure-bank=3Don Signed-off-by: Tao Tang --- hw/arm/smmuv3.c | 70 +++++++++++++++++++++++++++++++++++++++++ include/hw/arm/smmuv3.h | 1 + 2 files changed, 71 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 80fbc25cf5..2a1e80d179 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -2450,6 +2450,53 @@ static const VMStateDescription vmstate_smmuv3_queue= =3D { }, }; +static const VMStateDescription vmstate_smmuv3_bank =3D { + .name =3D "smmuv3_bank", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT32(features, SMMUv3RegBank), + VMSTATE_UINT8(sid_split, SMMUv3RegBank), + VMSTATE_UINT32_ARRAY(cr, SMMUv3RegBank, 3), + VMSTATE_UINT32(cr0ack, SMMUv3RegBank), + VMSTATE_UINT32(irq_ctrl, SMMUv3RegBank), + VMSTATE_UINT32(gerror, SMMUv3RegBank), + VMSTATE_UINT32(gerrorn, SMMUv3RegBank), + VMSTATE_UINT64(gerror_irq_cfg0, SMMUv3RegBank), + VMSTATE_UINT32(gerror_irq_cfg1, SMMUv3RegBank), + VMSTATE_UINT32(gerror_irq_cfg2, SMMUv3RegBank), + VMSTATE_UINT64(strtab_base, SMMUv3RegBank), + VMSTATE_UINT32(strtab_base_cfg, SMMUv3RegBank), + VMSTATE_UINT64(eventq_irq_cfg0, SMMUv3RegBank), + VMSTATE_UINT32(eventq_irq_cfg1, SMMUv3RegBank), + VMSTATE_UINT32(eventq_irq_cfg2, SMMUv3RegBank), + VMSTATE_STRUCT(cmdq, SMMUv3RegBank, 0, + vmstate_smmuv3_queue, SMMUQueue), + VMSTATE_STRUCT(eventq, SMMUv3RegBank, 0, + vmstate_smmuv3_queue, SMMUQueue), + VMSTATE_END_OF_LIST(), + }, +}; + +static bool smmuv3_secure_bank_needed(void *opaque) +{ + SMMUv3State *s =3D opaque; + + return s->secure_impl && s->migrate_secure_bank; +} + +static const VMStateDescription vmstate_smmuv3_bank_s =3D { + .name =3D "smmuv3/bank_s", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D smmuv3_secure_bank_needed, + .fields =3D (const VMStateField[]) { + VMSTATE_STRUCT(bank[SMMU_SEC_IDX_S], SMMUv3State, 0, + vmstate_smmuv3_bank, SMMUv3RegBank), + VMSTATE_END_OF_LIST(), + }, +}; + static bool smmuv3_gbpa_needed(void *opaque) { SMMUv3State *s =3D opaque; @@ -2469,6 +2516,25 @@ static const VMStateDescription vmstate_gbpa =3D { } }; +static bool smmuv3_gbpa_secure_needed(void *opaque) +{ + SMMUv3State *s =3D opaque; + + return s->secure_impl && s->migrate_secure_bank && + s->bank[SMMU_SEC_IDX_S].gbpa !=3D SMMU_GBPA_RESET_VAL; +} + +static const VMStateDescription vmstate_gbpa_secure =3D { + .name =3D "smmuv3/gbpa_secure", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D smmuv3_gbpa_secure_needed, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT32(bank[SMMU_SEC_IDX_S].gbpa, SMMUv3State), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_smmuv3 =3D { .name =3D "smmuv3", .version_id =3D 1, @@ -2502,6 +2568,8 @@ static const VMStateDescription vmstate_smmuv3 =3D { }, .subsections =3D (const VMStateDescription * const []) { &vmstate_gbpa, + &vmstate_smmuv3_bank_s, + &vmstate_gbpa_secure, NULL } }; @@ -2521,6 +2589,8 @@ static const Property smmuv3_properties[] =3D { * Defaults to false (0) */ DEFINE_PROP_BOOL("secure-impl", SMMUv3State, secure_impl, false), + DEFINE_PROP_BOOL("migrate-secure-bank", SMMUv3State, + migrate_secure_bank, false), }; static void smmuv3_instance_init(Object *obj) diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h index 572f15251e..5ffb609fa2 100644 --- a/include/hw/arm/smmuv3.h +++ b/include/hw/arm/smmuv3.h @@ -71,6 +71,7 @@ struct SMMUv3State { QemuMutex mutex; char *stage; bool secure_impl; + bool migrate_secure_bank; }; typedef enum { -- 2.34.1