# 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
|