| From foo@baz Tue Mar 8 08:40:58 PM CET 2022 |
| From: Steven Price <steven.price@arm.com> |
| Date: Mon, 21 Oct 2019 16:28:21 +0100 |
| Subject: arm/arm64: Provide a wrapper for SMCCC 1.1 calls |
| |
| From: Steven Price <steven.price@arm.com> |
| |
| commit 541625ac47ce9d0835efaee0fcbaa251b0000a37 upstream. |
| |
| SMCCC 1.1 calls may use either HVC or SMC depending on the PSCI |
| conduit. Rather than coding this in every call site, provide a macro |
| which uses the correct instruction. The macro also handles the case |
| where no conduit is configured/available returning a not supported error |
| in res, along with returning the conduit used for the call. |
| |
| This allow us to remove some duplicated code and will be useful later |
| when adding paravirtualized time hypervisor calls. |
| |
| Signed-off-by: Steven Price <steven.price@arm.com> |
| Acked-by: Will Deacon <will@kernel.org> |
| Signed-off-by: Marc Zyngier <maz@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/linux/arm-smccc.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 58 insertions(+) |
| |
| --- a/include/linux/arm-smccc.h |
| +++ b/include/linux/arm-smccc.h |
| @@ -311,5 +311,63 @@ asmlinkage void __arm_smccc_hvc(unsigned |
| #define SMCCC_RET_NOT_SUPPORTED -1 |
| #define SMCCC_RET_NOT_REQUIRED -2 |
| |
| +/* |
| + * Like arm_smccc_1_1* but always returns SMCCC_RET_NOT_SUPPORTED. |
| + * Used when the SMCCC conduit is not defined. The empty asm statement |
| + * avoids compiler warnings about unused variables. |
| + */ |
| +#define __fail_smccc_1_1(...) \ |
| + do { \ |
| + __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \ |
| + asm ("" __constraints(__count_args(__VA_ARGS__))); \ |
| + if (___res) \ |
| + ___res->a0 = SMCCC_RET_NOT_SUPPORTED; \ |
| + } while (0) |
| + |
| +/* |
| + * arm_smccc_1_1_invoke() - make an SMCCC v1.1 compliant call |
| + * |
| + * This is a variadic macro taking one to eight source arguments, and |
| + * an optional return structure. |
| + * |
| + * @a0-a7: arguments passed in registers 0 to 7 |
| + * @res: result values from registers 0 to 3 |
| + * |
| + * This macro will make either an HVC call or an SMC call depending on the |
| + * current SMCCC conduit. If no valid conduit is available then -1 |
| + * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied). |
| + * |
| + * The return value also provides the conduit that was used. |
| + */ |
| +#define arm_smccc_1_1_invoke(...) ({ \ |
| + int method = arm_smccc_1_1_get_conduit(); \ |
| + switch (method) { \ |
| + case SMCCC_CONDUIT_HVC: \ |
| + arm_smccc_1_1_hvc(__VA_ARGS__); \ |
| + break; \ |
| + case SMCCC_CONDUIT_SMC: \ |
| + arm_smccc_1_1_smc(__VA_ARGS__); \ |
| + break; \ |
| + default: \ |
| + __fail_smccc_1_1(__VA_ARGS__); \ |
| + method = SMCCC_CONDUIT_NONE; \ |
| + break; \ |
| + } \ |
| + method; \ |
| + }) |
| + |
| +/* Paravirtualised time calls (defined by ARM DEN0057A) */ |
| +#define ARM_SMCCC_HV_PV_TIME_FEATURES \ |
| + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ |
| + ARM_SMCCC_SMC_64, \ |
| + ARM_SMCCC_OWNER_STANDARD_HYP, \ |
| + 0x20) |
| + |
| +#define ARM_SMCCC_HV_PV_TIME_ST \ |
| + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ |
| + ARM_SMCCC_SMC_64, \ |
| + ARM_SMCCC_OWNER_STANDARD_HYP, \ |
| + 0x21) |
| + |
| #endif /*__ASSEMBLY__*/ |
| #endif /*__LINUX_ARM_SMCCC_H*/ |