VMX differentiates between processor and software generated exceptions
when injecting them into the guest. Extend vmx_queue_exception
accordingly (and refactor related constants) so that we can use this
service reliably for the new guest debugging framework.

Signed-off-by: Jan Kiszka <[EMAIL PROTECTED]>
---
 arch/x86/kvm/vmx.c |   34 +++++++++++++++++++---------------
 arch/x86/kvm/vmx.h |    3 ++-
 2 files changed, 21 insertions(+), 16 deletions(-)

Index: b/arch/x86/kvm/vmx.c
===================================================================
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -188,21 +188,21 @@ static inline int is_page_fault(u32 intr
 {
        return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
                             INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK);
+               (INTR_TYPE_HARD_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK);
 }
 
 static inline int is_no_device(u32 intr_info)
 {
        return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
                             INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_EXCEPTION | NM_VECTOR | INTR_INFO_VALID_MASK);
+               (INTR_TYPE_HARD_EXCEPTION | NM_VECTOR | INTR_INFO_VALID_MASK);
 }
 
 static inline int is_invalid_opcode(u32 intr_info)
 {
        return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
                             INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_EXCEPTION | UD_VECTOR | INTR_INFO_VALID_MASK);
+               (INTR_TYPE_HARD_EXCEPTION | UD_VECTOR | INTR_INFO_VALID_MASK);
 }
 
 static inline int is_external_interrupt(u32 intr_info)
@@ -746,29 +746,33 @@ static void vmx_queue_exception(struct k
                                bool has_error_code, u32 error_code)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
+       u32 intr_info = nr | INTR_INFO_VALID_MASK;
 
-       if (has_error_code)
+       if (has_error_code) {
                vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
+               intr_info |= INTR_INFO_DELIVER_CODE_MASK;
+       }
 
        if (vcpu->arch.rmode.active) {
                vmx->rmode.irq.pending = true;
                vmx->rmode.irq.vector = nr;
                vmx->rmode.irq.rip = kvm_rip_read(vcpu);
-               if (nr == BP_VECTOR)
+               if (nr == BP_VECTOR || nr == OF_VECTOR)
                        vmx->rmode.irq.rip++;
-               vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
-                            nr | INTR_TYPE_SOFT_INTR
-                            | (has_error_code ? INTR_INFO_DELIVER_CODE_MASK : 
0)
-                            | INTR_INFO_VALID_MASK);
+               intr_info |= INTR_TYPE_SOFT_INTR;
+               vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
                vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
                kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1);
                return;
        }
 
-       vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
-                    nr | INTR_TYPE_EXCEPTION
-                    | (has_error_code ? INTR_INFO_DELIVER_CODE_MASK : 0)
-                    | INTR_INFO_VALID_MASK);
+       if (nr == BP_VECTOR || nr == OF_VECTOR) {
+               vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
+               intr_info |= INTR_TYPE_SOFT_EXCEPTION;
+       } else
+               intr_info |= INTR_TYPE_HARD_EXCEPTION;
+
+       vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
 }
 
 static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
@@ -2616,7 +2620,7 @@ static int handle_exception(struct kvm_v
        }
 
        if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) ==
-           (INTR_TYPE_EXCEPTION | 1)) {
+           (INTR_TYPE_HARD_EXCEPTION | 1)) {
                kvm_run->exit_reason = KVM_EXIT_DEBUG;
                return 0;
        }
@@ -3218,7 +3222,7 @@ static void vmx_complete_interrupts(stru
                        vmx->vcpu.arch.nmi_injected = false;
        }
        kvm_clear_exception_queue(&vmx->vcpu);
-       if (idtv_info_valid && type == INTR_TYPE_EXCEPTION) {
+       if (idtv_info_valid && type == INTR_TYPE_HARD_EXCEPTION) {
                if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) {
                        error = vmcs_read32(IDT_VECTORING_ERROR_CODE);
                        kvm_queue_exception_e(&vmx->vcpu, vector, error);
Index: b/arch/x86/kvm/vmx.h
===================================================================
--- a/arch/x86/kvm/vmx.h
+++ b/arch/x86/kvm/vmx.h
@@ -263,8 +263,9 @@ enum vmcs_field {
 
 #define INTR_TYPE_EXT_INTR              (0 << 8) /* external interrupt */
 #define INTR_TYPE_NMI_INTR             (2 << 8) /* NMI */
-#define INTR_TYPE_EXCEPTION             (3 << 8) /* processor exception */
+#define INTR_TYPE_HARD_EXCEPTION       (3 << 8) /* processor exception */
 #define INTR_TYPE_SOFT_INTR             (4 << 8) /* software interrupt */
+#define INTR_TYPE_SOFT_EXCEPTION       (6 << 8) /* software exception */
 
 /* GUEST_INTERRUPTIBILITY_INFO flags. */
 #define GUEST_INTR_STATE_STI           0x00000001

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to