Skip to content

Commit 3e4d597

Browse files
author
Marc Zyngier
committed
KVM: arm64: Don't feed uninitialised data to HCR_EL2
When the guest executes an AT S1E{0,1} from EL2, and that its HCR_EL2.{E2H,TGE}=={1,1}, then this is a pure S1 translation that doesn't involve a guest-supplied S2, and the full S1 context is already in place. This allows us to take a shortcut and avoid save/restoring a bunch of registers. However, we set HCR_EL2 to a value suitable for the use of AT in guest context. And we do so by using the value that we saved. Or not. In the case described above, we restore whatever junk was on the stack, and carry on with it until the next entry. Needless to say, this is completely broken. But this also triggers the realisation that saving HCR_EL2 is a bit pointless. We are always in host context at the point where reach this code, and what we program to enter the guest is a known value (vcpu->arch.hcr_el2). Drop the pointless save/restore, and wrap the AT operations with writes that switch between guest and host values for HCR_EL2. Reported-by: D Scott Phillips <scott@os.amperecomputing.com> Link: https://lore.kernel.org/r/20250422122612.2675672-4-maz@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent ed648ab commit 3e4d597

File tree

1 file changed

+4
-6
lines changed

1 file changed

+4
-6
lines changed

arch/arm64/kvm/at.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,6 @@ struct mmu_config {
492492
u64 sctlr;
493493
u64 vttbr;
494494
u64 vtcr;
495-
u64 hcr;
496495
};
497496

498497
static void __mmu_config_save(struct mmu_config *config)
@@ -515,13 +514,10 @@ static void __mmu_config_save(struct mmu_config *config)
515514
config->sctlr = read_sysreg_el1(SYS_SCTLR);
516515
config->vttbr = read_sysreg(vttbr_el2);
517516
config->vtcr = read_sysreg(vtcr_el2);
518-
config->hcr = read_sysreg(hcr_el2);
519517
}
520518

521519
static void __mmu_config_restore(struct mmu_config *config)
522520
{
523-
write_sysreg(config->hcr, hcr_el2);
524-
525521
/*
526522
* ARM errata 1165522 and 1530923 require TGE to be 1 before
527523
* we update the guest state.
@@ -1271,8 +1267,8 @@ static u64 __kvm_at_s1e01_fast(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
12711267
__load_stage2(mmu, mmu->arch);
12721268

12731269
skip_mmu_switch:
1274-
/* Clear TGE, enable S2 translation, we're rolling */
1275-
write_sysreg((config.hcr & ~HCR_TGE) | HCR_VM, hcr_el2);
1270+
/* Temporarily switch back to guest context */
1271+
write_sysreg(vcpu->arch.hcr_el2, hcr_el2);
12761272
isb();
12771273

12781274
switch (op) {
@@ -1304,6 +1300,8 @@ static u64 __kvm_at_s1e01_fast(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
13041300
if (!fail)
13051301
par = read_sysreg_par();
13061302

1303+
write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2);
1304+
13071305
if (!(vcpu_el2_e2h_is_set(vcpu) && vcpu_el2_tge_is_set(vcpu)))
13081306
__mmu_config_restore(&config);
13091307

0 commit comments

Comments
 (0)