@@ -456,6 +456,11 @@ static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
456
456
if (check_output_size (desc & GENMASK (47 , va_bottom ), wi ))
457
457
goto addrsz ;
458
458
459
+ if (!(desc & PTE_AF )) {
460
+ fail_s1_walk (wr , ESR_ELx_FSC_ACCESS_L (level ), false);
461
+ return - EACCES ;
462
+ }
463
+
459
464
va_bottom += contiguous_bit_shift (desc , wi , level );
460
465
461
466
wr -> failed = false;
@@ -1209,7 +1214,8 @@ static u64 handle_at_slow(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
1209
1214
* If the translation is unsuccessful, the value may only contain
1210
1215
* PAR_EL1.F, and cannot be taken at face value. It isn't an
1211
1216
* indication of the translation having failed, only that the fast
1212
- * path did not succeed, *unless* it indicates a S1 permission fault.
1217
+ * path did not succeed, *unless* it indicates a S1 permission or
1218
+ * access fault.
1213
1219
*/
1214
1220
static u64 __kvm_at_s1e01_fast (struct kvm_vcpu * vcpu , u32 op , u64 vaddr )
1215
1221
{
@@ -1312,19 +1318,29 @@ static bool par_check_s1_perm_fault(u64 par)
1312
1318
!(par & SYS_PAR_EL1_S ));
1313
1319
}
1314
1320
1321
+ static bool par_check_s1_access_fault (u64 par )
1322
+ {
1323
+ u8 fst = FIELD_GET (SYS_PAR_EL1_FST , par );
1324
+
1325
+ return ((fst & ESR_ELx_FSC_TYPE ) == ESR_ELx_FSC_ACCESS &&
1326
+ !(par & SYS_PAR_EL1_S ));
1327
+ }
1328
+
1315
1329
void __kvm_at_s1e01 (struct kvm_vcpu * vcpu , u32 op , u64 vaddr )
1316
1330
{
1317
1331
u64 par = __kvm_at_s1e01_fast (vcpu , op , vaddr );
1318
1332
1319
1333
/*
1320
- * If PAR_EL1 reports that AT failed on a S1 permission fault, we
1321
- * know for sure that the PTW was able to walk the S1 tables and
1322
- * there's nothing else to do.
1334
+ * If PAR_EL1 reports that AT failed on a S1 permission or access
1335
+ * fault, we know for sure that the PTW was able to walk the S1
1336
+ * tables and there's nothing else to do.
1323
1337
*
1324
1338
* If AT failed for any other reason, then we must walk the guest S1
1325
1339
* to emulate the instruction.
1326
1340
*/
1327
- if ((par & SYS_PAR_EL1_F ) && !par_check_s1_perm_fault (par ))
1341
+ if ((par & SYS_PAR_EL1_F ) &&
1342
+ !par_check_s1_perm_fault (par ) &&
1343
+ !par_check_s1_access_fault (par ))
1328
1344
par = handle_at_slow (vcpu , op , vaddr );
1329
1345
1330
1346
vcpu_write_sys_reg (vcpu , par , PAR_EL1 );
0 commit comments