Skip to content

Commit c39f597

Browse files
jingzhangosoupton
authored andcommitted
KVM: arm64: Use generic sanitisation for ID_AA64PFR0_EL1
KVM allows userspace to write to the CSV2 and CSV3 fields of ID_AA64PFR0_EL1 so long as it doesn't over-promise on the Spectre/Meltdown mitigation state. Switch over to the new way of the world for screening user writes. Leave the old plumbing in place until we actually start handling ID register reads from the VM-wide values. Signed-off-by: Jing Zhang <jingzhangos@google.com> Link: https://lore.kernel.org/r/20230609190054.1542113-10-oliver.upton@linux.dev [Oliver: split from monster patch, added commit description] Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent c118cea commit c39f597

1 file changed

Lines changed: 45 additions & 21 deletions

File tree

arch/arm64/kvm/sys_regs.c

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,34 +1470,54 @@ static unsigned int sve_visibility(const struct kvm_vcpu *vcpu,
14701470
return REG_HIDDEN;
14711471
}
14721472

1473+
static u64 read_sanitised_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
1474+
const struct sys_reg_desc *rd)
1475+
{
1476+
u64 val = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
1477+
1478+
if (!vcpu_has_sve(vcpu))
1479+
val &= ~ID_AA64PFR0_EL1_SVE_MASK;
1480+
1481+
/*
1482+
* The default is to expose CSV2 == 1 if the HW isn't affected.
1483+
* Although this is a per-CPU feature, we make it global because
1484+
* asymmetric systems are just a nuisance.
1485+
*
1486+
* Userspace can override this as long as it doesn't promise
1487+
* the impossible.
1488+
*/
1489+
if (arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED) {
1490+
val &= ~ID_AA64PFR0_EL1_CSV2_MASK;
1491+
val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, CSV2, IMP);
1492+
}
1493+
if (arm64_get_meltdown_state() == SPECTRE_UNAFFECTED) {
1494+
val &= ~ID_AA64PFR0_EL1_CSV3_MASK;
1495+
val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, CSV3, IMP);
1496+
}
1497+
1498+
if (kvm_vgic_global_state.type == VGIC_V3) {
1499+
val &= ~ID_AA64PFR0_EL1_GIC_MASK;
1500+
val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP);
1501+
}
1502+
1503+
val &= ~ID_AA64PFR0_EL1_AMU_MASK;
1504+
1505+
return val;
1506+
}
1507+
14731508
static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
14741509
const struct sys_reg_desc *rd,
14751510
u64 val)
14761511
{
14771512
u8 csv2, csv3;
1513+
int r;
14781514

1479-
/*
1480-
* Allow AA64PFR0_EL1.CSV2 to be set from userspace as long as
1481-
* it doesn't promise more than what is actually provided (the
1482-
* guest could otherwise be covered in ectoplasmic residue).
1483-
*/
14841515
csv2 = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_EL1_CSV2_SHIFT);
1485-
if (csv2 > 1 ||
1486-
(csv2 && arm64_get_spectre_v2_state() != SPECTRE_UNAFFECTED))
1487-
return -EINVAL;
1488-
1489-
/* Same thing for CSV3 */
14901516
csv3 = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_EL1_CSV3_SHIFT);
1491-
if (csv3 > 1 ||
1492-
(csv3 && arm64_get_meltdown_state() != SPECTRE_UNAFFECTED))
1493-
return -EINVAL;
14941517

1495-
/* We can only differ with CSV[23], and anything else is an error */
1496-
val ^= read_id_reg(vcpu, rd);
1497-
val &= ~(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV2) |
1498-
ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV3));
1499-
if (val)
1500-
return -EINVAL;
1518+
r = set_id_reg(vcpu, rd, val);
1519+
if (r)
1520+
return r;
15011521

15021522
vcpu->kvm->arch.pfr0_csv2 = csv2;
15031523
vcpu->kvm->arch.pfr0_csv3 = csv3;
@@ -2041,8 +2061,12 @@ static const struct sys_reg_desc sys_reg_descs[] = {
20412061

20422062
/* AArch64 ID registers */
20432063
/* CRm=4 */
2044-
{ SYS_DESC(SYS_ID_AA64PFR0_EL1), .access = access_id_reg,
2045-
.get_user = get_id_reg, .set_user = set_id_aa64pfr0_el1, },
2064+
{ SYS_DESC(SYS_ID_AA64PFR0_EL1),
2065+
.access = access_id_reg,
2066+
.get_user = get_id_reg,
2067+
.set_user = set_id_aa64pfr0_el1,
2068+
.reset = read_sanitised_id_aa64pfr0_el1,
2069+
.val = ID_AA64PFR0_EL1_CSV2_MASK | ID_AA64PFR0_EL1_CSV3_MASK, },
20462070
ID_SANITISED(ID_AA64PFR1_EL1),
20472071
ID_UNALLOCATED(4,2),
20482072
ID_UNALLOCATED(4,3),

0 commit comments

Comments
 (0)