KVM: VMX: report internal error for MMIO #PF due to delivery event
authorXiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Wed, 17 Oct 2012 05:48:06 +0000 (13:48 +0800)
committerAvi Kivity <avi@redhat.com>
Thu, 18 Oct 2012 14:30:32 +0000 (16:30 +0200)
The #PF with PFEC.RSV = 1 indicates that the guest is accessing MMIO, we
can not fix it if it is caused by delivery event. Reporting internal error
for this case

Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
arch/x86/kvm/vmx.c

index b8a0841..6599e45 100644 (file)
@@ -4287,16 +4287,6 @@ static int handle_exception(struct kvm_vcpu *vcpu)
        if (is_machine_check(intr_info))
                return handle_machine_check(vcpu);
 
-       if ((vect_info & VECTORING_INFO_VALID_MASK) &&
-           !is_page_fault(intr_info)) {
-               vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-               vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_SIMUL_EX;
-               vcpu->run->internal.ndata = 2;
-               vcpu->run->internal.data[0] = vect_info;
-               vcpu->run->internal.data[1] = intr_info;
-               return 0;
-       }
-
        if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR)
                return 1;  /* already handled by vmx_vcpu_run() */
 
@@ -4315,6 +4305,22 @@ static int handle_exception(struct kvm_vcpu *vcpu)
        error_code = 0;
        if (intr_info & INTR_INFO_DELIVER_CODE_MASK)
                error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
+
+       /*
+        * The #PF with PFEC.RSVD = 1 indicates the guest is accessing
+        * MMIO, it is better to report an internal error.
+        * See the comments in vmx_handle_exit.
+        */
+       if ((vect_info & VECTORING_INFO_VALID_MASK) &&
+           !(is_page_fault(intr_info) && !(error_code & PFERR_RSVD_MASK))) {
+               vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+               vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_SIMUL_EX;
+               vcpu->run->internal.ndata = 2;
+               vcpu->run->internal.data[0] = vect_info;
+               vcpu->run->internal.data[1] = intr_info;
+               return 0;
+       }
+
        if (is_page_fault(intr_info)) {
                /* EPT won't cause page fault directly */
                BUG_ON(enable_ept);