From nobody Mon Apr 13 03:43:50 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1771228078182565.6824819440311; Sun, 15 Feb 2026 23:47:58 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1233713.1537072 (Exim 4.92) (envelope-from ) id 1vrtKC-0001SZ-4i; Mon, 16 Feb 2026 07:47:20 +0000 Received: by outflank-mailman (output) from mailman id 1233713.1537072; Mon, 16 Feb 2026 07:47:20 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vrtKC-0001SS-1b; Mon, 16 Feb 2026 07:47:20 +0000 Received: by outflank-mailman (input) for mailman id 1233713; Mon, 16 Feb 2026 07:47:19 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vrtKB-0001SM-AZ for xen-devel@lists.xenproject.org; Mon, 16 Feb 2026 07:47:19 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id b6824cde-0b0b-11f1-b163-2bf370ae4941; Mon, 16 Feb 2026 08:47:16 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 32D9F150C; Sun, 15 Feb 2026 23:47:09 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.56.129]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2849A3F632; Sun, 15 Feb 2026 23:47:14 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: b6824cde-0b0b-11f1-b163-2bf370ae4941 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Stefano Stabellini , Julien Grall , Michal Orzel , Volodymyr Babchuk Subject: [PATCH] xen/arm: smccc: Preserve argument types in v1.1 SMC Date: Mon, 16 Feb 2026 08:47:08 +0100 Message-ID: <0e2ba0af683fa5e53a3d2b4b625703751cf7ce54.1771228001.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.52.0 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1771228081637154100 Content-Type: text/plain; charset="utf-8" The SMCCC v1.1 inline helper currently forces a1-a4 into unsigned long and uses in/out constraints for r0-r3. In contrast, a5-a7 are passed with their original types via read-only constraints. On arm64 this means a 32-bit signed value in a1-a4 is converted to a 64-bit unsigned value, while the same value in a5-a7 keeps its signed 32-bit form. For example, a negative int in a2 is widened to unsigned long, but a negative int in a5 is passed as a 32-bit signed value, so the SMC sees different encodings depending on argument position. Switch the helper to use typed input registers arg0-arg7 derived from the call arguments (keeping a0 cast to u32) and separate output registers r0-r3. This preserves argument types consistently across all positions. Argument evaluation order is unchanged, so we do not reintroduce the issue fixed in "e00dc325bd9e" ("xen/arm: smccc-1.1: Handle function result as parameters"). This also aligns Xen's SMCCC parameter handling with Linux's type- preserving behavior (same externally visible argument handling, independent implementation) to avoid surprising differences between a1-a4 and a5-a7. Current callers (PSCI, SCMI, platform SMC pass-through, OP-TEE, and exynos5) pass unsigned values; exynos5 passes an int CPU id which should always be > 0. Signed-off-by: Bertrand Marquis Reported-by: Andrew ? Reviewed-by: Michal Orzel --- xen/arch/arm/include/asm/smccc.h | 69 +++++++++++++------------------- 1 file changed, 27 insertions(+), 42 deletions(-) diff --git a/xen/arch/arm/include/asm/smccc.h b/xen/arch/arm/include/asm/sm= ccc.h index 441b3ab65dee..5b30dd57b69d 100644 --- a/xen/arch/arm/include/asm/smccc.h +++ b/xen/arch/arm/include/asm/smccc.h @@ -99,87 +99,68 @@ struct arm_smccc_res { #define __count_args(...) \ ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0) =20 -#define __constraint_write_0 \ - "+r" (r0), "=3D&r" (r1), "=3D&r" (r2), "=3D&r" (r3) -#define __constraint_write_1 \ - "+r" (r0), "+r" (r1), "=3D&r" (r2), "=3D&r" (r3) -#define __constraint_write_2 \ - "+r" (r0), "+r" (r1), "+r" (r2), "=3D&r" (r3) -#define __constraint_write_3 \ - "+r" (r0), "+r" (r1), "+r" (r2), "+r" (r3) -#define __constraint_write_4 __constraint_write_3 -#define __constraint_write_5 __constraint_write_4 -#define __constraint_write_6 __constraint_write_5 -#define __constraint_write_7 __constraint_write_6 - -#define __constraint_read_0 -#define __constraint_read_1 -#define __constraint_read_2 -#define __constraint_read_3 -#define __constraint_read_4 "r" (r4) -#define __constraint_read_5 __constraint_read_4, "r" (r5) -#define __constraint_read_6 __constraint_read_5, "r" (r6) -#define __constraint_read_7 __constraint_read_6, "r" (r7) +#define __constraint_read_0 "r" (arg0) +#define __constraint_read_1 __constraint_read_0, "r" (arg1) +#define __constraint_read_2 __constraint_read_1, "r" (arg2) +#define __constraint_read_3 __constraint_read_2, "r" (arg3) +#define __constraint_read_4 __constraint_read_3, "r" (arg4) +#define __constraint_read_5 __constraint_read_4, "r" (arg5) +#define __constraint_read_6 __constraint_read_5, "r" (arg6) +#define __constraint_read_7 __constraint_read_6, "r" (arg7) =20 #define __declare_arg_0(a0, res) \ struct arm_smccc_res *___res =3D (res); \ - register unsigned long r0 ASM_REG(0) =3D (uint32_t)(a0); \ - register unsigned long r1 ASM_REG(1); \ - register unsigned long r2 ASM_REG(2); \ - register unsigned long r3 ASM_REG(3) + register unsigned long arg0 ASM_REG(0) =3D (uint32_t)(a0) =20 #define __declare_arg_1(a0, a1, res) \ typeof(a1) __a1 =3D (a1); \ struct arm_smccc_res *___res =3D (res); \ - register unsigned long r0 ASM_REG(0) =3D (uint32_t)(a0); \ - register unsigned long r1 ASM_REG(1) =3D __a1; \ - register unsigned long r2 ASM_REG(2); \ - register unsigned long r3 ASM_REG(3) + register unsigned long arg0 ASM_REG(0) =3D (uint32_t)(a0);\ + register typeof(a1) arg1 ASM_REG(1) =3D __a1 =20 #define __declare_arg_2(a0, a1, a2, res) \ typeof(a1) __a1 =3D (a1); \ typeof(a2) __a2 =3D (a2); \ struct arm_smccc_res *___res =3D (res); \ - register unsigned long r0 ASM_REG(0) =3D (uint32_t)(a0); \ - register unsigned long r1 ASM_REG(1) =3D __a1; \ - register unsigned long r2 ASM_REG(2) =3D __a2; \ - register unsigned long r3 ASM_REG(3) + register unsigned long arg0 ASM_REG(0) =3D (uint32_t)(a0);\ + register typeof(a1) arg1 ASM_REG(1) =3D __a1; \ + register typeof(a2) arg2 ASM_REG(2) =3D __a2 =20 #define __declare_arg_3(a0, a1, a2, a3, res) \ typeof(a1) __a1 =3D (a1); \ typeof(a2) __a2 =3D (a2); \ typeof(a3) __a3 =3D (a3); \ struct arm_smccc_res *___res =3D (res); \ - register unsigned long r0 ASM_REG(0) =3D (uint32_t)(a0); \ - register unsigned long r1 ASM_REG(1) =3D __a1; \ - register unsigned long r2 ASM_REG(2) =3D __a2; \ - register unsigned long r3 ASM_REG(3) =3D __a3 + register unsigned long arg0 ASM_REG(0) =3D (uint32_t)(a0);\ + register typeof(a1) arg1 ASM_REG(1) =3D __a1; \ + register typeof(a2) arg2 ASM_REG(2) =3D __a2; \ + register typeof(a3) arg3 ASM_REG(3) =3D __a3 =20 #define __declare_arg_4(a0, a1, a2, a3, a4, res) \ typeof(a4) __a4 =3D (a4); \ __declare_arg_3(a0, a1, a2, a3, res); \ - register unsigned long r4 ASM_REG(4) =3D __a4 + register typeof(a4) arg4 ASM_REG(4) =3D __a4 =20 #define __declare_arg_5(a0, a1, a2, a3, a4, a5, res) \ typeof(a5) __a5 =3D (a5); \ __declare_arg_4(a0, a1, a2, a3, a4, res); \ - register typeof(a5) r5 ASM_REG(5) =3D __a5 + register typeof(a5) arg5 ASM_REG(5) =3D __a5 =20 #define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res) \ typeof(a6) __a6 =3D (a6); \ __declare_arg_5(a0, a1, a2, a3, a4, a5, res); \ - register typeof(a6) r6 ASM_REG(6) =3D __a6 + register typeof(a6) arg6 ASM_REG(6) =3D __a6 =20 #define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res) \ typeof(a7) __a7 =3D (a7); \ __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res); \ - register typeof(a7) r7 ASM_REG(7) =3D __a7 + register typeof(a7) arg7 ASM_REG(7) =3D __a7 =20 #define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__) #define __declare_args(count, ...) ___declare_args(count, __VA_ARGS__) =20 #define ___constraints(count) \ - : __constraint_write_ ## count \ + : "=3Dr" (r0), "=3Dr" (r1), "=3Dr" (r2), "=3Dr" (r3) \ : __constraint_read_ ## count \ : "memory" #define __constraints(count) ___constraints(count) @@ -204,6 +185,10 @@ struct arm_smccc_res { */ #define arm_smccc_1_1_smc(...) \ do { \ + register unsigned long r0 ASM_REG(0); \ + register unsigned long r1 ASM_REG(1); \ + register unsigned long r2 ASM_REG(2); \ + register unsigned long r3 ASM_REG(3); \ __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \ asm volatile("smc #0\n" \ __constraints(__count_args(__VA_ARGS__))); \ --=20 2.52.0