]> xenbits.xensource.com Git - people/iwj/xen.git/commitdiff
x86/hvm: avoid p2m lookups for vlapic accesses. 4.3.0-rc2 xen-4.3.0-rc2
authorTim Deegan <tim@xen.org>
Thu, 9 May 2013 12:06:53 +0000 (13:06 +0100)
committerTim Deegan <tim@xen.org>
Thu, 16 May 2013 11:05:25 +0000 (12:05 +0100)
The LAPIC base address is a known GFN, so we can skip looking up the
p2m: we know it should be handled as emulated MMIO.  That helps
performance in older Windows OSes, which make a _lot_ of TPR accesses.

This will change the behaviour of any OS that maps other
memory/devices at its LAPIC address; the new behaviour (the LAPIC
mapping always wins) is closer to actual hardware behaviour.

Signed-off-by: Tim Deegan <tim@xen.org>
Acked-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/hvm/hvm.c

index 7c3cb15053b0f8854cde4c974d51e43d4dfdc507..bcf96093d4719b0f925ea08297a1fbc51eb24f77 100644 (file)
@@ -1361,6 +1361,17 @@ int hvm_hap_nested_page_fault(paddr_t gpa,
         }
     }
 
+    /* For the benefit of 32-bit WinXP (& older Windows) on AMD CPUs,
+     * a fast path for LAPIC accesses, skipping the p2m lookup. */
+    if ( !nestedhvm_vcpu_in_guestmode(v)
+         && gfn == PFN_DOWN(vlapic_base_address(vcpu_vlapic(v))) )
+    {
+        if ( !handle_mmio() )
+            hvm_inject_hw_exception(TRAP_gp_fault, 0);
+        rc = 1;
+        goto out;
+    }
+
     p2m = p2m_get_hostp2m(v->domain);
     mfn = get_gfn_type_access(p2m, gfn, &p2mt, &p2ma, 
                               P2M_ALLOC | (access_w ? P2M_UNSHARE : 0), NULL);
@@ -2471,6 +2482,12 @@ static enum hvm_copy_result __hvm_copy(
             gfn = addr >> PAGE_SHIFT;
         }
 
+        /* For the benefit of 32-bit WinXP (& older Windows) on AMD CPUs,
+         * a fast path for LAPIC accesses, skipping the p2m lookup. */
+        if ( !nestedhvm_vcpu_in_guestmode(curr)
+             && gfn == PFN_DOWN(vlapic_base_address(vcpu_vlapic(curr))) )
+            return HVMCOPY_bad_gfn_to_mfn;
+
         page = get_page_from_gfn(curr->domain, gfn, &p2mt, P2M_UNSHARE);
 
         if ( p2m_is_paging(p2mt) )