Commit f86e5465 authored by Marc Zyngier's avatar Marc Zyngier
Browse files

Merge remote-tracking branch 'origin/kvm-arm64/csv3' into kvmarm-master/queue



Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 90f0e16c 4f1df628
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ struct kvm_arch {
	unsigned int pmuver;

	u8 pfr0_csv2;
	u8 pfr0_csv3;
};

struct kvm_vcpu_fault_info {
+2 −0
Original line number Diff line number Diff line
@@ -91,5 +91,7 @@ bool has_spectre_v4(const struct arm64_cpu_capabilities *cap, int scope);
void spectre_v4_enable_mitigation(const struct arm64_cpu_capabilities *__unused);
void spectre_v4_enable_task_mitigation(struct task_struct *tsk);

enum mitigation_state arm64_get_meltdown_state(void);

#endif	/* __ASSEMBLY__ */
#endif	/* __ASM_SPECTRE_H */
+17 −3
Original line number Diff line number Diff line
@@ -2846,14 +2846,28 @@ static int __init enable_mrs_emulation(void)

core_initcall(enable_mrs_emulation);

enum mitigation_state arm64_get_meltdown_state(void)
{
	if (__meltdown_safe)
		return SPECTRE_UNAFFECTED;

	if (arm64_kernel_unmapped_at_el0())
		return SPECTRE_MITIGATED;

	return SPECTRE_VULNERABLE;
}

ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr,
			  char *buf)
{
	if (__meltdown_safe)
	switch (arm64_get_meltdown_state()) {
	case SPECTRE_UNAFFECTED:
		return sprintf(buf, "Not affected\n");

	if (arm64_kernel_unmapped_at_el0())
	case SPECTRE_MITIGATED:
		return sprintf(buf, "Mitigation: PTI\n");

	default:
		return sprintf(buf, "Vulnerable\n");
	}
}
+4 −2
Original line number Diff line number Diff line
@@ -101,7 +101,7 @@ static int kvm_arm_default_max_vcpus(void)
	return vgic_present ? kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS;
}

static void set_default_csv2(struct kvm *kvm)
static void set_default_spectre(struct kvm *kvm)
{
	/*
	 * The default is to expose CSV2 == 1 if the HW isn't affected.
@@ -113,6 +113,8 @@ static void set_default_csv2(struct kvm *kvm)
	 */
	if (arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED)
		kvm->arch.pfr0_csv2 = 1;
	if (arm64_get_meltdown_state() == SPECTRE_UNAFFECTED)
		kvm->arch.pfr0_csv3 = 1;
}

/**
@@ -140,7 +142,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
	/* The maximum number of VCPUs is limited by the host's GIC model */
	kvm->arch.max_vcpus = kvm_arm_default_max_vcpus();

	set_default_csv2(kvm);
	set_default_spectre(kvm);

	return ret;
out_free_stage2_pgd:
+13 −3
Original line number Diff line number Diff line
@@ -1026,6 +1026,8 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
		val &= ~(0xfUL << ID_AA64PFR0_AMU_SHIFT);
		val &= ~(0xfUL << ID_AA64PFR0_CSV2_SHIFT);
		val |= ((u64)vcpu->kvm->arch.pfr0_csv2 << ID_AA64PFR0_CSV2_SHIFT);
		val &= ~(0xfUL << ID_AA64PFR0_CSV3_SHIFT);
		val |= ((u64)vcpu->kvm->arch.pfr0_csv3 << ID_AA64PFR0_CSV3_SHIFT);
	} else if (id == SYS_ID_AA64PFR1_EL1) {
		val &= ~(0xfUL << ID_AA64PFR1_MTE_SHIFT);
	} else if (id == SYS_ID_AA64ISAR1_EL1 && !vcpu_has_ptrauth(vcpu)) {
@@ -1118,9 +1120,9 @@ static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
			       const struct kvm_one_reg *reg, void __user *uaddr)
{
	const u64 id = sys_reg_to_index(rd);
	u8 csv2, csv3;
	int err;
	u64 val;
	u8 csv2;

	err = reg_from_user(&val, uaddr, id);
	if (err)
@@ -1136,13 +1138,21 @@ static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
	    (csv2 && arm64_get_spectre_v2_state() != SPECTRE_UNAFFECTED))
		return -EINVAL;

	/* We can only differ with CSV2, and anything else is an error */
	/* Same thing for CSV3 */
	csv3 = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_CSV3_SHIFT);
	if (csv3 > 1 ||
	    (csv3 && arm64_get_meltdown_state() != SPECTRE_UNAFFECTED))
		return -EINVAL;

	/* We can only differ with CSV[23], and anything else is an error */
	val ^= read_id_reg(vcpu, rd, false);
	val &= ~(0xFUL << ID_AA64PFR0_CSV2_SHIFT);
	val &= ~((0xFUL << ID_AA64PFR0_CSV2_SHIFT) |
		 (0xFUL << ID_AA64PFR0_CSV3_SHIFT));
	if (val)
		return -EINVAL;

	vcpu->kvm->arch.pfr0_csv2 = csv2;
	vcpu->kvm->arch.pfr0_csv3 = csv3 ;

	return 0;
}