KVM: arm64: Allow SMCCC_ARCH_WORKAROUND_3 to be discovered and migrated
KVM allows the guest to discover whether the ARCH_WORKAROUND SMCCC are implemented, and to preserve that state during migration through its firmware register interface. Add the necessary boiler plate for SMCCC_ARCH_WORKAROUND_3. Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: James Morse <james.morse@arm.com>
This commit is contained in:
parent
558c303c97
commit
a5905d6af4
|
@ -281,6 +281,11 @@ struct kvm_arm_copy_mte_tags {
|
||||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED 3
|
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED 3
|
||||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED (1U << 4)
|
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED (1U << 4)
|
||||||
|
|
||||||
|
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3 KVM_REG_ARM_FW_REG(3)
|
||||||
|
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL 0
|
||||||
|
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL 1
|
||||||
|
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED 2
|
||||||
|
|
||||||
/* SVE registers */
|
/* SVE registers */
|
||||||
#define KVM_REG_ARM64_SVE (0x15 << KVM_REG_ARM_COPROC_SHIFT)
|
#define KVM_REG_ARM64_SVE (0x15 << KVM_REG_ARM_COPROC_SHIFT)
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,18 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ARM_SMCCC_ARCH_WORKAROUND_3:
|
||||||
|
switch (arm64_get_spectre_bhb_state()) {
|
||||||
|
case SPECTRE_VULNERABLE:
|
||||||
|
break;
|
||||||
|
case SPECTRE_MITIGATED:
|
||||||
|
val[0] = SMCCC_RET_SUCCESS;
|
||||||
|
break;
|
||||||
|
case SPECTRE_UNAFFECTED:
|
||||||
|
val[0] = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ARM_SMCCC_HV_PV_TIME_FEATURES:
|
case ARM_SMCCC_HV_PV_TIME_FEATURES:
|
||||||
val[0] = SMCCC_RET_SUCCESS;
|
val[0] = SMCCC_RET_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -406,7 +406,7 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
|
int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
return 3; /* PSCI version and two workaround registers */
|
return 4; /* PSCI version and three workaround registers */
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
|
int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
|
||||||
|
@ -420,6 +420,9 @@ int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
|
||||||
if (put_user(KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2, uindices++))
|
if (put_user(KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2, uindices++))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
if (put_user(KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3, uindices++))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,6 +462,17 @@ static int get_kernel_wa_level(u64 regid)
|
||||||
case SPECTRE_VULNERABLE:
|
case SPECTRE_VULNERABLE:
|
||||||
return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL;
|
return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
|
||||||
|
switch (arm64_get_spectre_bhb_state()) {
|
||||||
|
case SPECTRE_VULNERABLE:
|
||||||
|
return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL;
|
||||||
|
case SPECTRE_MITIGATED:
|
||||||
|
return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL;
|
||||||
|
case SPECTRE_UNAFFECTED:
|
||||||
|
return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED;
|
||||||
|
}
|
||||||
|
return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -475,6 +489,7 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
|
||||||
break;
|
break;
|
||||||
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
|
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
|
||||||
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
|
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
|
||||||
|
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
|
||||||
val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK;
|
val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -520,6 +535,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
|
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
|
||||||
|
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
|
||||||
if (val & ~KVM_REG_FEATURE_LEVEL_MASK)
|
if (val & ~KVM_REG_FEATURE_LEVEL_MASK)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue