Commit 5aea4096 authored by Oliver Upton's avatar Oliver Upton Committed by Marc Zyngier
Browse files

KVM: arm64: nv: Allow userspace to de-feature stage-2 TGRANs



KVM advertises the stage-2 TGRAN fields as writable to userspace but
prevents any modification for NV-enabled VMs. Update the special-cased
sanitization to permit de-featuring a particular TGRAN without allowing
the legacy value which refers to the stage-1 field for support.

Reported-by: default avatarItaru Kitayama <itaru.kitayama@linux.dev>
Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
Reviewed-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent ff37a41d
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -2148,16 +2148,29 @@ static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu,
	return set_id_reg(vcpu, rd, user_val);
}

/*
 * Allow userspace to de-feature a stage-2 translation granule but prevent it
 * from claiming the impossible.
 */
#define tgran2_val_allowed(tg, safe, user)			\
({								\
	u8 __s = SYS_FIELD_GET(ID_AA64MMFR0_EL1, tg, safe);	\
	u8 __u = SYS_FIELD_GET(ID_AA64MMFR0_EL1, tg, user);	\
								\
	__s == __u || __u == ID_AA64MMFR0_EL1_##tg##_NI;	\
})

static int set_id_aa64mmfr0_el1(struct kvm_vcpu *vcpu,
				const struct sys_reg_desc *rd, u64 user_val)
{
	u64 sanitized_val = kvm_read_sanitised_id_reg(vcpu, rd);
	u64 tgran2_mask = ID_AA64MMFR0_EL1_TGRAN4_2_MASK |
			  ID_AA64MMFR0_EL1_TGRAN16_2_MASK |
			  ID_AA64MMFR0_EL1_TGRAN64_2_MASK;

	if (vcpu_has_nv(vcpu) &&
	    ((sanitized_val & tgran2_mask) != (user_val & tgran2_mask)))
	if (!vcpu_has_nv(vcpu))
		return set_id_reg(vcpu, rd, user_val);

	if (!tgran2_val_allowed(TGRAN4_2, sanitized_val, user_val) ||
	    !tgran2_val_allowed(TGRAN16_2, sanitized_val, user_val) ||
	    !tgran2_val_allowed(TGRAN64_2, sanitized_val, user_val))
		return -EINVAL;

	return set_id_reg(vcpu, rd, user_val);