@@ -456,6 +456,11 @@ static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
456456 if (check_output_size (desc & GENMASK (47 , va_bottom ), wi ))
457457 goto addrsz ;
458458
459+ if (!(desc & PTE_AF )) {
460+ fail_s1_walk (wr , ESR_ELx_FSC_ACCESS_L (level ), false);
461+ return - EACCES ;
462+ }
463+
459464 va_bottom += contiguous_bit_shift (desc , wi , level );
460465
461466 wr -> failed = false;
@@ -1209,7 +1214,8 @@ static u64 handle_at_slow(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
12091214 * If the translation is unsuccessful, the value may only contain
12101215 * PAR_EL1.F, and cannot be taken at face value. It isn't an
12111216 * 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.
12131219 */
12141220static u64 __kvm_at_s1e01_fast (struct kvm_vcpu * vcpu , u32 op , u64 vaddr )
12151221{
@@ -1312,19 +1318,29 @@ static bool par_check_s1_perm_fault(u64 par)
13121318 !(par & SYS_PAR_EL1_S ));
13131319}
13141320
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+
13151329void __kvm_at_s1e01 (struct kvm_vcpu * vcpu , u32 op , u64 vaddr )
13161330{
13171331 u64 par = __kvm_at_s1e01_fast (vcpu , op , vaddr );
13181332
13191333 /*
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.
13231337 *
13241338 * If AT failed for any other reason, then we must walk the guest S1
13251339 * to emulate the instruction.
13261340 */
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 ))
13281344 par = handle_at_slow (vcpu , op , vaddr );
13291345
13301346 vcpu_write_sys_reg (vcpu , par , PAR_EL1 );
0 commit comments