aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Gross <andy.gross@linaro.org>2017-04-04 15:32:31 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-12 06:41:21 -0400
commit007f0a2f2c0fcfa9ecef016c0910aebd0b784fdd (patch)
tree9b5ec2f51c3f7b6c3ecdd587da358d77de6d2bac
parent703f48a1c302f66e686535355092116ebaeccaad (diff)
arm: kernel: Add SMC structure parameter
[ Upstream commit 680a0873e193bae666439f4b5e32c758e68f114c ] 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: Andy Gross <andy.gross@linaro.org> Reviewed-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Sasha Levin <alexander.levin@verizon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/arm/kernel/armksyms.c4
-rw-r--r--arch/arm/kernel/smccc-call.S14
-rw-r--r--arch/arm64/kernel/arm64ksyms.c4
-rw-r--r--arch/arm64/kernel/asm-offsets.c7
-rw-r--r--arch/arm64/kernel/smccc-call.S14
-rw-r--r--include/linux/arm-smccc.h40
6 files changed, 57 insertions, 26 deletions
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 7e45f69a0ddc..8e8d20cdbce7 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -178,6 +178,6 @@ EXPORT_SYMBOL(__pv_offset);
178#endif 178#endif
179 179
180#ifdef CONFIG_HAVE_ARM_SMCCC 180#ifdef CONFIG_HAVE_ARM_SMCCC
181EXPORT_SYMBOL(arm_smccc_smc); 181EXPORT_SYMBOL(__arm_smccc_smc);
182EXPORT_SYMBOL(arm_smccc_hvc); 182EXPORT_SYMBOL(__arm_smccc_hvc);
183#endif 183#endif
diff --git a/arch/arm/kernel/smccc-call.S b/arch/arm/kernel/smccc-call.S
index 2e48b674aab1..e5d43066b889 100644
--- a/arch/arm/kernel/smccc-call.S
+++ b/arch/arm/kernel/smccc-call.S
@@ -46,17 +46,19 @@ UNWIND( .fnend)
46/* 46/*
47 * void smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, 47 * void smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
48 * unsigned long a3, unsigned long a4, unsigned long a5, 48 * unsigned long a3, unsigned long a4, unsigned long a5,
49 * unsigned long a6, unsigned long a7, struct arm_smccc_res *res) 49 * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
50 * struct arm_smccc_quirk *quirk)
50 */ 51 */
51ENTRY(arm_smccc_smc) 52ENTRY(__arm_smccc_smc)
52 SMCCC SMCCC_SMC 53 SMCCC SMCCC_SMC
53ENDPROC(arm_smccc_smc) 54ENDPROC(__arm_smccc_smc)
54 55
55/* 56/*
56 * void smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2, 57 * void smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
57 * unsigned long a3, unsigned long a4, unsigned long a5, 58 * unsigned long a3, unsigned long a4, unsigned long a5,
58 * unsigned long a6, unsigned long a7, struct arm_smccc_res *res) 59 * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
60 * struct arm_smccc_quirk *quirk)
59 */ 61 */
60ENTRY(arm_smccc_hvc) 62ENTRY(__arm_smccc_hvc)
61 SMCCC SMCCC_HVC 63 SMCCC SMCCC_HVC
62ENDPROC(arm_smccc_hvc) 64ENDPROC(__arm_smccc_hvc)
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 78f368039c79..e9c4dc9e0ada 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -73,5 +73,5 @@ NOKPROBE_SYMBOL(_mcount);
73#endif 73#endif
74 74
75 /* arm-smccc */ 75 /* arm-smccc */
76EXPORT_SYMBOL(arm_smccc_smc); 76EXPORT_SYMBOL(__arm_smccc_smc);
77EXPORT_SYMBOL(arm_smccc_hvc); 77EXPORT_SYMBOL(__arm_smccc_hvc);
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 4a2f0f0fef32..c58ddf8c4062 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -140,8 +140,11 @@ int main(void)
140 DEFINE(SLEEP_STACK_DATA_SYSTEM_REGS, offsetof(struct sleep_stack_data, system_regs)); 140 DEFINE(SLEEP_STACK_DATA_SYSTEM_REGS, offsetof(struct sleep_stack_data, system_regs));
141 DEFINE(SLEEP_STACK_DATA_CALLEE_REGS, offsetof(struct sleep_stack_data, callee_saved_regs)); 141 DEFINE(SLEEP_STACK_DATA_CALLEE_REGS, offsetof(struct sleep_stack_data, callee_saved_regs));
142#endif 142#endif
143 DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0)); 143 DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
144 DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2)); 144 DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
145 DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
146 DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
147
145 BLANK(); 148 BLANK();
146 DEFINE(HIBERN_PBE_ORIG, offsetof(struct pbe, orig_address)); 149 DEFINE(HIBERN_PBE_ORIG, offsetof(struct pbe, orig_address));
147 DEFINE(HIBERN_PBE_ADDR, offsetof(struct pbe, address)); 150 DEFINE(HIBERN_PBE_ADDR, offsetof(struct pbe, address));
diff --git a/arch/arm64/kernel/smccc-call.S b/arch/arm64/kernel/smccc-call.S
index ae0496fa4235..ba60a8cb07d2 100644
--- a/arch/arm64/kernel/smccc-call.S
+++ b/arch/arm64/kernel/smccc-call.S
@@ -27,17 +27,19 @@
27/* 27/*
28 * void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, 28 * void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
29 * unsigned long a3, unsigned long a4, unsigned long a5, 29 * unsigned long a3, unsigned long a4, unsigned long a5,
30 * unsigned long a6, unsigned long a7, struct arm_smccc_res *res) 30 * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
31 * struct arm_smccc_quirk *quirk)
31 */ 32 */
32ENTRY(arm_smccc_smc) 33ENTRY(__arm_smccc_smc)
33 SMCCC smc 34 SMCCC smc
34ENDPROC(arm_smccc_smc) 35ENDPROC(__arm_smccc_smc)
35 36
36/* 37/*
37 * void arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2, 38 * void arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
38 * unsigned long a3, unsigned long a4, unsigned long a5, 39 * unsigned long a3, unsigned long a4, unsigned long a5,
39 * unsigned long a6, unsigned long a7, struct arm_smccc_res *res) 40 * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
41 * struct arm_smccc_quirk *quirk)
40 */ 42 */
41ENTRY(arm_smccc_hvc) 43ENTRY(__arm_smccc_hvc)
42 SMCCC hvc 44 SMCCC hvc
43ENDPROC(arm_smccc_hvc) 45ENDPROC(__arm_smccc_hvc)
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index b5abfda80465..c66f8ae94b5a 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -72,33 +72,57 @@ struct arm_smccc_res {
72}; 72};
73 73
74/** 74/**
75 * arm_smccc_smc() - make SMC calls 75 * struct arm_smccc_quirk - Contains quirk information
76 * @id: quirk identification
77 * @state: quirk specific information
78 * @a6: Qualcomm quirk entry for returning post-smc call contents of a6
79 */
80struct arm_smccc_quirk {
81 int id;
82 union {
83 unsigned long a6;
84 } state;
85};
86
87/**
88 * __arm_smccc_smc() - make SMC calls
76 * @a0-a7: arguments passed in registers 0 to 7 89 * @a0-a7: arguments passed in registers 0 to 7
77 * @res: result values from registers 0 to 3 90 * @res: result values from registers 0 to 3
91 * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
78 * 92 *
79 * This function is used to make SMC calls following SMC Calling Convention. 93 * This function is used to make SMC calls following SMC Calling Convention.
80 * The content of the supplied param are copied to registers 0 to 7 prior 94 * The content of the supplied param are copied to registers 0 to 7 prior
81 * to the SMC instruction. The return values are updated with the content 95 * to the SMC instruction. The return values are updated with the content
82 * from register 0 to 3 on return from the SMC instruction. 96 * from register 0 to 3 on return from the SMC instruction. An optional
97 * quirk structure provides vendor specific behavior.
83 */ 98 */
84asmlinkage void arm_smccc_smc(unsigned long a0, unsigned long a1, 99asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1,
85 unsigned long a2, unsigned long a3, unsigned long a4, 100 unsigned long a2, unsigned long a3, unsigned long a4,
86 unsigned long a5, unsigned long a6, unsigned long a7, 101 unsigned long a5, unsigned long a6, unsigned long a7,
87 struct arm_smccc_res *res); 102 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
88 103
89/** 104/**
90 * arm_smccc_hvc() - make HVC calls 105 * __arm_smccc_hvc() - make HVC calls
91 * @a0-a7: arguments passed in registers 0 to 7 106 * @a0-a7: arguments passed in registers 0 to 7
92 * @res: result values from registers 0 to 3 107 * @res: result values from registers 0 to 3
93 * 108 *
94 * This function is used to make HVC calls following SMC Calling 109 * This function is used to make HVC calls following SMC Calling
95 * Convention. The content of the supplied param are copied to registers 0 110 * Convention. The content of the supplied param are copied to registers 0
96 * to 7 prior to the HVC instruction. The return values are updated with 111 * to 7 prior to the HVC instruction. The return values are updated with
97 * the content from register 0 to 3 on return from the HVC instruction. 112 * the content from register 0 to 3 on return from the HVC instruction. An
113 * optional quirk structure provides vendor specific behavior.
98 */ 114 */
99asmlinkage void arm_smccc_hvc(unsigned long a0, unsigned long a1, 115asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
100 unsigned long a2, unsigned long a3, unsigned long a4, 116 unsigned long a2, unsigned long a3, unsigned long a4,
101 unsigned long a5, unsigned long a6, unsigned long a7, 117 unsigned long a5, unsigned long a6, unsigned long a7,
102 struct arm_smccc_res *res); 118 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
119
120#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
121
122#define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
123
124#define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL)
125
126#define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
103 127
104#endif /*__LINUX_ARM_SMCCC_H*/ 128#endif /*__LINUX_ARM_SMCCC_H*/