ia64/xen-unstable

changeset 15230:c49987e71dae

pv-on-hvm: Re-init hypercall stubs page after HVM save/restore.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri May 25 17:26:26 2007 +0100 (2007-05-25)
parents a00d55b15327
children f0772865c85a
files unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
line diff
     1.1 --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c	Fri May 25 16:06:36 2007 +0100
     1.2 +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c	Fri May 25 17:26:26 2007 +0100
     1.3 @@ -54,6 +54,7 @@
     1.4  #define DRV_VERSION "0.10"
     1.5  #define DRV_RELDATE "03/03/2005"
     1.6  
     1.7 +static int max_hypercall_stub_pages, nr_hypercall_stub_pages;
     1.8  char *hypercall_stubs;
     1.9  EXPORT_SYMBOL(hypercall_stubs);
    1.10  
    1.11 @@ -109,8 +110,8 @@ unsigned long alloc_xen_mmio(unsigned lo
    1.12  }
    1.13  
    1.14  #ifndef __ia64__
    1.15 -/* Lifted from hvmloader.c */
    1.16 -static int get_hypercall_stubs(void)
    1.17 +
    1.18 +static int init_hypercall_stubs(void)
    1.19  {
    1.20  	uint32_t eax, ebx, ecx, edx, pages, msr, i;
    1.21  	char signature[13];
    1.22 @@ -133,16 +134,27 @@ static int get_hypercall_stubs(void)
    1.23  
    1.24  	printk(KERN_INFO "Xen version %d.%d.\n", eax >> 16, eax & 0xffff);
    1.25  
    1.26 +	/*
    1.27 +	 * Find largest supported number of hypercall pages.
    1.28 +	 * We'll create as many as possible up to this number.
    1.29 +	 */
    1.30  	cpuid(0x40000002, &pages, &msr, &ecx, &edx);
    1.31  
    1.32 -	printk(KERN_INFO "Hypercall area is %u pages.\n", pages);
    1.33 +	/*
    1.34 +	 * Use __vmalloc() because vmalloc_exec() is not an exported symbol.
    1.35 +	 * PAGE_KERNEL_EXEC also is not exported, hence we use PAGE_KERNEL.
    1.36 +	 * hypercall_stubs = vmalloc_exec(pages * PAGE_SIZE);
    1.37 +	 */
    1.38 +	while (pages > 0) {
    1.39 +		hypercall_stubs = __vmalloc(
    1.40 +			pages * PAGE_SIZE,
    1.41 +			GFP_KERNEL | __GFP_HIGHMEM,
    1.42 +			__pgprot(__PAGE_KERNEL & ~_PAGE_NX));
    1.43 +		if (hypercall_stubs != NULL)
    1.44 +			break;
    1.45 +		pages--; /* vmalloc failed: try one fewer pages */
    1.46 +	}
    1.47  
    1.48 -	/* Use __vmalloc() because vmalloc_exec() is not an exported symbol. */
    1.49 -	/* PAGE_KERNEL_EXEC also is not exported, hence we use PAGE_KERNEL. */
    1.50 -	/* hypercall_stubs = vmalloc_exec(pages * PAGE_SIZE); */
    1.51 -	hypercall_stubs = __vmalloc(pages * PAGE_SIZE,
    1.52 -				    GFP_KERNEL | __GFP_HIGHMEM,
    1.53 -				    __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
    1.54  	if (hypercall_stubs == NULL)
    1.55  		return -ENOMEM;
    1.56  
    1.57 @@ -152,10 +164,46 @@ static int get_hypercall_stubs(void)
    1.58  		wrmsrl(msr, ((u64)pfn << PAGE_SHIFT) + i);
    1.59  	}
    1.60  
    1.61 +	nr_hypercall_stub_pages = pages;
    1.62 +	max_hypercall_stub_pages = pages;
    1.63 +
    1.64 +	printk(KERN_INFO "Hypercall area is %u pages.\n", pages);
    1.65 +
    1.66  	return 0;
    1.67  }
    1.68 +
    1.69 +static void resume_hypercall_stubs(void)
    1.70 +{
    1.71 +	uint32_t eax, ebx, ecx, edx, pages, msr, i;
    1.72 +	char signature[13];
    1.73 +
    1.74 +	cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
    1.75 +	*(uint32_t*)(signature + 0) = ebx;
    1.76 +	*(uint32_t*)(signature + 4) = ecx;
    1.77 +	*(uint32_t*)(signature + 8) = edx;
    1.78 +	signature[12] = 0;
    1.79 +
    1.80 +	BUG_ON(strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002));
    1.81 +
    1.82 +	cpuid(0x40000002, &pages, &msr, &ecx, &edx);
    1.83 +
    1.84 +	if (pages > max_hypercall_stub_pages)
    1.85 +		pages = max_hypercall_stub_pages;
    1.86 +
    1.87 +	for (i = 0; i < pages; i++) {
    1.88 +		unsigned long pfn;
    1.89 +		pfn = vmalloc_to_pfn((char *)hypercall_stubs + i*PAGE_SIZE);
    1.90 +		wrmsrl(msr, ((u64)pfn << PAGE_SHIFT) + i);
    1.91 +	}
    1.92 +
    1.93 +	nr_hypercall_stub_pages = pages;
    1.94 +}
    1.95 +
    1.96  #else /* __ia64__ */
    1.97 -#define get_hypercall_stubs()	(0)
    1.98 +
    1.99 +#define init_hypercall_stubs()		(0)
   1.100 +#define resume_hypercall_stubs()	((void)0)
   1.101 +
   1.102  #endif
   1.103  
   1.104  static uint64_t get_callback_via(struct pci_dev *pdev)
   1.105 @@ -247,7 +295,7 @@ static int __devinit platform_pci_init(s
   1.106  	platform_mmio = mmio_addr;
   1.107  	platform_mmiolen = mmio_len;
   1.108  
   1.109 -	ret = get_hypercall_stubs();
   1.110 +	ret = init_hypercall_stubs();
   1.111  	if (ret < 0)
   1.112  		goto out;
   1.113  
   1.114 @@ -302,10 +350,8 @@ void platform_pci_resume(void)
   1.115  {
   1.116  	struct xen_add_to_physmap xatp;
   1.117  
   1.118 -	/* do 2 things for PV driver restore on HVM
   1.119 -	 * 1: rebuild share info
   1.120 -	 * 2: set callback irq again
   1.121 -	 */
   1.122 +	resume_hypercall_stubs();
   1.123 +
   1.124  	xatp.domid = DOMID_SELF;
   1.125  	xatp.idx = 0;
   1.126  	xatp.space = XENMAPSPACE_shared_info;