ARM/ARM64: KVM: Make kvm_psci_call() return convention more flexible
authorAnup Patel <anup.patel@linaro.org>
Tue, 29 Apr 2014 05:54:18 +0000 (11:24 +0530)
committerChristoffer Dall <christoffer.dall@linaro.org>
Wed, 30 Apr 2014 11:18:57 +0000 (04:18 -0700)
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>
arch/arm/include/asm/kvm_psci.h
arch/arm/kvm/handle_exit.c
arch/arm/kvm/psci.c
arch/arm64/include/asm/kvm_psci.h
arch/arm64/kvm/handle_exit.c

index 4c0e3e1d15970b213c1e48840793c1556123da46..6bda945d31fa8effe1b9d51c589733c5f9f66183 100644 (file)
@@ -22,6 +22,6 @@
 #define KVM_ARM_PSCI_0_2       2
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
-bool kvm_psci_call(struct kvm_vcpu *vcpu);
+int kvm_psci_call(struct kvm_vcpu *vcpu);
 
 #endif /* __ARM_KVM_PSCI_H__ */
index 0de91fc6de0ff06e671357430c0544581127ea80..4c979d466cc1681c4b3efc70623345eee5974b78 100644 (file)
@@ -38,14 +38,18 @@ static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
+       int ret;
+
        trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
                      kvm_vcpu_hvc_get_imm(vcpu));
 
-       if (kvm_psci_call(vcpu))
+       ret = kvm_psci_call(vcpu);
+       if (ret < 0) {
+               kvm_inject_undefined(vcpu);
                return 1;
+       }
 
-       kvm_inject_undefined(vcpu);
-       return 1;
+       return ret;
 }
 
 static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
index 8c42596cdbdf6df15150fddf70ad765ef8381dc0..14e6fa6c8e35d8295e0b634185f32ea68f30bf91 100644 (file)
@@ -93,7 +93,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
        return KVM_ARM_PSCI_0_1;
 }
 
-static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
+static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 {
        unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
        unsigned long val;
@@ -128,14 +128,14 @@ static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
                val = PSCI_RET_NOT_SUPPORTED;
                break;
        default:
-               return false;
+               return -EINVAL;
        }
 
        *vcpu_reg(vcpu, 0) = val;
-       return true;
+       return 1;
 }
 
-static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
+static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 {
        unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
        unsigned long val;
@@ -153,11 +153,11 @@ static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
                val = PSCI_RET_NOT_SUPPORTED;
                break;
        default:
-               return false;
+               return -EINVAL;
        }
 
        *vcpu_reg(vcpu, 0) = val;
-       return true;
+       return 1;
 }
 
 /**
@@ -165,12 +165,16 @@ static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
  * @vcpu: Pointer to the VCPU struct
  *
  * Handle PSCI calls from guests through traps from HVC instructions.
- * The calling convention is similar to SMC calls to the secure world where
- * the function number is placed in r0 and this function returns true if the
- * function number specified in r0 is withing the PSCI range, and false
- * otherwise.
+ * The calling convention is similar to SMC calls to the secure world
+ * where the function number is placed in r0.
+ *
+ * This function returns: > 0 (success), 0 (success but exit to user
+ * space), and < 0 (errors)
+ *
+ * Errors:
+ * -EINVAL: Unrecognized PSCI function
  */
-bool kvm_psci_call(struct kvm_vcpu *vcpu)
+int kvm_psci_call(struct kvm_vcpu *vcpu)
 {
        switch (kvm_psci_version(vcpu)) {
        case KVM_ARM_PSCI_0_2:
@@ -178,6 +182,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu)
        case KVM_ARM_PSCI_0_1:
                return kvm_psci_0_1_call(vcpu);
        default:
-               return false;
+               return -EINVAL;
        };
 }
index e25c658a757b1dce639ea858aab4b56a70cadd3e..bc39e557c56c83e163e04c560ed45a3852e2d34f 100644 (file)
@@ -22,6 +22,6 @@
 #define KVM_ARM_PSCI_0_2       2
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
-bool kvm_psci_call(struct kvm_vcpu *vcpu);
+int kvm_psci_call(struct kvm_vcpu *vcpu);
 
 #endif /* __ARM64_KVM_PSCI_H__ */
index 7bc41eab4c649b8903a27793a8e19ab662b72f8a..182415e1a952bf5e54918b14f1534faaee731bba 100644 (file)
@@ -30,11 +30,15 @@ typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
 
 static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-       if (kvm_psci_call(vcpu))
+       int ret;
+
+       ret = kvm_psci_call(vcpu);
+       if (ret < 0) {
+               kvm_inject_undefined(vcpu);
                return 1;
+       }
 
-       kvm_inject_undefined(vcpu);
-       return 1;
+       return ret;
 }
 
 static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)