aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2015-06-05 06:21:23 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2015-06-05 06:21:23 -0400
commitaddc8120a784181cc6410973948eee94ea16f2bd (patch)
treede84cba276c224bcc4c1070a58a4f19625960723
parenteb7c11ee3c5ce6c45ac28a5015a8e60ed458b412 (diff)
parentc5a1330573c1748179898f4799f130e416ce4738 (diff)
Merge branch 'arm64/psci-rework' of git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux
* 'arm64/psci-rework' of git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux: arm64: psci: remove ACPI coupling arm64: psci: kill psci_power_state arm64: psci: account for Trusted OS instances arm64: psci: support unsigned return values arm64: psci: remove unnecessary id indirection arm64: smp: consistently use error codes arm64: smp_plat: add get_logical_index arm/arm64: kvm: add missing PSCI include Conflicts: arch/arm64/kernel/smp.c
-rw-r--r--arch/arm/kvm/psci.c2
-rw-r--r--arch/arm64/include/asm/acpi.h15
-rw-r--r--arch/arm64/include/asm/psci.h12
-rw-r--r--arch/arm64/include/asm/smp_plat.h16
-rw-r--r--arch/arm64/kernel/acpi.c11
-rw-r--r--arch/arm64/kernel/psci.c231
-rw-r--r--arch/arm64/kernel/smp.c10
7 files changed, 175 insertions, 122 deletions
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 02fa8eff6ae1..7e9398c6b387 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -24,6 +24,8 @@
24#include <asm/kvm_psci.h> 24#include <asm/kvm_psci.h>
25#include <asm/kvm_host.h> 25#include <asm/kvm_host.h>
26 26
27#include <uapi/linux/psci.h>
28
27/* 29/*
28 * This is an implementation of the Power State Coordination Interface 30 * This is an implementation of the Power State Coordination Interface
29 * as described in ARM document number ARM DEN 0022A. 31 * as described in ARM document number ARM DEN 0022A.
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index 1240b867d4a2..39248d3adf5d 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -16,6 +16,7 @@
16#include <linux/irqchip/arm-gic-acpi.h> 16#include <linux/irqchip/arm-gic-acpi.h>
17 17
18#include <asm/cputype.h> 18#include <asm/cputype.h>
19#include <asm/psci.h>
19#include <asm/smp_plat.h> 20#include <asm/smp_plat.h>
20 21
21/* Basic configuration for ACPI */ 22/* Basic configuration for ACPI */
@@ -39,18 +40,6 @@ extern int acpi_disabled;
39extern int acpi_noirq; 40extern int acpi_noirq;
40extern int acpi_pci_disabled; 41extern int acpi_pci_disabled;
41 42
42/* 1 to indicate PSCI 0.2+ is implemented */
43static inline bool acpi_psci_present(void)
44{
45 return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_COMPLIANT;
46}
47
48/* 1 to indicate HVC must be used instead of SMC as the PSCI conduit */
49static inline bool acpi_psci_use_hvc(void)
50{
51 return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC;
52}
53
54static inline void disable_acpi(void) 43static inline void disable_acpi(void)
55{ 44{
56 acpi_disabled = 1; 45 acpi_disabled = 1;
@@ -88,8 +77,6 @@ static inline void arch_fix_phys_package_id(int num, u32 slot) { }
88void __init acpi_init_cpus(void); 77void __init acpi_init_cpus(void);
89 78
90#else 79#else
91static inline bool acpi_psci_present(void) { return false; }
92static inline bool acpi_psci_use_hvc(void) { return false; }
93static inline void acpi_init_cpus(void) { } 80static inline void acpi_init_cpus(void) { }
94#endif /* CONFIG_ACPI */ 81#endif /* CONFIG_ACPI */
95 82
diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h
index 2454bc59c916..49d7e1aaebdc 100644
--- a/arch/arm64/include/asm/psci.h
+++ b/arch/arm64/include/asm/psci.h
@@ -14,7 +14,15 @@
14#ifndef __ASM_PSCI_H 14#ifndef __ASM_PSCI_H
15#define __ASM_PSCI_H 15#define __ASM_PSCI_H
16 16
17int psci_dt_init(void); 17int __init psci_dt_init(void);
18int psci_acpi_init(void); 18
19#ifdef CONFIG_ACPI
20int __init psci_acpi_init(void);
21bool __init acpi_psci_present(void);
22bool __init acpi_psci_use_hvc(void);
23#else
24static inline int psci_acpi_init(void) { return 0; }
25static inline bool acpi_psci_present(void) { return false; }
26#endif
19 27
20#endif /* __ASM_PSCI_H */ 28#endif /* __ASM_PSCI_H */
diff --git a/arch/arm64/include/asm/smp_plat.h b/arch/arm64/include/asm/smp_plat.h
index 8dcd61e32176..7abf7570c00f 100644
--- a/arch/arm64/include/asm/smp_plat.h
+++ b/arch/arm64/include/asm/smp_plat.h
@@ -19,6 +19,8 @@
19#ifndef __ASM_SMP_PLAT_H 19#ifndef __ASM_SMP_PLAT_H
20#define __ASM_SMP_PLAT_H 20#define __ASM_SMP_PLAT_H
21 21
22#include <linux/cpumask.h>
23
22#include <asm/types.h> 24#include <asm/types.h>
23 25
24struct mpidr_hash { 26struct mpidr_hash {
@@ -39,6 +41,20 @@ static inline u32 mpidr_hash_size(void)
39 */ 41 */
40extern u64 __cpu_logical_map[NR_CPUS]; 42extern u64 __cpu_logical_map[NR_CPUS];
41#define cpu_logical_map(cpu) __cpu_logical_map[cpu] 43#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
44/*
45 * Retrieve logical cpu index corresponding to a given MPIDR.Aff*
46 * - mpidr: MPIDR.Aff* bits to be used for the look-up
47 *
48 * Returns the cpu logical index or -EINVAL on look-up error
49 */
50static inline int get_logical_index(u64 mpidr)
51{
52 int cpu;
53 for (cpu = 0; cpu < nr_cpu_ids; cpu++)
54 if (cpu_logical_map(cpu) == mpidr)
55 return cpu;
56 return -EINVAL;
57}
42 58
43void __init do_post_cpus_up_work(void); 59void __init do_post_cpus_up_work(void);
44 60
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 732f57b8731b..19de7537e7d3 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -89,6 +89,17 @@ void __init __acpi_unmap_table(char *map, unsigned long size)
89 early_memunmap(map, size); 89 early_memunmap(map, size);
90} 90}
91 91
92bool __init acpi_psci_present(void)
93{
94 return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_COMPLIANT;
95}
96
97/* Whether HVC must be used instead of SMC as the PSCI conduit */
98bool __init acpi_psci_use_hvc(void)
99{
100 return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC;
101}
102
92/* 103/*
93 * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity 104 * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity
94 * checks on it 105 * checks on it
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index efe3480a97a9..cba05d9bcbc6 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -15,7 +15,6 @@
15 15
16#define pr_fmt(fmt) "psci: " fmt 16#define pr_fmt(fmt) "psci: " fmt
17 17
18#include <linux/acpi.h>
19#include <linux/init.h> 18#include <linux/init.h>
20#include <linux/of.h> 19#include <linux/of.h>
21#include <linux/smp.h> 20#include <linux/smp.h>
@@ -25,8 +24,8 @@
25#include <linux/slab.h> 24#include <linux/slab.h>
26#include <uapi/linux/psci.h> 25#include <uapi/linux/psci.h>
27 26
28#include <asm/acpi.h>
29#include <asm/compiler.h> 27#include <asm/compiler.h>
28#include <asm/cputype.h>
30#include <asm/cpu_ops.h> 29#include <asm/cpu_ops.h>
31#include <asm/errno.h> 30#include <asm/errno.h>
32#include <asm/psci.h> 31#include <asm/psci.h>
@@ -37,16 +36,36 @@
37#define PSCI_POWER_STATE_TYPE_STANDBY 0 36#define PSCI_POWER_STATE_TYPE_STANDBY 0
38#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1 37#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1
39 38
40struct psci_power_state { 39static bool psci_power_state_loses_context(u32 state)
41 u16 id; 40{
42 u8 type; 41 return state & PSCI_0_2_POWER_STATE_TYPE_MASK;
43 u8 affinity_level; 42}
44}; 43
44static bool psci_power_state_is_valid(u32 state)
45{
46 const u32 valid_mask = PSCI_0_2_POWER_STATE_ID_MASK |
47 PSCI_0_2_POWER_STATE_TYPE_MASK |
48 PSCI_0_2_POWER_STATE_AFFL_MASK;
49
50 return !(state & ~valid_mask);
51}
52
53/*
54 * The CPU any Trusted OS is resident on. The trusted OS may reject CPU_OFF
55 * calls to its resident CPU, so we must avoid issuing those. We never migrate
56 * a Trusted OS even if it claims to be capable of migration -- doing so will
57 * require cooperation with a Trusted OS driver.
58 */
59static int resident_cpu = -1;
60
61static bool psci_tos_resident_on(int cpu)
62{
63 return cpu == resident_cpu;
64}
45 65
46struct psci_operations { 66struct psci_operations {
47 int (*cpu_suspend)(struct psci_power_state state, 67 int (*cpu_suspend)(u32 state, unsigned long entry_point);
48 unsigned long entry_point); 68 int (*cpu_off)(u32 state);
49 int (*cpu_off)(struct psci_power_state state);
50 int (*cpu_on)(unsigned long cpuid, unsigned long entry_point); 69 int (*cpu_on)(unsigned long cpuid, unsigned long entry_point);
51 int (*migrate)(unsigned long cpuid); 70 int (*migrate)(unsigned long cpuid);
52 int (*affinity_info)(unsigned long target_affinity, 71 int (*affinity_info)(unsigned long target_affinity,
@@ -56,23 +75,21 @@ struct psci_operations {
56 75
57static struct psci_operations psci_ops; 76static struct psci_operations psci_ops;
58 77
59static int (*invoke_psci_fn)(u64, u64, u64, u64); 78typedef unsigned long (psci_fn)(unsigned long, unsigned long,
60typedef int (*psci_initcall_t)(const struct device_node *); 79 unsigned long, unsigned long);
61 80asmlinkage psci_fn __invoke_psci_fn_hvc;
62asmlinkage int __invoke_psci_fn_hvc(u64, u64, u64, u64); 81asmlinkage psci_fn __invoke_psci_fn_smc;
63asmlinkage int __invoke_psci_fn_smc(u64, u64, u64, u64); 82static psci_fn *invoke_psci_fn;
64 83
65enum psci_function { 84enum psci_function {
66 PSCI_FN_CPU_SUSPEND, 85 PSCI_FN_CPU_SUSPEND,
67 PSCI_FN_CPU_ON, 86 PSCI_FN_CPU_ON,
68 PSCI_FN_CPU_OFF, 87 PSCI_FN_CPU_OFF,
69 PSCI_FN_MIGRATE, 88 PSCI_FN_MIGRATE,
70 PSCI_FN_AFFINITY_INFO,
71 PSCI_FN_MIGRATE_INFO_TYPE,
72 PSCI_FN_MAX, 89 PSCI_FN_MAX,
73}; 90};
74 91
75static DEFINE_PER_CPU_READ_MOSTLY(struct psci_power_state *, psci_power_state); 92static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
76 93
77static u32 psci_function_id[PSCI_FN_MAX]; 94static u32 psci_function_id[PSCI_FN_MAX];
78 95
@@ -92,56 +109,28 @@ static int psci_to_linux_errno(int errno)
92 return -EINVAL; 109 return -EINVAL;
93} 110}
94 111
95static u32 psci_power_state_pack(struct psci_power_state state) 112static u32 psci_get_version(void)
96{
97 return ((state.id << PSCI_0_2_POWER_STATE_ID_SHIFT)
98 & PSCI_0_2_POWER_STATE_ID_MASK) |
99 ((state.type << PSCI_0_2_POWER_STATE_TYPE_SHIFT)
100 & PSCI_0_2_POWER_STATE_TYPE_MASK) |
101 ((state.affinity_level << PSCI_0_2_POWER_STATE_AFFL_SHIFT)
102 & PSCI_0_2_POWER_STATE_AFFL_MASK);
103}
104
105static void psci_power_state_unpack(u32 power_state,
106 struct psci_power_state *state)
107{ 113{
108 state->id = (power_state & PSCI_0_2_POWER_STATE_ID_MASK) >> 114 return invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
109 PSCI_0_2_POWER_STATE_ID_SHIFT;
110 state->type = (power_state & PSCI_0_2_POWER_STATE_TYPE_MASK) >>
111 PSCI_0_2_POWER_STATE_TYPE_SHIFT;
112 state->affinity_level =
113 (power_state & PSCI_0_2_POWER_STATE_AFFL_MASK) >>
114 PSCI_0_2_POWER_STATE_AFFL_SHIFT;
115} 115}
116 116
117static int psci_get_version(void) 117static int psci_cpu_suspend(u32 state, unsigned long entry_point)
118{ 118{
119 int err; 119 int err;
120 120 u32 fn;
121 err = invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
122 return err;
123}
124
125static int psci_cpu_suspend(struct psci_power_state state,
126 unsigned long entry_point)
127{
128 int err;
129 u32 fn, power_state;
130 121
131 fn = psci_function_id[PSCI_FN_CPU_SUSPEND]; 122 fn = psci_function_id[PSCI_FN_CPU_SUSPEND];
132 power_state = psci_power_state_pack(state); 123 err = invoke_psci_fn(fn, state, entry_point, 0);
133 err = invoke_psci_fn(fn, power_state, entry_point, 0);
134 return psci_to_linux_errno(err); 124 return psci_to_linux_errno(err);
135} 125}
136 126
137static int psci_cpu_off(struct psci_power_state state) 127static int psci_cpu_off(u32 state)
138{ 128{
139 int err; 129 int err;
140 u32 fn, power_state; 130 u32 fn;
141 131
142 fn = psci_function_id[PSCI_FN_CPU_OFF]; 132 fn = psci_function_id[PSCI_FN_CPU_OFF];
143 power_state = psci_power_state_pack(state); 133 err = invoke_psci_fn(fn, state, 0, 0);
144 err = invoke_psci_fn(fn, power_state, 0, 0);
145 return psci_to_linux_errno(err); 134 return psci_to_linux_errno(err);
146} 135}
147 136
@@ -168,28 +157,24 @@ static int psci_migrate(unsigned long cpuid)
168static int psci_affinity_info(unsigned long target_affinity, 157static int psci_affinity_info(unsigned long target_affinity,
169 unsigned long lowest_affinity_level) 158 unsigned long lowest_affinity_level)
170{ 159{
171 int err; 160 return invoke_psci_fn(PSCI_0_2_FN64_AFFINITY_INFO, target_affinity,
172 u32 fn; 161 lowest_affinity_level, 0);
173
174 fn = psci_function_id[PSCI_FN_AFFINITY_INFO];
175 err = invoke_psci_fn(fn, target_affinity, lowest_affinity_level, 0);
176 return err;
177} 162}
178 163
179static int psci_migrate_info_type(void) 164static int psci_migrate_info_type(void)
180{ 165{
181 int err; 166 return invoke_psci_fn(PSCI_0_2_FN_MIGRATE_INFO_TYPE, 0, 0, 0);
182 u32 fn; 167}
183 168
184 fn = psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE]; 169static unsigned long psci_migrate_info_up_cpu(void)
185 err = invoke_psci_fn(fn, 0, 0, 0); 170{
186 return err; 171 return invoke_psci_fn(PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU, 0, 0, 0);
187} 172}
188 173
189static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu) 174static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu)
190{ 175{
191 int i, ret, count = 0; 176 int i, ret, count = 0;
192 struct psci_power_state *psci_states; 177 u32 *psci_states;
193 struct device_node *state_node, *cpu_node; 178 struct device_node *state_node, *cpu_node;
194 179
195 cpu_node = of_get_cpu_node(cpu, NULL); 180 cpu_node = of_get_cpu_node(cpu, NULL);
@@ -218,13 +203,13 @@ static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu)
218 return -ENOMEM; 203 return -ENOMEM;
219 204
220 for (i = 0; i < count; i++) { 205 for (i = 0; i < count; i++) {
221 u32 psci_power_state; 206 u32 state;
222 207
223 state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); 208 state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
224 209
225 ret = of_property_read_u32(state_node, 210 ret = of_property_read_u32(state_node,
226 "arm,psci-suspend-param", 211 "arm,psci-suspend-param",
227 &psci_power_state); 212 &state);
228 if (ret) { 213 if (ret) {
229 pr_warn(" * %s missing arm,psci-suspend-param property\n", 214 pr_warn(" * %s missing arm,psci-suspend-param property\n",
230 state_node->full_name); 215 state_node->full_name);
@@ -233,9 +218,13 @@ static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu)
233 } 218 }
234 219
235 of_node_put(state_node); 220 of_node_put(state_node);
236 pr_debug("psci-power-state %#x index %d\n", psci_power_state, 221 pr_debug("psci-power-state %#x index %d\n", state, i);
237 i); 222 if (!psci_power_state_is_valid(state)) {
238 psci_power_state_unpack(psci_power_state, &psci_states[i]); 223 pr_warn("Invalid PSCI power state %#x\n", state);
224 ret = -EINVAL;
225 goto free_mem;
226 }
227 psci_states[i] = state;
239 } 228 }
240 /* Idle states parsed correctly, initialize per-cpu pointer */ 229 /* Idle states parsed correctly, initialize per-cpu pointer */
241 per_cpu(psci_power_state, cpu) = psci_states; 230 per_cpu(psci_power_state, cpu) = psci_states;
@@ -278,6 +267,46 @@ static void psci_sys_poweroff(void)
278 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0); 267 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
279} 268}
280 269
270/*
271 * Detect the presence of a resident Trusted OS which may cause CPU_OFF to
272 * return DENIED (which would be fatal).
273 */
274static void __init psci_init_migrate(void)
275{
276 unsigned long cpuid;
277 int type, cpu;
278
279 type = psci_ops.migrate_info_type();
280
281 if (type == PSCI_0_2_TOS_MP) {
282 pr_info("Trusted OS migration not required\n");
283 return;
284 }
285
286 if (type == PSCI_RET_NOT_SUPPORTED) {
287 pr_info("MIGRATE_INFO_TYPE not supported.\n");
288 return;
289 }
290
291 if (type != PSCI_0_2_TOS_UP_MIGRATE &&
292 type != PSCI_0_2_TOS_UP_NO_MIGRATE) {
293 pr_err("MIGRATE_INFO_TYPE returned unknown type (%d)\n", type);
294 return;
295 }
296
297 cpuid = psci_migrate_info_up_cpu();
298 if (cpuid & ~MPIDR_HWID_BITMASK) {
299 pr_warn("MIGRATE_INFO_UP_CPU reported invalid physical ID (0x%lx)\n",
300 cpuid);
301 return;
302 }
303
304 cpu = get_logical_index(cpuid);
305 resident_cpu = cpu >= 0 ? cpu : -1;
306
307 pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
308}
309
281static void __init psci_0_2_set_functions(void) 310static void __init psci_0_2_set_functions(void)
282{ 311{
283 pr_info("Using standard PSCI v0.2 function IDs\n"); 312 pr_info("Using standard PSCI v0.2 function IDs\n");
@@ -293,11 +322,8 @@ static void __init psci_0_2_set_functions(void)
293 psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN64_MIGRATE; 322 psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN64_MIGRATE;
294 psci_ops.migrate = psci_migrate; 323 psci_ops.migrate = psci_migrate;
295 324
296 psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_0_2_FN64_AFFINITY_INFO;
297 psci_ops.affinity_info = psci_affinity_info; 325 psci_ops.affinity_info = psci_affinity_info;
298 326
299 psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] =
300 PSCI_0_2_FN_MIGRATE_INFO_TYPE;
301 psci_ops.migrate_info_type = psci_migrate_info_type; 327 psci_ops.migrate_info_type = psci_migrate_info_type;
302 328
303 arm_pm_restart = psci_sys_reset; 329 arm_pm_restart = psci_sys_reset;
@@ -310,32 +336,26 @@ static void __init psci_0_2_set_functions(void)
310 */ 336 */
311static int __init psci_probe(void) 337static int __init psci_probe(void)
312{ 338{
313 int ver = psci_get_version(); 339 u32 ver = psci_get_version();
314 340
315 if (ver == PSCI_RET_NOT_SUPPORTED) { 341 pr_info("PSCIv%d.%d detected in firmware.\n",
316 /* 342 PSCI_VERSION_MAJOR(ver),
317 * PSCI versions >=0.2 mandates implementation of 343 PSCI_VERSION_MINOR(ver));
318 * PSCI_VERSION. 344
319 */ 345 if (PSCI_VERSION_MAJOR(ver) == 0 && PSCI_VERSION_MINOR(ver) < 2) {
320 pr_err("PSCI firmware does not comply with the v0.2 spec.\n"); 346 pr_err("Conflicting PSCI version detected.\n");
321 return -EOPNOTSUPP; 347 return -EINVAL;
322 } else {
323 pr_info("PSCIv%d.%d detected in firmware.\n",
324 PSCI_VERSION_MAJOR(ver),
325 PSCI_VERSION_MINOR(ver));
326
327 if (PSCI_VERSION_MAJOR(ver) == 0 &&
328 PSCI_VERSION_MINOR(ver) < 2) {
329 pr_err("Conflicting PSCI version detected.\n");
330 return -EINVAL;
331 }
332 } 348 }
333 349
334 psci_0_2_set_functions(); 350 psci_0_2_set_functions();
335 351
352 psci_init_migrate();
353
336 return 0; 354 return 0;
337} 355}
338 356
357typedef int (*psci_initcall_t)(const struct device_node *);
358
339/* 359/*
340 * PSCI init function for PSCI versions >=0.2 360 * PSCI init function for PSCI versions >=0.2
341 * 361 *
@@ -424,6 +444,7 @@ int __init psci_dt_init(void)
424 return init_fn(np); 444 return init_fn(np);
425} 445}
426 446
447#ifdef CONFIG_ACPI
427/* 448/*
428 * We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's 449 * We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's
429 * explicitly clarified in SBBR 450 * explicitly clarified in SBBR
@@ -444,6 +465,7 @@ int __init psci_acpi_init(void)
444 465
445 return psci_probe(); 466 return psci_probe();
446} 467}
468#endif
447 469
448#ifdef CONFIG_SMP 470#ifdef CONFIG_SMP
449 471
@@ -477,6 +499,11 @@ static int cpu_psci_cpu_disable(unsigned int cpu)
477 /* Fail early if we don't have CPU_OFF support */ 499 /* Fail early if we don't have CPU_OFF support */
478 if (!psci_ops.cpu_off) 500 if (!psci_ops.cpu_off)
479 return -EOPNOTSUPP; 501 return -EOPNOTSUPP;
502
503 /* Trusted OS will deny CPU_OFF */
504 if (psci_tos_resident_on(cpu))
505 return -EPERM;
506
480 return 0; 507 return 0;
481} 508}
482 509
@@ -487,9 +514,8 @@ static void cpu_psci_cpu_die(unsigned int cpu)
487 * There are no known implementations of PSCI actually using the 514 * There are no known implementations of PSCI actually using the
488 * power state field, pass a sensible default for now. 515 * power state field, pass a sensible default for now.
489 */ 516 */
490 struct psci_power_state state = { 517 u32 state = PSCI_POWER_STATE_TYPE_POWER_DOWN <<
491 .type = PSCI_POWER_STATE_TYPE_POWER_DOWN, 518 PSCI_0_2_POWER_STATE_TYPE_SHIFT;
492 };
493 519
494 ret = psci_ops.cpu_off(state); 520 ret = psci_ops.cpu_off(state);
495 521
@@ -501,7 +527,7 @@ static int cpu_psci_cpu_kill(unsigned int cpu)
501 int err, i; 527 int err, i;
502 528
503 if (!psci_ops.affinity_info) 529 if (!psci_ops.affinity_info)
504 return 1; 530 return 0;
505 /* 531 /*
506 * cpu_kill could race with cpu_die and we can 532 * cpu_kill could race with cpu_die and we can
507 * potentially end up declaring this cpu undead 533 * potentially end up declaring this cpu undead
@@ -512,7 +538,7 @@ static int cpu_psci_cpu_kill(unsigned int cpu)
512 err = psci_ops.affinity_info(cpu_logical_map(cpu), 0); 538 err = psci_ops.affinity_info(cpu_logical_map(cpu), 0);
513 if (err == PSCI_0_2_AFFINITY_LEVEL_OFF) { 539 if (err == PSCI_0_2_AFFINITY_LEVEL_OFF) {
514 pr_info("CPU%d killed.\n", cpu); 540 pr_info("CPU%d killed.\n", cpu);
515 return 1; 541 return 0;
516 } 542 }
517 543
518 msleep(10); 544 msleep(10);
@@ -521,15 +547,14 @@ static int cpu_psci_cpu_kill(unsigned int cpu)
521 547
522 pr_warn("CPU%d may not have shut down cleanly (AFFINITY_INFO reports %d)\n", 548 pr_warn("CPU%d may not have shut down cleanly (AFFINITY_INFO reports %d)\n",
523 cpu, err); 549 cpu, err);
524 /* Make op_cpu_kill() fail. */ 550 return -ETIMEDOUT;
525 return 0;
526} 551}
527#endif 552#endif
528#endif 553#endif
529 554
530static int psci_suspend_finisher(unsigned long index) 555static int psci_suspend_finisher(unsigned long index)
531{ 556{
532 struct psci_power_state *state = __this_cpu_read(psci_power_state); 557 u32 *state = __this_cpu_read(psci_power_state);
533 558
534 return psci_ops.cpu_suspend(state[index - 1], 559 return psci_ops.cpu_suspend(state[index - 1],
535 virt_to_phys(cpu_resume)); 560 virt_to_phys(cpu_resume));
@@ -538,7 +563,7 @@ static int psci_suspend_finisher(unsigned long index)
538static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index) 563static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index)
539{ 564{
540 int ret; 565 int ret;
541 struct psci_power_state *state = __this_cpu_read(psci_power_state); 566 u32 *state = __this_cpu_read(psci_power_state);
542 /* 567 /*
543 * idle state index 0 corresponds to wfi, should never be called 568 * idle state index 0 corresponds to wfi, should never be called
544 * from the cpu_suspend operations 569 * from the cpu_suspend operations
@@ -546,7 +571,7 @@ static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index)
546 if (WARN_ON_ONCE(!index)) 571 if (WARN_ON_ONCE(!index))
547 return -EINVAL; 572 return -EINVAL;
548 573
549 if (state[index - 1].type == PSCI_POWER_STATE_TYPE_STANDBY) 574 if (!psci_power_state_loses_context(state[index - 1]))
550 ret = psci_ops.cpu_suspend(state[index - 1], 0); 575 ret = psci_ops.cpu_suspend(state[index - 1], 0);
551 else 576 else
552 ret = __cpu_suspend(index, psci_suspend_finisher); 577 ret = __cpu_suspend(index, psci_suspend_finisher);
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 65f1a7f72697..4b2121bd7f9c 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -249,7 +249,7 @@ static int op_cpu_kill(unsigned int cpu)
249 * time and hope that it's dead, so let's skip the wait and just hope. 249 * time and hope that it's dead, so let's skip the wait and just hope.
250 */ 250 */
251 if (!cpu_ops[cpu]->cpu_kill) 251 if (!cpu_ops[cpu]->cpu_kill)
252 return 1; 252 return 0;
253 253
254 return cpu_ops[cpu]->cpu_kill(cpu); 254 return cpu_ops[cpu]->cpu_kill(cpu);
255} 255}
@@ -260,6 +260,8 @@ static int op_cpu_kill(unsigned int cpu)
260 */ 260 */
261void __cpu_die(unsigned int cpu) 261void __cpu_die(unsigned int cpu)
262{ 262{
263 int err;
264
263 if (!cpu_wait_death(cpu, 5)) { 265 if (!cpu_wait_death(cpu, 5)) {
264 pr_crit("CPU%u: cpu didn't die\n", cpu); 266 pr_crit("CPU%u: cpu didn't die\n", cpu);
265 return; 267 return;
@@ -272,8 +274,10 @@ void __cpu_die(unsigned int cpu)
272 * verify that it has really left the kernel before we consider 274 * verify that it has really left the kernel before we consider
273 * clobbering anything it might still be using. 275 * clobbering anything it might still be using.
274 */ 276 */
275 if (!op_cpu_kill(cpu)) 277 err = op_cpu_kill(cpu);
276 pr_warn("CPU%d may not have shut down cleanly\n", cpu); 278 if (err)
279 pr_warn("CPU%d may not have shut down cleanly: %d\n",
280 cpu, err);
277} 281}
278 282
279/* 283/*