Skip to content

Commit 680a087

Browse files
Andy Grosswildea01
authored andcommitted
arm: kernel: Add SMC structure parameter
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>
1 parent 757b435 commit 680a087

File tree

6 files changed

+57
-26
lines changed

6 files changed

+57
-26
lines changed

arch/arm/kernel/armksyms.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,6 @@ EXPORT_SYMBOL(__pv_offset);
178178
#endif
179179

180180
#ifdef CONFIG_HAVE_ARM_SMCCC
181-
EXPORT_SYMBOL(arm_smccc_smc);
182-
EXPORT_SYMBOL(arm_smccc_hvc);
181+
EXPORT_SYMBOL(__arm_smccc_smc);
182+
EXPORT_SYMBOL(__arm_smccc_hvc);
183183
#endif

arch/arm/kernel/smccc-call.S

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,19 @@ UNWIND( .fnend)
4646
/*
4747
* void smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
4848
* 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)
5051
*/
51-
ENTRY(arm_smccc_smc)
52+
ENTRY(__arm_smccc_smc)
5253
SMCCC SMCCC_SMC
53-
ENDPROC(arm_smccc_smc)
54+
ENDPROC(__arm_smccc_smc)
5455

5556
/*
5657
* void smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
5758
* 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)
5961
*/
60-
ENTRY(arm_smccc_hvc)
62+
ENTRY(__arm_smccc_hvc)
6163
SMCCC SMCCC_HVC
62-
ENDPROC(arm_smccc_hvc)
64+
ENDPROC(__arm_smccc_hvc)

arch/arm64/kernel/arm64ksyms.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,5 @@ NOKPROBE_SYMBOL(_mcount);
7373
#endif
7474

7575
/* arm-smccc */
76-
EXPORT_SYMBOL(arm_smccc_smc);
77-
EXPORT_SYMBOL(arm_smccc_hvc);
76+
EXPORT_SYMBOL(__arm_smccc_smc);
77+
EXPORT_SYMBOL(__arm_smccc_hvc);

arch/arm64/kernel/asm-offsets.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,11 @@ int main(void)
143143
DEFINE(SLEEP_STACK_DATA_SYSTEM_REGS, offsetof(struct sleep_stack_data, system_regs));
144144
DEFINE(SLEEP_STACK_DATA_CALLEE_REGS, offsetof(struct sleep_stack_data, callee_saved_regs));
145145
#endif
146-
DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
147-
DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
146+
DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
147+
DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
148+
DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
149+
DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
150+
148151
BLANK();
149152
DEFINE(HIBERN_PBE_ORIG, offsetof(struct pbe, orig_address));
150153
DEFINE(HIBERN_PBE_ADDR, offsetof(struct pbe, address));

arch/arm64/kernel/smccc-call.S

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,19 @@
2727
/*
2828
* void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
2929
* 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)
3132
*/
32-
ENTRY(arm_smccc_smc)
33+
ENTRY(__arm_smccc_smc)
3334
SMCCC smc
34-
ENDPROC(arm_smccc_smc)
35+
ENDPROC(__arm_smccc_smc)
3536

3637
/*
3738
* void arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
3839
* 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)
4042
*/
41-
ENTRY(arm_smccc_hvc)
43+
ENTRY(__arm_smccc_hvc)
4244
SMCCC hvc
43-
ENDPROC(arm_smccc_hvc)
45+
ENDPROC(__arm_smccc_hvc)

include/linux/arm-smccc.h

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,33 +72,57 @@ struct arm_smccc_res {
7272
};
7373

7474
/**
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+
*/
80+
struct arm_smccc_quirk {
81+
int id;
82+
union {
83+
unsigned long a6;
84+
} state;
85+
};
86+
87+
/**
88+
* __arm_smccc_smc() - make SMC calls
7689
* @a0-a7: arguments passed in registers 0 to 7
7790
* @res: result values from registers 0 to 3
91+
* @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
7892
*
7993
* This function is used to make SMC calls following SMC Calling Convention.
8094
* The content of the supplied param are copied to registers 0 to 7 prior
8195
* 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.
8398
*/
84-
asmlinkage void arm_smccc_smc(unsigned long a0, unsigned long a1,
99+
asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1,
85100
unsigned long a2, unsigned long a3, unsigned long a4,
86101
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);
88103

89104
/**
90-
* arm_smccc_hvc() - make HVC calls
105+
* __arm_smccc_hvc() - make HVC calls
91106
* @a0-a7: arguments passed in registers 0 to 7
92107
* @res: result values from registers 0 to 3
93108
*
94109
* This function is used to make HVC calls following SMC Calling
95110
* Convention. The content of the supplied param are copied to registers 0
96111
* 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.
98114
*/
99-
asmlinkage void arm_smccc_hvc(unsigned long a0, unsigned long a1,
115+
asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
100116
unsigned long a2, unsigned long a3, unsigned long a4,
101117
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__)
103127

104128
#endif /*__LINUX_ARM_SMCCC_H*/

0 commit comments

Comments
 (0)