Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Anup Patel and committed by
Christoffer Dall
e8e7fcc5 50bb0c94

+33 -21
+1 -1
arch/arm/include/asm/kvm_psci.h
··· 22 22 #define KVM_ARM_PSCI_0_2 2 23 23 24 24 int kvm_psci_version(struct kvm_vcpu *vcpu); 25 - bool kvm_psci_call(struct kvm_vcpu *vcpu); 25 + int kvm_psci_call(struct kvm_vcpu *vcpu); 26 26 27 27 #endif /* __ARM_KVM_PSCI_H__ */
+7 -3
arch/arm/kvm/handle_exit.c
··· 38 38 39 39 static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) 40 40 { 41 + int ret; 42 + 41 43 trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0), 42 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 49 return 1; 50 + } 46 51 47 - kvm_inject_undefined(vcpu); 48 - return 1; 52 + return ret; 49 53 } 50 54 51 55 static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
+16 -12
arch/arm/kvm/psci.c
··· 93 93 return KVM_ARM_PSCI_0_1; 94 94 } 95 95 96 - static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu) 96 + static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) 97 97 { 98 98 unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); 99 99 unsigned long val; ··· 128 128 val = PSCI_RET_NOT_SUPPORTED; 129 129 break; 130 130 default: 131 - return false; 131 + return -EINVAL; 132 132 } 133 133 134 134 *vcpu_reg(vcpu, 0) = val; 135 - return true; 135 + return 1; 136 136 } 137 137 138 - static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu) 138 + static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) 139 139 { 140 140 unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); 141 141 unsigned long val; ··· 153 153 val = PSCI_RET_NOT_SUPPORTED; 154 154 break; 155 155 default: 156 - return false; 156 + return -EINVAL; 157 157 } 158 158 159 159 *vcpu_reg(vcpu, 0) = val; 160 - return true; 160 + return 1; 161 161 } 162 162 163 163 /** ··· 165 165 * @vcpu: Pointer to the VCPU struct 166 166 * 167 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 169 - * the function number is placed in r0 and this function returns true if the 170 - * function number specified in r0 is withing the PSCI range, and false 171 - * otherwise. 168 + * The calling convention is similar to SMC calls to the secure world 169 + * where the function number is placed in r0. 170 + * 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 */ 173 - bool kvm_psci_call(struct kvm_vcpu *vcpu) 177 + int kvm_psci_call(struct kvm_vcpu *vcpu) 174 178 { 175 179 switch (kvm_psci_version(vcpu)) { 176 180 case KVM_ARM_PSCI_0_2: ··· 182 178 case KVM_ARM_PSCI_0_1: 183 179 return kvm_psci_0_1_call(vcpu); 184 180 default: 185 - return false; 181 + return -EINVAL; 186 182 }; 187 183 }
+1 -1
arch/arm64/include/asm/kvm_psci.h
··· 22 22 #define KVM_ARM_PSCI_0_2 2 23 23 24 24 int kvm_psci_version(struct kvm_vcpu *vcpu); 25 - bool kvm_psci_call(struct kvm_vcpu *vcpu); 25 + int kvm_psci_call(struct kvm_vcpu *vcpu); 26 26 27 27 #endif /* __ARM64_KVM_PSCI_H__ */
+8 -4
arch/arm64/kvm/handle_exit.c
··· 30 30 31 31 static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) 32 32 { 33 - if (kvm_psci_call(vcpu)) 34 - return 1; 33 + int ret; 35 34 36 - kvm_inject_undefined(vcpu); 37 - return 1; 35 + ret = kvm_psci_call(vcpu); 36 + if (ret < 0) { 37 + kvm_inject_undefined(vcpu); 38 + return 1; 39 + } 40 + 41 + return ret; 38 42 } 39 43 40 44 static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)