|
@@ -37,6 +37,26 @@ static unsigned long psci_affinity_mask(unsigned long affinity_level)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu)
|
|
|
|
+{
|
|
|
|
+ /*
|
|
|
|
+ * NOTE: For simplicity, we make VCPU suspend emulation to be
|
|
|
|
+ * same-as WFI (Wait-for-interrupt) emulation.
|
|
|
|
+ *
|
|
|
|
+ * This means for KVM the wakeup events are interrupts and
|
|
|
|
+ * this is consistent with intended use of StateID as described
|
|
|
|
+ * in section 5.4.1 of PSCI v0.2 specification (ARM DEN 0022A).
|
|
|
|
+ *
|
|
|
|
+ * Further, we also treat power-down request to be same as
|
|
|
|
+ * stand-by request as-per section 5.4.2 clause 3 of PSCI v0.2
|
|
|
|
+ * specification (ARM DEN 0022A). This means all suspend states
|
|
|
|
+ * for KVM will preserve the register state.
|
|
|
|
+ */
|
|
|
|
+ kvm_vcpu_block(vcpu);
|
|
|
|
+
|
|
|
|
+ return PSCI_RET_SUCCESS;
|
|
|
|
+}
|
|
|
|
+
|
|
static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
|
|
static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
|
|
{
|
|
{
|
|
vcpu->arch.pause = true;
|
|
vcpu->arch.pause = true;
|
|
@@ -183,6 +203,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
|
|
*/
|
|
*/
|
|
val = 2;
|
|
val = 2;
|
|
break;
|
|
break;
|
|
|
|
+ case PSCI_0_2_FN_CPU_SUSPEND:
|
|
|
|
+ case PSCI_0_2_FN64_CPU_SUSPEND:
|
|
|
|
+ val = kvm_psci_vcpu_suspend(vcpu);
|
|
|
|
+ break;
|
|
case PSCI_0_2_FN_CPU_OFF:
|
|
case PSCI_0_2_FN_CPU_OFF:
|
|
kvm_psci_vcpu_off(vcpu);
|
|
kvm_psci_vcpu_off(vcpu);
|
|
val = PSCI_RET_SUCCESS;
|
|
val = PSCI_RET_SUCCESS;
|
|
@@ -235,10 +259,6 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
|
|
val = PSCI_RET_INTERNAL_FAILURE;
|
|
val = PSCI_RET_INTERNAL_FAILURE;
|
|
ret = 0;
|
|
ret = 0;
|
|
break;
|
|
break;
|
|
- case PSCI_0_2_FN_CPU_SUSPEND:
|
|
|
|
- case PSCI_0_2_FN64_CPU_SUSPEND:
|
|
|
|
- val = PSCI_RET_NOT_SUPPORTED;
|
|
|
|
- break;
|
|
|
|
default:
|
|
default:
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|