Skip to content

Commit 32d43cd

Browse files
committed
kvm/x86: fix icebp instruction handling
The undocumented 'icebp' instruction (aka 'int1') works pretty much like 'int3' in the absense of in-circuit probing equipment (except, obviously, that it raises #DB instead of raising #BP), and is used by some validation test-suites as such. But Andy Lutomirski noticed that his test suite acted differently in kvm than on bare hardware. The reason is that kvm used an inexact test for the icebp instruction: it just assumed that an all-zero VM exit qualification value meant that the VM exit was due to icebp. That is not unlike the guess that do_debug() does for the actual exception handling case, but it's purely a heuristic, not an absolute rule. do_debug() does it because it wants to ascribe _some_ reasons to the #DB that happened, and an empty %dr6 value means that 'icebp' is the most likely casue and we have no better information. But kvm can just do it right, because unlike the do_debug() case, kvm actually sees the real reason for the #DB in the VM-exit interruption information field. So instead of relying on an inexact heuristic, just use the actual VM exit information that says "it was 'icebp'". Right now the 'icebp' instruction isn't technically documented by Intel, but that will hopefully change. The special "privileged software exception" information _is_ actually mentioned in the Intel SDM, even though the cause of it isn't enumerated. Reported-by: Andy Lutomirski <[email protected]> Tested-by: Paolo Bonzini <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 1b5f3ba commit 32d43cd

File tree

2 files changed

+9
-1
lines changed

2 files changed

+9
-1
lines changed

arch/x86/include/asm/vmx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ enum vmcs_field {
352352
#define INTR_TYPE_NMI_INTR (2 << 8) /* NMI */
353353
#define INTR_TYPE_HARD_EXCEPTION (3 << 8) /* processor exception */
354354
#define INTR_TYPE_SOFT_INTR (4 << 8) /* software interrupt */
355+
#define INTR_TYPE_PRIV_SW_EXCEPTION (5 << 8) /* ICE breakpoint - undocumented */
355356
#define INTR_TYPE_SOFT_EXCEPTION (6 << 8) /* software exception */
356357

357358
/* GUEST_INTERRUPTIBILITY_INFO flags. */

arch/x86/kvm/vmx.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,13 @@ static inline bool is_machine_check(u32 intr_info)
10451045
(INTR_TYPE_HARD_EXCEPTION | MC_VECTOR | INTR_INFO_VALID_MASK);
10461046
}
10471047

1048+
/* Undocumented: icebp/int1 */
1049+
static inline bool is_icebp(u32 intr_info)
1050+
{
1051+
return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
1052+
== (INTR_TYPE_PRIV_SW_EXCEPTION | INTR_INFO_VALID_MASK);
1053+
}
1054+
10481055
static inline bool cpu_has_vmx_msr_bitmap(void)
10491056
{
10501057
return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS;
@@ -6179,7 +6186,7 @@ static int handle_exception(struct kvm_vcpu *vcpu)
61796186
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
61806187
vcpu->arch.dr6 &= ~15;
61816188
vcpu->arch.dr6 |= dr6 | DR6_RTM;
6182-
if (!(dr6 & ~DR6_RESERVED)) /* icebp */
6189+
if (is_icebp(intr_info))
61836190
skip_emulated_instruction(vcpu);
61846191

61856192
kvm_queue_exception(vcpu, DB_VECTOR);

0 commit comments

Comments
 (0)