@@ -1535,6 +1535,7 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
15351535 val &= ~ARM64_FEATURE_MASK (ID_AA64PFR1_EL1_MTEX );
15361536 val &= ~ARM64_FEATURE_MASK (ID_AA64PFR1_EL1_DF2 );
15371537 val &= ~ARM64_FEATURE_MASK (ID_AA64PFR1_EL1_PFAR );
1538+ val &= ~ARM64_FEATURE_MASK (ID_AA64PFR1_EL1_MPAM_frac );
15381539 break ;
15391540 case SYS_ID_AA64PFR2_EL1 :
15401541 /* We only expose FPMR */
@@ -1724,6 +1725,13 @@ static u64 read_sanitised_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
17241725
17251726 val &= ~ID_AA64PFR0_EL1_AMU_MASK ;
17261727
1728+ /*
1729+ * MPAM is disabled by default as KVM also needs a set of PARTID to
1730+ * program the MPAMVPMx_EL2 PARTID remapping registers with. But some
1731+ * older kernels let the guest see the ID bit.
1732+ */
1733+ val &= ~ID_AA64PFR0_EL1_MPAM_MASK ;
1734+
17271735 return val ;
17281736}
17291737
@@ -1834,6 +1842,42 @@ static int set_id_dfr0_el1(struct kvm_vcpu *vcpu,
18341842 return set_id_reg (vcpu , rd , val );
18351843}
18361844
1845+ static int set_id_aa64pfr0_el1 (struct kvm_vcpu * vcpu ,
1846+ const struct sys_reg_desc * rd , u64 user_val )
1847+ {
1848+ u64 hw_val = read_sanitised_ftr_reg (SYS_ID_AA64PFR0_EL1 );
1849+ u64 mpam_mask = ID_AA64PFR0_EL1_MPAM_MASK ;
1850+
1851+ /*
1852+ * Commit 011e5f5bf529f ("arm64/cpufeature: Add remaining feature bits
1853+ * in ID_AA64PFR0 register") exposed the MPAM field of AA64PFR0_EL1 to
1854+ * guests, but didn't add trap handling. KVM doesn't support MPAM and
1855+ * always returns an UNDEF for these registers. The guest must see 0
1856+ * for this field.
1857+ *
1858+ * But KVM must also accept values from user-space that were provided
1859+ * by KVM. On CPUs that support MPAM, permit user-space to write
1860+ * the sanitizied value to ID_AA64PFR0_EL1.MPAM, but ignore this field.
1861+ */
1862+ if ((hw_val & mpam_mask ) == (user_val & mpam_mask ))
1863+ user_val &= ~ID_AA64PFR0_EL1_MPAM_MASK ;
1864+
1865+ return set_id_reg (vcpu , rd , user_val );
1866+ }
1867+
1868+ static int set_id_aa64pfr1_el1 (struct kvm_vcpu * vcpu ,
1869+ const struct sys_reg_desc * rd , u64 user_val )
1870+ {
1871+ u64 hw_val = read_sanitised_ftr_reg (SYS_ID_AA64PFR1_EL1 );
1872+ u64 mpam_mask = ID_AA64PFR1_EL1_MPAM_frac_MASK ;
1873+
1874+ /* See set_id_aa64pfr0_el1 for comment about MPAM */
1875+ if ((hw_val & mpam_mask ) == (user_val & mpam_mask ))
1876+ user_val &= ~ID_AA64PFR1_EL1_MPAM_frac_MASK ;
1877+
1878+ return set_id_reg (vcpu , rd , user_val );
1879+ }
1880+
18371881/*
18381882 * cpufeature ID register user accessors
18391883 *
@@ -2377,15 +2421,20 @@ static const struct sys_reg_desc sys_reg_descs[] = {
23772421 { SYS_DESC (SYS_ID_AA64PFR0_EL1 ),
23782422 .access = access_id_reg ,
23792423 .get_user = get_id_reg ,
2380- .set_user = set_id_reg ,
2424+ .set_user = set_id_aa64pfr0_el1 ,
23812425 .reset = read_sanitised_id_aa64pfr0_el1 ,
23822426 .val = ~(ID_AA64PFR0_EL1_AMU |
23832427 ID_AA64PFR0_EL1_MPAM |
23842428 ID_AA64PFR0_EL1_SVE |
23852429 ID_AA64PFR0_EL1_RAS |
23862430 ID_AA64PFR0_EL1_AdvSIMD |
23872431 ID_AA64PFR0_EL1_FP ), },
2388- ID_WRITABLE (ID_AA64PFR1_EL1 , ~(ID_AA64PFR1_EL1_PFAR |
2432+ { SYS_DESC (SYS_ID_AA64PFR1_EL1 ),
2433+ .access = access_id_reg ,
2434+ .get_user = get_id_reg ,
2435+ .set_user = set_id_aa64pfr1_el1 ,
2436+ .reset = kvm_read_sanitised_id_reg ,
2437+ .val = ~(ID_AA64PFR1_EL1_PFAR |
23892438 ID_AA64PFR1_EL1_DF2 |
23902439 ID_AA64PFR1_EL1_MTEX |
23912440 ID_AA64PFR1_EL1_THE |
@@ -2397,7 +2446,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
23972446 ID_AA64PFR1_EL1_RES0 |
23982447 ID_AA64PFR1_EL1_MPAM_frac |
23992448 ID_AA64PFR1_EL1_RAS_frac |
2400- ID_AA64PFR1_EL1_MTE )) ,
2449+ ID_AA64PFR1_EL1_MTE ), } ,
24012450 ID_WRITABLE (ID_AA64PFR2_EL1 , ID_AA64PFR2_EL1_FPMR ),
24022451 ID_UNALLOCATED (4 ,3 ),
24032452 ID_WRITABLE (ID_AA64ZFR0_EL1 , ~ID_AA64ZFR0_EL1_RES0 ),
0 commit comments