Skip to content

Commit 493b01d

Browse files
author
Marc Zyngier
committed
KVM: arm64: Fix PAR_EL1.{PTW,S} reporting on AT S1E*
When an AT S1E* operation fails, we need to report whether the translation failed at S2, and whether this was during a S1 PTW. But these two bits are not independent. PAR_EL1.PTW can only be set of PAR_EL1.S is also set, and PAR_EL1.S can only be set on its own when the full S1 PTW has succeeded, but that the access itself is reporting a fault at S2. As a result, it makes no sense to carry both ptw and s2 as parameters to fail_s1_walk(), and they should be unified. This fixes a number of cases where we were reporting PTW=1 *and* S=0, which makes no sense. Link: https://lore.kernel.org/r/20250422122612.2675672-2-maz@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent 9c32cda commit 493b01d

File tree

1 file changed

+11
-12
lines changed

1 file changed

+11
-12
lines changed

arch/arm64/kvm/at.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ struct s1_walk_result {
6060
bool failed;
6161
};
6262

63-
static void fail_s1_walk(struct s1_walk_result *wr, u8 fst, bool ptw, bool s2)
63+
static void fail_s1_walk(struct s1_walk_result *wr, u8 fst, bool s1ptw)
6464
{
6565
wr->fst = fst;
66-
wr->ptw = ptw;
67-
wr->s2 = s2;
66+
wr->ptw = s1ptw;
67+
wr->s2 = s1ptw;
6868
wr->failed = true;
6969
}
7070

@@ -345,11 +345,11 @@ static int setup_s1_walk(struct kvm_vcpu *vcpu, u32 op, struct s1_walk_info *wi,
345345
return 0;
346346

347347
addrsz: /* Address Size Fault level 0 */
348-
fail_s1_walk(wr, ESR_ELx_FSC_ADDRSZ_L(0), false, false);
348+
fail_s1_walk(wr, ESR_ELx_FSC_ADDRSZ_L(0), false);
349349
return -EFAULT;
350350

351351
transfault_l0: /* Translation Fault level 0 */
352-
fail_s1_walk(wr, ESR_ELx_FSC_FAULT_L(0), false, false);
352+
fail_s1_walk(wr, ESR_ELx_FSC_FAULT_L(0), false);
353353
return -EFAULT;
354354
}
355355

@@ -380,13 +380,13 @@ static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
380380
if (ret) {
381381
fail_s1_walk(wr,
382382
(s2_trans.esr & ~ESR_ELx_FSC_LEVEL) | level,
383-
true, true);
383+
true);
384384
return ret;
385385
}
386386

387387
if (!kvm_s2_trans_readable(&s2_trans)) {
388388
fail_s1_walk(wr, ESR_ELx_FSC_PERM_L(level),
389-
true, true);
389+
true);
390390

391391
return -EPERM;
392392
}
@@ -396,8 +396,7 @@ static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
396396

397397
ret = kvm_read_guest(vcpu->kvm, ipa, &desc, sizeof(desc));
398398
if (ret) {
399-
fail_s1_walk(wr, ESR_ELx_FSC_SEA_TTW(level),
400-
true, false);
399+
fail_s1_walk(wr, ESR_ELx_FSC_SEA_TTW(level), false);
401400
return ret;
402401
}
403402

@@ -468,10 +467,10 @@ static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
468467
return 0;
469468

470469
addrsz:
471-
fail_s1_walk(wr, ESR_ELx_FSC_ADDRSZ_L(level), true, false);
470+
fail_s1_walk(wr, ESR_ELx_FSC_ADDRSZ_L(level), false);
472471
return -EINVAL;
473472
transfault:
474-
fail_s1_walk(wr, ESR_ELx_FSC_FAULT_L(level), true, false);
473+
fail_s1_walk(wr, ESR_ELx_FSC_FAULT_L(level), false);
475474
return -ENOENT;
476475
}
477476

@@ -1198,7 +1197,7 @@ static u64 handle_at_slow(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
11981197
}
11991198

12001199
if (perm_fail)
1201-
fail_s1_walk(&wr, ESR_ELx_FSC_PERM_L(wr.level), false, false);
1200+
fail_s1_walk(&wr, ESR_ELx_FSC_PERM_L(wr.level), false);
12021201

12031202
compute_par:
12041203
return compute_par_s1(vcpu, &wr, wi.regime);

0 commit comments

Comments
 (0)