aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-05-27 09:58:14 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-05-27 09:58:14 -0400
commit04092204bb66c4f8e17465eeee64357dd2ad2585 (patch)
tree16e62ff55ac394af5d2e6adb4950533578a20ce1
parent9b88ae99d2fe11e359b3b3992aff953e28b0b43a (diff)
parent1252b3313642c3d0dff5b951b625468bf0dcd059 (diff)
Merge tag 'kvm-arm-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into kvm-next
Changed for the 3.16 merge window. This includes KVM support for PSCI v0.2 and also includes generic Linux support for PSCI v0.2 (on hosts that advertise that feature via their DT), since the latter depends on headers introduced by the former. Finally there's a small patch from Marc that enables Cortex-A53 support.
-rw-r--r--Documentation/devicetree/bindings/arm/psci.txt37
-rw-r--r--Documentation/virtual/kvm/api.txt17
-rw-r--r--arch/arm/include/asm/kvm_host.h2
-rw-r--r--arch/arm/include/asm/kvm_psci.h6
-rw-r--r--arch/arm/include/asm/psci.h7
-rw-r--r--arch/arm/include/uapi/asm/kvm.h10
-rw-r--r--arch/arm/kernel/psci.c196
-rw-r--r--arch/arm/kernel/psci_smp.c33
-rw-r--r--arch/arm/kvm/arm.c1
-rw-r--r--arch/arm/kvm/handle_exit.c10
-rw-r--r--arch/arm/kvm/psci.c235
-rw-r--r--arch/arm64/include/asm/cpu_ops.h2
-rw-r--r--arch/arm64/include/asm/cputype.h1
-rw-r--r--arch/arm64/include/asm/kvm_host.h2
-rw-r--r--arch/arm64/include/asm/kvm_psci.h6
-rw-r--r--arch/arm64/include/asm/psci.h2
-rw-r--r--arch/arm64/include/uapi/asm/kvm.h13
-rw-r--r--arch/arm64/kernel/psci.c231
-rw-r--r--arch/arm64/kernel/smp.c22
-rw-r--r--arch/arm64/kvm/guest.c2
-rw-r--r--arch/arm64/kvm/handle_exit.c10
-rw-r--r--arch/arm64/kvm/sys_regs_generic_v8.c2
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/kvm.h9
-rw-r--r--include/uapi/linux/psci.h90
25 files changed, 831 insertions, 116 deletions
diff --git a/Documentation/devicetree/bindings/arm/psci.txt b/Documentation/devicetree/bindings/arm/psci.txt
index 433afe9cb590..b4a58f39223c 100644
--- a/Documentation/devicetree/bindings/arm/psci.txt
+++ b/Documentation/devicetree/bindings/arm/psci.txt
@@ -21,7 +21,15 @@ to #0.
21 21
22Main node required properties: 22Main node required properties:
23 23
24 - compatible : Must be "arm,psci" 24 - compatible : should contain at least one of:
25
26 * "arm,psci" : for implementations complying to PSCI versions prior to
27 0.2. For these cases function IDs must be provided.
28
29 * "arm,psci-0.2" : for implementations complying to PSCI 0.2. Function
30 IDs are not required and should be ignored by an OS with PSCI 0.2
31 support, but are permitted to be present for compatibility with
32 existing software when "arm,psci" is later in the compatible list.
25 33
26 - method : The method of calling the PSCI firmware. Permitted 34 - method : The method of calling the PSCI firmware. Permitted
27 values are: 35 values are:
@@ -45,6 +53,8 @@ Main node optional properties:
45 53
46Example: 54Example:
47 55
56Case 1: PSCI v0.1 only.
57
48 psci { 58 psci {
49 compatible = "arm,psci"; 59 compatible = "arm,psci";
50 method = "smc"; 60 method = "smc";
@@ -53,3 +63,28 @@ Example:
53 cpu_on = <0x95c10002>; 63 cpu_on = <0x95c10002>;
54 migrate = <0x95c10003>; 64 migrate = <0x95c10003>;
55 }; 65 };
66
67
68Case 2: PSCI v0.2 only
69
70 psci {
71 compatible = "arm,psci-0.2";
72 method = "smc";
73 };
74
75Case 3: PSCI v0.2 and PSCI v0.1.
76
77 A DTB may provide IDs for use by kernels without PSCI 0.2 support,
78 enabling firmware and hypervisors to support existing and new kernels.
79 These IDs will be ignored by kernels with PSCI 0.2 support, which will
80 use the standard PSCI 0.2 IDs exclusively.
81
82 psci {
83 compatible = "arm,psci-0.2", "arm,psci";
84 method = "hvc";
85
86 cpu_on = < arbitrary value >;
87 cpu_off = < arbitrary value >;
88
89 ...
90 };
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 0581f6c40f2b..cac0ba127576 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2378,6 +2378,8 @@ Possible features:
2378 Depends on KVM_CAP_ARM_PSCI. 2378 Depends on KVM_CAP_ARM_PSCI.
2379 - KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode. 2379 - KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode.
2380 Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only). 2380 Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
2381 - KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 for the CPU.
2382 Depends on KVM_CAP_ARM_PSCI_0_2.
2381 2383
2382 2384
23834.83 KVM_ARM_PREFERRED_TARGET 23854.83 KVM_ARM_PREFERRED_TARGET
@@ -2740,6 +2742,21 @@ It gets triggered whenever both KVM_CAP_PPC_EPR are enabled and an
2740external interrupt has just been delivered into the guest. User space 2742external interrupt has just been delivered into the guest. User space
2741should put the acknowledged interrupt vector into the 'epr' field. 2743should put the acknowledged interrupt vector into the 'epr' field.
2742 2744
2745 /* KVM_EXIT_SYSTEM_EVENT */
2746 struct {
2747#define KVM_SYSTEM_EVENT_SHUTDOWN 1
2748#define KVM_SYSTEM_EVENT_RESET 2
2749 __u32 type;
2750 __u64 flags;
2751 } system_event;
2752
2753If exit_reason is KVM_EXIT_SYSTEM_EVENT then the vcpu has triggered
2754a system-level event using some architecture specific mechanism (hypercall
2755or some special instruction). In case of ARM/ARM64, this is triggered using
2756HVC instruction based PSCI call from the vcpu. The 'type' field describes
2757the system-level event type. The 'flags' field describes architecture
2758specific flags for the system-level event.
2759
2743 /* Fix the size of the union. */ 2760 /* Fix the size of the union. */
2744 char padding[256]; 2761 char padding[256];
2745 }; 2762 };
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 09af14999c9b..193ceaf01bfd 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -36,7 +36,7 @@
36#define KVM_COALESCED_MMIO_PAGE_OFFSET 1 36#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
37#define KVM_HAVE_ONE_REG 37#define KVM_HAVE_ONE_REG
38 38
39#define KVM_VCPU_MAX_FEATURES 1 39#define KVM_VCPU_MAX_FEATURES 2
40 40
41#include <kvm/arm_vgic.h> 41#include <kvm/arm_vgic.h>
42 42
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h
index 9a83d98bf170..6bda945d31fa 100644
--- a/arch/arm/include/asm/kvm_psci.h
+++ b/arch/arm/include/asm/kvm_psci.h
@@ -18,6 +18,10 @@
18#ifndef __ARM_KVM_PSCI_H__ 18#ifndef __ARM_KVM_PSCI_H__
19#define __ARM_KVM_PSCI_H__ 19#define __ARM_KVM_PSCI_H__
20 20
21bool kvm_psci_call(struct kvm_vcpu *vcpu); 21#define KVM_ARM_PSCI_0_1 1
22#define KVM_ARM_PSCI_0_2 2
23
24int kvm_psci_version(struct kvm_vcpu *vcpu);
25int kvm_psci_call(struct kvm_vcpu *vcpu);
22 26
23#endif /* __ARM_KVM_PSCI_H__ */ 27#endif /* __ARM_KVM_PSCI_H__ */
diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h
index c4ae171850f8..b93e34a9fdf1 100644
--- a/arch/arm/include/asm/psci.h
+++ b/arch/arm/include/asm/psci.h
@@ -29,16 +29,19 @@ struct psci_operations {
29 int (*cpu_off)(struct psci_power_state state); 29 int (*cpu_off)(struct psci_power_state state);
30 int (*cpu_on)(unsigned long cpuid, unsigned long entry_point); 30 int (*cpu_on)(unsigned long cpuid, unsigned long entry_point);
31 int (*migrate)(unsigned long cpuid); 31 int (*migrate)(unsigned long cpuid);
32 int (*affinity_info)(unsigned long target_affinity,
33 unsigned long lowest_affinity_level);
34 int (*migrate_info_type)(void);
32}; 35};
33 36
34extern struct psci_operations psci_ops; 37extern struct psci_operations psci_ops;
35extern struct smp_operations psci_smp_ops; 38extern struct smp_operations psci_smp_ops;
36 39
37#ifdef CONFIG_ARM_PSCI 40#ifdef CONFIG_ARM_PSCI
38void psci_init(void); 41int psci_init(void);
39bool psci_smp_available(void); 42bool psci_smp_available(void);
40#else 43#else
41static inline void psci_init(void) { } 44static inline int psci_init(void) { }
42static inline bool psci_smp_available(void) { return false; } 45static inline bool psci_smp_available(void) { return false; }
43#endif 46#endif
44 47
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index ef0c8785ba16..e6ebdd3471e5 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -20,6 +20,7 @@
20#define __ARM_KVM_H__ 20#define __ARM_KVM_H__
21 21
22#include <linux/types.h> 22#include <linux/types.h>
23#include <linux/psci.h>
23#include <asm/ptrace.h> 24#include <asm/ptrace.h>
24 25
25#define __KVM_HAVE_GUEST_DEBUG 26#define __KVM_HAVE_GUEST_DEBUG
@@ -83,6 +84,7 @@ struct kvm_regs {
83#define KVM_VGIC_V2_CPU_SIZE 0x2000 84#define KVM_VGIC_V2_CPU_SIZE 0x2000
84 85
85#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ 86#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
87#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
86 88
87struct kvm_vcpu_init { 89struct kvm_vcpu_init {
88 __u32 target; 90 __u32 target;
@@ -201,9 +203,9 @@ struct kvm_arch_memory_slot {
201#define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) 203#define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2)
202#define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3) 204#define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
203 205
204#define KVM_PSCI_RET_SUCCESS 0 206#define KVM_PSCI_RET_SUCCESS PSCI_RET_SUCCESS
205#define KVM_PSCI_RET_NI ((unsigned long)-1) 207#define KVM_PSCI_RET_NI PSCI_RET_NOT_SUPPORTED
206#define KVM_PSCI_RET_INVAL ((unsigned long)-2) 208#define KVM_PSCI_RET_INVAL PSCI_RET_INVALID_PARAMS
207#define KVM_PSCI_RET_DENIED ((unsigned long)-3) 209#define KVM_PSCI_RET_DENIED PSCI_RET_DENIED
208 210
209#endif /* __ARM_KVM_H__ */ 211#endif /* __ARM_KVM_H__ */
diff --git a/arch/arm/kernel/psci.c b/arch/arm/kernel/psci.c
index 46931880093d..f73891b6b730 100644
--- a/arch/arm/kernel/psci.c
+++ b/arch/arm/kernel/psci.c
@@ -17,63 +17,58 @@
17 17
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/reboot.h>
21#include <linux/pm.h>
22#include <uapi/linux/psci.h>
20 23
21#include <asm/compiler.h> 24#include <asm/compiler.h>
22#include <asm/errno.h> 25#include <asm/errno.h>
23#include <asm/opcodes-sec.h> 26#include <asm/opcodes-sec.h>
24#include <asm/opcodes-virt.h> 27#include <asm/opcodes-virt.h>
25#include <asm/psci.h> 28#include <asm/psci.h>
29#include <asm/system_misc.h>
26 30
27struct psci_operations psci_ops; 31struct psci_operations psci_ops;
28 32
29static int (*invoke_psci_fn)(u32, u32, u32, u32); 33static int (*invoke_psci_fn)(u32, u32, u32, u32);
34typedef int (*psci_initcall_t)(const struct device_node *);
30 35
31enum psci_function { 36enum psci_function {
32 PSCI_FN_CPU_SUSPEND, 37 PSCI_FN_CPU_SUSPEND,
33 PSCI_FN_CPU_ON, 38 PSCI_FN_CPU_ON,
34 PSCI_FN_CPU_OFF, 39 PSCI_FN_CPU_OFF,
35 PSCI_FN_MIGRATE, 40 PSCI_FN_MIGRATE,
41 PSCI_FN_AFFINITY_INFO,
42 PSCI_FN_MIGRATE_INFO_TYPE,
36 PSCI_FN_MAX, 43 PSCI_FN_MAX,
37}; 44};
38 45
39static u32 psci_function_id[PSCI_FN_MAX]; 46static u32 psci_function_id[PSCI_FN_MAX];
40 47
41#define PSCI_RET_SUCCESS 0
42#define PSCI_RET_EOPNOTSUPP -1
43#define PSCI_RET_EINVAL -2
44#define PSCI_RET_EPERM -3
45
46static int psci_to_linux_errno(int errno) 48static int psci_to_linux_errno(int errno)
47{ 49{
48 switch (errno) { 50 switch (errno) {
49 case PSCI_RET_SUCCESS: 51 case PSCI_RET_SUCCESS:
50 return 0; 52 return 0;
51 case PSCI_RET_EOPNOTSUPP: 53 case PSCI_RET_NOT_SUPPORTED:
52 return -EOPNOTSUPP; 54 return -EOPNOTSUPP;
53 case PSCI_RET_EINVAL: 55 case PSCI_RET_INVALID_PARAMS:
54 return -EINVAL; 56 return -EINVAL;
55 case PSCI_RET_EPERM: 57 case PSCI_RET_DENIED:
56 return -EPERM; 58 return -EPERM;
57 }; 59 };
58 60
59 return -EINVAL; 61 return -EINVAL;
60} 62}
61 63
62#define PSCI_POWER_STATE_ID_MASK 0xffff
63#define PSCI_POWER_STATE_ID_SHIFT 0
64#define PSCI_POWER_STATE_TYPE_MASK 0x1
65#define PSCI_POWER_STATE_TYPE_SHIFT 16
66#define PSCI_POWER_STATE_AFFL_MASK 0x3
67#define PSCI_POWER_STATE_AFFL_SHIFT 24
68
69static u32 psci_power_state_pack(struct psci_power_state state) 64static u32 psci_power_state_pack(struct psci_power_state state)
70{ 65{
71 return ((state.id & PSCI_POWER_STATE_ID_MASK) 66 return ((state.id << PSCI_0_2_POWER_STATE_ID_SHIFT)
72 << PSCI_POWER_STATE_ID_SHIFT) | 67 & PSCI_0_2_POWER_STATE_ID_MASK) |
73 ((state.type & PSCI_POWER_STATE_TYPE_MASK) 68 ((state.type << PSCI_0_2_POWER_STATE_TYPE_SHIFT)
74 << PSCI_POWER_STATE_TYPE_SHIFT) | 69 & PSCI_0_2_POWER_STATE_TYPE_MASK) |
75 ((state.affinity_level & PSCI_POWER_STATE_AFFL_MASK) 70 ((state.affinity_level << PSCI_0_2_POWER_STATE_AFFL_SHIFT)
76 << PSCI_POWER_STATE_AFFL_SHIFT); 71 & PSCI_0_2_POWER_STATE_AFFL_MASK);
77} 72}
78 73
79/* 74/*
@@ -110,6 +105,14 @@ static noinline int __invoke_psci_fn_smc(u32 function_id, u32 arg0, u32 arg1,
110 return function_id; 105 return function_id;
111} 106}
112 107
108static int psci_get_version(void)
109{
110 int err;
111
112 err = invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
113 return err;
114}
115
113static int psci_cpu_suspend(struct psci_power_state state, 116static int psci_cpu_suspend(struct psci_power_state state,
114 unsigned long entry_point) 117 unsigned long entry_point)
115{ 118{
@@ -153,26 +156,36 @@ static int psci_migrate(unsigned long cpuid)
153 return psci_to_linux_errno(err); 156 return psci_to_linux_errno(err);
154} 157}
155 158
156static const struct of_device_id psci_of_match[] __initconst = { 159static int psci_affinity_info(unsigned long target_affinity,
157 { .compatible = "arm,psci", }, 160 unsigned long lowest_affinity_level)
158 {}, 161{
159}; 162 int err;
163 u32 fn;
164
165 fn = psci_function_id[PSCI_FN_AFFINITY_INFO];
166 err = invoke_psci_fn(fn, target_affinity, lowest_affinity_level, 0);
167 return err;
168}
160 169
161void __init psci_init(void) 170static int psci_migrate_info_type(void)
162{ 171{
163 struct device_node *np; 172 int err;
164 const char *method; 173 u32 fn;
165 u32 id;
166 174
167 np = of_find_matching_node(NULL, psci_of_match); 175 fn = psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE];
168 if (!np) 176 err = invoke_psci_fn(fn, 0, 0, 0);
169 return; 177 return err;
178}
179
180static int get_set_conduit_method(struct device_node *np)
181{
182 const char *method;
170 183
171 pr_info("probing function IDs from device-tree\n"); 184 pr_info("probing for conduit method from DT.\n");
172 185
173 if (of_property_read_string(np, "method", &method)) { 186 if (of_property_read_string(np, "method", &method)) {
174 pr_warning("missing \"method\" property\n"); 187 pr_warn("missing \"method\" property\n");
175 goto out_put_node; 188 return -ENXIO;
176 } 189 }
177 190
178 if (!strcmp("hvc", method)) { 191 if (!strcmp("hvc", method)) {
@@ -180,10 +193,99 @@ void __init psci_init(void)
180 } else if (!strcmp("smc", method)) { 193 } else if (!strcmp("smc", method)) {
181 invoke_psci_fn = __invoke_psci_fn_smc; 194 invoke_psci_fn = __invoke_psci_fn_smc;
182 } else { 195 } else {
183 pr_warning("invalid \"method\" property: %s\n", method); 196 pr_warn("invalid \"method\" property: %s\n", method);
197 return -EINVAL;
198 }
199 return 0;
200}
201
202static void psci_sys_reset(enum reboot_mode reboot_mode, const char *cmd)
203{
204 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
205}
206
207static void psci_sys_poweroff(void)
208{
209 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
210}
211
212/*
213 * PSCI Function IDs for v0.2+ are well defined so use
214 * standard values.
215 */
216static int psci_0_2_init(struct device_node *np)
217{
218 int err, ver;
219
220 err = get_set_conduit_method(np);
221
222 if (err)
223 goto out_put_node;
224
225 ver = psci_get_version();
226
227 if (ver == PSCI_RET_NOT_SUPPORTED) {
228 /* PSCI v0.2 mandates implementation of PSCI_ID_VERSION. */
229 pr_err("PSCI firmware does not comply with the v0.2 spec.\n");
230 err = -EOPNOTSUPP;
184 goto out_put_node; 231 goto out_put_node;
232 } else {
233 pr_info("PSCIv%d.%d detected in firmware.\n",
234 PSCI_VERSION_MAJOR(ver),
235 PSCI_VERSION_MINOR(ver));
236
237 if (PSCI_VERSION_MAJOR(ver) == 0 &&
238 PSCI_VERSION_MINOR(ver) < 2) {
239 err = -EINVAL;
240 pr_err("Conflicting PSCI version detected.\n");
241 goto out_put_node;
242 }
185 } 243 }
186 244
245 pr_info("Using standard PSCI v0.2 function IDs\n");
246 psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN_CPU_SUSPEND;
247 psci_ops.cpu_suspend = psci_cpu_suspend;
248
249 psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF;
250 psci_ops.cpu_off = psci_cpu_off;
251
252 psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN_CPU_ON;
253 psci_ops.cpu_on = psci_cpu_on;
254
255 psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN_MIGRATE;
256 psci_ops.migrate = psci_migrate;
257
258 psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_0_2_FN_AFFINITY_INFO;
259 psci_ops.affinity_info = psci_affinity_info;
260
261 psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] =
262 PSCI_0_2_FN_MIGRATE_INFO_TYPE;
263 psci_ops.migrate_info_type = psci_migrate_info_type;
264
265 arm_pm_restart = psci_sys_reset;
266
267 pm_power_off = psci_sys_poweroff;
268
269out_put_node:
270 of_node_put(np);
271 return err;
272}
273
274/*
275 * PSCI < v0.2 get PSCI Function IDs via DT.
276 */
277static int psci_0_1_init(struct device_node *np)
278{
279 u32 id;
280 int err;
281
282 err = get_set_conduit_method(np);
283
284 if (err)
285 goto out_put_node;
286
287 pr_info("Using PSCI v0.1 Function IDs from DT\n");
288
187 if (!of_property_read_u32(np, "cpu_suspend", &id)) { 289 if (!of_property_read_u32(np, "cpu_suspend", &id)) {
188 psci_function_id[PSCI_FN_CPU_SUSPEND] = id; 290 psci_function_id[PSCI_FN_CPU_SUSPEND] = id;
189 psci_ops.cpu_suspend = psci_cpu_suspend; 291 psci_ops.cpu_suspend = psci_cpu_suspend;
@@ -206,5 +308,25 @@ void __init psci_init(void)
206 308
207out_put_node: 309out_put_node:
208 of_node_put(np); 310 of_node_put(np);
209 return; 311 return err;
312}
313
314static const struct of_device_id psci_of_match[] __initconst = {
315 { .compatible = "arm,psci", .data = psci_0_1_init},
316 { .compatible = "arm,psci-0.2", .data = psci_0_2_init},
317 {},
318};
319
320int __init psci_init(void)
321{
322 struct device_node *np;
323 const struct of_device_id *matched_np;
324 psci_initcall_t init_fn;
325
326 np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
327 if (!np)
328 return -ENODEV;
329
330 init_fn = (psci_initcall_t)matched_np->data;
331 return init_fn(np);
210} 332}
diff --git a/arch/arm/kernel/psci_smp.c b/arch/arm/kernel/psci_smp.c
index 570a48cc3d64..28a1db4da704 100644
--- a/arch/arm/kernel/psci_smp.c
+++ b/arch/arm/kernel/psci_smp.c
@@ -16,6 +16,8 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/smp.h> 17#include <linux/smp.h>
18#include <linux/of.h> 18#include <linux/of.h>
19#include <linux/delay.h>
20#include <uapi/linux/psci.h>
19 21
20#include <asm/psci.h> 22#include <asm/psci.h>
21#include <asm/smp_plat.h> 23#include <asm/smp_plat.h>
@@ -66,6 +68,36 @@ void __ref psci_cpu_die(unsigned int cpu)
66 /* We should never return */ 68 /* We should never return */
67 panic("psci: cpu %d failed to shutdown\n", cpu); 69 panic("psci: cpu %d failed to shutdown\n", cpu);
68} 70}
71
72int __ref psci_cpu_kill(unsigned int cpu)
73{
74 int err, i;
75
76 if (!psci_ops.affinity_info)
77 return 1;
78 /*
79 * cpu_kill could race with cpu_die and we can
80 * potentially end up declaring this cpu undead
81 * while it is dying. So, try again a few times.
82 */
83
84 for (i = 0; i < 10; i++) {
85 err = psci_ops.affinity_info(cpu_logical_map(cpu), 0);
86 if (err == PSCI_0_2_AFFINITY_LEVEL_OFF) {
87 pr_info("CPU%d killed.\n", cpu);
88 return 1;
89 }
90
91 msleep(10);
92 pr_info("Retrying again to check for CPU kill\n");
93 }
94
95 pr_warn("CPU%d may not have shut down cleanly (AFFINITY_INFO reports %d)\n",
96 cpu, err);
97 /* Make platform_cpu_kill() fail. */
98 return 0;
99}
100
69#endif 101#endif
70 102
71bool __init psci_smp_available(void) 103bool __init psci_smp_available(void)
@@ -78,5 +110,6 @@ struct smp_operations __initdata psci_smp_ops = {
78 .smp_boot_secondary = psci_boot_secondary, 110 .smp_boot_secondary = psci_boot_secondary,
79#ifdef CONFIG_HOTPLUG_CPU 111#ifdef CONFIG_HOTPLUG_CPU
80 .cpu_die = psci_cpu_die, 112 .cpu_die = psci_cpu_die,
113 .cpu_kill = psci_cpu_kill,
81#endif 114#endif
82}; 115};
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index f0e50a0f3a65..3c82b37c0f9e 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -197,6 +197,7 @@ int kvm_dev_ioctl_check_extension(long ext)
197 case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: 197 case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
198 case KVM_CAP_ONE_REG: 198 case KVM_CAP_ONE_REG:
199 case KVM_CAP_ARM_PSCI: 199 case KVM_CAP_ARM_PSCI:
200 case KVM_CAP_ARM_PSCI_0_2:
200 r = 1; 201 r = 1;
201 break; 202 break;
202 case KVM_CAP_COALESCED_MMIO: 203 case KVM_CAP_COALESCED_MMIO:
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 0de91fc6de0f..4c979d466cc1 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -38,14 +38,18 @@ static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
38 38
39static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) 39static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
40{ 40{
41 int ret;
42
41 trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0), 43 trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
42 kvm_vcpu_hvc_get_imm(vcpu)); 44 kvm_vcpu_hvc_get_imm(vcpu));
43 45
44 if (kvm_psci_call(vcpu)) 46 ret = kvm_psci_call(vcpu);
47 if (ret < 0) {
48 kvm_inject_undefined(vcpu);
45 return 1; 49 return 1;
50 }
46 51
47 kvm_inject_undefined(vcpu); 52 return ret;
48 return 1;
49} 53}
50 54
51static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) 55static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 448f60e8d23c..09cf37737ee2 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -27,6 +27,36 @@
27 * as described in ARM document number ARM DEN 0022A. 27 * as described in ARM document number ARM DEN 0022A.
28 */ 28 */
29 29
30#define AFFINITY_MASK(level) ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1)
31
32static unsigned long psci_affinity_mask(unsigned long affinity_level)
33{
34 if (affinity_level <= 3)
35 return MPIDR_HWID_BITMASK & AFFINITY_MASK(affinity_level);
36
37 return 0;
38}
39
40static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu)
41{
42 /*
43 * NOTE: For simplicity, we make VCPU suspend emulation to be
44 * same-as WFI (Wait-for-interrupt) emulation.
45 *
46 * This means for KVM the wakeup events are interrupts and
47 * this is consistent with intended use of StateID as described
48 * in section 5.4.1 of PSCI v0.2 specification (ARM DEN 0022A).
49 *
50 * Further, we also treat power-down request to be same as
51 * stand-by request as-per section 5.4.2 clause 3 of PSCI v0.2
52 * specification (ARM DEN 0022A). This means all suspend states
53 * for KVM will preserve the register state.
54 */
55 kvm_vcpu_block(vcpu);
56
57 return PSCI_RET_SUCCESS;
58}
59
30static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) 60static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
31{ 61{
32 vcpu->arch.pause = true; 62 vcpu->arch.pause = true;
@@ -38,6 +68,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
38 struct kvm_vcpu *vcpu = NULL, *tmp; 68 struct kvm_vcpu *vcpu = NULL, *tmp;
39 wait_queue_head_t *wq; 69 wait_queue_head_t *wq;
40 unsigned long cpu_id; 70 unsigned long cpu_id;
71 unsigned long context_id;
41 unsigned long mpidr; 72 unsigned long mpidr;
42 phys_addr_t target_pc; 73 phys_addr_t target_pc;
43 int i; 74 int i;
@@ -58,10 +89,17 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
58 * Make sure the caller requested a valid CPU and that the CPU is 89 * Make sure the caller requested a valid CPU and that the CPU is
59 * turned off. 90 * turned off.
60 */ 91 */
61 if (!vcpu || !vcpu->arch.pause) 92 if (!vcpu)
62 return KVM_PSCI_RET_INVAL; 93 return PSCI_RET_INVALID_PARAMS;
94 if (!vcpu->arch.pause) {
95 if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1)
96 return PSCI_RET_ALREADY_ON;
97 else
98 return PSCI_RET_INVALID_PARAMS;
99 }
63 100
64 target_pc = *vcpu_reg(source_vcpu, 2); 101 target_pc = *vcpu_reg(source_vcpu, 2);
102 context_id = *vcpu_reg(source_vcpu, 3);
65 103
66 kvm_reset_vcpu(vcpu); 104 kvm_reset_vcpu(vcpu);
67 105
@@ -76,26 +114,160 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
76 kvm_vcpu_set_be(vcpu); 114 kvm_vcpu_set_be(vcpu);
77 115
78 *vcpu_pc(vcpu) = target_pc; 116 *vcpu_pc(vcpu) = target_pc;
117 /*
118 * NOTE: We always update r0 (or x0) because for PSCI v0.1
119 * the general puspose registers are undefined upon CPU_ON.
120 */
121 *vcpu_reg(vcpu, 0) = context_id;
79 vcpu->arch.pause = false; 122 vcpu->arch.pause = false;
80 smp_mb(); /* Make sure the above is visible */ 123 smp_mb(); /* Make sure the above is visible */
81 124
82 wq = kvm_arch_vcpu_wq(vcpu); 125 wq = kvm_arch_vcpu_wq(vcpu);
83 wake_up_interruptible(wq); 126 wake_up_interruptible(wq);
84 127
85 return KVM_PSCI_RET_SUCCESS; 128 return PSCI_RET_SUCCESS;
86} 129}
87 130
88/** 131static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
89 * kvm_psci_call - handle PSCI call if r0 value is in range 132{
90 * @vcpu: Pointer to the VCPU struct 133 int i;
91 * 134 unsigned long mpidr;
92 * Handle PSCI calls from guests through traps from HVC instructions. 135 unsigned long target_affinity;
93 * The calling convention is similar to SMC calls to the secure world where 136 unsigned long target_affinity_mask;
94 * the function number is placed in r0 and this function returns true if the 137 unsigned long lowest_affinity_level;
95 * function number specified in r0 is withing the PSCI range, and false 138 struct kvm *kvm = vcpu->kvm;
96 * otherwise. 139 struct kvm_vcpu *tmp;
97 */ 140
98bool kvm_psci_call(struct kvm_vcpu *vcpu) 141 target_affinity = *vcpu_reg(vcpu, 1);
142 lowest_affinity_level = *vcpu_reg(vcpu, 2);
143
144 /* Determine target affinity mask */
145 target_affinity_mask = psci_affinity_mask(lowest_affinity_level);
146 if (!target_affinity_mask)
147 return PSCI_RET_INVALID_PARAMS;
148
149 /* Ignore other bits of target affinity */
150 target_affinity &= target_affinity_mask;
151
152 /*
153 * If one or more VCPU matching target affinity are running
154 * then ON else OFF
155 */
156 kvm_for_each_vcpu(i, tmp, kvm) {
157 mpidr = kvm_vcpu_get_mpidr(tmp);
158 if (((mpidr & target_affinity_mask) == target_affinity) &&
159 !tmp->arch.pause) {
160 return PSCI_0_2_AFFINITY_LEVEL_ON;
161 }
162 }
163
164 return PSCI_0_2_AFFINITY_LEVEL_OFF;
165}
166
167static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type)
168{
169 memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
170 vcpu->run->system_event.type = type;
171 vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
172}
173
174static void kvm_psci_system_off(struct kvm_vcpu *vcpu)
175{
176 kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN);
177}
178
179static void kvm_psci_system_reset(struct kvm_vcpu *vcpu)
180{
181 kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET);
182}
183
184int kvm_psci_version(struct kvm_vcpu *vcpu)
185{
186 if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
187 return KVM_ARM_PSCI_0_2;
188
189 return KVM_ARM_PSCI_0_1;
190}
191
192static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
193{
194 int ret = 1;
195 unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
196 unsigned long val;
197
198 switch (psci_fn) {
199 case PSCI_0_2_FN_PSCI_VERSION:
200 /*
201 * Bits[31:16] = Major Version = 0
202 * Bits[15:0] = Minor Version = 2
203 */
204 val = 2;
205 break;
206 case PSCI_0_2_FN_CPU_SUSPEND:
207 case PSCI_0_2_FN64_CPU_SUSPEND:
208 val = kvm_psci_vcpu_suspend(vcpu);
209 break;
210 case PSCI_0_2_FN_CPU_OFF:
211 kvm_psci_vcpu_off(vcpu);
212 val = PSCI_RET_SUCCESS;
213 break;
214 case PSCI_0_2_FN_CPU_ON:
215 case PSCI_0_2_FN64_CPU_ON:
216 val = kvm_psci_vcpu_on(vcpu);
217 break;
218 case PSCI_0_2_FN_AFFINITY_INFO:
219 case PSCI_0_2_FN64_AFFINITY_INFO:
220 val = kvm_psci_vcpu_affinity_info(vcpu);
221 break;
222 case PSCI_0_2_FN_MIGRATE:
223 case PSCI_0_2_FN64_MIGRATE:
224 val = PSCI_RET_NOT_SUPPORTED;
225 break;
226 case PSCI_0_2_FN_MIGRATE_INFO_TYPE:
227 /*
228 * Trusted OS is MP hence does not require migration
229 * or
230 * Trusted OS is not present
231 */
232 val = PSCI_0_2_TOS_MP;
233 break;
234 case PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
235 case PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
236 val = PSCI_RET_NOT_SUPPORTED;
237 break;
238 case PSCI_0_2_FN_SYSTEM_OFF:
239 kvm_psci_system_off(vcpu);
240 /*
241 * We should'nt be going back to guest VCPU after
242 * receiving SYSTEM_OFF request.
243 *
244 * If user space accidently/deliberately resumes
245 * guest VCPU after SYSTEM_OFF request then guest
246 * VCPU should see internal failure from PSCI return
247 * value. To achieve this, we preload r0 (or x0) with
248 * PSCI return value INTERNAL_FAILURE.
249 */
250 val = PSCI_RET_INTERNAL_FAILURE;
251 ret = 0;
252 break;
253 case PSCI_0_2_FN_SYSTEM_RESET:
254 kvm_psci_system_reset(vcpu);
255 /*
256 * Same reason as SYSTEM_OFF for preloading r0 (or x0)
257 * with PSCI return value INTERNAL_FAILURE.
258 */
259 val = PSCI_RET_INTERNAL_FAILURE;
260 ret = 0;
261 break;
262 default:
263 return -EINVAL;
264 }
265
266 *vcpu_reg(vcpu, 0) = val;
267 return ret;
268}
269
270static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
99{ 271{
100 unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); 272 unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
101 unsigned long val; 273 unsigned long val;
@@ -103,20 +275,45 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu)
103 switch (psci_fn) { 275 switch (psci_fn) {
104 case KVM_PSCI_FN_CPU_OFF: 276 case KVM_PSCI_FN_CPU_OFF:
105 kvm_psci_vcpu_off(vcpu); 277 kvm_psci_vcpu_off(vcpu);
106 val = KVM_PSCI_RET_SUCCESS; 278 val = PSCI_RET_SUCCESS;
107 break; 279 break;
108 case KVM_PSCI_FN_CPU_ON: 280 case KVM_PSCI_FN_CPU_ON:
109 val = kvm_psci_vcpu_on(vcpu); 281 val = kvm_psci_vcpu_on(vcpu);
110 break; 282 break;
111 case KVM_PSCI_FN_CPU_SUSPEND: 283 case KVM_PSCI_FN_CPU_SUSPEND:
112 case KVM_PSCI_FN_MIGRATE: 284 case KVM_PSCI_FN_MIGRATE:
113 val = KVM_PSCI_RET_NI; 285 val = PSCI_RET_NOT_SUPPORTED;
114 break; 286 break;
115
116 default: 287 default:
117 return false; 288 return -EINVAL;
118 } 289 }
119 290
120 *vcpu_reg(vcpu, 0) = val; 291 *vcpu_reg(vcpu, 0) = val;
121 return true; 292 return 1;
293}
294
295/**
296 * kvm_psci_call - handle PSCI call if r0 value is in range
297 * @vcpu: Pointer to the VCPU struct
298 *
299 * Handle PSCI calls from guests through traps from HVC instructions.
300 * The calling convention is similar to SMC calls to the secure world
301 * where the function number is placed in r0.
302 *
303 * This function returns: > 0 (success), 0 (success but exit to user
304 * space), and < 0 (errors)
305 *
306 * Errors:
307 * -EINVAL: Unrecognized PSCI function
308 */
309int kvm_psci_call(struct kvm_vcpu *vcpu)
310{
311 switch (kvm_psci_version(vcpu)) {
312 case KVM_ARM_PSCI_0_2:
313 return kvm_psci_0_2_call(vcpu);
314 case KVM_ARM_PSCI_0_1:
315 return kvm_psci_0_1_call(vcpu);
316 default:
317 return -EINVAL;
318 };
122} 319}
diff --git a/arch/arm64/include/asm/cpu_ops.h b/arch/arm64/include/asm/cpu_ops.h
index 152413076503..d7b4b38a8e86 100644
--- a/arch/arm64/include/asm/cpu_ops.h
+++ b/arch/arm64/include/asm/cpu_ops.h
@@ -39,6 +39,7 @@ struct device_node;
39 * from the cpu to be killed. 39 * from the cpu to be killed.
40 * @cpu_die: Makes a cpu leave the kernel. Must not fail. Called from the 40 * @cpu_die: Makes a cpu leave the kernel. Must not fail. Called from the
41 * cpu being killed. 41 * cpu being killed.
42 * @cpu_kill: Ensures a cpu has left the kernel. Called from another cpu.
42 * @cpu_suspend: Suspends a cpu and saves the required context. May fail owing 43 * @cpu_suspend: Suspends a cpu and saves the required context. May fail owing
43 * to wrong parameters or error conditions. Called from the 44 * to wrong parameters or error conditions. Called from the
44 * CPU being suspended. Must be called with IRQs disabled. 45 * CPU being suspended. Must be called with IRQs disabled.
@@ -52,6 +53,7 @@ struct cpu_operations {
52#ifdef CONFIG_HOTPLUG_CPU 53#ifdef CONFIG_HOTPLUG_CPU
53 int (*cpu_disable)(unsigned int cpu); 54 int (*cpu_disable)(unsigned int cpu);
54 void (*cpu_die)(unsigned int cpu); 55 void (*cpu_die)(unsigned int cpu);
56 int (*cpu_kill)(unsigned int cpu);
55#endif 57#endif
56#ifdef CONFIG_ARM64_CPU_SUSPEND 58#ifdef CONFIG_ARM64_CPU_SUSPEND
57 int (*cpu_suspend)(unsigned long); 59 int (*cpu_suspend)(unsigned long);
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index c404fb0df3a6..27f54a7cc81b 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -41,6 +41,7 @@
41 41
42#define ARM_CPU_PART_AEM_V8 0xD0F0 42#define ARM_CPU_PART_AEM_V8 0xD0F0
43#define ARM_CPU_PART_FOUNDATION 0xD000 43#define ARM_CPU_PART_FOUNDATION 0xD000
44#define ARM_CPU_PART_CORTEX_A53 0xD030
44#define ARM_CPU_PART_CORTEX_A57 0xD070 45#define ARM_CPU_PART_CORTEX_A57 0xD070
45 46
46#define APM_CPU_PART_POTENZA 0x0000 47#define APM_CPU_PART_POTENZA 0x0000
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 0a1d69751562..92242ce06309 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -39,7 +39,7 @@
39#include <kvm/arm_vgic.h> 39#include <kvm/arm_vgic.h>
40#include <kvm/arm_arch_timer.h> 40#include <kvm/arm_arch_timer.h>
41 41
42#define KVM_VCPU_MAX_FEATURES 2 42#define KVM_VCPU_MAX_FEATURES 3
43 43
44struct kvm_vcpu; 44struct kvm_vcpu;
45int kvm_target_cpu(void); 45int kvm_target_cpu(void);
diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h
index e301a4816355..bc39e557c56c 100644
--- a/arch/arm64/include/asm/kvm_psci.h
+++ b/arch/arm64/include/asm/kvm_psci.h
@@ -18,6 +18,10 @@
18#ifndef __ARM64_KVM_PSCI_H__ 18#ifndef __ARM64_KVM_PSCI_H__
19#define __ARM64_KVM_PSCI_H__ 19#define __ARM64_KVM_PSCI_H__
20 20
21bool kvm_psci_call(struct kvm_vcpu *vcpu); 21#define KVM_ARM_PSCI_0_1 1
22#define KVM_ARM_PSCI_0_2 2
23
24int kvm_psci_version(struct kvm_vcpu *vcpu);
25int kvm_psci_call(struct kvm_vcpu *vcpu);
22 26
23#endif /* __ARM64_KVM_PSCI_H__ */ 27#endif /* __ARM64_KVM_PSCI_H__ */
diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h
index d15ab8b46336..e5312ea0ec1a 100644
--- a/arch/arm64/include/asm/psci.h
+++ b/arch/arm64/include/asm/psci.h
@@ -14,6 +14,6 @@
14#ifndef __ASM_PSCI_H 14#ifndef __ASM_PSCI_H
15#define __ASM_PSCI_H 15#define __ASM_PSCI_H
16 16
17void psci_init(void); 17int psci_init(void);
18 18
19#endif /* __ASM_PSCI_H */ 19#endif /* __ASM_PSCI_H */
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index eaf54a30bedc..e633ff8cdec8 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -31,6 +31,7 @@
31#define KVM_NR_SPSR 5 31#define KVM_NR_SPSR 5
32 32
33#ifndef __ASSEMBLY__ 33#ifndef __ASSEMBLY__
34#include <linux/psci.h>
34#include <asm/types.h> 35#include <asm/types.h>
35#include <asm/ptrace.h> 36#include <asm/ptrace.h>
36 37
@@ -56,8 +57,9 @@ struct kvm_regs {
56#define KVM_ARM_TARGET_FOUNDATION_V8 1 57#define KVM_ARM_TARGET_FOUNDATION_V8 1
57#define KVM_ARM_TARGET_CORTEX_A57 2 58#define KVM_ARM_TARGET_CORTEX_A57 2
58#define KVM_ARM_TARGET_XGENE_POTENZA 3 59#define KVM_ARM_TARGET_XGENE_POTENZA 3
60#define KVM_ARM_TARGET_CORTEX_A53 4
59 61
60#define KVM_ARM_NUM_TARGETS 4 62#define KVM_ARM_NUM_TARGETS 5
61 63
62/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */ 64/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
63#define KVM_ARM_DEVICE_TYPE_SHIFT 0 65#define KVM_ARM_DEVICE_TYPE_SHIFT 0
@@ -77,6 +79,7 @@ struct kvm_regs {
77 79
78#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ 80#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
79#define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ 81#define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */
82#define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */
80 83
81struct kvm_vcpu_init { 84struct kvm_vcpu_init {
82 __u32 target; 85 __u32 target;
@@ -186,10 +189,10 @@ struct kvm_arch_memory_slot {
186#define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2) 189#define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2)
187#define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3) 190#define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
188 191
189#define KVM_PSCI_RET_SUCCESS 0 192#define KVM_PSCI_RET_SUCCESS PSCI_RET_SUCCESS
190#define KVM_PSCI_RET_NI ((unsigned long)-1) 193#define KVM_PSCI_RET_NI PSCI_RET_NOT_SUPPORTED
191#define KVM_PSCI_RET_INVAL ((unsigned long)-2) 194#define KVM_PSCI_RET_INVAL PSCI_RET_INVALID_PARAMS
192#define KVM_PSCI_RET_DENIED ((unsigned long)-3) 195#define KVM_PSCI_RET_DENIED PSCI_RET_DENIED
193 196
194#endif 197#endif
195 198
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index ea4828a4aa96..9e9798f91172 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -18,12 +18,17 @@
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/smp.h> 20#include <linux/smp.h>
21#include <linux/reboot.h>
22#include <linux/pm.h>
23#include <linux/delay.h>
24#include <uapi/linux/psci.h>
21 25
22#include <asm/compiler.h> 26#include <asm/compiler.h>
23#include <asm/cpu_ops.h> 27#include <asm/cpu_ops.h>
24#include <asm/errno.h> 28#include <asm/errno.h>
25#include <asm/psci.h> 29#include <asm/psci.h>
26#include <asm/smp_plat.h> 30#include <asm/smp_plat.h>
31#include <asm/system_misc.h>
27 32
28#define PSCI_POWER_STATE_TYPE_STANDBY 0 33#define PSCI_POWER_STATE_TYPE_STANDBY 0
29#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1 34#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1
@@ -40,58 +45,52 @@ struct psci_operations {
40 int (*cpu_off)(struct psci_power_state state); 45 int (*cpu_off)(struct psci_power_state state);
41 int (*cpu_on)(unsigned long cpuid, unsigned long entry_point); 46 int (*cpu_on)(unsigned long cpuid, unsigned long entry_point);
42 int (*migrate)(unsigned long cpuid); 47 int (*migrate)(unsigned long cpuid);
48 int (*affinity_info)(unsigned long target_affinity,
49 unsigned long lowest_affinity_level);
50 int (*migrate_info_type)(void);
43}; 51};
44 52
45static struct psci_operations psci_ops; 53static struct psci_operations psci_ops;
46 54
47static int (*invoke_psci_fn)(u64, u64, u64, u64); 55static int (*invoke_psci_fn)(u64, u64, u64, u64);
56typedef int (*psci_initcall_t)(const struct device_node *);
48 57
49enum psci_function { 58enum psci_function {
50 PSCI_FN_CPU_SUSPEND, 59 PSCI_FN_CPU_SUSPEND,
51 PSCI_FN_CPU_ON, 60 PSCI_FN_CPU_ON,
52 PSCI_FN_CPU_OFF, 61 PSCI_FN_CPU_OFF,
53 PSCI_FN_MIGRATE, 62 PSCI_FN_MIGRATE,
63 PSCI_FN_AFFINITY_INFO,
64 PSCI_FN_MIGRATE_INFO_TYPE,
54 PSCI_FN_MAX, 65 PSCI_FN_MAX,
55}; 66};
56 67
57static u32 psci_function_id[PSCI_FN_MAX]; 68static u32 psci_function_id[PSCI_FN_MAX];
58 69
59#define PSCI_RET_SUCCESS 0
60#define PSCI_RET_EOPNOTSUPP -1
61#define PSCI_RET_EINVAL -2
62#define PSCI_RET_EPERM -3
63
64static int psci_to_linux_errno(int errno) 70static int psci_to_linux_errno(int errno)
65{ 71{
66 switch (errno) { 72 switch (errno) {
67 case PSCI_RET_SUCCESS: 73 case PSCI_RET_SUCCESS:
68 return 0; 74 return 0;
69 case PSCI_RET_EOPNOTSUPP: 75 case PSCI_RET_NOT_SUPPORTED:
70 return -EOPNOTSUPP; 76 return -EOPNOTSUPP;
71 case PSCI_RET_EINVAL: 77 case PSCI_RET_INVALID_PARAMS:
72 return -EINVAL; 78 return -EINVAL;
73 case PSCI_RET_EPERM: 79 case PSCI_RET_DENIED:
74 return -EPERM; 80 return -EPERM;
75 }; 81 };
76 82
77 return -EINVAL; 83 return -EINVAL;
78} 84}
79 85
80#define PSCI_POWER_STATE_ID_MASK 0xffff
81#define PSCI_POWER_STATE_ID_SHIFT 0
82#define PSCI_POWER_STATE_TYPE_MASK 0x1
83#define PSCI_POWER_STATE_TYPE_SHIFT 16
84#define PSCI_POWER_STATE_AFFL_MASK 0x3
85#define PSCI_POWER_STATE_AFFL_SHIFT 24
86
87static u32 psci_power_state_pack(struct psci_power_state state) 86static u32 psci_power_state_pack(struct psci_power_state state)
88{ 87{
89 return ((state.id & PSCI_POWER_STATE_ID_MASK) 88 return ((state.id << PSCI_0_2_POWER_STATE_ID_SHIFT)
90 << PSCI_POWER_STATE_ID_SHIFT) | 89 & PSCI_0_2_POWER_STATE_ID_MASK) |
91 ((state.type & PSCI_POWER_STATE_TYPE_MASK) 90 ((state.type << PSCI_0_2_POWER_STATE_TYPE_SHIFT)
92 << PSCI_POWER_STATE_TYPE_SHIFT) | 91 & PSCI_0_2_POWER_STATE_TYPE_MASK) |
93 ((state.affinity_level & PSCI_POWER_STATE_AFFL_MASK) 92 ((state.affinity_level << PSCI_0_2_POWER_STATE_AFFL_SHIFT)
94 << PSCI_POWER_STATE_AFFL_SHIFT); 93 & PSCI_0_2_POWER_STATE_AFFL_MASK);
95} 94}
96 95
97/* 96/*
@@ -128,6 +127,14 @@ static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1,
128 return function_id; 127 return function_id;
129} 128}
130 129
130static int psci_get_version(void)
131{
132 int err;
133
134 err = invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
135 return err;
136}
137
131static int psci_cpu_suspend(struct psci_power_state state, 138static int psci_cpu_suspend(struct psci_power_state state,
132 unsigned long entry_point) 139 unsigned long entry_point)
133{ 140{
@@ -171,26 +178,36 @@ static int psci_migrate(unsigned long cpuid)
171 return psci_to_linux_errno(err); 178 return psci_to_linux_errno(err);
172} 179}
173 180
174static const struct of_device_id psci_of_match[] __initconst = { 181static int psci_affinity_info(unsigned long target_affinity,
175 { .compatible = "arm,psci", }, 182 unsigned long lowest_affinity_level)
176 {}, 183{
177}; 184 int err;
185 u32 fn;
186
187 fn = psci_function_id[PSCI_FN_AFFINITY_INFO];
188 err = invoke_psci_fn(fn, target_affinity, lowest_affinity_level, 0);
189 return err;
190}
178 191
179void __init psci_init(void) 192static int psci_migrate_info_type(void)
180{ 193{
181 struct device_node *np; 194 int err;
182 const char *method; 195 u32 fn;
183 u32 id;
184 196
185 np = of_find_matching_node(NULL, psci_of_match); 197 fn = psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE];
186 if (!np) 198 err = invoke_psci_fn(fn, 0, 0, 0);
187 return; 199 return err;
200}
188 201
189 pr_info("probing function IDs from device-tree\n"); 202static int get_set_conduit_method(struct device_node *np)
203{
204 const char *method;
205
206 pr_info("probing for conduit method from DT.\n");
190 207
191 if (of_property_read_string(np, "method", &method)) { 208 if (of_property_read_string(np, "method", &method)) {
192 pr_warning("missing \"method\" property\n"); 209 pr_warn("missing \"method\" property\n");
193 goto out_put_node; 210 return -ENXIO;
194 } 211 }
195 212
196 if (!strcmp("hvc", method)) { 213 if (!strcmp("hvc", method)) {
@@ -198,10 +215,99 @@ void __init psci_init(void)
198 } else if (!strcmp("smc", method)) { 215 } else if (!strcmp("smc", method)) {
199 invoke_psci_fn = __invoke_psci_fn_smc; 216 invoke_psci_fn = __invoke_psci_fn_smc;
200 } else { 217 } else {
201 pr_warning("invalid \"method\" property: %s\n", method); 218 pr_warn("invalid \"method\" property: %s\n", method);
219 return -EINVAL;
220 }
221 return 0;
222}
223
224static void psci_sys_reset(enum reboot_mode reboot_mode, const char *cmd)
225{
226 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
227}
228
229static void psci_sys_poweroff(void)
230{
231 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
232}
233
234/*
235 * PSCI Function IDs for v0.2+ are well defined so use
236 * standard values.
237 */
238static int psci_0_2_init(struct device_node *np)
239{
240 int err, ver;
241
242 err = get_set_conduit_method(np);
243
244 if (err)
245 goto out_put_node;
246
247 ver = psci_get_version();
248
249 if (ver == PSCI_RET_NOT_SUPPORTED) {
250 /* PSCI v0.2 mandates implementation of PSCI_ID_VERSION. */
251 pr_err("PSCI firmware does not comply with the v0.2 spec.\n");
252 err = -EOPNOTSUPP;
202 goto out_put_node; 253 goto out_put_node;
254 } else {
255 pr_info("PSCIv%d.%d detected in firmware.\n",
256 PSCI_VERSION_MAJOR(ver),
257 PSCI_VERSION_MINOR(ver));
258
259 if (PSCI_VERSION_MAJOR(ver) == 0 &&
260 PSCI_VERSION_MINOR(ver) < 2) {
261 err = -EINVAL;
262 pr_err("Conflicting PSCI version detected.\n");
263 goto out_put_node;
264 }
203 } 265 }
204 266
267 pr_info("Using standard PSCI v0.2 function IDs\n");
268 psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND;
269 psci_ops.cpu_suspend = psci_cpu_suspend;
270
271 psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF;
272 psci_ops.cpu_off = psci_cpu_off;
273
274 psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN64_CPU_ON;
275 psci_ops.cpu_on = psci_cpu_on;
276
277 psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN64_MIGRATE;
278 psci_ops.migrate = psci_migrate;
279
280 psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_0_2_FN64_AFFINITY_INFO;
281 psci_ops.affinity_info = psci_affinity_info;
282
283 psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] =
284 PSCI_0_2_FN_MIGRATE_INFO_TYPE;
285 psci_ops.migrate_info_type = psci_migrate_info_type;
286
287 arm_pm_restart = psci_sys_reset;
288
289 pm_power_off = psci_sys_poweroff;
290
291out_put_node:
292 of_node_put(np);
293 return err;
294}
295
296/*
297 * PSCI < v0.2 get PSCI Function IDs via DT.
298 */
299static int psci_0_1_init(struct device_node *np)
300{
301 u32 id;
302 int err;
303
304 err = get_set_conduit_method(np);
305
306 if (err)
307 goto out_put_node;
308
309 pr_info("Using PSCI v0.1 Function IDs from DT\n");
310
205 if (!of_property_read_u32(np, "cpu_suspend", &id)) { 311 if (!of_property_read_u32(np, "cpu_suspend", &id)) {
206 psci_function_id[PSCI_FN_CPU_SUSPEND] = id; 312 psci_function_id[PSCI_FN_CPU_SUSPEND] = id;
207 psci_ops.cpu_suspend = psci_cpu_suspend; 313 psci_ops.cpu_suspend = psci_cpu_suspend;
@@ -224,7 +330,28 @@ void __init psci_init(void)
224 330
225out_put_node: 331out_put_node:
226 of_node_put(np); 332 of_node_put(np);
227 return; 333 return err;
334}
335
336static const struct of_device_id psci_of_match[] __initconst = {
337 { .compatible = "arm,psci", .data = psci_0_1_init},
338 { .compatible = "arm,psci-0.2", .data = psci_0_2_init},
339 {},
340};
341
342int __init psci_init(void)
343{
344 struct device_node *np;
345 const struct of_device_id *matched_np;
346 psci_initcall_t init_fn;
347
348 np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
349
350 if (!np)
351 return -ENODEV;
352
353 init_fn = (psci_initcall_t)matched_np->data;
354 return init_fn(np);
228} 355}
229 356
230#ifdef CONFIG_SMP 357#ifdef CONFIG_SMP
@@ -277,6 +404,35 @@ static void cpu_psci_cpu_die(unsigned int cpu)
277 404
278 pr_crit("unable to power off CPU%u (%d)\n", cpu, ret); 405 pr_crit("unable to power off CPU%u (%d)\n", cpu, ret);
279} 406}
407
408static int cpu_psci_cpu_kill(unsigned int cpu)
409{
410 int err, i;
411
412 if (!psci_ops.affinity_info)
413 return 1;
414 /*
415 * cpu_kill could race with cpu_die and we can
416 * potentially end up declaring this cpu undead
417 * while it is dying. So, try again a few times.
418 */
419
420 for (i = 0; i < 10; i++) {
421 err = psci_ops.affinity_info(cpu_logical_map(cpu), 0);
422 if (err == PSCI_0_2_AFFINITY_LEVEL_OFF) {
423 pr_info("CPU%d killed.\n", cpu);
424 return 1;
425 }
426
427 msleep(10);
428 pr_info("Retrying again to check for CPU kill\n");
429 }
430
431 pr_warn("CPU%d may not have shut down cleanly (AFFINITY_INFO reports %d)\n",
432 cpu, err);
433 /* Make op_cpu_kill() fail. */
434 return 0;
435}
280#endif 436#endif
281 437
282const struct cpu_operations cpu_psci_ops = { 438const struct cpu_operations cpu_psci_ops = {
@@ -287,6 +443,7 @@ const struct cpu_operations cpu_psci_ops = {
287#ifdef CONFIG_HOTPLUG_CPU 443#ifdef CONFIG_HOTPLUG_CPU
288 .cpu_disable = cpu_psci_cpu_disable, 444 .cpu_disable = cpu_psci_cpu_disable,
289 .cpu_die = cpu_psci_cpu_die, 445 .cpu_die = cpu_psci_cpu_die,
446 .cpu_kill = cpu_psci_cpu_kill,
290#endif 447#endif
291}; 448};
292 449
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index f0a141dd5655..c3cb160edc69 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -228,6 +228,19 @@ int __cpu_disable(void)
228 return 0; 228 return 0;
229} 229}
230 230
231static int op_cpu_kill(unsigned int cpu)
232{
233 /*
234 * If we have no means of synchronising with the dying CPU, then assume
235 * that it is really dead. We can only wait for an arbitrary length of
236 * time and hope that it's dead, so let's skip the wait and just hope.
237 */
238 if (!cpu_ops[cpu]->cpu_kill)
239 return 1;
240
241 return cpu_ops[cpu]->cpu_kill(cpu);
242}
243
231static DECLARE_COMPLETION(cpu_died); 244static DECLARE_COMPLETION(cpu_died);
232 245
233/* 246/*
@@ -241,6 +254,15 @@ void __cpu_die(unsigned int cpu)
241 return; 254 return;
242 } 255 }
243 pr_notice("CPU%u: shutdown\n", cpu); 256 pr_notice("CPU%u: shutdown\n", cpu);
257
258 /*
259 * Now that the dying CPU is beyond the point of no return w.r.t.
260 * in-kernel synchronisation, try to get the firwmare to help us to
261 * verify that it has really left the kernel before we consider
262 * clobbering anything it might still be using.
263 */
264 if (!op_cpu_kill(cpu))
265 pr_warn("CPU%d may not have shut down cleanly\n", cpu);
244} 266}
245 267
246/* 268/*
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 08745578d54d..60b5c31f3c10 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -214,6 +214,8 @@ int __attribute_const__ kvm_target_cpu(void)
214 return KVM_ARM_TARGET_AEM_V8; 214 return KVM_ARM_TARGET_AEM_V8;
215 case ARM_CPU_PART_FOUNDATION: 215 case ARM_CPU_PART_FOUNDATION:
216 return KVM_ARM_TARGET_FOUNDATION_V8; 216 return KVM_ARM_TARGET_FOUNDATION_V8;
217 case ARM_CPU_PART_CORTEX_A53:
218 return KVM_ARM_TARGET_CORTEX_A53;
217 case ARM_CPU_PART_CORTEX_A57: 219 case ARM_CPU_PART_CORTEX_A57:
218 return KVM_ARM_TARGET_CORTEX_A57; 220 return KVM_ARM_TARGET_CORTEX_A57;
219 }; 221 };
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 7bc41eab4c64..182415e1a952 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -30,11 +30,15 @@ typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
30 30
31static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) 31static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
32{ 32{
33 if (kvm_psci_call(vcpu)) 33 int ret;
34
35 ret = kvm_psci_call(vcpu);
36 if (ret < 0) {
37 kvm_inject_undefined(vcpu);
34 return 1; 38 return 1;
39 }
35 40
36 kvm_inject_undefined(vcpu); 41 return ret;
37 return 1;
38} 42}
39 43
40static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) 44static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
diff --git a/arch/arm64/kvm/sys_regs_generic_v8.c b/arch/arm64/kvm/sys_regs_generic_v8.c
index 8fe6f76b0edc..475fd2929310 100644
--- a/arch/arm64/kvm/sys_regs_generic_v8.c
+++ b/arch/arm64/kvm/sys_regs_generic_v8.c
@@ -88,6 +88,8 @@ static int __init sys_reg_genericv8_init(void)
88 &genericv8_target_table); 88 &genericv8_target_table);
89 kvm_register_target_sys_reg_table(KVM_ARM_TARGET_FOUNDATION_V8, 89 kvm_register_target_sys_reg_table(KVM_ARM_TARGET_FOUNDATION_V8,
90 &genericv8_target_table); 90 &genericv8_target_table);
91 kvm_register_target_sys_reg_table(KVM_ARM_TARGET_CORTEX_A53,
92 &genericv8_target_table);
91 kvm_register_target_sys_reg_table(KVM_ARM_TARGET_CORTEX_A57, 93 kvm_register_target_sys_reg_table(KVM_ARM_TARGET_CORTEX_A57,
92 &genericv8_target_table); 94 &genericv8_target_table);
93 kvm_register_target_sys_reg_table(KVM_ARM_TARGET_XGENE_POTENZA, 95 kvm_register_target_sys_reg_table(KVM_ARM_TARGET_XGENE_POTENZA,
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 6929571b79b0..24e9033f8b3f 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -317,6 +317,7 @@ header-y += ppp-ioctl.h
317header-y += ppp_defs.h 317header-y += ppp_defs.h
318header-y += pps.h 318header-y += pps.h
319header-y += prctl.h 319header-y += prctl.h
320header-y += psci.h
320header-y += ptp_clock.h 321header-y += ptp_clock.h
321header-y += ptrace.h 322header-y += ptrace.h
322header-y += qnx4_fs.h 323header-y += qnx4_fs.h
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 2b83cf35437a..32cf446f1911 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -171,6 +171,7 @@ struct kvm_pit_config {
171#define KVM_EXIT_WATCHDOG 21 171#define KVM_EXIT_WATCHDOG 21
172#define KVM_EXIT_S390_TSCH 22 172#define KVM_EXIT_S390_TSCH 22
173#define KVM_EXIT_EPR 23 173#define KVM_EXIT_EPR 23
174#define KVM_EXIT_SYSTEM_EVENT 24
174 175
175/* For KVM_EXIT_INTERNAL_ERROR */ 176/* For KVM_EXIT_INTERNAL_ERROR */
176/* Emulate instruction failed. */ 177/* Emulate instruction failed. */
@@ -301,6 +302,13 @@ struct kvm_run {
301 struct { 302 struct {
302 __u32 epr; 303 __u32 epr;
303 } epr; 304 } epr;
305 /* KVM_EXIT_SYSTEM_EVENT */
306 struct {
307#define KVM_SYSTEM_EVENT_SHUTDOWN 1
308#define KVM_SYSTEM_EVENT_RESET 2
309 __u32 type;
310 __u64 flags;
311 } system_event;
304 /* Fix the size of the union. */ 312 /* Fix the size of the union. */
305 char padding[256]; 313 char padding[256];
306 }; 314 };
@@ -748,6 +756,7 @@ struct kvm_ppc_smmu_info {
748#define KVM_CAP_S390_IRQCHIP 99 756#define KVM_CAP_S390_IRQCHIP 99
749#define KVM_CAP_IOEVENTFD_NO_LENGTH 100 757#define KVM_CAP_IOEVENTFD_NO_LENGTH 100
750#define KVM_CAP_VM_ATTRIBUTES 101 758#define KVM_CAP_VM_ATTRIBUTES 101
759#define KVM_CAP_ARM_PSCI_0_2 102
751 760
752#ifdef KVM_CAP_IRQ_ROUTING 761#ifdef KVM_CAP_IRQ_ROUTING
753 762
diff --git a/include/uapi/linux/psci.h b/include/uapi/linux/psci.h
new file mode 100644
index 000000000000..310d83e0a91b
--- /dev/null
+++ b/include/uapi/linux/psci.h
@@ -0,0 +1,90 @@
1/*
2 * ARM Power State and Coordination Interface (PSCI) header
3 *
4 * This header holds common PSCI defines and macros shared
5 * by: ARM kernel, ARM64 kernel, KVM ARM/ARM64 and user space.
6 *
7 * Copyright (C) 2014 Linaro Ltd.
8 * Author: Anup Patel <anup.patel@linaro.org>
9 */
10
11#ifndef _UAPI_LINUX_PSCI_H
12#define _UAPI_LINUX_PSCI_H
13
14/*
15 * PSCI v0.1 interface
16 *
17 * The PSCI v0.1 function numbers are implementation defined.
18 *
19 * Only PSCI return values such as: SUCCESS, NOT_SUPPORTED,
20 * INVALID_PARAMS, and DENIED defined below are applicable
21 * to PSCI v0.1.
22 */
23
24/* PSCI v0.2 interface */
25#define PSCI_0_2_FN_BASE 0x84000000
26#define PSCI_0_2_FN(n) (PSCI_0_2_FN_BASE + (n))
27#define PSCI_0_2_64BIT 0x40000000
28#define PSCI_0_2_FN64_BASE \
29 (PSCI_0_2_FN_BASE + PSCI_0_2_64BIT)
30#define PSCI_0_2_FN64(n) (PSCI_0_2_FN64_BASE + (n))
31
32#define PSCI_0_2_FN_PSCI_VERSION PSCI_0_2_FN(0)
33#define PSCI_0_2_FN_CPU_SUSPEND PSCI_0_2_FN(1)
34#define PSCI_0_2_FN_CPU_OFF PSCI_0_2_FN(2)
35#define PSCI_0_2_FN_CPU_ON PSCI_0_2_FN(3)
36#define PSCI_0_2_FN_AFFINITY_INFO PSCI_0_2_FN(4)
37#define PSCI_0_2_FN_MIGRATE PSCI_0_2_FN(5)
38#define PSCI_0_2_FN_MIGRATE_INFO_TYPE PSCI_0_2_FN(6)
39#define PSCI_0_2_FN_MIGRATE_INFO_UP_CPU PSCI_0_2_FN(7)
40#define PSCI_0_2_FN_SYSTEM_OFF PSCI_0_2_FN(8)
41#define PSCI_0_2_FN_SYSTEM_RESET PSCI_0_2_FN(9)
42
43#define PSCI_0_2_FN64_CPU_SUSPEND PSCI_0_2_FN64(1)
44#define PSCI_0_2_FN64_CPU_ON PSCI_0_2_FN64(3)
45#define PSCI_0_2_FN64_AFFINITY_INFO PSCI_0_2_FN64(4)
46#define PSCI_0_2_FN64_MIGRATE PSCI_0_2_FN64(5)
47#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7)
48
49/* PSCI v0.2 power state encoding for CPU_SUSPEND function */
50#define PSCI_0_2_POWER_STATE_ID_MASK 0xffff
51#define PSCI_0_2_POWER_STATE_ID_SHIFT 0
52#define PSCI_0_2_POWER_STATE_TYPE_SHIFT 16
53#define PSCI_0_2_POWER_STATE_TYPE_MASK \
54 (0x1 << PSCI_0_2_POWER_STATE_TYPE_SHIFT)
55#define PSCI_0_2_POWER_STATE_AFFL_SHIFT 24
56#define PSCI_0_2_POWER_STATE_AFFL_MASK \
57 (0x3 << PSCI_0_2_POWER_STATE_AFFL_SHIFT)
58
59/* PSCI v0.2 affinity level state returned by AFFINITY_INFO */
60#define PSCI_0_2_AFFINITY_LEVEL_ON 0
61#define PSCI_0_2_AFFINITY_LEVEL_OFF 1
62#define PSCI_0_2_AFFINITY_LEVEL_ON_PENDING 2
63
64/* PSCI v0.2 multicore support in Trusted OS returned by MIGRATE_INFO_TYPE */
65#define PSCI_0_2_TOS_UP_MIGRATE 0
66#define PSCI_0_2_TOS_UP_NO_MIGRATE 1
67#define PSCI_0_2_TOS_MP 2
68
69/* PSCI version decoding (independent of PSCI version) */
70#define PSCI_VERSION_MAJOR_SHIFT 16
71#define PSCI_VERSION_MINOR_MASK \
72 ((1U << PSCI_VERSION_MAJOR_SHIFT) - 1)
73#define PSCI_VERSION_MAJOR_MASK ~PSCI_VERSION_MINOR_MASK
74#define PSCI_VERSION_MAJOR(ver) \
75 (((ver) & PSCI_VERSION_MAJOR_MASK) >> PSCI_VERSION_MAJOR_SHIFT)
76#define PSCI_VERSION_MINOR(ver) \
77 ((ver) & PSCI_VERSION_MINOR_MASK)
78
79/* PSCI return values (inclusive of all PSCI versions) */
80#define PSCI_RET_SUCCESS 0
81#define PSCI_RET_NOT_SUPPORTED -1
82#define PSCI_RET_INVALID_PARAMS -2
83#define PSCI_RET_DENIED -3
84#define PSCI_RET_ALREADY_ON -4
85#define PSCI_RET_ON_PENDING -5
86#define PSCI_RET_INTERNAL_FAILURE -6
87#define PSCI_RET_NOT_PRESENT -7
88#define PSCI_RET_DISABLED -8
89
90#endif /* _UAPI_LINUX_PSCI_H */