@@ -96,26 +96,59 @@ start:
.text
/*
- * psci_invoke_hvc / psci_invoke_smc
+ * arm_smccc_hvc / arm_smccc_smc
*
* Inputs:
* r0 -- function_id
* r1 -- arg0
* r2 -- arg1
* r3 -- arg2
+ * [sp] - arg3
+ * [sp + #4] - arg4
+ * [sp + #8] - arg5
+ * [sp + #12] - arg6
+ * [sp + #16] - arg7
+ * [sp + #20] - arg8
+ * [sp + #24] - arg9
+ * [sp + #28] - arg10
+ * [sp + #32] - result (as a pointer to a struct smccc_result)
*
* Outputs:
* r0 -- return code
+ *
+ * If result pointer is not NULL:
+ * result.r0 -- return code
+ * result.r1 -- r1
+ * result.r2 -- r2
+ * result.r3 -- r3
+ * result.r4 -- r4
+ * result.r5 -- r5
+ * result.r6 -- r6
+ * result.r7 -- r7
+ * result.r8 -- r8
+ * result.r9 -- r9
*/
-.globl psci_invoke_hvc
-psci_invoke_hvc:
- hvc #0
+.macro do_smccc_call instr
+ mov r12, sp
+ push {r4-r11}
+ ldm r12, {r4-r11}
+ \instr #0
+ ldr r10, [sp, #64]
+ cmp r10, #0
+ beq 1f
+ stm r10, {r0-r9}
+1:
+ pop {r4-r11}
mov pc, lr
+.endm
-.globl psci_invoke_smc
-psci_invoke_smc:
- smc #0
- mov pc, lr
+.globl arm_smccc_hvc
+arm_smccc_hvc:
+ do_smccc_call hvc
+
+.globl arm_smccc_smc
+arm_smccc_smc:
+ do_smccc_call smc
enable_vfp:
/* Enable full access to CP10 and CP11: */
@@ -110,26 +110,65 @@ start:
.text
/*
- * psci_invoke_hvc / psci_invoke_smc
+ * arm_smccc_hvc / arm_smccc_smc
*
* Inputs:
* w0 -- function_id
* x1 -- arg0
* x2 -- arg1
* x3 -- arg2
+ * x4 -- arg3
+ * x5 -- arg4
+ * x6 -- arg5
+ * x7 -- arg6
+ * sp -- { arg7, arg8, arg9, arg10, result }
*
* Outputs:
* x0 -- return code
+ *
+ * If result pointer is not NULL:
+ * result.r0 -- return code
+ * result.r1 -- x1
+ * result.r2 -- x2
+ * result.r3 -- x3
+ * result.r4 -- x4
+ * result.r5 -- x5
+ * result.r6 -- x6
+ * result.r7 -- x7
+ * result.r8 -- x8
+ * result.r9 -- x9
*/
-.globl psci_invoke_hvc
-psci_invoke_hvc:
- hvc #0
+.macro do_smccc_call instr
+ /* Save x8-x11 on stack */
+ stp x9, x8, [sp, #-16]!
+ stp x11, x10, [sp, #-16]!
+ /* Load arg7 - arg10 from the stack */
+ ldp x8, x9, [sp, #32]
+ ldp x10, x11, [sp, #48]
+ \instr #0
+ /* Get the result address */
+ ldr x10, [sp, #64]
+ cmp x10, xzr
+ b.eq 1f
+ stp x0, x1, [x10, #0]
+ stp x2, x3, [x10, #16]
+ stp x4, x5, [x10, #32]
+ stp x6, x7, [x10, #48]
+ stp x8, x9, [x10, #64]
+1:
+ /* Restore x8-x11 from stack */
+ ldp x11, x10, [sp], #16
+ ldp x9, x8, [sp], #16
ret
+.endm
-.globl psci_invoke_smc
-psci_invoke_smc:
- smc #0
- ret
+.globl arm_smccc_hvc
+arm_smccc_hvc:
+ do_smccc_call hvc
+
+.globl arm_smccc_smc
+arm_smccc_smc:
+ do_smccc_call smc
get_mmu_off:
adrp x0, auxinfo
@@ -405,7 +405,7 @@ static void psci_print(void)
int ver = psci_invoke(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
report_info("PSCI version: %d.%d", PSCI_VERSION_MAJOR(ver),
PSCI_VERSION_MINOR(ver));
- report_info("PSCI method: %s", psci_invoke == psci_invoke_hvc ?
+ report_info("PSCI method: %s", psci_invoke_fn == arm_smccc_hvc ?
"hvc" : "smc");
}
new file mode 100644
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Arm Limited.
+ * All rights reserved.
+ */
+#ifndef _ASMARM_ARM_SMCCC_H_
+#define _ASMARM_ARM_SMCCC_H_
+
+struct smccc_result {
+ unsigned long r0;
+ unsigned long r1;
+ unsigned long r2;
+ unsigned long r3;
+ unsigned long r4;
+ unsigned long r5;
+ unsigned long r6;
+ unsigned long r7;
+ unsigned long r8;
+ unsigned long r9;
+};
+
+typedef int (*smccc_invoke_fn)(unsigned int function_id, unsigned long arg0,
+ unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4,
+ unsigned long arg5, unsigned long arg6,
+ unsigned long arg7, unsigned long arg8,
+ unsigned long arg9, unsigned long arg10,
+ struct smccc_result *result);
+extern int arm_smccc_hvc(unsigned int function_id, unsigned long arg0,
+ unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4,
+ unsigned long arg5, unsigned long arg6,
+ unsigned long arg7, unsigned long arg8,
+ unsigned long arg9, unsigned long arg10,
+ struct smccc_result *result);
+extern int arm_smccc_smc(unsigned int function_id, unsigned long arg0,
+ unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4,
+ unsigned long arg5, unsigned long arg6,
+ unsigned long arg7, unsigned long arg8,
+ unsigned long arg9, unsigned long arg10,
+ struct smccc_result *result);
+
+#endif /* _ASMARM_ARM_SMCCC_H_ */
@@ -3,13 +3,12 @@
#include <libcflat.h>
#include <linux/psci.h>
-typedef int (*psci_invoke_fn)(unsigned int function_id, unsigned long arg0,
- unsigned long arg1, unsigned long arg2);
-extern psci_invoke_fn psci_invoke;
-extern int psci_invoke_hvc(unsigned int function_id, unsigned long arg0,
- unsigned long arg1, unsigned long arg2);
-extern int psci_invoke_smc(unsigned int function_id, unsigned long arg0,
- unsigned long arg1, unsigned long arg2);
+#include <asm/arm-smccc.h>
+
+extern smccc_invoke_fn psci_invoke_fn;
+
+extern int psci_invoke(unsigned int function_id, unsigned long arg0,
+ unsigned long arg1, unsigned long arg2);
extern void psci_set_conduit(void);
extern int psci_cpu_on(unsigned long cpuid, unsigned long entry_point);
extern void psci_system_reset(void);
@@ -13,13 +13,24 @@
#include <asm/smp.h>
static int psci_invoke_none(unsigned int function_id, unsigned long arg0,
- unsigned long arg1, unsigned long arg2)
+ unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4,
+ unsigned long arg5, unsigned long arg6,
+ unsigned long arg7, unsigned long arg8,
+ unsigned long arg9, unsigned long arg10,
+ struct smccc_result *result)
{
printf("No PSCI method configured! Can't invoke...\n");
return PSCI_RET_NOT_PRESENT;
}
-psci_invoke_fn psci_invoke = psci_invoke_none;
+smccc_invoke_fn psci_invoke_fn = psci_invoke_none;
+
+int psci_invoke(unsigned int function_id, unsigned long arg0,
+ unsigned long arg1, unsigned long arg2)
+{
+ return psci_invoke_fn(function_id, arg0, arg1, arg2, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
+}
int psci_cpu_on(unsigned long cpuid, unsigned long entry_point)
{
@@ -69,9 +80,9 @@ void psci_set_conduit(void)
assert(method != NULL && len == 4);
if (strcmp(method->data, "hvc") == 0)
- psci_invoke = psci_invoke_hvc;
+ psci_invoke_fn = arm_smccc_hvc;
else if (strcmp(method->data, "smc") == 0)
- psci_invoke = psci_invoke_smc;
+ psci_invoke_fn = arm_smccc_smc;
else
assert_msg(false, "Unknown PSCI conduit: %s", method->data);
}
new file mode 100644
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Arm Limited.
+ * All rights reserved.
+ */
+#include "../../arm/asm/arm-smccc.h"