[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] pv-on-hvm: Re-init hypercall stubs page after HVM save/restore.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1180110386 -3600
# Node ID c49987e71daefdac6b294ad0f1dd4553bae75fc6
# Parent  a00d55b15327d0e3cece3a6b57c37d63535cb17b
pv-on-hvm: Re-init hypercall stubs page after HVM save/restore.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 unmodified_drivers/linux-2.6/platform-pci/platform-pci.c |   78 +++++++++++----
 1 files changed, 62 insertions(+), 16 deletions(-)

diff -r a00d55b15327 -r c49987e71dae 
unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
--- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c  Fri May 25 
16:06:36 2007 +0100
+++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c  Fri May 25 
17:26:26 2007 +0100
@@ -54,6 +54,7 @@
 #define DRV_VERSION "0.10"
 #define DRV_RELDATE "03/03/2005"
 
+static int max_hypercall_stub_pages, nr_hypercall_stub_pages;
 char *hypercall_stubs;
 EXPORT_SYMBOL(hypercall_stubs);
 
@@ -109,8 +110,8 @@ unsigned long alloc_xen_mmio(unsigned lo
 }
 
 #ifndef __ia64__
-/* Lifted from hvmloader.c */
-static int get_hypercall_stubs(void)
+
+static int init_hypercall_stubs(void)
 {
        uint32_t eax, ebx, ecx, edx, pages, msr, i;
        char signature[13];
@@ -133,16 +134,27 @@ static int get_hypercall_stubs(void)
 
        printk(KERN_INFO "Xen version %d.%d.\n", eax >> 16, eax & 0xffff);
 
+       /*
+        * Find largest supported number of hypercall pages.
+        * We'll create as many as possible up to this number.
+        */
        cpuid(0x40000002, &pages, &msr, &ecx, &edx);
 
-       printk(KERN_INFO "Hypercall area is %u pages.\n", pages);
-
-       /* Use __vmalloc() because vmalloc_exec() is not an exported symbol. */
-       /* PAGE_KERNEL_EXEC also is not exported, hence we use PAGE_KERNEL. */
-       /* hypercall_stubs = vmalloc_exec(pages * PAGE_SIZE); */
-       hypercall_stubs = __vmalloc(pages * PAGE_SIZE,
-                                   GFP_KERNEL | __GFP_HIGHMEM,
-                                   __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
+       /*
+        * Use __vmalloc() because vmalloc_exec() is not an exported symbol.
+        * PAGE_KERNEL_EXEC also is not exported, hence we use PAGE_KERNEL.
+        * hypercall_stubs = vmalloc_exec(pages * PAGE_SIZE);
+        */
+       while (pages > 0) {
+               hypercall_stubs = __vmalloc(
+                       pages * PAGE_SIZE,
+                       GFP_KERNEL | __GFP_HIGHMEM,
+                       __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
+               if (hypercall_stubs != NULL)
+                       break;
+               pages--; /* vmalloc failed: try one fewer pages */
+       }
+
        if (hypercall_stubs == NULL)
                return -ENOMEM;
 
@@ -152,10 +164,46 @@ static int get_hypercall_stubs(void)
                wrmsrl(msr, ((u64)pfn << PAGE_SHIFT) + i);
        }
 
+       nr_hypercall_stub_pages = pages;
+       max_hypercall_stub_pages = pages;
+
+       printk(KERN_INFO "Hypercall area is %u pages.\n", pages);
+
        return 0;
 }
+
+static void resume_hypercall_stubs(void)
+{
+       uint32_t eax, ebx, ecx, edx, pages, msr, i;
+       char signature[13];
+
+       cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
+       *(uint32_t*)(signature + 0) = ebx;
+       *(uint32_t*)(signature + 4) = ecx;
+       *(uint32_t*)(signature + 8) = edx;
+       signature[12] = 0;
+
+       BUG_ON(strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002));
+
+       cpuid(0x40000002, &pages, &msr, &ecx, &edx);
+
+       if (pages > max_hypercall_stub_pages)
+               pages = max_hypercall_stub_pages;
+
+       for (i = 0; i < pages; i++) {
+               unsigned long pfn;
+               pfn = vmalloc_to_pfn((char *)hypercall_stubs + i*PAGE_SIZE);
+               wrmsrl(msr, ((u64)pfn << PAGE_SHIFT) + i);
+       }
+
+       nr_hypercall_stub_pages = pages;
+}
+
 #else /* __ia64__ */
-#define get_hypercall_stubs()  (0)
+
+#define init_hypercall_stubs()         (0)
+#define resume_hypercall_stubs()       ((void)0)
+
 #endif
 
 static uint64_t get_callback_via(struct pci_dev *pdev)
@@ -247,7 +295,7 @@ static int __devinit platform_pci_init(s
        platform_mmio = mmio_addr;
        platform_mmiolen = mmio_len;
 
-       ret = get_hypercall_stubs();
+       ret = init_hypercall_stubs();
        if (ret < 0)
                goto out;
 
@@ -302,10 +350,8 @@ void platform_pci_resume(void)
 {
        struct xen_add_to_physmap xatp;
 
-       /* do 2 things for PV driver restore on HVM
-        * 1: rebuild share info
-        * 2: set callback irq again
-        */
+       resume_hypercall_stubs();
+
        xatp.domid = DOMID_SELF;
        xatp.idx = 0;
        xatp.space = XENMAPSPACE_shared_info;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.