diff mbox series

[v3,1/4] arm64: smccc: add Xn registers support used by SMC calls

Message ID 20220801172053.20163-2-abdellatif.elkhlifi@arm.com
State Superseded
Delegated to: Tom Rini
Headers show
Series introduce Arm FF-A support | expand

Commit Message

Abdellatif El Khlifi Aug. 1, 2022, 5:20 p.m. UTC
use x0-x17 registers in the SMC32/SMC64 calls according to SMCCCv1.2

Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
---
 arch/arm/cpu/armv8/smccc-call.S | 53 +++++++++++++++++++++++++++++++++
 arch/arm/lib/asm-offsets.c      | 13 ++++++++
 include/linux/arm-smccc.h       | 43 ++++++++++++++++++++++++++
 3 files changed, 109 insertions(+)

Comments

Sudeep Holla Aug. 1, 2022, 6:41 p.m. UTC | #1
On Mon, Aug 01, 2022 at 06:20:50PM +0100, Abdellatif El Khlifi wrote:
> use x0-x17 registers in the SMC32/SMC64 calls according to SMCCCv1.2
> 
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Please drop my signed-off as I didn't. I am seeing this patch on the list
for the first time and AFAIK I haven't posted any previous version of the
patch that you are picking up.

IIUC, you are importing this code from the Linux kernel tree which I assume
is fine. You can just mention the same and must not add anyone's sign-off
without consulting them.

OTH, if you cherry-pick the commit as is and use it in u-boot tree(e.g.
DTS patches), then you can retain them. That is my understanding. Happy
to be corrected if my assumptions are not correct here.

--
Regards,
Sudeep
Abdellatif El Khlifi Aug. 5, 2022, 11:17 a.m. UTC | #2
On Mon, Aug 01, 2022 at 07:41:16PM +0100, Sudeep Holla wrote:
> On Mon, Aug 01, 2022 at 06:20:50PM +0100, Abdellatif El Khlifi wrote:
> > use x0-x17 registers in the SMC32/SMC64 calls according to SMCCCv1.2
> > 
> > Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> 
> Please drop my signed-off as I didn't. I am seeing this patch on the list
> for the first time and AFAIK I haven't posted any previous version of the
> patch that you are picking up.
> 
> IIUC, you are importing this code from the Linux kernel tree which I assume
> is fine. You can just mention the same and must not add anyone's sign-off
> without consulting them.
> 
> OTH, if you cherry-pick the commit as is and use it in u-boot tree(e.g.
> DTS patches), then you can retain them. That is my understanding. Happy
> to be corrected if my assumptions are not correct here.
> 
> --
> Regards,
> Sudeep

No worries. I'll remove the signed-off. I just wanted to give credit to the original author :)

For the FF-A driver in u-boot, only the SMC part of the kernel patch is needed. No need for HVC
support at the moment. The SMC part has been tested and proven to work. Hence, this patch.

I'll rename this commit to:

arm64: smccc: add support for SMCCCv1.2 x0-x17 registers

I'll also state in the commit description that this work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

You're welcome to provide review comments.

Cheers,
Abdellatif
diff mbox series

Patch

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..ec6f299bc9 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,6 +1,8 @@ 
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
@@ -45,3 +47,54 @@  ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 22fd541f9a..b6bd1b32b0 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,8 @@ 
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * (C) Copyright 2022 ARM Limited
  */
 
 #include <common.h>
@@ -117,6 +119,17 @@  int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+	#ifdef CONFIG_ARM64
+		DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+		DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+		DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+		DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+		DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+		DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+		DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+		DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+		DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+	#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..9105031d55 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,8 @@ 
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +72,47 @@  struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_smccc_1_2_regs {
+	unsigned long a0;
+	unsigned long a1;
+	unsigned long a2;
+	unsigned long a3;
+	unsigned long a4;
+	unsigned long a5;
+	unsigned long a6;
+	unsigned long a7;
+	unsigned long a8;
+	unsigned long a9;
+	unsigned long a10;
+	unsigned long a11;
+	unsigned long a12;
+	unsigned long a13;
+	unsigned long a14;
+	unsigned long a15;
+	unsigned long a16;
+	unsigned long a17;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification