@@ -1063,13 +1063,12 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu,
10631063}
10641064
10651065/* Read a sanitised cpufeature ID register by sys_reg_desc */
1066- static u64 read_id_reg (const struct kvm_vcpu * vcpu ,
1067- struct sys_reg_desc const * r , bool raz )
1066+ static u64 read_id_reg (const struct kvm_vcpu * vcpu , struct sys_reg_desc const * r )
10681067{
10691068 u32 id = reg_to_encoding (r );
10701069 u64 val ;
10711070
1072- if (raz )
1071+ if (sysreg_visible_as_raz ( vcpu , r ) )
10731072 return 0 ;
10741073
10751074 val = read_sanitised_ftr_reg (id );
@@ -1145,34 +1144,37 @@ static unsigned int id_visibility(const struct kvm_vcpu *vcpu,
11451144 return 0 ;
11461145}
11471146
1148- /* cpufeature ID register access trap handlers */
1149-
1150- static bool __access_id_reg (struct kvm_vcpu * vcpu ,
1151- struct sys_reg_params * p ,
1152- const struct sys_reg_desc * r ,
1153- bool raz )
1147+ static unsigned int aa32_id_visibility (const struct kvm_vcpu * vcpu ,
1148+ const struct sys_reg_desc * r )
11541149{
1155- if (p -> is_write )
1156- return write_to_read_only (vcpu , p , r );
1150+ /*
1151+ * AArch32 ID registers are UNKNOWN if AArch32 isn't implemented at any
1152+ * EL. Promote to RAZ/WI in order to guarantee consistency between
1153+ * systems.
1154+ */
1155+ if (!kvm_supports_32bit_el0 ())
1156+ return REG_RAZ | REG_USER_WI ;
11571157
1158- p -> regval = read_id_reg (vcpu , r , raz );
1159- return true;
1158+ return id_visibility (vcpu , r );
11601159}
11611160
1161+ static unsigned int raz_visibility (const struct kvm_vcpu * vcpu ,
1162+ const struct sys_reg_desc * r )
1163+ {
1164+ return REG_RAZ ;
1165+ }
1166+
1167+ /* cpufeature ID register access trap handlers */
1168+
11621169static bool access_id_reg (struct kvm_vcpu * vcpu ,
11631170 struct sys_reg_params * p ,
11641171 const struct sys_reg_desc * r )
11651172{
1166- bool raz = sysreg_visible_as_raz (vcpu , r );
1167-
1168- return __access_id_reg (vcpu , p , r , raz );
1169- }
1173+ if (p -> is_write )
1174+ return write_to_read_only (vcpu , p , r );
11701175
1171- static bool access_raz_id_reg (struct kvm_vcpu * vcpu ,
1172- struct sys_reg_params * p ,
1173- const struct sys_reg_desc * r )
1174- {
1175- return __access_id_reg (vcpu , p , r , true);
1176+ p -> regval = read_id_reg (vcpu , r );
1177+ return true;
11761178}
11771179
11781180/* Visibility overrides for SVE-specific control registers */
@@ -1208,7 +1210,7 @@ static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
12081210 return - EINVAL ;
12091211
12101212 /* We can only differ with CSV[23], and anything else is an error */
1211- val ^= read_id_reg (vcpu , rd , false );
1213+ val ^= read_id_reg (vcpu , rd );
12121214 val &= ~((0xFUL << ID_AA64PFR0_CSV2_SHIFT ) |
12131215 (0xFUL << ID_AA64PFR0_CSV3_SHIFT ));
12141216 if (val )
@@ -1227,45 +1229,21 @@ static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
12271229 * are stored, and for set_id_reg() we don't allow the effective value
12281230 * to be changed.
12291231 */
1230- static int __get_id_reg (const struct kvm_vcpu * vcpu ,
1231- const struct sys_reg_desc * rd , u64 * val ,
1232- bool raz )
1233- {
1234- * val = read_id_reg (vcpu , rd , raz );
1235- return 0 ;
1236- }
1237-
1238- static int __set_id_reg (const struct kvm_vcpu * vcpu ,
1239- const struct sys_reg_desc * rd , u64 val ,
1240- bool raz )
1241- {
1242- /* This is what we mean by invariant: you can't change it. */
1243- if (val != read_id_reg (vcpu , rd , raz ))
1244- return - EINVAL ;
1245-
1246- return 0 ;
1247- }
1248-
12491232static int get_id_reg (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
12501233 u64 * val )
12511234{
1252- bool raz = sysreg_visible_as_raz (vcpu , rd );
1253-
1254- return __get_id_reg (vcpu , rd , val , raz );
1235+ * val = read_id_reg (vcpu , rd );
1236+ return 0 ;
12551237}
12561238
12571239static int set_id_reg (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
12581240 u64 val )
12591241{
1260- bool raz = sysreg_visible_as_raz (vcpu , rd );
1261-
1262- return __set_id_reg (vcpu , rd , val , raz );
1263- }
1242+ /* This is what we mean by invariant: you can't change it. */
1243+ if (val != read_id_reg (vcpu , rd ))
1244+ return - EINVAL ;
12641245
1265- static int set_raz_id_reg (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
1266- u64 val )
1267- {
1268- return __set_id_reg (vcpu , rd , val , true);
1246+ return 0 ;
12691247}
12701248
12711249static int get_raz_reg (struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
@@ -1367,16 +1345,26 @@ static unsigned int mte_visibility(const struct kvm_vcpu *vcpu,
13671345 .visibility = id_visibility, \
13681346}
13691347
1348+ /* sys_reg_desc initialiser for known cpufeature ID registers */
1349+ #define AA32_ID_SANITISED (name ) { \
1350+ SYS_DESC(SYS_##name), \
1351+ .access = access_id_reg, \
1352+ .get_user = get_id_reg, \
1353+ .set_user = set_id_reg, \
1354+ .visibility = aa32_id_visibility, \
1355+ }
1356+
13701357/*
13711358 * sys_reg_desc initialiser for architecturally unallocated cpufeature ID
13721359 * register with encoding Op0=3, Op1=0, CRn=0, CRm=crm, Op2=op2
13731360 * (1 <= crm < 8, 0 <= Op2 < 8).
13741361 */
13751362#define ID_UNALLOCATED (crm , op2 ) { \
13761363 Op0(3), Op1(0), CRn(0), CRm(crm), Op2(op2), \
1377- .access = access_raz_id_reg, \
1378- .get_user = get_raz_reg, \
1379- .set_user = set_raz_id_reg, \
1364+ .access = access_id_reg, \
1365+ .get_user = get_id_reg, \
1366+ .set_user = set_id_reg, \
1367+ .visibility = raz_visibility \
13801368}
13811369
13821370/*
@@ -1386,9 +1374,10 @@ static unsigned int mte_visibility(const struct kvm_vcpu *vcpu,
13861374 */
13871375#define ID_HIDDEN (name ) { \
13881376 SYS_DESC(SYS_##name), \
1389- .access = access_raz_id_reg, \
1390- .get_user = get_raz_reg, \
1391- .set_user = set_raz_id_reg, \
1377+ .access = access_id_reg, \
1378+ .get_user = get_id_reg, \
1379+ .set_user = set_id_reg, \
1380+ .visibility = raz_visibility, \
13921381}
13931382
13941383/*
@@ -1452,33 +1441,33 @@ static const struct sys_reg_desc sys_reg_descs[] = {
14521441
14531442 /* AArch64 mappings of the AArch32 ID registers */
14541443 /* CRm=1 */
1455- ID_SANITISED (ID_PFR0_EL1 ),
1456- ID_SANITISED (ID_PFR1_EL1 ),
1457- ID_SANITISED (ID_DFR0_EL1 ),
1444+ AA32_ID_SANITISED (ID_PFR0_EL1 ),
1445+ AA32_ID_SANITISED (ID_PFR1_EL1 ),
1446+ AA32_ID_SANITISED (ID_DFR0_EL1 ),
14581447 ID_HIDDEN (ID_AFR0_EL1 ),
1459- ID_SANITISED (ID_MMFR0_EL1 ),
1460- ID_SANITISED (ID_MMFR1_EL1 ),
1461- ID_SANITISED (ID_MMFR2_EL1 ),
1462- ID_SANITISED (ID_MMFR3_EL1 ),
1448+ AA32_ID_SANITISED (ID_MMFR0_EL1 ),
1449+ AA32_ID_SANITISED (ID_MMFR1_EL1 ),
1450+ AA32_ID_SANITISED (ID_MMFR2_EL1 ),
1451+ AA32_ID_SANITISED (ID_MMFR3_EL1 ),
14631452
14641453 /* CRm=2 */
1465- ID_SANITISED (ID_ISAR0_EL1 ),
1466- ID_SANITISED (ID_ISAR1_EL1 ),
1467- ID_SANITISED (ID_ISAR2_EL1 ),
1468- ID_SANITISED (ID_ISAR3_EL1 ),
1469- ID_SANITISED (ID_ISAR4_EL1 ),
1470- ID_SANITISED (ID_ISAR5_EL1 ),
1471- ID_SANITISED (ID_MMFR4_EL1 ),
1472- ID_SANITISED (ID_ISAR6_EL1 ),
1454+ AA32_ID_SANITISED (ID_ISAR0_EL1 ),
1455+ AA32_ID_SANITISED (ID_ISAR1_EL1 ),
1456+ AA32_ID_SANITISED (ID_ISAR2_EL1 ),
1457+ AA32_ID_SANITISED (ID_ISAR3_EL1 ),
1458+ AA32_ID_SANITISED (ID_ISAR4_EL1 ),
1459+ AA32_ID_SANITISED (ID_ISAR5_EL1 ),
1460+ AA32_ID_SANITISED (ID_MMFR4_EL1 ),
1461+ AA32_ID_SANITISED (ID_ISAR6_EL1 ),
14731462
14741463 /* CRm=3 */
1475- ID_SANITISED (MVFR0_EL1 ),
1476- ID_SANITISED (MVFR1_EL1 ),
1477- ID_SANITISED (MVFR2_EL1 ),
1464+ AA32_ID_SANITISED (MVFR0_EL1 ),
1465+ AA32_ID_SANITISED (MVFR1_EL1 ),
1466+ AA32_ID_SANITISED (MVFR2_EL1 ),
14781467 ID_UNALLOCATED (3 ,3 ),
1479- ID_SANITISED (ID_PFR2_EL1 ),
1468+ AA32_ID_SANITISED (ID_PFR2_EL1 ),
14801469 ID_HIDDEN (ID_DFR1_EL1 ),
1481- ID_SANITISED (ID_MMFR5_EL1 ),
1470+ AA32_ID_SANITISED (ID_MMFR5_EL1 ),
14821471 ID_UNALLOCATED (3 ,7 ),
14831472
14841473 /* AArch64 ID registers */
@@ -2809,6 +2798,9 @@ int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,
28092798 if (!r )
28102799 return - ENOENT ;
28112800
2801+ if (sysreg_user_write_ignore (vcpu , r ))
2802+ return 0 ;
2803+
28122804 if (r -> set_user ) {
28132805 ret = (r -> set_user )(vcpu , r , val );
28142806 } else {
0 commit comments