Skip to content

Commit

Permalink
KVM: arm64: AArch32: Fix spurious trapping of conditional instructions
Browse files Browse the repository at this point in the history
commit c92e8b9eacebb4060634ebd9395bba1b29aadc68 upstream.

We recently upgraded the view of ESR_EL2 to 64bit, in keeping with
the requirements of the architecture.

However, the AArch32 emulation code was left unaudited, and the
(already dodgy) code that triages whether a trap is spurious or not
(because the condition code failed) broke in a subtle way:

If ESR_EL2.ISS2 is ever non-zero (unlikely, but hey, this is the ARM
architecture we're talking about), the hack that tests the top bits
of ESR_EL2.EC will break in an interesting way.

Instead, use kvm_vcpu_trap_get_class() to obtain the EC, and list
all the possible ECs that can fail a condition code check.

While we're at it, add SMC32 to the list, as it is explicitly listed
as being allowed to trap despite failing a condition code check (as
described in the HCR_EL2.TSC documentation).

Fixes: 0b12620 ("KVM: arm64: Treat ESR_EL2 as a 64-bit register")
Cc: [email protected]
Acked-by: Oliver Upton <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Marc Zyngier <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
Marc Zyngier authored and Avenger-285714 committed Dec 10, 2024
1 parent e845e01 commit 95d2323
Showing 1 changed file with 16 additions and 2 deletions.
18 changes: 16 additions & 2 deletions arch/arm64/kvm/hyp/aarch32.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,23 @@ bool kvm_condition_valid32(const struct kvm_vcpu *vcpu)
u32 cpsr_cond;
int cond;

/* Top two bits non-zero? Unconditional. */
if (kvm_vcpu_get_esr(vcpu) >> 30)
/*
* These are the exception classes that could fire with a
* conditional instruction.
*/
switch (kvm_vcpu_trap_get_class(vcpu)) {
case ESR_ELx_EC_CP15_32:
case ESR_ELx_EC_CP15_64:
case ESR_ELx_EC_CP14_MR:
case ESR_ELx_EC_CP14_LS:
case ESR_ELx_EC_FP_ASIMD:
case ESR_ELx_EC_CP10_ID:
case ESR_ELx_EC_CP14_64:
case ESR_ELx_EC_SVC32:
break;
default:
return true;
}

/* Is condition field valid? */
cond = kvm_vcpu_get_condition(vcpu);
Expand Down

0 comments on commit 95d2323

Please sign in to comment.