Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm: KVM: Survive unknown traps from guests

Currently we BUG() if we see a HSR.EC value we don't recognise. As
configurable disables/enables are added to the architecture (controlled
by RES1/RES0 bits respectively), with associated synchronous exceptions,
it may be possible for a guest to trigger exceptions with classes that
we don't recognise.

While we can't service these exceptions in a manner useful to the guest,
we can avoid bringing down the host. Per ARM DDI 0406C.c, all currently
unallocated HSR EC encodings are reserved, and per ARM DDI
0487A.k_iss10775, page G6-4395, EC values within the range 0x00 - 0x2c
are reserved for future use with synchronous exceptions, and EC values
within the range 0x2d - 0x3f may be used for either synchronous or
asynchronous exceptions.

The patch makes KVM handle any unknown EC by injecting an UNDEFINED
exception into the guest, with a corresponding (ratelimited) warning in
the host dmesg. We could later improve on this with with a new (opt-in)
exit to the host userspace.

Cc: Dave Martin <dave.martin@arm.com>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

authored by

Mark Rutland and committed by
Marc Zyngier
f050fe7a 370a0ec1

+13 -7
+1
arch/arm/include/asm/kvm_arm.h
··· 209 209 #define HSR_EC_IABT_HYP (0x21) 210 210 #define HSR_EC_DABT (0x24) 211 211 #define HSR_EC_DABT_HYP (0x25) 212 + #define HSR_EC_MAX (0x3f) 212 213 213 214 #define HSR_WFI_IS_WFE (_AC(1, UL) << 0) 214 215
+12 -7
arch/arm/kvm/handle_exit.c
··· 79 79 return 1; 80 80 } 81 81 82 + static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu, struct kvm_run *run) 83 + { 84 + u32 hsr = kvm_vcpu_get_hsr(vcpu); 85 + 86 + kvm_pr_unimpl("Unknown exception class: hsr: %#08x\n", 87 + hsr); 88 + 89 + kvm_inject_undefined(vcpu); 90 + return 1; 91 + } 92 + 82 93 static exit_handle_fn arm_exit_handlers[] = { 94 + [0 ... HSR_EC_MAX] = kvm_handle_unknown_ec, 83 95 [HSR_EC_WFI] = kvm_handle_wfx, 84 96 [HSR_EC_CP15_32] = kvm_handle_cp15_32, 85 97 [HSR_EC_CP15_64] = kvm_handle_cp15_64, ··· 109 97 static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) 110 98 { 111 99 u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu); 112 - 113 - if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers) || 114 - !arm_exit_handlers[hsr_ec]) { 115 - kvm_err("Unknown exception class: hsr: %#08x\n", 116 - (unsigned int)kvm_vcpu_get_hsr(vcpu)); 117 - BUG(); 118 - } 119 100 120 101 return arm_exit_handlers[hsr_ec]; 121 102 }