]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/xen.git/commitdiff
x86 hvm viridian: Provide dummy support for APIC assist page to satisfy Win7.
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 26 May 2009 09:13:43 +0000 (10:13 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 26 May 2009 09:13:43 +0000 (10:13 +0100)
From: Tim Deegan <tim.deegan@citrix.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/hvm/viridian.c

index a18ea9e3d14bfa0fe728d9b62e46a88da2a6ac81..ca4f2246014366386bf328f5390e6ddbd53ee67f 100644 (file)
@@ -22,6 +22,7 @@
 #define VIRIDIAN_MSR_EOI         0x40000070
 #define VIRIDIAN_MSR_ICR         0x40000071
 #define VIRIDIAN_MSR_TPR         0x40000072
+#define VIRIDIAN_MSR_APIC_ASSIST 0x40000073
 
 /* Viridian Hypercall Status Codes. */
 #define HV_STATUS_SUCCESS                       0x0000
@@ -49,14 +50,14 @@ int cpuid_viridian_leaves(unsigned int leaf, unsigned int *eax,
         return 0;
 
     leaf -= 0x40000000;
-    if ( leaf > 5 )
+    if ( leaf > 6 )
         return 0;
 
     *eax = *ebx = *ecx = *edx = 0;
     switch ( leaf )
     {
     case 0:
-        *eax = 0x40000005; /* Maximum leaf */
+        *eax = 0x40000006; /* Maximum leaf */
         *ebx = 0x7263694d; /* Magic numbers  */
         *ecx = 0x666F736F;
         *edx = 0x76482074;
@@ -192,6 +193,30 @@ int wrmsr_viridian_regs(uint32_t idx, uint32_t eax, uint32_t edx)
         vlapic_set_reg(vcpu_vlapic(current), APIC_TASKPRI, eax & 0xff);
         break;
 
+    case VIRIDIAN_MSR_APIC_ASSIST:
+        /*
+         * We don't support the APIC assist page, and that fact is reflected in
+         * our CPUID flags. However, Windows 7 build 7000 has a bug which means
+         * that it doesn't recognise that, and tries to use the page anyway. We
+         * therefore have to fake up just enough to keep win7 happy.
+         * Fortunately, that's really easy: just setting the first four bytes
+         * in the page to zero effectively disables the page again, so that's
+         * what we do. Semantically, the first four bytes are supposed to be a
+         * flag saying whether the guest really needs to issue an EOI. Setting
+         * that flag to zero means that it must always issue one, which is what
+         * we want. Once a page has been repurposed as an APIC assist page the
+         * guest isn't allowed to set anything in it, so the flag remains zero
+         * and all is fine. The guest is allowed to clear flags in the page,
+         * but that doesn't cause us any problems.
+         */
+        if ( val & 1 ) /* APIC assist page enabled? */
+        {
+            uint32_t word = 0;
+            paddr_t page_start = val & ~1ul;
+            hvm_copy_to_guest_phys(page_start, &word, sizeof(word));
+        }
+        break;
+
     default:
         return 0;
     }