Skip to content

Commit e9b57d7

Browse files
shamiali2008oupton
authored andcommitted
KVM: arm64: Make L1Ip feature in CTR_EL0 writable from userspace
Only allow userspace to set VIPT(0b10) or PIPT(0b11) for L1Ip based on what hardware reports as both AIVIVT (0b01) and VPIPT (0b00) are documented as reserved. Using a VIPT for Guest where hardware reports PIPT may lead to over invalidation, but is still correct. Hence, we can allow downgrading PIPT to VIPT, but not the other way around. Reviewed-by: Sebastian Ott <sebott@redhat.com> Reviewed-by: Marc Zyngier <maz@kernel.org> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> Link: https://lore.kernel.org/r/20241022073943.35764-1-shameerali.kolothum.thodi@huawei.com Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent 75cd027 commit e9b57d7

File tree

1 file changed

+34
-4
lines changed

1 file changed

+34
-4
lines changed

arch/arm64/kvm/sys_regs.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,6 +1881,34 @@ static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu,
18811881
return set_id_reg(vcpu, rd, user_val);
18821882
}
18831883

1884+
static int set_ctr_el0(struct kvm_vcpu *vcpu,
1885+
const struct sys_reg_desc *rd, u64 user_val)
1886+
{
1887+
u8 user_L1Ip = SYS_FIELD_GET(CTR_EL0, L1Ip, user_val);
1888+
1889+
/*
1890+
* Both AIVIVT (0b01) and VPIPT (0b00) are documented as reserved.
1891+
* Hence only allow to set VIPT(0b10) or PIPT(0b11) for L1Ip based
1892+
* on what hardware reports.
1893+
*
1894+
* Using a VIPT software model on PIPT will lead to over invalidation,
1895+
* but still correct. Hence, we can allow downgrading PIPT to VIPT,
1896+
* but not the other way around. This is handled via arm64_ftr_safe_value()
1897+
* as CTR_EL0 ftr_bits has L1Ip field with type FTR_EXACT and safe value
1898+
* set as VIPT.
1899+
*/
1900+
switch (user_L1Ip) {
1901+
case CTR_EL0_L1Ip_RESERVED_VPIPT:
1902+
case CTR_EL0_L1Ip_RESERVED_AIVIVT:
1903+
return -EINVAL;
1904+
case CTR_EL0_L1Ip_VIPT:
1905+
case CTR_EL0_L1Ip_PIPT:
1906+
return set_id_reg(vcpu, rd, user_val);
1907+
default:
1908+
return -ENOENT;
1909+
}
1910+
}
1911+
18841912
/*
18851913
* cpufeature ID register user accessors
18861914
*
@@ -2651,10 +2679,12 @@ static const struct sys_reg_desc sys_reg_descs[] = {
26512679
{ SYS_DESC(SYS_CCSIDR2_EL1), undef_access },
26522680
{ SYS_DESC(SYS_SMIDR_EL1), undef_access },
26532681
{ SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
2654-
ID_WRITABLE(CTR_EL0, CTR_EL0_DIC_MASK |
2655-
CTR_EL0_IDC_MASK |
2656-
CTR_EL0_DminLine_MASK |
2657-
CTR_EL0_IminLine_MASK),
2682+
ID_FILTERED(CTR_EL0, ctr_el0,
2683+
CTR_EL0_DIC_MASK |
2684+
CTR_EL0_IDC_MASK |
2685+
CTR_EL0_DminLine_MASK |
2686+
CTR_EL0_L1Ip_MASK |
2687+
CTR_EL0_IminLine_MASK),
26582688
{ SYS_DESC(SYS_SVCR), undef_access, reset_val, SVCR, 0, .visibility = sme_visibility },
26592689
{ SYS_DESC(SYS_FPMR), undef_access, reset_val, FPMR, 0, .visibility = fp8_visibility },
26602690

0 commit comments

Comments
 (0)