lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <54953d15-3d0a-4fbb-9e8a-02dbfb2d8a00@amd.com>
Date: Wed, 2 Oct 2024 12:55:24 +0200
From: Michal Simek <michal.simek@....com>
To: Ronak Jain <ronak.jain@....com>
Cc: linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH] firmware: xilinx: add support for new SMC call format



On 9/20/24 07:55, Ronak Jain wrote:
> Added zynqmp_pm_invoke_fw_fn() to use new SMC format in which
> lower 12 bits of SMC id are fixed and firmware header is moved to
> subsequent SMC arguments. The new SMC format supports full request and
> response buffers.
> 
> Added zynqmp_pm_get_sip_svc_version() to get SiP SVC version
> number to check if TF-A is newer or older and use the SMC format
> accordingly to handle backward compatibility.
> 
> Used new SMC format for PM_QUERY_DATA API as more response values are
> required in it.
> 
> Signed-off-by: Ronak Jain <ronak.jain@....com>
> Signed-off-by: Jay Buddhabhatti <jay.buddhabhatti@....com>
> ---
>   drivers/firmware/xilinx/zynqmp.c     | 137 ++++++++++++++++++++++++++-
>   include/linux/firmware/xlnx-zynqmp.h |  26 ++++-
>   2 files changed, 157 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
> index c8be32d9c6af..5ab0dfb2b225 100644
> --- a/drivers/firmware/xilinx/zynqmp.c
> +++ b/drivers/firmware/xilinx/zynqmp.c
> @@ -3,7 +3,7 @@
>    * Xilinx Zynq MPSoC Firmware layer
>    *
>    *  Copyright (C) 2014-2022 Xilinx, Inc.
> - *  Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc.
> + *  Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
>    *
>    *  Michal Simek <michal.simek@....com>
>    *  Davorin Mista <davorin.mista@...ios.com>
> @@ -46,6 +46,7 @@ static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
>   static u32 ioctl_features[FEATURE_PAYLOAD_SIZE];
>   static u32 query_features[FEATURE_PAYLOAD_SIZE];
>   
> +static u32 sip_svc_version;
>   static struct platform_device *em_dev;
>   
>   /**
> @@ -151,6 +152,9 @@ static noinline int do_fw_call_smc(u32 *ret_payload, u32 num_args, ...)
>   		ret_payload[1] = upper_32_bits(res.a0);
>   		ret_payload[2] = lower_32_bits(res.a1);
>   		ret_payload[3] = upper_32_bits(res.a1);
> +		ret_payload[4] = lower_32_bits(res.a2);
> +		ret_payload[5] = upper_32_bits(res.a2);
> +		ret_payload[6] = lower_32_bits(res.a3);
>   	}
>   
>   	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
> @@ -191,6 +195,9 @@ static noinline int do_fw_call_hvc(u32 *ret_payload, u32 num_args, ...)
>   		ret_payload[1] = upper_32_bits(res.a0);
>   		ret_payload[2] = lower_32_bits(res.a1);
>   		ret_payload[3] = upper_32_bits(res.a1);
> +		ret_payload[4] = lower_32_bits(res.a2);
> +		ret_payload[5] = upper_32_bits(res.a2);
> +		ret_payload[6] = lower_32_bits(res.a3);
>   	}
>   
>   	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
> @@ -331,6 +338,70 @@ int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
>   }
>   EXPORT_SYMBOL_GPL(zynqmp_pm_is_function_supported);
>   
> +/**
> + * zynqmp_pm_invoke_fw_fn() - Invoke the system-level platform management layer
> + *			caller function depending on the configuration
> + * @pm_api_id:		Requested PM-API call
> + * @ret_payload:	Returned value array
> + * @num_args:		Number of arguments to requested PM-API call
> + *
> + * Invoke platform management function for SMC or HVC call, depending on
> + * configuration.
> + * Following SMC Calling Convention (SMCCC) for SMC64:
> + * Pm Function Identifier,
> + * PM_SIP_SVC + PASS_THROUGH_FW_CMD_ID =
> + *	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
> + *	((SMC_64) << FUNCID_CC_SHIFT)
> + *	((SIP_START) << FUNCID_OEN_SHIFT)
> + *	(PASS_THROUGH_FW_CMD_ID))
> + *
> + * PM_SIP_SVC - Registered ZynqMP SIP Service Call.
> + * PASS_THROUGH_FW_CMD_ID - Fixed SiP SVC call ID for FW specific calls.
> + *
> + * Return: Returns status, either success or error+reason
> + */
> +int zynqmp_pm_invoke_fw_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...)
> +{
> +	/*
> +	 * Added SIP service call Function Identifier
> +	 * Make sure to stay in x0 register
> +	 */
> +	u64 smc_arg[SMC_ARG_CNT_64];
> +	int ret, i;
> +	va_list arg_list;
> +	u32 args[SMC_ARG_CNT_32] = {0};
> +	u32 module_id;
> +
> +	if (num_args > SMC_ARG_CNT_32)
> +		return -EINVAL;
> +
> +	va_start(arg_list, num_args);
> +
> +	/* Check if feature is supported or not */
> +	ret = zynqmp_pm_feature(pm_api_id);
> +	if (ret < 0)
> +		return ret;
> +
> +	for (i = 0; i < num_args; i++)
> +		args[i] = va_arg(arg_list, u32);
> +
> +	va_end(arg_list);
> +
> +	module_id = FIELD_GET(PLM_MODULE_ID_MASK, pm_api_id);
> +
> +	if (module_id == 0)
> +		module_id = XPM_MODULE_ID;
> +
> +	smc_arg[0] = PM_SIP_SVC | PASS_THROUGH_FW_CMD_ID;
> +	smc_arg[1] = ((u64)args[0] << 32U) | FIELD_PREP(PLM_MODULE_ID_MASK, module_id) |
> +		      (pm_api_id & API_ID_MASK);
> +	for (i = 1; i < (SMC_ARG_CNT_64 - 1); i++)
> +		smc_arg[i + 1] = ((u64)args[(i * 2)] << 32U) | args[(i * 2) - 1];
> +
> +	return do_fw_call(ret_payload, 8, smc_arg[0], smc_arg[1], smc_arg[2], smc_arg[3],
> +			  smc_arg[4], smc_arg[5], smc_arg[6], smc_arg[7]);
> +}
> +
>   /**
>    * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
>    *			   caller function depending on the configuration
> @@ -488,6 +559,35 @@ int zynqmp_pm_get_family_info(u32 *family, u32 *subfamily)
>   }
>   EXPORT_SYMBOL_GPL(zynqmp_pm_get_family_info);
>   
> +/**
> + * zynqmp_pm_get_sip_svc_version() - Get SiP service call version
> + * @version:	Returned version value
> + *
> + * Return: Returns status, either success or error+reason
> + */
> +static int zynqmp_pm_get_sip_svc_version(u32 *version)
> +{
> +	struct arm_smccc_res res;
> +	u64 args[SMC_ARG_CNT_64] = {0};
> +
> +	if (!version)
> +		return -EINVAL;
> +
> +	/* Check if SiP SVC version already verified */
> +	if (sip_svc_version > 0) {
> +		*version = sip_svc_version;
> +		return 0;
> +	}
> +
> +	args[0] = GET_SIP_SVC_VERSION;
> +
> +	arm_smccc_smc(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], &res);
> +
> +	*version = ((lower_32_bits(res.a0) << 16U) | lower_32_bits(res.a1));
> +
> +	return zynqmp_pm_ret_code(XST_PM_SUCCESS);
> +}
> +
>   /**
>    * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
>    * @version:	Returned version value
> @@ -552,10 +652,34 @@ static int get_set_conduit_method(struct device_node *np)
>    */
>   int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
>   {
> -	int ret;
> +	int ret, i = 0;
> +	u32 ret_payload[PAYLOAD_ARG_CNT] = {0};
> +
> +	if (sip_svc_version >= SIP_SVC_PASSTHROUGH_VERSION) {
> +		ret = zynqmp_pm_invoke_fw_fn(PM_QUERY_DATA, ret_payload, 4,
> +					     qdata.qid, qdata.arg1,
> +					     qdata.arg2, qdata.arg3);
> +		/* To support backward compatibility */
> +		if (!ret && !ret_payload[0]) {
> +			/*
> +			 * TF-A passes return status on 0th index but
> +			 * api to get clock name reads data from 0th
> +			 * index so pass data at 0th index instead of
> +			 * return status
> +			 */
> +			if (qdata.qid == PM_QID_CLOCK_GET_NAME ||
> +			    qdata.qid == PM_QID_PINCTRL_GET_FUNCTION_NAME)
> +				i = 1;
> +
> +			for (; i < PAYLOAD_ARG_CNT; i++, out++)
> +				*out = ret_payload[i];
>   
> -	ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, out, 4, qdata.qid, qdata.arg1, qdata.arg2,
> -				  qdata.arg3);
> +			return ret;
> +		}
> +	}
> +
> +	ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, out, 4, qdata.qid,
> +				  qdata.arg1, qdata.arg2, qdata.arg3);
>   
>   	/*
>   	 * For clock name query, all bytes in SMC response are clock name
> @@ -1887,6 +2011,11 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
>   	if (ret)
>   		return ret;
>   
> +	/* Get SiP SVC version number */
> +	ret = zynqmp_pm_get_sip_svc_version(&sip_svc_version);
> +	if (ret)
> +		return ret;
> +
>   	ret = do_feature_check_call(PM_FEATURE_CHECK);
>   	if (ret >= 0 && ((ret & FIRMWARE_VERSION_MASK) >= PM_API_VERSION_1))
>   		feature_check_enabled = true;
> diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h
> index 5b938fc2adad..76d85ad82ec0 100644
> --- a/include/linux/firmware/xlnx-zynqmp.h
> +++ b/include/linux/firmware/xlnx-zynqmp.h
> @@ -3,7 +3,7 @@
>    * Xilinx Zynq MPSoC Firmware layer
>    *
>    *  Copyright (C) 2014-2021 Xilinx
> - *  Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc.
> + *  Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
>    *
>    *  Michal Simek <michal.simek@....com>
>    *  Davorin Mista <davorin.mista@...ios.com>
> @@ -32,6 +32,19 @@
>   /* SMC SIP service Call Function Identifier Prefix */
>   #define PM_SIP_SVC			0xC2000000
>   
> +/* SMC function ID to get SiP SVC version */
> +#define GET_SIP_SVC_VERSION	(0x8200ff03U)
> +
> +/* SiP Service Calls version numbers */
> +#define SIP_SVC_VERSION_MAJOR		(0U)
> +#define SIP_SVC_VERSION_MINOR		(2U)
> +
> +#define SIP_SVC_PASSTHROUGH_VERSION	((SIP_SVC_VERSION_MAJOR << 16) | \
> +					 SIP_SVC_VERSION_MINOR)
> +
> +/* Fixed ID for FW specific APIs */
> +#define PASS_THROUGH_FW_CMD_ID	GENMASK(11, 0)
> +
>   /* PM API versions */
>   #define PM_API_VERSION_1	1
>   #define PM_API_VERSION_2	2
> @@ -51,6 +64,7 @@
>   
>   #define API_ID_MASK		GENMASK(7, 0)
>   #define MODULE_ID_MASK		GENMASK(11, 8)
> +#define PLM_MODULE_ID_MASK	GENMASK(15, 8)
>   
>   /* Firmware feature check version mask */
>   #define FIRMWARE_VERSION_MASK		0xFFFFU
> @@ -62,7 +76,13 @@
>   #define GET_CALLBACK_DATA		0xa01
>   
>   /* Number of 32bits values in payload */
> -#define PAYLOAD_ARG_CNT	4U
> +#define PAYLOAD_ARG_CNT	7U
> +
> +/* Number of 64bits arguments for SMC call */
> +#define SMC_ARG_CNT_64	8U
> +
> +/* Number of 32bits arguments for SMC call */
> +#define SMC_ARG_CNT_32	13U
>   
>   /* Number of arguments for a callback */
>   #define CB_ARG_CNT     4
> @@ -130,6 +150,7 @@
>   
>   enum pm_module_id {
>   	PM_MODULE_ID = 0x0,
> +	XPM_MODULE_ID = 0x2,
>   	XSEM_MODULE_ID = 0x3,
>   	TF_A_MODULE_ID = 0xa,
>   };
> @@ -537,6 +558,7 @@ struct zynqmp_pm_query_data {
>   };
>   
>   int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...);
> +int zynqmp_pm_invoke_fw_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...);
>   
>   #if IS_REACHABLE(CONFIG_ZYNQMP_FIRMWARE)
>   int zynqmp_pm_get_api_version(u32 *version);

Applied.
M

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ