aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@linaro.org>2014-04-29 01:54:18 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2014-04-30 07:18:57 -0400
commite8e7fcc5e2710b31ef842ee799db99c07986c364 (patch)
tree2f9005ad128030c359da457486de308260ebba89 /arch
parent50bb0c94759bff8c62f1c7c8f774255e44ec1a41 (diff)
ARM/ARM64: KVM: Make kvm_psci_call() return convention more flexible
Currently, the kvm_psci_call() returns 'true' or 'false' based on whether the PSCI function call was handled successfully or not. This does not help us emulate system-level PSCI functions where the actual emulation work will be done by user space (QEMU or KVMTOOL). Examples of such system-level PSCI functions are: PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET. This patch updates kvm_psci_call() to return three types of values: 1) > 0 (success) 2) = 0 (success but exit to user space) 3) < 0 (errors) Signed-off-by: Anup Patel <anup.patel@linaro.org> Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Acked-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/asm/kvm_psci.h2
-rw-r--r--arch/arm/kvm/handle_exit.c10
-rw-r--r--arch/arm/kvm/psci.c28
-rw-r--r--arch/arm64/include/asm/kvm_psci.h2
-rw-r--r--arch/arm64/kvm/handle_exit.c10
5 files changed, 32 insertions, 20 deletions
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h
index 4c0e3e1d1597..6bda945d31fa 100644
--- a/arch/arm/include/asm/kvm_psci.h
+++ b/arch/arm/include/asm/kvm_psci.h
@@ -22,6 +22,6 @@
22#define KVM_ARM_PSCI_0_2 2 22#define KVM_ARM_PSCI_0_2 2
23 23
24int kvm_psci_version(struct kvm_vcpu *vcpu); 24int kvm_psci_version(struct kvm_vcpu *vcpu);
25bool kvm_psci_call(struct kvm_vcpu *vcpu); 25int kvm_psci_call(struct kvm_vcpu *vcpu);
26 26
27#endif /* __ARM_KVM_PSCI_H__ */ 27#endif /* __ARM_KVM_PSCI_H__ */
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 8c42596cdbdf..14e6fa6c8e35 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -93,7 +93,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
93 return KVM_ARM_PSCI_0_1; 93 return KVM_ARM_PSCI_0_1;
94} 94}
95 95
96static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) 96static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
97{ 97{
98 unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); 98 unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
99 unsigned long val; 99 unsigned long val;
@@ -128,14 +128,14 @@ static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
128 val = PSCI_RET_NOT_SUPPORTED; 128 val = PSCI_RET_NOT_SUPPORTED;
129 break; 129 break;
130 default: 130 default:
131 return false; 131 return -EINVAL;
132 } 132 }
133 133
134 *vcpu_reg(vcpu, 0) = val; 134 *vcpu_reg(vcpu, 0) = val;
135 return true; 135 return 1;
136} 136}
137 137
138static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) 138static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
139{ 139{
140 unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); 140 unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
141 unsigned long val; 141 unsigned long val;
@@ -153,11 +153,11 @@ static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
153 val = PSCI_RET_NOT_SUPPORTED; 153 val = PSCI_RET_NOT_SUPPORTED;
154 break; 154 break;
155 default: 155 default:
156 return false; 156 return -EINVAL;
157 } 157 }
158 158
159 *vcpu_reg(vcpu, 0) = val; 159 *vcpu_reg(vcpu, 0) = val;
160 return true; 160 return 1;
161} 161}
162 162
163/** 163/**
@@ -165,12 +165,16 @@ static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
165 * @vcpu: Pointer to the VCPU struct 165 * @vcpu: Pointer to the VCPU struct
166 * 166 *
167 * Handle PSCI calls from guests through traps from HVC instructions. 167 * Handle PSCI calls from guests through traps from HVC instructions.
168 * The calling convention is similar to SMC calls to the secure world where 168 * The calling convention is similar to SMC calls to the secure world
169 * the function number is placed in r0 and this function returns true if the 169 * where the function number is placed in r0.
170 * function number specified in r0 is withing the PSCI range, and false 170 *
171 * otherwise. 171 * This function returns: > 0 (success), 0 (success but exit to user
172 * space), and < 0 (errors)
173 *
174 * Errors:
175 * -EINVAL: Unrecognized PSCI function
172 */ 176 */
173bool kvm_psci_call(struct kvm_vcpu *vcpu) 177int kvm_psci_call(struct kvm_vcpu *vcpu)
174{ 178{
175 switch (kvm_psci_version(vcpu)) { 179 switch (kvm_psci_version(vcpu)) {
176 case KVM_ARM_PSCI_0_2: 180 case KVM_ARM_PSCI_0_2:
@@ -178,6 +182,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu)
178 case KVM_ARM_PSCI_0_1: 182 case KVM_ARM_PSCI_0_1:
179 return kvm_psci_0_1_call(vcpu); 183 return kvm_psci_0_1_call(vcpu);
180 default: 184 default:
181 return false; 185 return -EINVAL;
182 }; 186 };
183} 187}
diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h
index e25c658a757b..bc39e557c56c 100644
--- a/arch/arm64/include/asm/kvm_psci.h
+++ b/arch/arm64/include/asm/kvm_psci.h
@@ -22,6 +22,6 @@
22#define KVM_ARM_PSCI_0_2 2 22#define KVM_ARM_PSCI_0_2 2
23 23
24int kvm_psci_version(struct kvm_vcpu *vcpu); 24int kvm_psci_version(struct kvm_vcpu *vcpu);
25bool kvm_psci_call(struct kvm_vcpu *vcpu); 25int kvm_psci_call(struct kvm_vcpu *vcpu);
26 26
27#endif /* __ARM64_KVM_PSCI_H__ */ 27#endif /* __ARM64_KVM_PSCI_H__ */
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)