blob: dd2b96537f9a9ae5ede0a4f39dce0c68a6500c33 [file] [log] [blame]
Andrew Geissler9347dd42023-03-03 12:38:41 -06001From 9da48e3433b919868650cd60e28827273a42c63b Mon Sep 17 00:00:00 2001
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002From: Jaxson Han <jaxson.han@arm.com>
3Date: Tue, 25 Jan 2022 14:56:36 +0800
4Subject: [PATCH] PSCI: Add function call entry point
5
6The max exception level of Armv8R AArch64 is EL2, which means it has no
7exclusive EL for firmware. That is, firmware and hypervisors have to share
8the EL2. Also, hypervisors cannot call firmware services via a 'smc'
9instruction. Thus, boot-wrapper has to provide a function entry point
10for Armv8R AArch64.
11
12Issue-Id: SCM-3816
13Upstream-Status: Inappropriate [other]
14 Implementation pending further discussion
15Signed-off-by: Jaxson Han <jaxson.han@arm.com>
16Change-Id: I06ec8e50298603155c6d8ae2330e71db2f111182
17---
18 common/psci.c | 24 ++++++++++++++++++++----
19 1 file changed, 20 insertions(+), 4 deletions(-)
20
21diff --git a/common/psci.c b/common/psci.c
22index 6efc695..8fdefb5 100644
23--- a/common/psci.c
24+++ b/common/psci.c
25@@ -20,6 +20,8 @@
26
27 extern unsigned int spsr_to_elx;
28
29+unsigned long flag_from_smc_fn[NR_CPUS];
30+
31 static unsigned long branch_table[NR_CPUS];
32
33 bakery_ticket_t branch_table_lock[NR_CPUS];
34@@ -49,12 +51,14 @@ static int psci_cpu_on(unsigned long target_mpidr, unsigned long address)
35 return PSCI_RET_INVALID_PARAMETERS;
36
37 bakery_lock(branch_table_lock, this_cpu);
38- ret = psci_store_address(cpu, address);
39- bakery_unlock(branch_table_lock, this_cpu);
40-
41 #ifdef KEEP_EL
42- spsr_to_elx = SPSR_KERNEL_EL1;
43+ if (!flag_from_smc_fn[this_cpu]) {
44+ spsr_to_elx = SPSR_KERNEL_EL1;
45+ flush_per_cpu_data((void*)&(spsr_to_elx));
46+ }
47 #endif
48+ ret = psci_store_address(cpu, address);
49+ bakery_unlock(branch_table_lock, this_cpu);
50
51 return ret;
52 }
53@@ -90,6 +94,18 @@ long psci_call(unsigned long fid, unsigned long arg1, unsigned long arg2)
54 }
55 }
56
57+long smc_fn_entry(unsigned long fid, unsigned long arg1, unsigned long arg2)
58+{
59+ long ret;
60+ unsigned int this_cpu = this_cpu_logical_id();
61+
62+ flag_from_smc_fn[this_cpu] = 1;
63+ ret = psci_call(fid, arg1, arg2);
64+ flag_from_smc_fn[this_cpu] = 0;
65+
66+ return ret;
67+}
68+
69 void __noreturn psci_first_spin(unsigned int cpu)
70 {
71 if (cpu == MPIDR_INVALID)