Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: arm64: Make ID_AA64PFR1_EL1.RAS_frac writable

Allow userspace to write to RAS_frac, under the condition that
the host supports RASv1p1 with RAS_frac==1. Other configurations
will result in RAS_frac being exposed as 0, and therefore implicitly
not writable.

To avoid the clutter, the ID_AA64PFR1_EL1 sanitisation is moved to
its own function.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Link: https://lore.kernel.org/r/20250817202158.395078-6-maz@kernel.org
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>

authored by

Marc Zyngier and committed by
Oliver Upton
7a765aa8 1fab657c

+27 -14
+27 -14
arch/arm64/kvm/sys_regs.c
··· 1584 1584 } 1585 1585 1586 1586 static u64 sanitise_id_aa64pfr0_el1(const struct kvm_vcpu *vcpu, u64 val); 1587 + static u64 sanitise_id_aa64pfr1_el1(const struct kvm_vcpu *vcpu, u64 val); 1587 1588 static u64 sanitise_id_aa64dfr0_el1(const struct kvm_vcpu *vcpu, u64 val); 1588 1589 1589 1590 /* Read a sanitised cpufeature ID register by sys_reg_desc */ ··· 1607 1606 val = sanitise_id_aa64pfr0_el1(vcpu, val); 1608 1607 break; 1609 1608 case SYS_ID_AA64PFR1_EL1: 1610 - if (!kvm_has_mte(vcpu->kvm)) { 1611 - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE); 1612 - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE_frac); 1613 - } 1614 - 1615 - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_SME); 1616 - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_RNDR_trap); 1617 - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_NMI); 1618 - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_GCS); 1619 - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_THE); 1620 - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTEX); 1621 - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_PFAR); 1622 - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MPAM_frac); 1609 + val = sanitise_id_aa64pfr1_el1(vcpu, val); 1623 1610 break; 1624 1611 case SYS_ID_AA64PFR2_EL1: 1625 1612 /* We only expose FPMR */ ··· 1819 1830 * older kernels let the guest see the ID bit. 1820 1831 */ 1821 1832 val &= ~ID_AA64PFR0_EL1_MPAM_MASK; 1833 + 1834 + return val; 1835 + } 1836 + 1837 + static u64 sanitise_id_aa64pfr1_el1(const struct kvm_vcpu *vcpu, u64 val) 1838 + { 1839 + u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1); 1840 + 1841 + if (!kvm_has_mte(vcpu->kvm)) { 1842 + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE); 1843 + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE_frac); 1844 + } 1845 + 1846 + if (!(cpus_have_final_cap(ARM64_HAS_RASV1P1_EXTN) && 1847 + SYS_FIELD_GET(ID_AA64PFR0_EL1, RAS, pfr0) == ID_AA64PFR0_EL1_RAS_IMP)) 1848 + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_RAS_frac); 1849 + 1850 + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_SME); 1851 + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_RNDR_trap); 1852 + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_NMI); 1853 + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_GCS); 1854 + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_THE); 1855 + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTEX); 1856 + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_PFAR); 1857 + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MPAM_frac); 1822 1858 1823 1859 return val; 1824 1860 } ··· 2966 2952 ID_AA64PFR1_EL1_SME | 2967 2953 ID_AA64PFR1_EL1_RES0 | 2968 2954 ID_AA64PFR1_EL1_MPAM_frac | 2969 - ID_AA64PFR1_EL1_RAS_frac | 2970 2955 ID_AA64PFR1_EL1_MTE)), 2971 2956 ID_WRITABLE(ID_AA64PFR2_EL1, ID_AA64PFR2_EL1_FPMR), 2972 2957 ID_UNALLOCATED(4,3),