arm/arm64: KVM: Implement PSCI 1.0 support
authorMark Rutland <mark.rutland@arm.com>
Thu, 12 Apr 2018 11:11:27 +0000 (12:11 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 20 Apr 2018 06:21:05 +0000 (08:21 +0200)
From: Marc Zyngier <marc.zyngier@arm.com>

commit 58e0b2239a4d997094ba63986ef4de29ddc91d87 upstream.

PSCI 1.0 can be trivially implemented by providing the FEATURES
call on top of PSCI 0.2 and returning 1.0 as the PSCI version.

We happily ignore everything else, as they are either optional or
are clarifications that do not require any additional change.

PSCI 1.0 is now the default until we decide to add a userspace
selection API.

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
[v4.9: account for files moved to virt/ upstream]
Signed-off-by: Mark Rutland <mark.rutland@arm.com> [v4.9 backport]
Tested-by: Greg Hackmann <ghackmann@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm/kvm/psci.c
include/kvm/arm_psci.h

index f579ed9d279b41940ad268e7a50a2951fb07e71d..220eaa04b1c4d78e8c81a945b849ea0848f0b28a 100644 (file)
@@ -232,7 +232,7 @@ static void kvm_psci_system_reset(struct kvm_vcpu *vcpu)
 int kvm_psci_version(struct kvm_vcpu *vcpu)
 {
        if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
-               return KVM_ARM_PSCI_0_2;
+               return KVM_ARM_PSCI_LATEST;
 
        return KVM_ARM_PSCI_0_1;
 }
@@ -311,6 +311,47 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
        return ret;
 }
 
+static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
+{
+       u32 psci_fn = smccc_get_function(vcpu);
+       u32 feature;
+       unsigned long val;
+       int ret = 1;
+
+       switch(psci_fn) {
+       case PSCI_0_2_FN_PSCI_VERSION:
+               val = KVM_ARM_PSCI_1_0;
+               break;
+       case PSCI_1_0_FN_PSCI_FEATURES:
+               feature = smccc_get_arg1(vcpu);
+               switch(feature) {
+               case PSCI_0_2_FN_PSCI_VERSION:
+               case PSCI_0_2_FN_CPU_SUSPEND:
+               case PSCI_0_2_FN64_CPU_SUSPEND:
+               case PSCI_0_2_FN_CPU_OFF:
+               case PSCI_0_2_FN_CPU_ON:
+               case PSCI_0_2_FN64_CPU_ON:
+               case PSCI_0_2_FN_AFFINITY_INFO:
+               case PSCI_0_2_FN64_AFFINITY_INFO:
+               case PSCI_0_2_FN_MIGRATE_INFO_TYPE:
+               case PSCI_0_2_FN_SYSTEM_OFF:
+               case PSCI_0_2_FN_SYSTEM_RESET:
+               case PSCI_1_0_FN_PSCI_FEATURES:
+                       val = 0;
+                       break;
+               default:
+                       val = PSCI_RET_NOT_SUPPORTED;
+                       break;
+               }
+               break;
+       default:
+               return kvm_psci_0_2_call(vcpu);
+       }
+
+       smccc_set_retval(vcpu, val, 0, 0, 0);
+       return ret;
+}
+
 static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 {
        struct kvm *kvm = vcpu->kvm;
@@ -353,6 +394,8 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 int kvm_psci_call(struct kvm_vcpu *vcpu)
 {
        switch (kvm_psci_version(vcpu)) {
+       case KVM_ARM_PSCI_1_0:
+               return kvm_psci_1_0_call(vcpu);
        case KVM_ARM_PSCI_0_2:
                return kvm_psci_0_2_call(vcpu);
        case KVM_ARM_PSCI_0_1:
index 5659343580a3e026f34bab768f5a41417c32526c..32360432cff507ef9268d7c96d51f1970bf02e0f 100644 (file)
@@ -22,6 +22,9 @@
 
 #define KVM_ARM_PSCI_0_1       PSCI_VERSION(0, 1)
 #define KVM_ARM_PSCI_0_2       PSCI_VERSION(0, 2)
+#define KVM_ARM_PSCI_1_0       PSCI_VERSION(1, 0)
+
+#define KVM_ARM_PSCI_LATEST    KVM_ARM_PSCI_1_0
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);