mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/arm: Rewrite arm_smccc_*() to return by value
Use statement expressions to return struct arm_smccc_res which makes the code read a lot more normally, and avoids needing to pass in NULL in order to skip return information. More importantly, it removes the local implementation of __count_args() which is off by two and deeply confusing to try and follow. No functional change. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Bertrand Marquis <bertrand.marquis@arm.com>
This commit is contained in:
1 parent
1b5ff89cc3
commit
715f2c3c25
7 files changed
+88
-99
No files matched your search
@@ -179,8 +179,8 @@ static int enable_smccc_arch_workaround_1(void *data)
|
|||||||
if ( smccc_ver < SMCCC_VERSION(1, 1) )
|
if ( smccc_ver < SMCCC_VERSION(1, 1) )
|
||||||
goto warn;
|
goto warn;
|
||||||
|
|
||||||
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FID,
|
res = arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FID,
|
||||||
ARM_SMCCC_ARCH_WORKAROUND_1_FID, &res);
|
ARM_SMCCC_ARCH_WORKAROUND_1_FID);
|
||||||
/* The return value is in the lower 32-bits. */
|
/* The return value is in the lower 32-bits. */
|
||||||
if ( (int)res.a0 < 0 )
|
if ( (int)res.a0 < 0 )
|
||||||
goto warn;
|
goto warn;
|
||||||
@@ -256,8 +256,8 @@ static int enable_spectre_bhb_workaround(void *data)
|
|||||||
if ( smccc_ver < SMCCC_VERSION(1, 1) )
|
if ( smccc_ver < SMCCC_VERSION(1, 1) )
|
||||||
goto warn;
|
goto warn;
|
||||||
|
|
||||||
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FID,
|
res = arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FID,
|
||||||
ARM_SMCCC_ARCH_WORKAROUND_3_FID, &res);
|
ARM_SMCCC_ARCH_WORKAROUND_3_FID);
|
||||||
/* The return value is in the lower 32-bits. */
|
/* The return value is in the lower 32-bits. */
|
||||||
if ( (int)res.a0 < 0 )
|
if ( (int)res.a0 < 0 )
|
||||||
{
|
{
|
||||||
@@ -398,8 +398,8 @@ static bool has_ssbd_mitigation(const struct arm_cpu_capabilities *entry)
|
|||||||
if ( smccc_ver < SMCCC_VERSION(1, 1) )
|
if ( smccc_ver < SMCCC_VERSION(1, 1) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FID,
|
res = arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FID,
|
||||||
ARM_SMCCC_ARCH_WORKAROUND_2_FID, &res);
|
ARM_SMCCC_ARCH_WORKAROUND_2_FID);
|
||||||
|
|
||||||
switch ( (int)res.a0 )
|
switch ( (int)res.a0 )
|
||||||
{
|
{
|
||||||
@@ -429,7 +429,7 @@ static bool has_ssbd_mitigation(const struct arm_cpu_capabilities *entry)
|
|||||||
case ARM_SSBD_FORCE_DISABLE:
|
case ARM_SSBD_FORCE_DISABLE:
|
||||||
printk_once("%s disabled from command-line\n", entry->desc);
|
printk_once("%s disabled from command-line\n", entry->desc);
|
||||||
|
|
||||||
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 0, NULL);
|
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 0);
|
||||||
required = false;
|
required = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -437,7 +437,7 @@ static bool has_ssbd_mitigation(const struct arm_cpu_capabilities *entry)
|
|||||||
if ( required )
|
if ( required )
|
||||||
{
|
{
|
||||||
this_cpu(ssbd_callback_required) = 1;
|
this_cpu(ssbd_callback_required) = 1;
|
||||||
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 1, NULL);
|
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -445,7 +445,7 @@ static bool has_ssbd_mitigation(const struct arm_cpu_capabilities *entry)
|
|||||||
case ARM_SSBD_FORCE_ENABLE:
|
case ARM_SSBD_FORCE_ENABLE:
|
||||||
printk_once("%s forced from command-line\n", entry->desc);
|
printk_once("%s forced from command-line\n", entry->desc);
|
||||||
|
|
||||||
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 1, NULL);
|
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 1);
|
||||||
required = true;
|
required = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -95,20 +95,14 @@ struct arm_smccc_res {
|
|||||||
unsigned long a3;
|
unsigned long a3;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SMCCC v1.1 implementation madness follows */
|
#define __constraint_read_1 "r" (arg0)
|
||||||
#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
|
#define __constraint_read_2 __constraint_read_1, "r" (arg1)
|
||||||
|
#define __constraint_read_3 __constraint_read_2, "r" (arg2)
|
||||||
#define __count_args(...) \
|
#define __constraint_read_4 __constraint_read_3, "r" (arg3)
|
||||||
___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
|
#define __constraint_read_5 __constraint_read_4, "r" (arg4)
|
||||||
|
#define __constraint_read_6 __constraint_read_5, "r" (arg5)
|
||||||
#define __constraint_read_0 "r" (arg0)
|
#define __constraint_read_7 __constraint_read_6, "r" (arg6)
|
||||||
#define __constraint_read_1 __constraint_read_0, "r" (arg1)
|
#define __constraint_read_8 __constraint_read_7, "r" (arg7)
|
||||||
#define __constraint_read_2 __constraint_read_1, "r" (arg2)
|
|
||||||
#define __constraint_read_3 __constraint_read_2, "r" (arg3)
|
|
||||||
#define __constraint_read_4 __constraint_read_3, "r" (arg4)
|
|
||||||
#define __constraint_read_5 __constraint_read_4, "r" (arg5)
|
|
||||||
#define __constraint_read_6 __constraint_read_5, "r" (arg6)
|
|
||||||
#define __constraint_read_7 __constraint_read_6, "r" (arg7)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macro arguments MUST be evaluated before being assigned to a register
|
* Macro arguments MUST be evaluated before being assigned to a register
|
||||||
@@ -117,44 +111,43 @@ struct arm_smccc_res {
|
|||||||
* This is manual register scheduling for the asm() statement, and any other
|
* This is manual register scheduling for the asm() statement, and any other
|
||||||
* logic to evaluate may clobber the already-scheduled registers.
|
* logic to evaluate may clobber the already-scheduled registers.
|
||||||
*/
|
*/
|
||||||
#define __declare_arg_0(a0, res) \
|
#define __declare_arg_1(a0) \
|
||||||
auto __a0 = (uint32_t)(a0); \
|
auto __a0 = (uint32_t)(a0); \
|
||||||
struct arm_smccc_res *___res = (res); \
|
|
||||||
register unsigned long arg0 ASM_REG(0) = __a0
|
register unsigned long arg0 ASM_REG(0) = __a0
|
||||||
|
|
||||||
#define __declare_arg_1(a0, a1, res) \
|
#define __declare_arg_2(a0, a1) \
|
||||||
auto __a1 = (a1); \
|
auto __a1 = (a1); \
|
||||||
__declare_arg_0(a0, res); \
|
__declare_arg_1(a0); \
|
||||||
register auto arg1 ASM_REG(1) = __a1
|
register auto arg1 ASM_REG(1) = __a1
|
||||||
|
|
||||||
#define __declare_arg_2(a0, a1, a2, res) \
|
#define __declare_arg_3(a0, a1, a2) \
|
||||||
auto __a2 = (a2); \
|
auto __a2 = (a2); \
|
||||||
__declare_arg_1(a0, a1, res); \
|
__declare_arg_2(a0, a1); \
|
||||||
register auto arg2 ASM_REG(2) = __a2
|
register auto arg2 ASM_REG(2) = __a2
|
||||||
|
|
||||||
#define __declare_arg_3(a0, a1, a2, a3, res) \
|
#define __declare_arg_4(a0, a1, a2, a3) \
|
||||||
auto __a3 = (a3); \
|
auto __a3 = (a3); \
|
||||||
__declare_arg_2(a0, a1, a2, res); \
|
__declare_arg_3(a0, a1, a2); \
|
||||||
register auto arg3 ASM_REG(3) = __a3
|
register auto arg3 ASM_REG(3) = __a3
|
||||||
|
|
||||||
#define __declare_arg_4(a0, a1, a2, a3, a4, res) \
|
#define __declare_arg_5(a0, a1, a2, a3, a4) \
|
||||||
auto __a4 = (a4); \
|
auto __a4 = (a4); \
|
||||||
__declare_arg_3(a0, a1, a2, a3, res); \
|
__declare_arg_4(a0, a1, a2, a3); \
|
||||||
register auto arg4 ASM_REG(4) = __a4
|
register auto arg4 ASM_REG(4) = __a4
|
||||||
|
|
||||||
#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res) \
|
#define __declare_arg_6(a0, a1, a2, a3, a4, a5) \
|
||||||
auto __a5 = (a5); \
|
auto __a5 = (a5); \
|
||||||
__declare_arg_4(a0, a1, a2, a3, a4, res); \
|
__declare_arg_5(a0, a1, a2, a3, a4); \
|
||||||
register auto arg5 ASM_REG(5) = __a5
|
register auto arg5 ASM_REG(5) = __a5
|
||||||
|
|
||||||
#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res) \
|
#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6) \
|
||||||
auto __a6 = (a6); \
|
auto __a6 = (a6); \
|
||||||
__declare_arg_5(a0, a1, a2, a3, a4, a5, res); \
|
__declare_arg_6(a0, a1, a2, a3, a4, a5); \
|
||||||
register auto arg6 ASM_REG(6) = __a6
|
register auto arg6 ASM_REG(6) = __a6
|
||||||
|
|
||||||
#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res) \
|
#define __declare_arg_8(a0, a1, a2, a3, a4, a5, a6, a7) \
|
||||||
auto __a7 = (a7); \
|
auto __a7 = (a7); \
|
||||||
__declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res); \
|
__declare_arg_7(a0, a1, a2, a3, a4, a5, a6); \
|
||||||
register auto arg7 ASM_REG(7) = __a7
|
register auto arg7 ASM_REG(7) = __a7
|
||||||
|
|
||||||
#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
|
#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
|
||||||
@@ -166,36 +159,34 @@ struct arm_smccc_res {
|
|||||||
* arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
|
* arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
|
||||||
*
|
*
|
||||||
* This is a variadic macro taking one to eight source arguments, and
|
* This is a variadic macro taking one to eight source arguments, and
|
||||||
* an optional return structure.
|
* returns four values.
|
||||||
*
|
*
|
||||||
* @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 macro is used to make SMC calls following SMC Calling Convention v1.1.
|
* This macro is used to make SMC calls following SMC Calling Convention v1.1.
|
||||||
* 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.
|
||||||
* from register 0 to 3 on return from the SMC instruction if not NULL.
|
|
||||||
*
|
*
|
||||||
* We have an output list that is not necessarily used, and GCC feels
|
* We have an output list that is not necessarily used, and GCC feels
|
||||||
* entitled to optimise the whole sequence away. "volatile" is what
|
* entitled to optimise the whole sequence away. "volatile" is what
|
||||||
* makes it stick.
|
* makes it stick.
|
||||||
*/
|
*/
|
||||||
#define arm_smccc_1_1_smc(...) \
|
#define arm_smccc_1_1_smc(...) \
|
||||||
do { \
|
({ \
|
||||||
register unsigned long r0 ASM_REG(0); \
|
register unsigned long r0 ASM_REG(0); \
|
||||||
register unsigned long r1 ASM_REG(1); \
|
register unsigned long r1 ASM_REG(1); \
|
||||||
register unsigned long r2 ASM_REG(2); \
|
register unsigned long r2 ASM_REG(2); \
|
||||||
register unsigned long r3 ASM_REG(3); \
|
register unsigned long r3 ASM_REG(3); \
|
||||||
__declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \
|
__declare_args(count_args(__VA_ARGS__), __VA_ARGS__); \
|
||||||
asm volatile ( \
|
asm volatile ( \
|
||||||
"smc #0" \
|
"smc #0" \
|
||||||
: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3) \
|
: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3) \
|
||||||
: PASTE(__constraint_read_, \
|
: PASTE(__constraint_read_, \
|
||||||
__count_args(__VA_ARGS__)) \
|
count_args(__VA_ARGS__)) \
|
||||||
: "memory" ); \
|
: "memory" ); \
|
||||||
if ( ___res ) \
|
(struct arm_smccc_res){ r0, r1, r2, r3 }; \
|
||||||
*___res = (struct arm_smccc_res){ r0, r1, r2, r3 }; \
|
})
|
||||||
} while ( 0 )
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The calling convention for arm32 is the same for both SMCCC v1.0 and
|
* The calling convention for arm32 is the same for both SMCCC v1.0 and
|
||||||
@@ -208,8 +199,8 @@ static inline void arm_smccc_guest_smc(struct cpu_user_regs *regs)
|
|||||||
{
|
{
|
||||||
struct arm_smccc_res res;
|
struct arm_smccc_res res;
|
||||||
|
|
||||||
arm_smccc_1_1_smc(regs->r0, regs->r1, regs->r2, regs->r3,
|
res = arm_smccc_1_1_smc(regs->r0, regs->r1, regs->r2, regs->r3,
|
||||||
regs->r4, regs->r5, regs->r6, regs->r7, &res);
|
regs->r4, regs->r5, regs->r6, regs->r7);
|
||||||
|
|
||||||
regs->r0 = res.a0;
|
regs->r0 = res.a0;
|
||||||
regs->r1 = res.a1;
|
regs->r1 = res.a1;
|
||||||
@@ -226,7 +217,7 @@ static inline void arm_smccc_guest_smc(struct cpu_user_regs *regs)
|
|||||||
* are strictly preserved. Always mark x4 through x17 as clobbered.
|
* are strictly preserved. Always mark x4 through x17 as clobbered.
|
||||||
*/
|
*/
|
||||||
#define arm_smccc_smc(...) \
|
#define arm_smccc_smc(...) \
|
||||||
do { \
|
({ \
|
||||||
register unsigned long r0 ASM_REG(0); \
|
register unsigned long r0 ASM_REG(0); \
|
||||||
register unsigned long r1 ASM_REG(1); \
|
register unsigned long r1 ASM_REG(1); \
|
||||||
register unsigned long r2 ASM_REG(2); \
|
register unsigned long r2 ASM_REG(2); \
|
||||||
@@ -246,7 +237,7 @@ static inline void arm_smccc_guest_smc(struct cpu_user_regs *regs)
|
|||||||
register unsigned long c15 ASM_REG(15); \
|
register unsigned long c15 ASM_REG(15); \
|
||||||
register unsigned long c16 ASM_REG(16); \
|
register unsigned long c16 ASM_REG(16); \
|
||||||
register unsigned long c17 ASM_REG(17); \
|
register unsigned long c17 ASM_REG(17); \
|
||||||
__declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \
|
__declare_args(count_args(__VA_ARGS__), __VA_ARGS__); \
|
||||||
asm volatile ( \
|
asm volatile ( \
|
||||||
"smc #0" \
|
"smc #0" \
|
||||||
: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3), \
|
: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3), \
|
||||||
@@ -255,11 +246,10 @@ static inline void arm_smccc_guest_smc(struct cpu_user_regs *regs)
|
|||||||
"=r" (c12), "=r" (c13), "=r" (c14), "=r" (c15), \
|
"=r" (c12), "=r" (c13), "=r" (c14), "=r" (c15), \
|
||||||
"=r" (c16), "=r" (c17) \
|
"=r" (c16), "=r" (c17) \
|
||||||
: PASTE(__constraint_read_, \
|
: PASTE(__constraint_read_, \
|
||||||
__count_args(__VA_ARGS__)) \
|
count_args(__VA_ARGS__)) \
|
||||||
: "memory" ); \
|
: "memory" ); \
|
||||||
if ( ___res ) \
|
(struct arm_smccc_res){ r0, r1, r2, r3 }; \
|
||||||
*___res = (struct arm_smccc_res){ r0, r1, r2, r3 }; \
|
})
|
||||||
} while ( 0 )
|
|
||||||
|
|
||||||
#define arm_smccc_1_1_smc(...) arm_smccc_smc(__VA_ARGS__)
|
#define arm_smccc_1_1_smc(...) arm_smccc_smc(__VA_ARGS__)
|
||||||
|
|
||||||
@@ -268,8 +258,8 @@ static inline void arm_smccc_guest_smc(struct cpu_user_regs *regs)
|
|||||||
{
|
{
|
||||||
struct arm_smccc_res res;
|
struct arm_smccc_res res;
|
||||||
|
|
||||||
arm_smccc_1_1_smc(regs->x0, regs->x1, regs->x2, regs->x3,
|
res = arm_smccc_1_1_smc(regs->x0, regs->x1, regs->x2, regs->x3,
|
||||||
regs->x4, regs->x5, regs->x6, regs->x7, &res);
|
regs->x4, regs->x5, regs->x6, regs->x7);
|
||||||
|
|
||||||
regs->x0 = res.a0;
|
regs->x0 = res.a0;
|
||||||
regs->x1 = res.a1;
|
regs->x1 = res.a1;
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ static int exynos5_cpu_up(int cpu)
|
|||||||
iounmap(power);
|
iounmap(power);
|
||||||
|
|
||||||
if ( secure_firmware )
|
if ( secure_firmware )
|
||||||
arm_smccc_smc(SMC_CMD_CPU1BOOT, cpu, NULL);
|
arm_smccc_smc(SMC_CMD_CPU1BOOT, cpu);
|
||||||
|
|
||||||
return cpu_up_send_sgi(cpu);
|
return cpu_up_send_sgi(cpu);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ static const char * const seattle_dt_compat[] __initconst =
|
|||||||
*/
|
*/
|
||||||
static void seattle_system_reset(void)
|
static void seattle_system_reset(void)
|
||||||
{
|
{
|
||||||
arm_smccc_smc(PSCI_0_2_FN32_SYSTEM_RESET, NULL);
|
arm_smccc_smc(PSCI_0_2_FN32_SYSTEM_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void seattle_system_off(void)
|
static void seattle_system_off(void)
|
||||||
{
|
{
|
||||||
arm_smccc_smc(PSCI_0_2_FN32_SYSTEM_OFF, NULL);
|
arm_smccc_smc(PSCI_0_2_FN32_SYSTEM_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLATFORM_START(seattle, "SEATTLE")
|
PLATFORM_START(seattle, "SEATTLE")
|
||||||
|
|||||||
+8
-9
@@ -41,8 +41,8 @@ int call_psci_cpu_on(int cpu)
|
|||||||
{
|
{
|
||||||
struct arm_smccc_res res;
|
struct arm_smccc_res res;
|
||||||
|
|
||||||
arm_smccc_smc(psci_cpu_on_nr, cpu_logical_map(cpu), __pa(init_secondary),
|
res = arm_smccc_smc(psci_cpu_on_nr, cpu_logical_map(cpu),
|
||||||
&res);
|
__pa(init_secondary));
|
||||||
|
|
||||||
return PSCI_RET(res);
|
return PSCI_RET(res);
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ void call_psci_cpu_off(void)
|
|||||||
struct arm_smccc_res res;
|
struct arm_smccc_res res;
|
||||||
|
|
||||||
/* If successfull the PSCI cpu_off call doesn't return */
|
/* If successfull the PSCI cpu_off call doesn't return */
|
||||||
arm_smccc_smc(PSCI_0_2_FN32_CPU_OFF, &res);
|
res = arm_smccc_smc(PSCI_0_2_FN32_CPU_OFF);
|
||||||
panic("PSCI cpu off failed for CPU%d err=%d\n", smp_processor_id(),
|
panic("PSCI cpu off failed for CPU%d err=%d\n", smp_processor_id(),
|
||||||
PSCI_RET(res));
|
PSCI_RET(res));
|
||||||
}
|
}
|
||||||
@@ -63,13 +63,13 @@ void call_psci_cpu_off(void)
|
|||||||
void call_psci_system_off(void)
|
void call_psci_system_off(void)
|
||||||
{
|
{
|
||||||
if ( psci_ver > PSCI_VERSION(0, 1) )
|
if ( psci_ver > PSCI_VERSION(0, 1) )
|
||||||
arm_smccc_smc(PSCI_0_2_FN32_SYSTEM_OFF, NULL);
|
arm_smccc_smc(PSCI_0_2_FN32_SYSTEM_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void call_psci_system_reset(void)
|
void call_psci_system_reset(void)
|
||||||
{
|
{
|
||||||
if ( psci_ver > PSCI_VERSION(0, 1) )
|
if ( psci_ver > PSCI_VERSION(0, 1) )
|
||||||
arm_smccc_smc(PSCI_0_2_FN32_SYSTEM_RESET, NULL);
|
arm_smccc_smc(PSCI_0_2_FN32_SYSTEM_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init psci_features(uint32_t psci_func_id)
|
static int __init psci_features(uint32_t psci_func_id)
|
||||||
@@ -79,7 +79,7 @@ static int __init psci_features(uint32_t psci_func_id)
|
|||||||
if ( psci_ver < PSCI_VERSION(1, 0) )
|
if ( psci_ver < PSCI_VERSION(1, 0) )
|
||||||
return PSCI_NOT_SUPPORTED;
|
return PSCI_NOT_SUPPORTED;
|
||||||
|
|
||||||
arm_smccc_smc(PSCI_1_0_FN32_PSCI_FEATURES, psci_func_id, &res);
|
res = arm_smccc_smc(PSCI_1_0_FN32_PSCI_FEATURES, psci_func_id);
|
||||||
|
|
||||||
return PSCI_RET(res);
|
return PSCI_RET(res);
|
||||||
}
|
}
|
||||||
@@ -116,9 +116,8 @@ static void __init psci_init_smccc(void)
|
|||||||
|
|
||||||
if ( psci_features(ARM_SMCCC_VERSION_FID) != PSCI_NOT_SUPPORTED )
|
if ( psci_features(ARM_SMCCC_VERSION_FID) != PSCI_NOT_SUPPORTED )
|
||||||
{
|
{
|
||||||
struct arm_smccc_res res;
|
struct arm_smccc_res res = arm_smccc_smc(ARM_SMCCC_VERSION_FID);
|
||||||
|
|
||||||
arm_smccc_smc(ARM_SMCCC_VERSION_FID, &res);
|
|
||||||
if ( PSCI_RET(res) != ARM_SMCCC_NOT_SUPPORTED )
|
if ( PSCI_RET(res) != ARM_SMCCC_NOT_SUPPORTED )
|
||||||
smccc_ver = PSCI_RET(res);
|
smccc_ver = PSCI_RET(res);
|
||||||
}
|
}
|
||||||
@@ -191,7 +190,7 @@ static int __init psci_init_0_2(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arm_smccc_smc(PSCI_0_2_FN32_PSCI_VERSION, &res);
|
res = arm_smccc_smc(PSCI_0_2_FN32_PSCI_VERSION);
|
||||||
psci_ver = PSCI_RET(res);
|
psci_ver = PSCI_RET(res);
|
||||||
|
|
||||||
/* For the moment, we only support PSCI 0.2 and PSCI 1.x */
|
/* For the moment, we only support PSCI 0.2 and PSCI 1.x */
|
||||||
|
|||||||
+25
-25
@@ -178,7 +178,7 @@ static bool optee_probe(void)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Check UID */
|
/* Check UID */
|
||||||
arm_smccc_smc(ARM_SMCCC_CALL_UID_FID(TRUSTED_OS_END), &resp);
|
resp = arm_smccc_smc(ARM_SMCCC_CALL_UID_FID(TRUSTED_OS_END));
|
||||||
|
|
||||||
if ( (uint32_t)resp.a0 != OPTEE_MSG_UID_0 ||
|
if ( (uint32_t)resp.a0 != OPTEE_MSG_UID_0 ||
|
||||||
(uint32_t)resp.a1 != OPTEE_MSG_UID_1 ||
|
(uint32_t)resp.a1 != OPTEE_MSG_UID_1 ||
|
||||||
@@ -187,7 +187,7 @@ static bool optee_probe(void)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Read number of threads */
|
/* Read number of threads */
|
||||||
arm_smccc_smc(OPTEE_SMC_GET_THREAD_COUNT, &resp);
|
resp = arm_smccc_smc(OPTEE_SMC_GET_THREAD_COUNT);
|
||||||
if ( resp.a0 == OPTEE_SMC_RETURN_OK )
|
if ( resp.a0 == OPTEE_SMC_RETURN_OK )
|
||||||
{
|
{
|
||||||
max_optee_threads = resp.a1;
|
max_optee_threads = resp.a1;
|
||||||
@@ -209,7 +209,7 @@ static bool optee_probe(void)
|
|||||||
* call. It will return OPTEE_SMC_RETURN_UNKNOWN_FUNCTION if
|
* call. It will return OPTEE_SMC_RETURN_UNKNOWN_FUNCTION if
|
||||||
* OP-TEE have no virtualization support enabled.
|
* OP-TEE have no virtualization support enabled.
|
||||||
*/
|
*/
|
||||||
arm_smccc_smc(OPTEE_SMC_VM_DESTROYED, 0, 0, 0, 0, 0, 0, 0, &resp);
|
resp = arm_smccc_smc(OPTEE_SMC_VM_DESTROYED, 0, 0, 0, 0, 0, 0, 0);
|
||||||
if ( resp.a0 == OPTEE_SMC_RETURN_UNKNOWN_FUNCTION )
|
if ( resp.a0 == OPTEE_SMC_RETURN_UNKNOWN_FUNCTION )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -243,8 +243,8 @@ static int optee_domain_init(struct domain *d)
|
|||||||
*
|
*
|
||||||
* a7 should be 0, so we can't skip last 6 parameters of arm_smccc_smc()
|
* a7 should be 0, so we can't skip last 6 parameters of arm_smccc_smc()
|
||||||
*/
|
*/
|
||||||
arm_smccc_smc(OPTEE_SMC_VM_CREATED, OPTEE_CLIENT_ID(d), 0, 0, 0, 0, 0, 0,
|
resp = arm_smccc_smc(OPTEE_SMC_VM_CREATED, OPTEE_CLIENT_ID(d),
|
||||||
&resp);
|
0, 0, 0, 0, 0, 0);
|
||||||
if ( resp.a0 != OPTEE_SMC_RETURN_OK )
|
if ( resp.a0 != OPTEE_SMC_RETURN_OK )
|
||||||
{
|
{
|
||||||
printk(XENLOG_WARNING "%pd: Unable to create OPTEE client: rc = 0x%X\n",
|
printk(XENLOG_WARNING "%pd: Unable to create OPTEE client: rc = 0x%X\n",
|
||||||
@@ -681,8 +681,8 @@ static int optee_relinquish_resources(struct domain *d)
|
|||||||
*
|
*
|
||||||
* a7 should be 0, so we can't skip last 6 parameters of arm_smccc_smc()
|
* a7 should be 0, so we can't skip last 6 parameters of arm_smccc_smc()
|
||||||
*/
|
*/
|
||||||
arm_smccc_smc(OPTEE_SMC_VM_DESTROYED, OPTEE_CLIENT_ID(d), 0, 0, 0, 0, 0, 0,
|
resp = arm_smccc_smc(OPTEE_SMC_VM_DESTROYED, OPTEE_CLIENT_ID(d),
|
||||||
&resp);
|
0, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
ASSERT(!spin_is_locked(&ctx->lock));
|
ASSERT(!spin_is_locked(&ctx->lock));
|
||||||
ASSERT(!atomic_read(&ctx->call_count));
|
ASSERT(!atomic_read(&ctx->call_count));
|
||||||
@@ -1171,15 +1171,15 @@ static void do_call_with_arg(struct optee_domain *ctx,
|
|||||||
{
|
{
|
||||||
struct arm_smccc_res res;
|
struct arm_smccc_res res;
|
||||||
|
|
||||||
arm_smccc_smc(a0, a1, a2, a3, a4, a5, 0, OPTEE_CLIENT_ID(current->domain),
|
res = arm_smccc_smc(a0, a1, a2, a3, a4, a5, 0,
|
||||||
&res);
|
OPTEE_CLIENT_ID(current->domain));
|
||||||
|
|
||||||
if ( OPTEE_SMC_RETURN_IS_RPC(res.a0) )
|
if ( OPTEE_SMC_RETURN_IS_RPC(res.a0) )
|
||||||
{
|
{
|
||||||
while ( handle_rpc_return(ctx, &res, regs, call) == -ERESTART )
|
while ( handle_rpc_return(ctx, &res, regs, call) == -ERESTART )
|
||||||
{
|
{
|
||||||
arm_smccc_smc(res.a0, res.a1, res.a2, res.a3, 0, 0, 0,
|
res = arm_smccc_smc(res.a0, res.a1, res.a2, res.a3, 0, 0, 0,
|
||||||
OPTEE_CLIENT_ID(current->domain), &res);
|
OPTEE_CLIENT_ID(current->domain));
|
||||||
|
|
||||||
if ( !OPTEE_SMC_RETURN_IS_RPC(res.a0) )
|
if ( !OPTEE_SMC_RETURN_IS_RPC(res.a0) )
|
||||||
break;
|
break;
|
||||||
@@ -1619,8 +1619,8 @@ static void handle_exchange_capabilities(struct cpu_user_regs *regs)
|
|||||||
caps = get_user_reg(regs, 1);
|
caps = get_user_reg(regs, 1);
|
||||||
caps &= OPTEE_KNOWN_NSEC_CAPS;
|
caps &= OPTEE_KNOWN_NSEC_CAPS;
|
||||||
|
|
||||||
arm_smccc_smc(OPTEE_SMC_EXCHANGE_CAPABILITIES, caps, 0, 0, 0, 0, 0,
|
resp = arm_smccc_smc(OPTEE_SMC_EXCHANGE_CAPABILITIES, caps, 0, 0, 0, 0, 0,
|
||||||
OPTEE_CLIENT_ID(current->domain), &resp);
|
OPTEE_CLIENT_ID(current->domain));
|
||||||
if ( resp.a0 != OPTEE_SMC_RETURN_OK ) {
|
if ( resp.a0 != OPTEE_SMC_RETURN_OK ) {
|
||||||
set_user_reg(regs, 0, resp.a0);
|
set_user_reg(regs, 0, resp.a0);
|
||||||
return;
|
return;
|
||||||
@@ -1664,8 +1664,8 @@ static bool optee_handle_call(struct cpu_user_regs *regs)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case OPTEE_SMC_CALLS_UID:
|
case OPTEE_SMC_CALLS_UID:
|
||||||
arm_smccc_smc(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0,
|
resp = arm_smccc_smc(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0,
|
||||||
OPTEE_CLIENT_ID(current->domain), &resp);
|
OPTEE_CLIENT_ID(current->domain));
|
||||||
set_user_reg(regs, 0, resp.a0);
|
set_user_reg(regs, 0, resp.a0);
|
||||||
set_user_reg(regs, 1, resp.a1);
|
set_user_reg(regs, 1, resp.a1);
|
||||||
set_user_reg(regs, 2, resp.a2);
|
set_user_reg(regs, 2, resp.a2);
|
||||||
@@ -1673,15 +1673,15 @@ static bool optee_handle_call(struct cpu_user_regs *regs)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case OPTEE_SMC_CALLS_REVISION:
|
case OPTEE_SMC_CALLS_REVISION:
|
||||||
arm_smccc_smc(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0,
|
resp = arm_smccc_smc(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0,
|
||||||
OPTEE_CLIENT_ID(current->domain), &resp);
|
OPTEE_CLIENT_ID(current->domain));
|
||||||
set_user_reg(regs, 0, resp.a0);
|
set_user_reg(regs, 0, resp.a0);
|
||||||
set_user_reg(regs, 1, resp.a1);
|
set_user_reg(regs, 1, resp.a1);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case OPTEE_SMC_CALL_GET_OS_UUID:
|
case OPTEE_SMC_CALL_GET_OS_UUID:
|
||||||
arm_smccc_smc(OPTEE_SMC_CALL_GET_OS_UUID, 0, 0, 0, 0, 0, 0,
|
resp = arm_smccc_smc(OPTEE_SMC_CALL_GET_OS_UUID, 0, 0, 0, 0, 0, 0,
|
||||||
OPTEE_CLIENT_ID(current->domain),&resp);
|
OPTEE_CLIENT_ID(current->domain));
|
||||||
set_user_reg(regs, 0, resp.a0);
|
set_user_reg(regs, 0, resp.a0);
|
||||||
set_user_reg(regs, 1, resp.a1);
|
set_user_reg(regs, 1, resp.a1);
|
||||||
set_user_reg(regs, 2, resp.a2);
|
set_user_reg(regs, 2, resp.a2);
|
||||||
@@ -1689,21 +1689,21 @@ static bool optee_handle_call(struct cpu_user_regs *regs)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case OPTEE_SMC_CALL_GET_OS_REVISION:
|
case OPTEE_SMC_CALL_GET_OS_REVISION:
|
||||||
arm_smccc_smc(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0,
|
resp = arm_smccc_smc(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0,
|
||||||
OPTEE_CLIENT_ID(current->domain), &resp);
|
OPTEE_CLIENT_ID(current->domain));
|
||||||
set_user_reg(regs, 0, resp.a0);
|
set_user_reg(regs, 0, resp.a0);
|
||||||
set_user_reg(regs, 1, resp.a1);
|
set_user_reg(regs, 1, resp.a1);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case OPTEE_SMC_ENABLE_SHM_CACHE:
|
case OPTEE_SMC_ENABLE_SHM_CACHE:
|
||||||
arm_smccc_smc(OPTEE_SMC_ENABLE_SHM_CACHE, 0, 0, 0, 0, 0, 0,
|
resp = arm_smccc_smc(OPTEE_SMC_ENABLE_SHM_CACHE, 0, 0, 0, 0, 0, 0,
|
||||||
OPTEE_CLIENT_ID(current->domain), &resp);
|
OPTEE_CLIENT_ID(current->domain));
|
||||||
set_user_reg(regs, 0, resp.a0);
|
set_user_reg(regs, 0, resp.a0);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case OPTEE_SMC_DISABLE_SHM_CACHE:
|
case OPTEE_SMC_DISABLE_SHM_CACHE:
|
||||||
arm_smccc_smc(OPTEE_SMC_DISABLE_SHM_CACHE, 0, 0, 0, 0, 0, 0,
|
resp = arm_smccc_smc(OPTEE_SMC_DISABLE_SHM_CACHE, 0, 0, 0, 0, 0, 0,
|
||||||
OPTEE_CLIENT_ID(current->domain), &resp);
|
OPTEE_CLIENT_ID(current->domain));
|
||||||
set_user_reg(regs, 0, resp.a0);
|
set_user_reg(regs, 0, resp.a0);
|
||||||
if ( resp.a0 == OPTEE_SMC_RETURN_OK ) {
|
if ( resp.a0 == OPTEE_SMC_RETURN_OK ) {
|
||||||
free_shm_rpc(ctx, regpair_to_uint64(resp.a1, resp.a2));
|
free_shm_rpc(ctx, regpair_to_uint64(resp.a1, resp.a2));
|
||||||
|
|||||||
@@ -1991,7 +1991,7 @@ void asmlinkage enter_hypervisor_from_guest_preirq(void)
|
|||||||
|
|
||||||
/* If the guest has disabled the workaround, bring it back on. */
|
/* If the guest has disabled the workaround, bring it back on. */
|
||||||
if ( needs_ssbd_flip(v) )
|
if ( needs_ssbd_flip(v) )
|
||||||
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 1, NULL);
|
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2334,7 +2334,7 @@ void asmlinkage leave_hypervisor_to_guest(void)
|
|||||||
* If the guest wants it disabled, so be it...
|
* If the guest wants it disabled, so be it...
|
||||||
*/
|
*/
|
||||||
if ( needs_ssbd_flip(current) )
|
if ( needs_ssbd_flip(current) )
|
||||||
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 0, NULL);
|
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||