mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 11:03:43 +02:00
KVM: arm64: nv: Don't erroneously claim FEAT_DoubleLock for NV VMs
ID_AA64DFR0_EL1.DoubleLock is one of those annoying signed feature fields where a non-negative value implies that a feature is implemented and a negative value implies that it is not. While the intention of masking this field was likely to hide the feature, KVM actually advertises it, even on unsupporting hardware. Remove FEAT_DoubleLock from the mask, making the NI value visible to the VM. Take care to accept the old, incorrect values for this field as we've lied to userspace. Signed-off-by: Oliver Upton <oliver.upton@linux.dev> Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
parent
d3c35b7c57
commit
49da9872a6
|
|
@ -1582,7 +1582,6 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
|
|||
ID_AA64DFR0_EL1_MTPMU |
|
||||
ID_AA64DFR0_EL1_TraceBuffer |
|
||||
ID_AA64DFR0_EL1_TraceFilt |
|
||||
ID_AA64DFR0_EL1_DoubleLock |
|
||||
ID_AA64DFR0_EL1_PMSVer |
|
||||
ID_AA64DFR0_EL1_CTX_CMPs |
|
||||
ID_AA64DFR0_EL1_SEBEP |
|
||||
|
|
|
|||
|
|
@ -1997,6 +1997,26 @@ static u64 sanitise_id_aa64dfr0_el1(const struct kvm_vcpu *vcpu, u64 val)
|
|||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Older versions of KVM erroneously claim support for FEAT_DoubleLock with
|
||||
* NV-enabled VMs on unsupporting hardware. Silently ignore the incorrect
|
||||
* value if it is consistent with the bug.
|
||||
*/
|
||||
static bool ignore_feat_doublelock(struct kvm_vcpu *vcpu, u64 val)
|
||||
{
|
||||
u8 host, user;
|
||||
|
||||
if (!vcpu_has_nv(vcpu))
|
||||
return false;
|
||||
|
||||
host = SYS_FIELD_GET(ID_AA64DFR0_EL1, DoubleLock,
|
||||
read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1));
|
||||
user = SYS_FIELD_GET(ID_AA64DFR0_EL1, DoubleLock, val);
|
||||
|
||||
return host == ID_AA64DFR0_EL1_DoubleLock_NI &&
|
||||
user == ID_AA64DFR0_EL1_DoubleLock_IMP;
|
||||
}
|
||||
|
||||
static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
|
||||
const struct sys_reg_desc *rd,
|
||||
u64 val)
|
||||
|
|
@ -2028,6 +2048,11 @@ static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
|
|||
if (debugver < ID_AA64DFR0_EL1_DebugVer_IMP)
|
||||
return -EINVAL;
|
||||
|
||||
if (ignore_feat_doublelock(vcpu, val)) {
|
||||
val &= ~ID_AA64DFR0_EL1_DoubleLock;
|
||||
val |= SYS_FIELD_PREP_ENUM(ID_AA64DFR0_EL1, DoubleLock, NI);
|
||||
}
|
||||
|
||||
return set_id_reg(vcpu, rd, val);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user