Commit cc9b9deb authored by Andy Gross's avatar Andy Gross Committed by Greg Kroah-Hartman

arm: kernel: Add SMC structure parameter

[ Upstream commit 680a0873 ]

This patch adds a quirk parameter to the arm_smccc_(smc/hvc) calls.
The quirk structure allows for specialized SMC operations due to SoC
specific requirements.  The current arm_smccc_(smc/hvc) is renamed and
macros are used instead to specify the standard arm_smccc_(smc/hvc) or
the arm_smccc_(smc/hvc)_quirk function.

This patch and partial implementation was suggested by Will Deacon.
Signed-off-by: default avatarAndy Gross <andy.gross@linaro.org>
Reviewed-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarSasha Levin <alexander.levin@verizon.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2dca786b
...@@ -178,6 +178,6 @@ EXPORT_SYMBOL(__pv_offset); ...@@ -178,6 +178,6 @@ EXPORT_SYMBOL(__pv_offset);
#endif #endif
#ifdef CONFIG_HAVE_ARM_SMCCC #ifdef CONFIG_HAVE_ARM_SMCCC
EXPORT_SYMBOL(arm_smccc_smc); EXPORT_SYMBOL(__arm_smccc_smc);
EXPORT_SYMBOL(arm_smccc_hvc); EXPORT_SYMBOL(__arm_smccc_hvc);
#endif #endif
...@@ -46,17 +46,19 @@ UNWIND( .fnend) ...@@ -46,17 +46,19 @@ UNWIND( .fnend)
/* /*
* void smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, * void smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
* unsigned long a3, unsigned long a4, unsigned long a5, * unsigned long a3, unsigned long a4, unsigned long a5,
* unsigned long a6, unsigned long a7, struct arm_smccc_res *res) * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
* struct arm_smccc_quirk *quirk)
*/ */
ENTRY(arm_smccc_smc) ENTRY(__arm_smccc_smc)
SMCCC SMCCC_SMC SMCCC SMCCC_SMC
ENDPROC(arm_smccc_smc) ENDPROC(__arm_smccc_smc)
/* /*
* void smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2, * void smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
* unsigned long a3, unsigned long a4, unsigned long a5, * unsigned long a3, unsigned long a4, unsigned long a5,
* unsigned long a6, unsigned long a7, struct arm_smccc_res *res) * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
* struct arm_smccc_quirk *quirk)
*/ */
ENTRY(arm_smccc_hvc) ENTRY(__arm_smccc_hvc)
SMCCC SMCCC_HVC SMCCC SMCCC_HVC
ENDPROC(arm_smccc_hvc) ENDPROC(__arm_smccc_hvc)
...@@ -73,5 +73,5 @@ NOKPROBE_SYMBOL(_mcount); ...@@ -73,5 +73,5 @@ NOKPROBE_SYMBOL(_mcount);
#endif #endif
/* arm-smccc */ /* arm-smccc */
EXPORT_SYMBOL(arm_smccc_smc); EXPORT_SYMBOL(__arm_smccc_smc);
EXPORT_SYMBOL(arm_smccc_hvc); EXPORT_SYMBOL(__arm_smccc_hvc);
...@@ -143,8 +143,11 @@ int main(void) ...@@ -143,8 +143,11 @@ int main(void)
DEFINE(SLEEP_STACK_DATA_SYSTEM_REGS, offsetof(struct sleep_stack_data, system_regs)); DEFINE(SLEEP_STACK_DATA_SYSTEM_REGS, offsetof(struct sleep_stack_data, system_regs));
DEFINE(SLEEP_STACK_DATA_CALLEE_REGS, offsetof(struct sleep_stack_data, callee_saved_regs)); DEFINE(SLEEP_STACK_DATA_CALLEE_REGS, offsetof(struct sleep_stack_data, callee_saved_regs));
#endif #endif
DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0)); DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2)); 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));
BLANK(); BLANK();
DEFINE(HIBERN_PBE_ORIG, offsetof(struct pbe, orig_address)); DEFINE(HIBERN_PBE_ORIG, offsetof(struct pbe, orig_address));
DEFINE(HIBERN_PBE_ADDR, offsetof(struct pbe, address)); DEFINE(HIBERN_PBE_ADDR, offsetof(struct pbe, address));
......
...@@ -27,17 +27,19 @@ ...@@ -27,17 +27,19 @@
/* /*
* void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, * void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
* unsigned long a3, unsigned long a4, unsigned long a5, * unsigned long a3, unsigned long a4, unsigned long a5,
* unsigned long a6, unsigned long a7, struct arm_smccc_res *res) * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
* struct arm_smccc_quirk *quirk)
*/ */
ENTRY(arm_smccc_smc) ENTRY(__arm_smccc_smc)
SMCCC smc SMCCC smc
ENDPROC(arm_smccc_smc) ENDPROC(__arm_smccc_smc)
/* /*
* void arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2, * void arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
* unsigned long a3, unsigned long a4, unsigned long a5, * unsigned long a3, unsigned long a4, unsigned long a5,
* unsigned long a6, unsigned long a7, struct arm_smccc_res *res) * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
* struct arm_smccc_quirk *quirk)
*/ */
ENTRY(arm_smccc_hvc) ENTRY(__arm_smccc_hvc)
SMCCC hvc SMCCC hvc
ENDPROC(arm_smccc_hvc) ENDPROC(__arm_smccc_hvc)
...@@ -72,33 +72,57 @@ struct arm_smccc_res { ...@@ -72,33 +72,57 @@ struct arm_smccc_res {
}; };
/** /**
* arm_smccc_smc() - make SMC calls * struct arm_smccc_quirk - Contains quirk information
* @id: quirk identification
* @state: quirk specific information
* @a6: Qualcomm quirk entry for returning post-smc call contents of a6
*/
struct arm_smccc_quirk {
int id;
union {
unsigned long a6;
} state;
};
/**
* __arm_smccc_smc() - make SMC calls
* @a0-a7: arguments passed in registers 0 to 7 * @a0-a7: arguments passed in registers 0 to 7
* @res: result values from registers 0 to 3 * @res: result values from registers 0 to 3
* @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
* *
* This function is used to make SMC calls following SMC Calling Convention. * This function is used to make SMC calls following SMC Calling Convention.
* The content of the supplied param are copied to registers 0 to 7 prior * The content of the supplied param are copied to registers 0 to 7 prior
* to the SMC instruction. The return values are updated with the content * to the SMC instruction. The return values are updated with the content
* from register 0 to 3 on return from the SMC instruction. * from register 0 to 3 on return from the SMC instruction. An optional
* quirk structure provides vendor specific behavior.
*/ */
asmlinkage void arm_smccc_smc(unsigned long a0, unsigned long a1, asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1,
unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a2, unsigned long a3, unsigned long a4,
unsigned long a5, unsigned long a6, unsigned long a7, unsigned long a5, unsigned long a6, unsigned long a7,
struct arm_smccc_res *res); struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
/** /**
* arm_smccc_hvc() - make HVC calls * __arm_smccc_hvc() - make HVC calls
* @a0-a7: arguments passed in registers 0 to 7 * @a0-a7: arguments passed in registers 0 to 7
* @res: result values from registers 0 to 3 * @res: result values from registers 0 to 3
* *
* This function is used to make HVC calls following SMC Calling * This function is used to make HVC calls following SMC Calling
* Convention. The content of the supplied param are copied to registers 0 * Convention. The content of the supplied param are copied to registers 0
* to 7 prior to the HVC instruction. The return values are updated with * to 7 prior to the HVC instruction. The return values are updated with
* the content from register 0 to 3 on return from the HVC instruction. * the content from register 0 to 3 on return from the HVC instruction. An
* optional quirk structure provides vendor specific behavior.
*/ */
asmlinkage void arm_smccc_hvc(unsigned long a0, unsigned long a1, asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a2, unsigned long a3, unsigned long a4,
unsigned long a5, unsigned long a6, unsigned long a7, unsigned long a5, unsigned long a6, unsigned long a7,
struct arm_smccc_res *res); struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
#define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
#define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL)
#define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
#endif /*__LINUX_ARM_SMCCC_H*/ #endif /*__LINUX_ARM_SMCCC_H*/
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment