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

Re: Xen "pvhvm" driver support for squeeze?



On Thu, 2010-08-12 at 12:10 +0100, Ben Hutchings wrote:
> On Thu, 2010-08-12 at 09:35 +0100, Ian Campbell wrote:
> > On Wed, 2010-07-28 at 03:43 +0100, Ben Hutchings wrote:
> > > 
> > > Can we put off this decision for a week or so, so you and your
> > > colleagues have time to test the backport branch and we can also see
> > > Linus's decision on whether to pull the changes into 2.6.36?
> > 
> > So I go on holiday for a week and when I get back you've only gone and
> > frozen squeeze ;-)
> > 
> > Is that a blocker to adding new drivers like this or should I continue
> > looking into it? FWIW Linus has now pulled it into his tree.
> 
> I think we can get away with adding this.

I've rebased the commits which went into 2.6.36-rc1 onto 2.6.32.19. A
pull-request style thing is below for reference. The main difference
with the backport is the adjustments made because the generic hypervisor
detection infrastructure is not present in 2.6.32. I thought backporting
this might be too intrusive so I adjusted the pvhvm driver to work
without it. Much of the pvhvm driver work was done before the hypervisor
detection infrastructure was available so this isn't really new or
untried code.

I exported these rebased changesets, added them to the sid series and
adjusted the pvops.patch (the featureset=xen patch) to remove the bits
which are now already included. I have confirmed that there is no change
to the resulting featureset=xen tree (which is expected since everything
in these patches are already included there).

The debdiff is attached and diffstat is below. I need to do some more
testing on 32 and 64 bit but are there any objections to my committing
this in the near(ish) future?

 debian/changelog                                                                                     |    5 
 debian/config/kernelarch-x86/config                                                                  |    1 
 debian/control.md5sum                                                                                |    2 
 debian/patches/features/all/xen/pvhvm/0001-xen-Add-support-for-HVM-hypercalls.patch                  |  211 +
 debian/patches/features/all/xen/pvhvm/0002-x86-early-PV-on-HVM-features-initialization.patch         |  242 +
 debian/patches/features/all/xen/pvhvm/0003-x86-xen-event-channels-delivery-on-HVM.patch              |  334 +
 debian/patches/features/all/xen/pvhvm/0004-xen-Xen-PCI-platform-device-driver.patch                  |  564 +++
 debian/patches/features/all/xen/pvhvm/0005-xen-Add-suspend-resume-support-for-PV-on-HVM-guests.patch |  283 +
 debian/patches/features/all/xen/pvhvm/0006-xen-Fix-find_unbound_irq-in-presence-of-ioapic-irqs.patch |   55 
 debian/patches/features/all/xen/pvhvm/0007-x86-Use-xen_vcpuop_clockevent-xen_clocksource-and.patch   |  227 +
 debian/patches/features/all/xen/pvhvm/0008-x86-Unplug-emulated-disks-and-nics.patch                  |  378 ++
 debian/patches/features/all/xen/pvhvm/0009-x86-Call-HVMOP_pagetable_dying-on-exit_mmap.patch         |  112 
 debian/patches/features/all/xen/pvhvm/0010-xenfs-enable-for-HVM-domains-too.patch                    |   36 
 debian/patches/features/all/xen/pvhvm/0011-support-multiple-.discard.-sections-to-avoid-sectio.patch |   45 
 debian/patches/features/all/xen/pvhvm/0012-blkfront-do-not-create-a-PV-cdrom-device-if-xen_hvm.patch |   70 
 debian/patches/features/all/xen/pvhvm/0013-Introduce-CONFIG_XEN_PVHVM-compile-option.patch           |  147 
 debian/patches/features/all/xen/pvhvm/0014-pvops-do-not-notify-callers-from-register_xenstore_.patch |   40 
 debian/patches/features/all/xen/pvops.patch                                                          | 1834 +---------
 debian/patches/series/21                                                                             |   15 
 19 files changed, 3071 insertions(+), 1530 deletions(-)

Ian.

The following changes since commit c6f69a472db92993073d11e5cde047655aba0f2c:
  Greg Kroah-Hartman (1):
        Linux 2.6.32.19

are available in the git repository at:

  git://xenbits.xensource.com/people/ianc/linux-2.6.git debian/squeeze/pvhvm

Jeremy Fitzhardinge (3):
      xen: Add support for HVM hypercalls.
      xenfs: enable for HVM domains too
      support multiple .discard.* sections to avoid section type conflicts

Sheng Yang (2):
      x86: early PV on HVM features initialization.
      x86/xen: event channels delivery on HVM.

Stefano Stabellini (9):
      xen: Xen PCI platform device driver.
      xen: Add suspend/resume support for PV on HVM guests.
      xen: Fix find_unbound_irq in presence of ioapic irqs.
      x86: Use xen_vcpuop_clockevent, xen_clocksource and xen wallclock.
      x86: Unplug emulated disks and nics.
      x86: Call HVMOP_pagetable_dying on exit_mmap.
      blkfront: do not create a PV cdrom device if xen_hvm_guest
      Introduce CONFIG_XEN_PVHVM compile option
      pvops: do not notify callers from register_xenstore_notifier

 Documentation/kernel-parameters.txt   |   11 ++
 arch/x86/include/asm/irq_vectors.h    |    3 +
 arch/x86/include/asm/setup.h          |    2 +-
 arch/x86/include/asm/xen/hypercall.h  |    6 +
 arch/x86/include/asm/xen/hypervisor.h |    2 +
 arch/x86/kernel/entry_32.S            |    3 +
 arch/x86/kernel/entry_64.S            |    3 +
 arch/x86/kernel/setup.c               |    2 +
 arch/x86/xen/Kconfig                  |    5 +
 arch/x86/xen/Makefile                 |    2 +-
 arch/x86/xen/enlighten.c              |  139 ++++++++++++++++++++--
 arch/x86/xen/mmu.c                    |   35 ++++++
 arch/x86/xen/mmu.h                    |    1 +
 arch/x86/xen/platform-pci-unplug.c    |  137 ++++++++++++++++++++++
 arch/x86/xen/suspend.c                |   12 ++
 arch/x86/xen/time.c                   |   57 +++++++++-
 arch/x86/xen/xen-ops.h                |   11 +-
 drivers/block/xen-blkfront.c          |   30 +++++
 drivers/input/xen-kbdfront.c          |    2 +-
 drivers/video/xen-fbfront.c           |    2 +-
 drivers/xen/Kconfig                   |   12 ++-
 drivers/xen/Makefile                  |    3 +-
 drivers/xen/events.c                  |   94 +++++++++++++--
 drivers/xen/grant-table.c             |   77 +++++++++++--
 drivers/xen/manage.c                  |   45 +++++++-
 drivers/xen/platform-pci.c            |  207 +++++++++++++++++++++++++++++++++
 drivers/xen/xenbus/xenbus_probe.c     |   52 +++++++--
 drivers/xen/xenfs/super.c             |    4 +-
 include/asm-generic/vmlinux.lds.h     |    1 +
 include/linux/pci_ids.h               |    3 +
 include/xen/events.h                  |    7 +
 include/xen/grant_table.h             |    4 +
 include/xen/hvm.h                     |   30 +++++
 include/xen/interface/features.h      |    6 +
 include/xen/interface/grant_table.h   |    1 +
 include/xen/interface/hvm/hvm_op.h    |   46 +++++++
 include/xen/interface/hvm/params.h    |   95 +++++++++++++++
 include/xen/platform_pci.h            |   49 ++++++++
 include/xen/xen-ops.h                 |    3 +
 39 files changed, 1138 insertions(+), 66 deletions(-)
 create mode 100644 arch/x86/xen/platform-pci-unplug.c
 create mode 100644 drivers/xen/platform-pci.c
 create mode 100644 include/xen/hvm.h
 create mode 100644 include/xen/interface/hvm/hvm_op.h
 create mode 100644 include/xen/interface/hvm/params.h
 create mode 100644 include/xen/platform_pci.h



-- 
Ian Campbell
Current Noise: Rotting Christ - After Dark I Feel

Old Mother Hubbard lived in a shoe,
She had so many children,
She didn't know what to do.
So she moved to Atlanta.
diff -u linux-2.6-2.6.32/debian/changelog linux-2.6-2.6.32/debian/changelog
--- linux-2.6-2.6.32/debian/changelog
+++ linux-2.6-2.6.32/debian/changelog
@@ -8,7 +8,10 @@
     - mm: keep a guard page below a grow-down stack segment (CVE-2010-2240)
   * Add drm and other relevant changes from stable 2.6.34.4
 
- -- Ben Hutchings <ben@decadent.org.uk>  Thu, 12 Aug 2010 23:20:55 +0100
+  [ Ian Campbell ]
+  * Add Xen PVonHVM driver.
+
+ -- Ian Campbell <Ian.Campbell@citrix.com>  Tue, 17 Aug 2010 16:38:51 +0100
 
 linux-2.6 (2.6.32-20) unstable; urgency=low
 
diff -u linux-2.6-2.6.32/debian/control.md5sum linux-2.6-2.6.32/debian/control.md5sum
--- linux-2.6-2.6.32/debian/control.md5sum
+++ linux-2.6-2.6.32/debian/control.md5sum
@@ -1,5 +1,5 @@
 20393011e88a2f6076ff1037d6a5f7e3  debian/bin/gencontrol.py
-0917c6cd88a82d573b30991793de9e0a  debian/changelog
+9259b41cf4195343338d5d8ebac575b1  debian/changelog
 a7fce16056bed535af9419ca4ff700f8  debian/templates/control.headers.arch.in
 4360172797de60fea4681d641a46e139  debian/templates/control.headers.featureset.in
 05f7ae2c60c6c50068834f68f13cdd0f  debian/templates/control.headers.in
diff -u linux-2.6-2.6.32/debian/config/kernelarch-x86/config linux-2.6-2.6.32/debian/config/kernelarch-x86/config
--- linux-2.6-2.6.32/debian/config/kernelarch-x86/config
+++ linux-2.6-2.6.32/debian/config/kernelarch-x86/config
@@ -1268,6 +1268,7 @@
 CONFIG_XENFS=m
 CONFIG_XEN_COMPAT_XENFS=y
 CONFIG_XEN_SYS_HYPERVISOR=y
+CONFIG_XEN_PLATFORM_PCI=m
 
 ##
 ## file: fs/partitions/Kconfig
diff -u linux-2.6-2.6.32/debian/patches/features/all/xen/pvops.patch linux-2.6-2.6.32/debian/patches/features/all/xen/pvops.patch
--- linux-2.6-2.6.32/debian/patches/features/all/xen/pvops.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvops.patch
@@ -1,35 +1,6 @@
 Patch based on commit 78b55f90e72348e231092dbe3e50ac7414b9e1af of
 git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git.
 
-diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
-index 5f6aa11..3e30e60 100644
---- a/Documentation/kernel-parameters.txt
-+++ b/Documentation/kernel-parameters.txt
-@@ -113,6 +113,7 @@ parameter is applicable:
- 			More X86-64 boot options can be found in
- 			Documentation/x86/x86_64/boot-options.txt .
- 	X86	Either 32bit or 64bit x86 (same as X86-32+X86-64)
-+	XEN	Xen support is enabled
- 
- In addition, the following text indicates that the option:
- 
-@@ -2760,6 +2761,16 @@ and is between 256 and 4096 characters. It is defined in the file
- 	xd=		[HW,XT] Original XT pre-IDE (RLL encoded) disks.
- 	xd_geo=		See header of drivers/block/xd.c.
- 
-+	xen_emul_unplug=		[HW,X86,XEN]
-+			Unplug Xen emulated devices
-+			Format: [unplug0,][unplug1]
-+			ide-disks -- unplug primary master IDE devices
-+			aux-ide-disks -- unplug non-primary-master IDE devices
-+			nics -- unplug network devices
-+			all -- unplug all emulated devices (NICs and IDE disks)
-+			ignore -- continue loading the Xen platform PCI driver even
-+				if the version check failed
-+
- 	xirc2ps_cs=	[NET,PCMCIA]
- 			Format:
- 			<irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
 diff --git a/Documentation/x86/x86_64/boot-options.txt b/Documentation/x86/x86_64/boot-options.txt
 index 29a6ff8..81f9b94 100644
 --- a/Documentation/x86/x86_64/boot-options.txt
@@ -422,16 +393,16 @@
 index 6e90a04..ba4dc7b 100644
 --- a/arch/x86/include/asm/irq_vectors.h
 +++ b/arch/x86/include/asm/irq_vectors.h
-@@ -120,6 +120,12 @@
+@@ -120,9 +120,12 @@
   */
  #define MCE_SELF_VECTOR			0xeb
  
 +#ifdef CONFIG_XEN
-+/* Xen vector callback to receive events in a HVM domain */
-+#define XEN_HVM_EVTCHN_CALLBACK		0xe9
+ /* Xen vector callback to receive events in a HVM domain */
+ #define XEN_HVM_EVTCHN_CALLBACK		0xe9
 +#endif
 +
-+
+ 
  /*
   * First APIC vector available to drivers: (vectors 0x30-0xee) we
   * start at 0x31(0x41) to spread out vectors evenly between priority
@@ -886,19 +857,6 @@
  HYPERVISOR_set_debugreg(int reg, unsigned long value)
  {
  	return _hypercall2(int, set_debugreg, reg, value);
-@@ -417,6 +450,12 @@ HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
- 	return _hypercall2(int, nmi_op, op, arg);
- }
- 
-+static inline unsigned long __must_check
-+HYPERVISOR_hvm_op(int op, void *arg)
-+{
-+       return _hypercall2(unsigned long, hvm_op, op, arg);
-+}
-+
- static inline void
- MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
- {
 @@ -424,6 +463,14 @@ MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
  	mcl->args[0] = set;
  }
@@ -932,7 +890,7 @@
 index d5b7e90..396ff4c 100644
 --- a/arch/x86/include/asm/xen/hypervisor.h
 +++ b/arch/x86/include/asm/xen/hypervisor.h
-@@ -37,31 +37,4 @@
+@@ -37,33 +37,4 @@
  extern struct shared_info *HYPERVISOR_shared_info;
  extern struct start_info *xen_start_info;
  
@@ -944,8 +902,10 @@
 -
 -#ifdef CONFIG_XEN
 -extern enum xen_domain_type xen_domain_type;
+-extern void __init xen_hvm_guest_init(void);
 -#else
 -#define xen_domain_type		XEN_NATIVE
+-#define xen_hvm_guest_init() do { } while (0)
 -#endif
 -
 -#define xen_domain()		(xen_domain_type != XEN_NATIVE)
@@ -1996,12 +1956,14 @@
 index c097e7d..21feb03 100644
 --- a/arch/x86/kernel/entry_32.S
 +++ b/arch/x86/kernel/entry_32.S
-@@ -1088,6 +1088,8 @@ ENTRY(xen_failsafe_callback)
+@@ -1088,9 +1088,8 @@ ENTRY(xen_failsafe_callback)
  .previous
  ENDPROC(xen_failsafe_callback)
  
+-BUILD_INTERRUPT3(xen_hvm_callback_vector, XEN_HVM_EVTCHN_CALLBACK,
+-		xen_evtchn_do_upcall)
 +BUILD_INTERRUPT(xen_hvm_callback_vector, XEN_HVM_EVTCHN_CALLBACK)
-+
+ 
  #endif	/* CONFIG_XEN */
  
  #ifdef CONFIG_FUNCTION_TRACER
@@ -2009,13 +1971,14 @@
 index b5c061f..1bf0911 100644
 --- a/arch/x86/kernel/entry_64.S
 +++ b/arch/x86/kernel/entry_64.S
-@@ -1364,6 +1364,9 @@ ENTRY(xen_failsafe_callback)
+@@ -1364,9 +1364,9 @@ ENTRY(xen_failsafe_callback)
  	CFI_ENDPROC
  END(xen_failsafe_callback)
  
-+apicinterrupt XEN_HVM_EVTCHN_CALLBACK \
+ apicinterrupt XEN_HVM_EVTCHN_CALLBACK \
+-	xen_hvm_callback_vector xen_evtchn_do_upcall
 +	xen_hvm_callback_vector smp_xen_hvm_callback_vector
-+
+ 
  #endif /* CONFIG_XEN */
  
  /*
@@ -2965,6 +2928,14 @@
  
  #include <asm/system.h>
  #include <asm/vsyscall.h>
+@@ -102,7 +102,6 @@
+ 
+ #include <asm/paravirt.h>
+ #include <asm/hypervisor.h>
+-#include <asm/xen/hypervisor.h>
+ 
+ #include <asm/percpu.h>
+ #include <asm/topology.h>
 @@ -966,6 +968,9 @@ void __init setup_arch(char **cmdline_p)
  
  	initmem_init(0, max_pfn);
@@ -2975,14 +2946,6 @@
  #ifdef CONFIG_ACPI_SLEEP
  	/*
  	 * Reserve low memory region for sleep support.
-@@ -1034,6 +1039,7 @@ void __init setup_arch(char **cmdline_p)
- 	probe_nr_irqs_gsi();
- 
- 	kvm_guest_init();
-+	xen_hvm_guest_init();
- 
- 	e820_reserve_resources();
- 	e820_mark_nosave_regions(max_low_pfn);
 diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
 index 4449a4a..d11c5ff 100644
 --- a/arch/x86/kernel/x86_init.c
@@ -3444,6 +3407,18 @@
 index b83e119..3db328f 100644
 --- a/arch/x86/xen/Kconfig
 +++ b/arch/x86/xen/Kconfig
+@@ -13,11 +13,6 @@ config XEN
+ 	  kernel to boot in a paravirtualized environment under the
+ 	  Xen hypervisor.
+ 
+-config XEN_PVHVM
+-	def_bool y
+-	depends on XEN
+-	depends on X86_LOCAL_APIC
+-
+ config XEN_MAX_DOMAIN_MEMORY
+        int "Maximum allowed size of a domain in gigabytes"
+        default 8 if X86_32
 @@ -36,3 +40,40 @@ config XEN_DEBUG_FS
  	help
  	  Enable statistics output and various tuning options in debugfs.
@@ -3489,13 +3464,7 @@
 index 3bb4fc2..13ca65c 100644
 --- a/arch/x86/xen/Makefile
 +++ b/arch/x86/xen/Makefile
-@@ -12,9 +12,12 @@ CFLAGS_mmu.o			:= $(nostackp)
- 
- obj-y		:= enlighten.o setup.o multicalls.o mmu.o irq.o \
- 			time.o xen-asm.o xen-asm_$(BITS).o \
--			grant-table.o suspend.o
-+			grant-table.o suspend.o platform-pci-unplug.o
- 
+@@ -17,4 +17,7 @@
  obj-$(CONFIG_SMP)		+= smp.o
  obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
  obj-$(CONFIG_XEN_DEBUG_FS)	+= debugfs.o
@@ -3548,38 +3517,21 @@
 index 3578688..b20e9c5 100644
 --- a/arch/x86/xen/enlighten.c
 +++ b/arch/x86/xen/enlighten.c
-@@ -11,6 +11,7 @@
-  * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007
-  */
- 
-+#include <linux/cpu.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/smp.h>
-@@ -28,12 +29,15 @@
+@@ -28,5 +29,6 @@
  #include <linux/highmem.h>
  #include <linux/console.h>
  
 +#include <xen/xen.h>
  #include <xen/interface/xen.h>
  #include <xen/interface/version.h>
- #include <xen/interface/physdev.h>
- #include <xen/interface/vcpu.h>
-+#include <xen/interface/memory.h>
- #include <xen/features.h>
- #include <xen/page.h>
-+#include <xen/hvm.h>
- #include <xen/hvc-console.h>
- 
- #include <asm/paravirt.h>
-@@ -53,6 +57,7 @@
+@@ -55,7 +56,6 @@
+ #include <asm/pgtable.h>
  #include <asm/tlbflush.h>
  #include <asm/reboot.h>
+-#include <asm/setup.h>
  #include <asm/stackprotector.h>
-+#include <asm/hypervisor.h>
+ #include <asm/hypervisor.h>
  
- #include "xen-ops.h"
- #include "mmu.h"
 @@ -66,6 +71,11 @@ DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
  enum xen_domain_type xen_domain_type = XEN_NATIVE;
  EXPORT_SYMBOL_GPL(xen_domain_type);
@@ -3592,16 +3544,6 @@
  struct start_info *xen_start_info;
  EXPORT_SYMBOL_GPL(xen_start_info);
  
-@@ -73,6 +83,9 @@ struct shared_info xen_dummy_shared_info;
- 
- void *xen_initial_gdt;
- 
-+__read_mostly int xen_have_vector_callback;
-+EXPORT_SYMBOL_GPL(xen_have_vector_callback);
-+
- /*
-  * Point at some empty memory to start with. We map the real shared_info
-  * page as soon as fixmap is up and running.
 @@ -101,13 +114,17 @@ static void xen_vcpu_setup(int cpu)
  	struct vcpu_info *vcpup;
  
@@ -3769,17 +3711,6 @@
  	default:
  		ret = native_write_msr_safe(msr, low, high);
  	}
-@@ -923,10 +967,6 @@ static const struct pv_init_ops xen_init_ops __initdata = {
- 	.patch = xen_patch,
- };
- 
--static const struct pv_time_ops xen_time_ops __initdata = {
--	.sched_clock = xen_clocksource_read,
--};
--
- static const struct pv_cpu_ops xen_cpu_ops __initdata = {
- 	.cpuid = xen_cpuid,
- 
 @@ -978,6 +1018,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
  	.load_sp0 = xen_load_sp0,
  
@@ -3812,7 +3743,7 @@
  	.shutdown = xen_machine_halt,
  	.crash_shutdown = xen_crash_shutdown,
  	.emergency_restart = xen_emergency_restart,
-@@ -1061,10 +1110,11 @@ asmlinkage void __init xen_start_kernel(void)
+@@ -1061,6 +1110,8 @@ asmlinkage void __init xen_start_kernel(void)
  
  	xen_domain_type = XEN_PV_DOMAIN;
  
@@ -3821,25 +3752,6 @@
  	/* Install Xen paravirt ops */
  	pv_info = xen_info;
  	pv_init_ops = xen_init_ops;
--	pv_time_ops = xen_time_ops;
- 	pv_cpu_ops = xen_cpu_ops;
- 	pv_apic_ops = xen_apic_ops;
- 
-@@ -1072,13 +1122,7 @@ asmlinkage void __init xen_start_kernel(void)
- 	x86_init.oem.arch_setup = xen_arch_setup;
- 	x86_init.oem.banner = xen_banner;
- 
--	x86_init.timers.timer_init = xen_time_init;
--	x86_init.timers.setup_percpu_clockev = x86_init_noop;
--	x86_cpuinit.setup_percpu_clockev = x86_init_noop;
--
--	x86_platform.calibrate_tsc = xen_tsc_khz;
--	x86_platform.get_wallclock = xen_get_wallclock;
--	x86_platform.set_wallclock = xen_set_wallclock;
-+	xen_init_time_ops();
- 
- 	/*
- 	 * Set up some pagetable state before starting to set any ptes.
 @@ -1116,6 +1160,10 @@ asmlinkage void __init xen_start_kernel(void)
  	 */
  	xen_setup_stackprotector();
@@ -3900,131 +3812,47 @@
  	}
  
  	xen_raw_console_write("about to get started...\n");
-@@ -1197,3 +1266,124 @@ asmlinkage void __init xen_start_kernel(void)
- 	x86_64_start_reservations((char *)__pa_symbol(&boot_params));
- #endif
- }
-+
-+static uint32_t xen_cpuid_base(void)
-+{
-+	uint32_t base, eax, ebx, ecx, edx;
-+	char signature[13];
-+
-+	for (base = 0x40000000; base < 0x40010000; base += 0x100) {
-+		cpuid(base, &eax, &ebx, &ecx, &edx);
-+		*(uint32_t *)(signature + 0) = ebx;
-+		*(uint32_t *)(signature + 4) = ecx;
-+		*(uint32_t *)(signature + 8) = edx;
-+		signature[12] = 0;
-+
-+		if (!strcmp("XenVMMXenVMM", signature) && ((eax - base) >= 2))
-+			return base;
-+	}
-+
-+	return 0;
-+}
-+
-+static int init_hvm_pv_info(int *major, int *minor)
-+{
-+	uint32_t eax, ebx, ecx, edx, pages, msr, base;
-+	u64 pfn;
-+
-+	base = xen_cpuid_base();
+@@ -1186,6 +1255,9 @@ static int init_hvm_pv_info(int *major, 
+ 	u64 pfn;
+ 
+ 	base = xen_cpuid_base();
 +	if (!base)
 +		return -EINVAL;
 +
-+	cpuid(base + 1, &eax, &ebx, &ecx, &edx);
-+
-+	*major = eax >> 16;
-+	*minor = eax & 0xffff;
-+	printk(KERN_INFO "Xen version %d.%d.\n", *major, *minor);
-+
-+	cpuid(base + 2, &pages, &msr, &ecx, &edx);
-+
-+	pfn = __pa(hypercall_page);
-+	wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
-+
-+	xen_setup_features();
-+
-+	pv_info = xen_info;
-+	pv_info.kernel_rpl = 0;
-+
-+	xen_domain_type = XEN_HVM_DOMAIN;
-+
-+	return 0;
-+}
-+
-+void xen_hvm_init_shared_info(void)
-+{
-+	int cpu;
-+	struct xen_add_to_physmap xatp;
-+	static struct shared_info *shared_info_page = 0;
-+
-+	if (!shared_info_page)
-+		shared_info_page = (struct shared_info *) alloc_bootmem_pages(PAGE_SIZE);
-+	xatp.domid = DOMID_SELF;
-+	xatp.idx = 0;
-+	xatp.space = XENMAPSPACE_shared_info;
-+	xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
-+	if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
-+		BUG();
-+
-+	HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
-+
-+	/* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
-+	 * page, we use it in the event channel upcall and in some pvclock
-+	 * related functions. We don't need the vcpu_info placement
-+	 * optimizations because we don't use any pv_mmu or pv_irq op on
-+	 * HVM.
-+	 * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is
-+	 * online but xen_hvm_init_shared_info is run at resume time too and
-+	 * in that case multiple vcpus might be online. */
-+	for_each_online_cpu(cpu) {
-+		per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
-+	}
-+}
-+
-+static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
-+				    unsigned long action, void *hcpu)
-+{
-+	int cpu = (long)hcpu;
-+	switch (action) {
-+	case CPU_UP_PREPARE:
-+		per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
-+		break;
-+	default:
-+		break;
-+	}
-+	return NOTIFY_OK;
-+}
-+
-+static struct notifier_block __cpuinitdata xen_hvm_cpu_notifier = {
-+	.notifier_call	= xen_hvm_cpu_notify,
-+};
-+
-+void __init xen_hvm_guest_init(void)
-+{
-+	int r;
-+	int major, minor;
-+
+ 	cpuid(base + 1, &eax, &ebx, &ecx, &edx);
+ 
+ 	*major = eax >> 16;
+@@ -1305,7 +1305,6 @@ void xen_hvm_init_shared_info(void)
+ 
+ 	if (!shared_info_page)
+ 		shared_info_page = (struct shared_info *) alloc_bootmem_pages(PAGE_SIZE);
+-
+ 	xatp.domid = DOMID_SELF;
+ 	xatp.idx = 0;
+ 	xatp.space = XENMAPSPACE_shared_info;
+@@ -1310,7 +1330,6 @@ void xen_hvm_init_shared_info(void)
+ 	}
+ }
+ 
+-#ifdef CONFIG_XEN_PVHVM
+ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
+ 				    unsigned long action, void *hcpu)
+ {
+@@ -1324,6 +1353,9 @@
+ 	int r;
+ 	int major, minor;
+ 
 +	if (xen_pv_domain())
 +		return;
 +
-+	r = init_hvm_pv_info(&major, &minor);
-+	if (r < 0)
-+		return;
-+
-+	xen_hvm_init_shared_info();
-+
-+	if (xen_feature(XENFEAT_hvm_callback_vector))
-+		xen_have_vector_callback = 1;
-+	register_cpu_notifier(&xen_hvm_cpu_notifier);
-+	xen_unplug_emulated_devices();
-+	have_vcpu_info_placement = 0;
-+	x86_init.irqs.intr_init = xen_init_IRQ;
-+	xen_hvm_init_time_ops();
-+	xen_hvm_init_mmu_ops();
-+}
+ 	r = init_hvm_pv_info(&major, &minor);
+ 	if (r < 0)
+ 		return;
+@@ -1372,4 +1371,3 @@ void __init xen_hvm_guest_init(void)
+ 	xen_hvm_init_time_ops();
+ 	xen_hvm_init_mmu_ops();
+ }
+-#endif
 diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
 index 350a3de..74e284f 100644
 --- a/arch/x86/xen/mmu.c
@@ -4037,7 +3865,7 @@
  #include <linux/module.h>
  
  #include <asm/pgtable.h>
-@@ -50,14 +51,19 @@
+@@ -50,7 +51,10 @@
  #include <asm/mmu_context.h>
  #include <asm/setup.h>
  #include <asm/paravirt.h>
@@ -4048,10 +3876,9 @@
  
  #include <asm/xen/hypercall.h>
  #include <asm/xen/hypervisor.h>
- 
- #include <xen/page.h>
+@@ -59,6 +63,7 @@
  #include <xen/interface/xen.h>
-+#include <xen/interface/hvm/hvm_op.h>
+ #include <xen/interface/hvm/hvm_op.h>
  #include <xen/interface/version.h>
 +#include <xen/interface/memory.h>
  #include <xen/hvc-console.h>
@@ -4483,7 +4310,7 @@
  static __init void xen_post_allocator_init(void)
  {
  	pv_mmu_ops.set_pte = xen_set_pte;
-@@ -1960,6 +2205,301 @@ void __init xen_init_mmu_ops(void)
+@@ -1960,8 +2205,270 @@ void __init xen_init_mmu_ops(void)
  	x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start;
  	x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done;
  	pv_mmu_ops = xen_mmu_ops;
@@ -4749,52 +4576,20 @@
 +	flush_tlb_all();
 +
 +	return err;
-+}
+ }
 +EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
-+
-+static void xen_hvm_exit_mmap(struct mm_struct *mm)
-+{
-+	struct xen_hvm_pagetable_dying a;
-+	int rc;
-+
-+	a.domid = DOMID_SELF;
-+	a.gpa = __pa(mm->pgd);
-+	rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
-+	WARN_ON_ONCE(rc < 0);
-+}
-+
-+static int is_pagetable_dying_supported(void)
-+{
-+	struct xen_hvm_pagetable_dying a;
-+	int rc = 0;
-+
-+	a.domid = DOMID_SELF;
-+	a.gpa = 0x00;
-+	rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
-+	if (rc < 0) {
-+		printk(KERN_DEBUG "HVMOP_pagetable_dying not supported\n");
-+		return 0;
-+	}
-+	return 1;
-+}
-+
-+void __init xen_hvm_init_mmu_ops(void)
-+{
-+	if (is_pagetable_dying_supported())
-+		pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap;
+ 
+-#ifdef CONFIG_XEN_PVHVM
+ static void xen_hvm_exit_mmap(struct mm_struct *mm)
+ {
+@@ -2501,7 +2501,6 @@ void __init xen_hvm_init_mmu_ops(void)
+ 	if (is_pagetable_dying_supported())
+ 		pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap;
  }
+-#endif
  
  #ifdef CONFIG_XEN_DEBUG_FS
-diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h
-index 5fe6bc7..fa938c4 100644
---- a/arch/x86/xen/mmu.h
-+++ b/arch/x86/xen/mmu.h
-@@ -60,4 +60,5 @@ void  xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
- unsigned long xen_read_cr2_direct(void);
- 
- extern void xen_init_mmu_ops(void);
-+extern void xen_hvm_init_mmu_ops(void);
- #endif	/* _XEN_MMU_H */
+ 
 diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c
 new file mode 100644
 index 0000000..4d55524
@@ -5156,146 +4951,21 @@
 +}
 +EXPORT_SYMBOL(xen_unregister_device_domain_owner);
 diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c
-new file mode 100644
-index 0000000..2f7f3fb
---- /dev/null
+--- a/arch/x86/xen/platform-pci-unplug.c
 +++ b/arch/x86/xen/platform-pci-unplug.c
-@@ -0,0 +1,135 @@
-+/******************************************************************************
-+ * platform-pci-unplug.c
-+ *
-+ * Xen platform PCI device driver
-+ * Copyright (c) 2010, Citrix
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-+ * Place - Suite 330, Boston, MA 02111-1307 USA.
-+ *
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+
-+#include <xen/platform_pci.h>
-+
-+#define XEN_PLATFORM_ERR_MAGIC -1
-+#define XEN_PLATFORM_ERR_PROTOCOL -2
-+#define XEN_PLATFORM_ERR_BLACKLIST -3
-+
-+/* store the value of xen_emul_unplug after the unplug is done */
-+int xen_platform_pci_unplug;
-+EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
-+static int xen_emul_unplug;
-+
-+static int __init check_platform_magic(void)
-+{
-+	short magic;
-+	char protocol;
-+
-+	magic = inw(XEN_IOPORT_MAGIC);
-+	if (magic != XEN_IOPORT_MAGIC_VAL) {
-+		printk(KERN_ERR "Xen Platform PCI: unrecognised magic value\n");
-+		return XEN_PLATFORM_ERR_MAGIC;
-+	}
-+
-+	protocol = inb(XEN_IOPORT_PROTOVER);
-+
-+	printk(KERN_DEBUG "Xen Platform PCI: I/O protocol version %d\n",
-+			protocol);
-+
-+	switch (protocol) {
-+	case 1:
-+		outw(XEN_IOPORT_LINUX_PRODNUM, XEN_IOPORT_PRODNUM);
-+		outl(XEN_IOPORT_LINUX_DRVVER, XEN_IOPORT_DRVVER);
-+		if (inw(XEN_IOPORT_MAGIC) != XEN_IOPORT_MAGIC_VAL) {
-+			printk(KERN_ERR "Xen Platform: blacklisted by host\n");
-+			return XEN_PLATFORM_ERR_BLACKLIST;
-+		}
-+		break;
-+	default:
-+		printk(KERN_WARNING "Xen Platform PCI: unknown I/O protocol version");
-+		return XEN_PLATFORM_ERR_PROTOCOL;
-+	}
-+
-+	return 0;
-+}
-+
-+void __init xen_unplug_emulated_devices(void)
-+{
-+	int r;
-+
-+	/* check the version of the xen platform PCI device */
-+	r = check_platform_magic();
-+	/* If the version matches enable the Xen platform PCI driver.
-+	 * Also enable the Xen platform PCI driver if the version is really old
-+	 * and the user told us to ignore it. */
-+	if (r && !(r == XEN_PLATFORM_ERR_MAGIC &&
-+			(xen_emul_unplug & XEN_UNPLUG_IGNORE)))
-+		return;
-+	/* Set the default value of xen_emul_unplug depending on whether or
-+	 * not the Xen PV frontends and the Xen platform PCI driver have
-+	 * been compiled for this kernel (modules or built-in are both OK). */
-+	if (!xen_emul_unplug) {
-+		if (xen_must_unplug_nics()) {
-+			printk(KERN_INFO "Netfront and the Xen platform PCI driver have "
-+					"been compiled for this kernel: unplug emulated NICs.\n");
-+			xen_emul_unplug |= XEN_UNPLUG_ALL_NICS;
-+		}
-+		if (xen_must_unplug_disks()) {
-+			printk(KERN_INFO "Blkfront and the Xen platform PCI driver have "
-+					"been compiled for this kernel: unplug emulated disks.\n"
-+					"You might have to change the root device\n"
-+					"from /dev/hd[a-d] to /dev/xvd[a-d]\n"
-+					"in your root= kernel command line option\n");
-+			xen_emul_unplug |= XEN_UNPLUG_ALL_IDE_DISKS;
-+		}
-+	}
-+	/* Now unplug the emulated devices */
-+	if (!(xen_emul_unplug & XEN_UNPLUG_IGNORE))
-+		outw(xen_emul_unplug, XEN_IOPORT_UNPLUG);
-+	xen_platform_pci_unplug = xen_emul_unplug;
-+}
-+
-+static int __init parse_xen_emul_unplug(char *arg)
-+{
-+	char *p, *q;
-+	int l;
-+
-+	for (p = arg; p; p = q) {
-+		q = strchr(p, ',');
-+		if (q) {
-+			l = q - p;
-+			q++;
-+		} else {
-+			l = strlen(p);
-+		}
-+		if (!strncmp(p, "all", l))
-+			xen_emul_unplug |= XEN_UNPLUG_ALL;
-+		else if (!strncmp(p, "ide-disks", l))
-+			xen_emul_unplug |= XEN_UNPLUG_ALL_IDE_DISKS;
-+		else if (!strncmp(p, "aux-ide-disks", l))
-+			xen_emul_unplug |= XEN_UNPLUG_AUX_IDE_DISKS;
-+		else if (!strncmp(p, "nics", l))
-+			xen_emul_unplug |= XEN_UNPLUG_ALL_NICS;
-+		else if (!strncmp(p, "ignore", l))
-+			xen_emul_unplug |= XEN_UNPLUG_IGNORE;
-+		else
-+			printk(KERN_WARNING "unrecognised option '%s' "
-+				 "in parameter 'xen_emul_unplug'\n", p);
-+	}
-+	return 0;
-+}
-+early_param("xen_emul_unplug", parse_xen_emul_unplug);
+@@ -32,7 +32,6 @@
+ /* store the value of xen_emul_unplug after the unplug is done */
+ int xen_platform_pci_unplug;
+ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
+-#ifdef CONFIG_XEN_PVHVM
+ static int xen_emul_unplug;
+ 
+ static int __init check_platform_magic(void)
+@@ -134,4 +133,3 @@ static int __init parse_xen_emul_unplug(
+ 	return 0;
+ }
+ early_param("xen_emul_unplug", parse_xen_emul_unplug);
+-#endif
 diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
 index ad0047f..f008629 100644
 --- a/arch/x86/xen/setup.c
@@ -5514,65 +5184,14 @@
  	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
  
  	/* make sure interrupts start blocked */
-diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
-index a9c6611..1d789d5 100644
---- a/arch/x86/xen/suspend.c
-+++ b/arch/x86/xen/suspend.c
-@@ -26,6 +26,18 @@ void xen_pre_suspend(void)
- 		BUG();
- }
- 
-+void xen_hvm_post_suspend(int suspend_cancelled)
-+{
-+	int cpu;
-+	xen_hvm_init_shared_info();
-+	xen_callback_vector();
-+	if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
-+		for_each_online_cpu(cpu) {
-+			xen_setup_runstate_info(cpu);
-+		}
-+	}
-+}
-+
- void xen_post_suspend(int suspend_cancelled)
- {
- 	xen_build_mfn_list_list();
 diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
 index 9d1f853..ca8efdb 100644
 --- a/arch/x86/xen/time.c
 +++ b/arch/x86/xen/time.c
-@@ -19,6 +19,7 @@
- #include <asm/xen/hypercall.h>
- 
- #include <xen/events.h>
-+#include <xen/features.h>
- #include <xen/interface/xen.h>
- #include <xen/interface/vcpu.h>
- 
-@@ -191,7 +193,7 @@ unsigned long long xen_sched_clock(void)
+@@ -238,9 +240,23 @@
  }
  
- /* Get the TSC speed from Xen */
--unsigned long xen_tsc_khz(void)
-+static unsigned long xen_tsc_khz(void)
- {
- 	struct pvclock_vcpu_time_info *info =
- 		&HYPERVISOR_shared_info->vcpu_info[0].time;
-@@ -229,7 +231,7 @@ static void xen_read_wallclock(struct timespec *ts)
- 	put_cpu_var(xen_vcpu);
- }
- 
--unsigned long xen_get_wallclock(void)
-+static unsigned long xen_get_wallclock(void)
- {
- 	struct timespec ts;
- 
-@@ -237,10 +239,24 @@ unsigned long xen_get_wallclock(void)
- 	return ts.tv_sec;
- }
- 
--int xen_set_wallclock(unsigned long now)
-+static int xen_set_wallclock(unsigned long now)
+ static int xen_set_wallclock(unsigned long now)
  {
 +	struct xen_platform_op op;
 +	int rc;
@@ -5603,65 +5222,41 @@
  }
  
  void xen_teardown_timer(int cpu)
-@@ -472,7 +490,7 @@ void xen_timer_resume(void)
+@@ -450,10 +450,6 @@ void xen_timer_resume(void)
  	}
  }
  
--__init void xen_time_init(void)
-+static __init void xen_time_init(void)
+-static const struct pv_time_ops xen_time_ops __initdata = {
+-	.sched_clock = xen_clocksource_read,
+-};
+-
+ static __init void xen_time_init(void)
  {
  	int cpu = smp_processor_id();
- 
-@@ -496,3 +514,49 @@ __init void xen_time_init(void)
- 	xen_setup_timer(cpu);
+@@ -479,6 +475,10 @@ static __init void xen_time_init(void)
  	xen_setup_cpu_clockevents();
  }
-+
+ 
 +static const struct pv_time_ops xen_time_ops __initdata = {
 +       .sched_clock = xen_clocksource_read,
 +};
 +
-+__init void xen_init_time_ops(void)
-+{
-+	pv_time_ops = xen_time_ops;
-+
-+	x86_init.timers.timer_init = xen_time_init;
-+	x86_init.timers.setup_percpu_clockev = x86_init_noop;
-+	x86_cpuinit.setup_percpu_clockev = x86_init_noop;
-+
-+	x86_platform.calibrate_tsc = xen_tsc_khz;
-+	x86_platform.get_wallclock = xen_get_wallclock;
-+	x86_platform.set_wallclock = xen_set_wallclock;
-+}
-+
-+static void xen_hvm_setup_cpu_clockevents(void)
-+{
-+	int cpu = smp_processor_id();
-+	xen_setup_runstate_info(cpu);
-+	xen_setup_timer(cpu);
-+	xen_setup_cpu_clockevents();
-+}
-+
-+__init void xen_hvm_init_time_ops(void)
-+{
-+	/* vector callback is needed otherwise we cannot receive interrupts
-+	 * on cpu > 0 */
-+	if (!xen_have_vector_callback && num_present_cpus() > 1)
-+		return;
-+	if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
-+		printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
-+				"disable pv timer\n");
-+		return;
-+	}
-+
-+	pv_time_ops = xen_time_ops;
-+	x86_init.timers.setup_percpu_clockev = xen_time_init;
-+	x86_cpuinit.setup_percpu_clockev = xen_hvm_setup_cpu_clockevents;
-+
-+	x86_platform.calibrate_tsc = xen_tsc_khz;
-+	x86_platform.get_wallclock = xen_get_wallclock;
-+	x86_platform.set_wallclock = xen_set_wallclock;
-+}
+ __init void xen_init_time_ops(void)
+ {
+ 	pv_time_ops = xen_time_ops;
+@@ -492,7 +492,6 @@ __init void xen_init_time_ops(void)
+ 	x86_platform.set_wallclock = xen_set_wallclock;
+ }
+ 
+-#ifdef CONFIG_XEN_PVHVM
+ static void xen_hvm_setup_cpu_clockevents(void)
+ {
+ 	int cpu = smp_processor_id();
+@@ -520,4 +520,3 @@ __init void xen_hvm_init_time_ops(void)
+ 	x86_platform.get_wallclock = xen_get_wallclock;
+ 	x86_platform.set_wallclock = xen_set_wallclock;
+ }
+-#endif
 diff --git a/arch/x86/xen/vga.c b/arch/x86/xen/vga.c
 new file mode 100644
 index 0000000..1cd7f4d
@@ -5749,31 +5344,6 @@
  
  char * __init xen_memory_setup(void);
  void __init xen_arch_setup(void);
-@@ -38,6 +41,10 @@ void xen_enable_sysenter(void);
- void xen_enable_syscall(void);
- void xen_vcpu_restore(void);
- 
-+void xen_callback_vector(void);
-+void xen_hvm_init_shared_info(void);
-+void __init xen_unplug_emulated_devices(void);
-+
- void __init xen_build_dynamic_phys_to_machine(void);
- 
- void xen_init_irq_ops(void);
-@@ -46,11 +53,8 @@ void xen_setup_runstate_info(int cpu);
- void xen_teardown_timer(int cpu);
- cycle_t xen_clocksource_read(void);
- void xen_setup_cpu_clockevents(void);
--unsigned long xen_tsc_khz(void);
--void __init xen_time_init(void);
--unsigned long xen_get_wallclock(void);
--int xen_set_wallclock(unsigned long time);
--unsigned long long xen_sched_clock(void);
-+void __init xen_init_time_ops(void);
-+void __init xen_hvm_init_time_ops(void);
- 
- irqreturn_t xen_debug_interrupt(int irq, void *dev_id);
- 
 @@ -82,6 +86,23 @@ static inline void xen_uninit_lock_cpu(int cpu)
  }
  #endif
@@ -6790,19 +6360,13 @@
 index b8578bb..89adac5 100644
 --- a/drivers/block/xen-blkfront.c
 +++ b/drivers/block/xen-blkfront.c
-@@ -42,10 +42,12 @@
+@@ -42,5 +42,6 @@
  #include <linux/module.h>
  #include <linux/scatterlist.h>
  
 +#include <xen/xen.h>
  #include <xen/xenbus.h>
  #include <xen/grant_table.h>
- #include <xen/events.h>
- #include <xen/page.h>
-+#include <xen/platform_pci.h>
- 
- #include <xen/interface/grant_table.h>
- #include <xen/interface/io/blkif.h>
 @@ -76,6 +78,7 @@ static const struct block_device_operations xlvbd_block_fops;
   */
  struct blkfront_info
@@ -6976,10 +6540,35 @@
  /**
   * Entry point to this code when a new device is created.  Allocate the basic
   * structures and the ring buffer for communication with the backend, and
-@@ -736,12 +825,29 @@ static int blkfront_probe(struct xenbus_device *dev,
+@@ -737,34 +737,21 @@ static int blkfront_probe(struct xenbus_
  		}
  	}
  
+-	if (xen_hvm_domain()) {
+-		char *type;
+-		int len;
+-		/* no unplug has been done: do not hook devices != xen vbds */
+-		if (xen_platform_pci_unplug & XEN_UNPLUG_IGNORE) {
+-			int major;
+-
+-			if (!VDEV_IS_EXTENDED(vdevice))
+-				major = BLKIF_MAJOR(vdevice);
+-			else
+-				major = XENVBD_MAJOR;
+-
+-			if (major != XENVBD_MAJOR) {
+-				printk(KERN_INFO
+-						"%s: HVM does not support vbd %d as xen block device\n",
+-						__FUNCTION__, vdevice);
+-				return -ENODEV;
+-			}
+-		}
+-		/* do not create a PV cdrom device if we are an HVM guest */
+-		type = xenbus_read(XBT_NIL, dev->nodename, "device-type", &len);
+-		if (IS_ERR(type))
+-			return -ENODEV;
+-		if (strncmp(type, "cdrom", 5) == 0) {
+-			kfree(type);
 +	/* no unplug has been done: do not hook devices != xen vbds */
 +	if (xen_hvm_domain() && (xen_platform_pci_unplug & XEN_UNPLUG_IGNORE)) {
 +		int major;
@@ -6993,12 +6582,13 @@
 +			printk(KERN_INFO
 +					"%s: HVM does not support vbd %d as xen block device\n",
 +					__FUNCTION__, vdevice);
-+			return -ENODEV;
-+		}
-+	}
+ 			return -ENODEV;
+ 		}
+-		kfree(type);
+ 	}
  	info = kzalloc(sizeof(*info), GFP_KERNEL);
  	if (!info) {
- 		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+@@ -742,6 +847,7 @@
  		return -ENOMEM;
  	}
  
@@ -7771,7 +7361,7 @@
  
  static int __init xenkbd_init(void)
  {
--	if (!xen_domain())
+-	if (!xen_pv_domain())
 +	if (!xen_domain() || xen_hvm_domain())
  		return -ENODEV;
  
@@ -9740,7 +9330,7 @@
  
  static int __init xenfb_init(void)
  {
--	if (!xen_domain())
+-	if (!xen_pv_domain())
 +	if (!xen_domain() || xen_hvm_domain())
  		return -ENODEV;
  
@@ -9860,13 +9450,11 @@
  config XENFS
  	tristate "Xen filesystem"
  	depends on XEN
-@@ -60,4 +164,37 @@ config XEN_SYS_HYPERVISOR
+@@ -60,7 +164,30 @@ config XEN_SYS_HYPERVISOR
           Create entries under /sys/hypervisor describing the Xen
  	 hypervisor environment.  When running native or in another
  	 virtual environment, /sys/hypervisor will still be present,
--	 but will have no xen contents.
-\ No newline at end of file
-+	 but will have no xen contents.
+ 	 but will have no xen contents.
 +
 +config XEN_MCE
 +       def_bool y
@@ -9890,21 +9478,23 @@
 +	   tristate
 +	   depends on XEN_DOM0 && ACPI_PROCESSOR && CPU_FREQ
 +	   default y
-+
-+config XEN_PLATFORM_PCI
-+	tristate "xen platform pci device driver"
+ 
+ config XEN_PLATFORM_PCI
+ 	tristate "xen platform pci device driver"
+@@ -191,7 +191,7 @@ config ACPI_PROCESSOR_XEN
+ 
+ config XEN_PLATFORM_PCI
+ 	tristate "xen platform pci device driver"
+-	depends on XEN_PVHVM
 +	depends on XEN
-+	default m
-+	help
-+	  Driver for the Xen PCI Platform device: it is responsible for
-+	  initializing xenbus and grant_table when running in a Xen HVM
-+	  domain. As a consequence this driver is required to run any Xen PV
-+	  frontend on Xen HVM.
+ 	default m
+ 	help
+ 	  Driver for the Xen PCI Platform device: it is responsible for
 diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
 index 7c28434..ef1ea63 100644
 --- a/drivers/xen/Makefile
 +++ b/drivers/xen/Makefile
-@@ -1,12 +1,27 @@
+@@ -1,13 +1,27 @@
 -obj-y	+= grant-table.o features.o events.o manage.o
 +obj-y	+= grant-table.o features.o events.o manage.o biomerge.o pcpu.o
  obj-y	+= xenbus/
@@ -9918,7 +9508,6 @@
 -obj-$(CONFIG_XEN_DEV_EVTCHN)	+= evtchn.o
 -obj-$(CONFIG_XENFS)		+= xenfs/
 -obj-$(CONFIG_XEN_SYS_HYPERVISOR)	+= sys-hypervisor.o
-\ No newline at end of file
 +obj-$(CONFIG_PCI)			+= pci.o
 +obj-$(CONFIG_HOTPLUG_CPU)		+= cpu_hotplug.o
 +obj-$(CONFIG_XEN_XENCOMM)		+= xencomm.o
@@ -9936,7 +9525,7 @@
 +obj-$(CONFIG_XEN_S3)           += acpi.o
 +obj-$(CONFIG_ACPI_PROCESSOR_XEN) += acpi_processor.o
 +obj-$(CONFIG_ACPI_HOTPLUG_MEMORY)  += xen_acpi_memhotplug.o
-+obj-$(CONFIG_XEN_PLATFORM_PCI)	+= platform-pci.o
+ obj-$(CONFIG_XEN_PLATFORM_PCI)	+= platform-pci.o
 +
 +xen-evtchn-y				:= evtchn.o
 +xen-gntdev-y				:= gntdev.o
@@ -15351,7 +14940,7 @@
   *
   * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007
   */
-@@ -27,18 +27,31 @@
+@@ -27,22 +27,31 @@
  #include <linux/module.h>
  #include <linux/string.h>
  #include <linux/bootmem.h>
@@ -15360,7 +14949,7 @@
 +#include <linux/pci.h>
 +#include <linux/msi.h>
  
-+#include <asm/desc.h>
+ #include <asm/desc.h>
  #include <asm/ptrace.h>
  #include <asm/irq.h>
  #include <asm/idle.h>
@@ -15371,13 +14960,13 @@
 +#include <asm/xen/pci.h>
  
 +#include <xen/xen.h>
-+#include <xen/hvm.h>
+ #include <xen/hvm.h>
  #include <xen/xen-ops.h>
  #include <xen/events.h>
  #include <xen/interface/xen.h>
  #include <xen/interface/event_channel.h>
-+#include <xen/interface/hvm/hvm_op.h>
-+#include <xen/interface/hvm/params.h>
+ #include <xen/interface/hvm/hvm_op.h>
+ #include <xen/interface/hvm/params.h>
 +
 +#include "../pci/msi.h"
  
@@ -15460,7 +15049,7 @@
  static inline unsigned long active_evtchns(unsigned int cpu,
  					   struct shared_info *sh,
  					   unsigned int idx)
-@@ -329,27 +360,372 @@ static void unmask_evtchn(int port)
+@@ -329,36 +360,372 @@ static void unmask_evtchn(int port)
  	put_cpu();
  }
  
@@ -15482,23 +15071,23 @@
 +	int start = get_nr_hw_irqs();
 +	void *chip_data;
  
--	for (irq = 0; irq < nr_irqs; irq++)
+-	for (irq = 0; irq < nr_irqs; irq++) {
 +	if (start == nr_irqs)
 +		goto no_irqs;
 +
 +	/* nr_irqs is a magic value. Must not use it.*/
 +	for (irq = nr_irqs-1; irq > start; irq--) {
-+		desc = irq_to_desc(irq);
-+		/* only 0->15 have init'd desc; handle irq > 16 */
-+		if (desc == NULL)
-+			break;
-+		if (desc->chip == &no_irq_chip)
-+			break;
-+		if (desc->chip != &xen_dynamic_chip)
-+			continue;
+ 		desc = irq_to_desc(irq);
+ 		/* only 0->15 have init'd desc; handle irq > 16 */
+ 		if (desc == NULL)
+ 			break;
+ 		if (desc->chip == &no_irq_chip)
+ 			break;
+ 		if (desc->chip != &xen_dynamic_chip)
+ 			continue;
  		if (irq_info[irq].type == IRQT_UNBOUND)
  			break;
-+	}
+ 	}
  
 -	if (irq == nr_irqs)
 -		panic("No available IRQ to bind to: increase nr_irqs!\n");
@@ -15511,7 +15100,8 @@
  
 +	/* save and restore chip_data */
 +	chip_data = desc->chip_data;
- 	dynamic_irq_init(irq);
+-	dynamic_irq_init_keep_chip_data(irq);
++	dynamic_irq_init(irq);
 +	desc->chip_data = chip_data;
  
  	return irq;
@@ -15891,25 +15481,6 @@
  int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
  			    irq_handler_t handler,
  			    unsigned long irqflags, const char *devname, void *dev_id)
-@@ -616,17 +1031,13 @@ static DEFINE_PER_CPU(unsigned, xed_nesting_count);
-  * a bitset of words which contain pending event bits.  The second
-  * level is a bitset of pending events themselves.
-  */
--void xen_evtchn_do_upcall(struct pt_regs *regs)
-+static void __xen_evtchn_do_upcall(struct pt_regs *regs)
- {
- 	int cpu = get_cpu();
--	struct pt_regs *old_regs = set_irq_regs(regs);
- 	struct shared_info *s = HYPERVISOR_shared_info;
- 	struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
-  	unsigned count;
- 
--	exit_idle();
--	irq_enter();
--
- 	do {
- 		unsigned long pending_words;
- 
 @@ -649,9 +1060,13 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
  				int bit_idx = __ffs(pending_bits);
  				int port = (word_idx * BITS_PER_LONG) + bit_idx;
@@ -15926,53 +15497,15 @@
  			}
  		}
  
-@@ -659,14 +1074,32 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
- 
- 		count = __get_cpu_var(xed_nesting_count);
- 		__get_cpu_var(xed_nesting_count) = 0;
--	} while(count != 1);
-+	} while (count != 1 || vcpu_info->evtchn_upcall_pending);
- 
- out:
-+
-+	put_cpu();
-+}
-+
-+void xen_evtchn_do_upcall(struct pt_regs *regs)
-+{
-+	struct pt_regs *old_regs = set_irq_regs(regs);
-+
-+	exit_idle();
-+	irq_enter();
-+
-+	__xen_evtchn_do_upcall(regs);
-+
- 	irq_exit();
- 	set_irq_regs(old_regs);
-+}
- 
--	put_cpu();
-+void xen_hvm_evtchn_do_upcall(void)
-+{
+@@ -669,6 +1097,7 @@
+ void xen_hvm_evtchn_do_upcall(void)
+ {
+-	__xen_evtchn_do_upcall(get_irq_regs());
 +	struct pt_regs *regs = get_irq_regs();
 +	__xen_evtchn_do_upcall(regs);
  }
-+EXPORT_SYMBOL_GPL(xen_hvm_evtchn_do_upcall);
+ EXPORT_SYMBOL_GPL(xen_hvm_evtchn_do_upcall);
  
- /* Rebind a new event channel to an existing irq. */
- void rebind_evtchn_irq(int evtchn, int irq)
-@@ -703,7 +1136,10 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
- 	struct evtchn_bind_vcpu bind_vcpu;
- 	int evtchn = evtchn_from_irq(irq);
- 
--	if (!VALID_EVTCHN(evtchn))
-+	/* events delivered via platform PCI interrupts are always
-+	 * routed to vcpu 0 */
-+	if (!VALID_EVTCHN(evtchn) ||
-+		(xen_hvm_domain() && !xen_have_vector_callback))
- 		return -1;
- 
- 	/* Send future instances of this interrupt to other vcpu. */
 @@ -855,7 +1291,7 @@ void xen_clear_irq_pending(int irq)
  	if (VALID_EVTCHN(evtchn))
  		clear_evtchn(evtchn);
@@ -16029,7 +15562,7 @@
  
  void xen_irq_resume(void)
  {
-@@ -928,13 +1384,85 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
+@@ -928,17 +1384,51 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
  	.retrigger	= retrigger_dynirq,
  };
  
@@ -16053,16 +15586,17 @@
 +	.retrigger	= retrigger_dynirq,
 +};
 +
-+int xen_set_callback_via(uint64_t via)
-+{
-+	struct xen_hvm_param a;
-+	a.domid = DOMID_SELF;
-+	a.index = HVM_PARAM_CALLBACK_IRQ;
-+	a.value = via;
-+	return HYPERVISOR_hvm_op(HVMOP_set_param, &a);
-+}
-+EXPORT_SYMBOL_GPL(xen_set_callback_via);
-+
+ int xen_set_callback_via(uint64_t via)
+ {
+ 	struct xen_hvm_param a;
+ 	a.domid = DOMID_SELF;
+ 	a.index = HVM_PARAM_CALLBACK_IRQ;
+ 	a.value = via;
+ 	return HYPERVISOR_hvm_op(HVMOP_set_param, &a);
+ }
+ EXPORT_SYMBOL_GPL(xen_set_callback_via);
+ 
+-#ifdef CONFIG_XEN_PVHVM
 +void smp_xen_hvm_callback_vector(struct pt_regs *regs)
 +{
 +	struct pt_regs *old_regs = set_irq_regs(regs);
@@ -16078,31 +15612,26 @@
 +	set_irq_regs(old_regs);
 +}
 +
-+/* Vector callbacks are better than PCI interrupts to receive event
-+ * channel notifications because we can receive vector callbacks on any
-+ * vcpu and we don't need PCI support or APIC interactions. */
-+void xen_callback_vector(void)
-+{
-+	int rc;
-+	uint64_t callback_via;
-+	if (xen_have_vector_callback) {
-+		callback_via = HVM_CALLBACK_VECTOR(XEN_HVM_EVTCHN_CALLBACK);
-+		rc = xen_set_callback_via(callback_via);
-+		if (rc) {
-+			printk(KERN_ERR "Request for Xen HVM callback vector"
-+					" failed.\n");
-+			xen_have_vector_callback = 0;
-+			return;
-+		}
-+		printk(KERN_INFO "Xen HVM callback vector for event delivery is "
-+				"enabled\n");
+ /* Vector callbacks are better than PCI interrupts to receive event
+  * channel notifications because we can receive vector callbacks on any
+  * vcpu and we don't need PCI support or APIC interactions. */
+@@ -932,14 +1447,9 @@ void xen_callback_vector(void)
+ 		}
+ 		printk(KERN_INFO "Xen HVM callback vector for event delivery is "
+ 				"enabled\n");
+-		/* in the restore case the vector has already been allocated */
+-		if (!test_bit(XEN_HVM_EVTCHN_CALLBACK, used_vectors))
+-			alloc_intr_gate(XEN_HVM_EVTCHN_CALLBACK, xen_hvm_callback_vector);
 +		alloc_intr_gate(XEN_HVM_EVTCHN_CALLBACK, xen_hvm_callback_vector);
-+	}
-+}
-+
+ 	}
+ }
+-#else
+-void xen_callback_vector(void) {}
+-#endif
+ 
  void __init xen_init_IRQ(void)
  {
- 	int i;
+@@ -944,7 +1457,12 @@
  
  	cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s),
  				    GFP_KERNEL);
@@ -16116,18 +15645,12 @@
  
  	init_evtchn_cpu_bindings();
  
-@@ -942,5 +1470,11 @@ void __init xen_init_IRQ(void)
- 	for (i = 0; i < NR_EVENT_CHANNELS; i++)
- 		mask_evtchn(i);
- 
--	irq_ctx_init(smp_processor_id());
-+	if (xen_hvm_domain()) {
-+		xen_callback_vector();
-+		native_init_IRQ();
-+	} else {
-+		irq_ctx_init(smp_processor_id());
+@@ -1477,5 +1475,6 @@ void __init xen_init_IRQ(void)
+ 		native_init_IRQ();
+ 	} else {
+ 		irq_ctx_init(smp_processor_id());
 +		xen_setup_pirqs();
-+	}
+ 	}
  }
 diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c
 index 79bedba..b82666a 100644
@@ -17007,87 +16530,14 @@
 index 7d8f531..5a8ad45 100644
 --- a/drivers/xen/grant-table.c
 +++ b/drivers/xen/grant-table.c
-@@ -36,10 +36,13 @@
- #include <linux/mm.h>
- #include <linux/vmalloc.h>
+@@ -38,5 +38,6 @@
  #include <linux/uaccess.h>
-+#include <linux/io.h>
+ #include <linux/io.h>
  
 +#include <xen/xen.h>
  #include <xen/interface/xen.h>
  #include <xen/page.h>
- #include <xen/grant_table.h>
-+#include <xen/interface/memory.h>
- #include <asm/xen/hypercall.h>
- 
- #include <asm/pgtable.h>
-@@ -57,6 +60,8 @@ static unsigned int boot_max_nr_grant_frames;
- static int gnttab_free_count;
- static grant_ref_t gnttab_free_head;
- static DEFINE_SPINLOCK(gnttab_list_lock);
-+unsigned long xen_hvm_resume_frames;
-+EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
- 
- static struct grant_entry *shared;
- 
-@@ -431,7 +436,7 @@ static unsigned int __max_nr_grant_frames(void)
- 	return query.max_nr_frames;
- }
- 
--static inline unsigned int max_nr_grant_frames(void)
-+unsigned int gnttab_max_grant_frames(void)
- {
- 	unsigned int xen_max = __max_nr_grant_frames();
- 
-@@ -439,6 +444,7 @@ static inline unsigned int max_nr_grant_frames(void)
- 		return boot_max_nr_grant_frames;
- 	return xen_max;
- }
-+EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
- 
- static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
- {
-@@ -447,6 +453,30 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
- 	unsigned int nr_gframes = end_idx + 1;
- 	int rc;
- 
-+	if (xen_hvm_domain()) {
-+		struct xen_add_to_physmap xatp;
-+		unsigned int i = end_idx;
-+		rc = 0;
-+		/*
-+		 * Loop backwards, so that the first hypercall has the largest
-+		 * index, ensuring that the table will grow only once.
-+		 */
-+		do {
-+			xatp.domid = DOMID_SELF;
-+			xatp.idx = i;
-+			xatp.space = XENMAPSPACE_grant_table;
-+			xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i;
-+			rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
-+			if (rc != 0) {
-+				printk(KERN_WARNING
-+						"grant table add_to_physmap failed, err=%d\n", rc);
-+				break;
-+			}
-+		} while (i-- > start_idx);
-+
-+		return rc;
-+	}
-+
- 	frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
- 	if (!frames)
- 		return -ENOMEM;
-@@ -463,7 +493,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
- 
- 	BUG_ON(rc || setup.status);
- 
--	rc = arch_gnttab_map_shared(frames, nr_gframes, max_nr_grant_frames(),
-+	rc = arch_gnttab_map_shared(frames, nr_gframes, gnttab_max_grant_frames(),
- 				    &shared);
- 	BUG_ON(rc);
- 
-@@ -472,11 +502,134 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+@@ -472,5 +502,110 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
  	return 0;
  }
  
@@ -17198,78 +16648,6 @@
 +
  int gnttab_resume(void)
  {
--	if (max_nr_grant_frames() < nr_grant_frames)
-+	unsigned int max_nr_gframes;
-+
-+	max_nr_gframes = gnttab_max_grant_frames();
-+	if (max_nr_gframes < nr_grant_frames)
- 		return -ENOSYS;
--	return gnttab_map(0, nr_grant_frames - 1);
-+
-+	if (xen_pv_domain())
-+		return gnttab_map(0, nr_grant_frames - 1);
-+
-+	if (!shared) {
-+		shared = ioremap(xen_hvm_resume_frames, PAGE_SIZE * max_nr_gframes);
-+		if (shared == NULL) {
-+			printk(KERN_WARNING
-+					"Failed to ioremap gnttab share frames!");
-+			return -ENOMEM;
-+		}
-+	}
-+
-+	gnttab_map(0, nr_grant_frames - 1);
-+
-+	return 0;
- }
- 
- int gnttab_suspend(void)
-@@ -493,7 +646,7 @@ static int gnttab_expand(unsigned int req_entries)
- 	cur = nr_grant_frames;
- 	extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
- 		 GREFS_PER_GRANT_FRAME);
--	if (cur + extra > max_nr_grant_frames())
-+	if (cur + extra > gnttab_max_grant_frames())
- 		return -ENOSPC;
- 
- 	rc = gnttab_map(cur, cur + extra - 1);
-@@ -503,15 +656,12 @@ static int gnttab_expand(unsigned int req_entries)
- 	return rc;
- }
- 
--static int __devinit gnttab_init(void)
-+int gnttab_init(void)
- {
- 	int i;
- 	unsigned int max_nr_glist_frames, nr_glist_frames;
- 	unsigned int nr_init_grefs;
- 
--	if (!xen_domain())
--		return -ENODEV;
--
- 	nr_grant_frames = 1;
- 	boot_max_nr_grant_frames = __max_nr_grant_frames();
- 
-@@ -554,5 +704,18 @@ static int __devinit gnttab_init(void)
- 	kfree(gnttab_list);
- 	return -ENOMEM;
- }
-+EXPORT_SYMBOL_GPL(gnttab_init);
-+
-+static int __devinit __gnttab_init(void)
-+{
-+	/* Delay grant-table initialization in the PV on HVM case */
-+	if (xen_hvm_domain())
-+		return 0;
-+
-+	if (!xen_pv_domain())
-+		return -ENODEV;
-+
-+	return gnttab_init();
-+}
- 
--core_initcall(gnttab_init);
-+core_initcall(__gnttab_init);
 diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
 index 5d42d55..0b50906 100644
 --- a/drivers/xen/manage.c
@@ -17282,79 +16660,14 @@
  #include <xen/xenbus.h>
  #include <xen/grant_table.h>
  #include <xen/events.h>
-@@ -32,10 +33,30 @@ enum shutdown_state {
- static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
- 
- #ifdef CONFIG_PM_SLEEP
--static int xen_suspend(void *data)
-+static int xen_hvm_suspend(void *data)
- {
-+	struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
- 	int *cancelled = data;
-+
-+	BUG_ON(!irqs_disabled());
-+
-+	*cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
-+
-+	xen_hvm_post_suspend(*cancelled);
-+	gnttab_resume();
-+
-+	if (!*cancelled) {
-+		xen_irq_resume();
-+		xen_timer_resume();
-+	}
-+
-+	return 0;
-+}
-+
-+static int xen_suspend(void *data)
-+{
- 	int err;
-+	int *cancelled = data;
- 
- 	BUG_ON(!irqs_disabled());
+@@ -17,7 +17,6 @@
  
-@@ -111,7 +132,10 @@ static void do_suspend(void)
- 		goto out_resume;
- 	}
- 
--	err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
-+	if (xen_hvm_domain())
-+		err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0));
-+	else
-+		err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
- 
- 	dpm_resume_noirq(PMSG_RESUME);
- 
-@@ -260,7 +284,19 @@ static int shutdown_event(struct notifier_block *notifier,
- 	return NOTIFY_DONE;
- }
- 
--static int __init setup_shutdown_event(void)
-+static int __init __setup_shutdown_event(void)
-+{
-+	/* Delay initialization in the PV on HVM case */
-+	if (xen_hvm_domain())
-+		return 0;
-+
-+	if (!xen_pv_domain())
-+		return -ENODEV;
-+
-+	return xen_setup_shutdown_event();
-+}
-+
-+int xen_setup_shutdown_event(void)
- {
- 	static struct notifier_block xenstore_notifier = {
- 		.notifier_call = shutdown_event
-@@ -269,5 +305,6 @@ static int __init setup_shutdown_event(void)
- 
- 	return 0;
- }
-+EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
+ #include <asm/xen/hypercall.h>
+ #include <asm/xen/page.h>
+-#include <asm/xen/hypervisor.h>
  
--subsys_initcall(setup_shutdown_event);
-+subsys_initcall(__setup_shutdown_event);
+ enum shutdown_state {
+ 	SHUTDOWN_INVALID = -1,
 diff --git a/drivers/xen/mce.c b/drivers/xen/mce.c
 new file mode 100644
 index 0000000..da566a5
@@ -26495,219 +25808,6 @@
 +}
 +
 +subsys_initcall(xen_pcpu_init);
-diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
-new file mode 100644
-index 0000000..c01b5dd
---- /dev/null
-+++ b/drivers/xen/platform-pci.c
-@@ -0,0 +1,207 @@
-+/******************************************************************************
-+ * platform-pci.c
-+ *
-+ * Xen platform PCI device driver
-+ * Copyright (c) 2005, Intel Corporation.
-+ * Copyright (c) 2007, XenSource Inc.
-+ * Copyright (c) 2010, Citrix
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-+ * Place - Suite 330, Boston, MA 02111-1307 USA.
-+ *
-+ */
-+
-+
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+
-+#include <xen/platform_pci.h>
-+#include <xen/grant_table.h>
-+#include <xen/xenbus.h>
-+#include <xen/events.h>
-+#include <xen/hvm.h>
-+#include <xen/xen-ops.h>
-+
-+#define DRV_NAME    "xen-platform-pci"
-+
-+MODULE_AUTHOR("ssmith@xensource.com and stefano.stabellini@eu.citrix.com");
-+MODULE_DESCRIPTION("Xen platform PCI device");
-+MODULE_LICENSE("GPL");
-+
-+static unsigned long platform_mmio;
-+static unsigned long platform_mmio_alloc;
-+static unsigned long platform_mmiolen;
-+static uint64_t callback_via;
-+
-+unsigned long alloc_xen_mmio(unsigned long len)
-+{
-+	unsigned long addr;
-+
-+	addr = platform_mmio + platform_mmio_alloc;
-+	platform_mmio_alloc += len;
-+	BUG_ON(platform_mmio_alloc > platform_mmiolen);
-+
-+	return addr;
-+}
-+
-+static uint64_t get_callback_via(struct pci_dev *pdev)
-+{
-+	u8 pin;
-+	int irq;
-+
-+	irq = pdev->irq;
-+	if (irq < 16)
-+		return irq; /* ISA IRQ */
-+
-+	pin = pdev->pin;
-+
-+	/* We don't know the GSI. Specify the PCI INTx line instead. */
-+	return ((uint64_t)0x01 << 56) | /* PCI INTx identifier */
-+		((uint64_t)pci_domain_nr(pdev->bus) << 32) |
-+		((uint64_t)pdev->bus->number << 16) |
-+		((uint64_t)(pdev->devfn & 0xff) << 8) |
-+		((uint64_t)(pin - 1) & 3);
-+}
-+
-+static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id)
-+{
-+	xen_hvm_evtchn_do_upcall();
-+	return IRQ_HANDLED;
-+}
-+
-+static int xen_allocate_irq(struct pci_dev *pdev)
-+{
-+	return request_irq(pdev->irq, do_hvm_evtchn_intr,
-+			IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
-+			"xen-platform-pci", pdev);
-+}
-+
-+static int platform_pci_resume(struct pci_dev *pdev)
-+{
-+	int err;
-+	if (xen_have_vector_callback)
-+		return 0;
-+	err = xen_set_callback_via(callback_via);
-+	if (err) {
-+		dev_err(&pdev->dev, "platform_pci_resume failure!\n");
-+		return err;
-+	}
-+	return 0;
-+}
-+
-+static int __devinit platform_pci_init(struct pci_dev *pdev,
-+				       const struct pci_device_id *ent)
-+{
-+	int i, ret;
-+	long ioaddr, iolen;
-+	long mmio_addr, mmio_len;
-+	unsigned int max_nr_gframes;
-+
-+	i = pci_enable_device(pdev);
-+	if (i)
-+		return i;
-+
-+	ioaddr = pci_resource_start(pdev, 0);
-+	iolen = pci_resource_len(pdev, 0);
-+
-+	mmio_addr = pci_resource_start(pdev, 1);
-+	mmio_len = pci_resource_len(pdev, 1);
-+
-+	if (mmio_addr == 0 || ioaddr == 0) {
-+		dev_err(&pdev->dev, "no resources found\n");
-+		ret = -ENOENT;
-+		goto pci_out;
-+	}
-+
-+	if (request_mem_region(mmio_addr, mmio_len, DRV_NAME) == NULL) {
-+		dev_err(&pdev->dev, "MEM I/O resource 0x%lx @ 0x%lx busy\n",
-+		       mmio_addr, mmio_len);
-+		ret = -EBUSY;
-+		goto pci_out;
-+	}
-+
-+	if (request_region(ioaddr, iolen, DRV_NAME) == NULL) {
-+		dev_err(&pdev->dev, "I/O resource 0x%lx @ 0x%lx busy\n",
-+		       iolen, ioaddr);
-+		ret = -EBUSY;
-+		goto mem_out;
-+	}
-+
-+	platform_mmio = mmio_addr;
-+	platform_mmiolen = mmio_len;
-+
-+	if (!xen_have_vector_callback) {
-+		ret = xen_allocate_irq(pdev);
-+		if (ret) {
-+			dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret);
-+			goto out;
-+		}
-+		callback_via = get_callback_via(pdev);
-+		ret = xen_set_callback_via(callback_via);
-+		if (ret) {
-+			dev_warn(&pdev->dev, "Unable to set the evtchn callback "
-+					 "err=%d\n", ret);
-+			goto out;
-+		}
-+	}
-+
-+	max_nr_gframes = gnttab_max_grant_frames();
-+	xen_hvm_resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
-+	ret = gnttab_init();
-+	if (ret)
-+		goto out;
-+	xenbus_probe(NULL);
-+	ret = xen_setup_shutdown_event();
-+	if (ret)
-+		goto out;
-+	return 0;
-+
-+out:
-+	release_region(ioaddr, iolen);
-+mem_out:
-+	release_mem_region(mmio_addr, mmio_len);
-+pci_out:
-+	pci_disable_device(pdev);
-+	return ret;
-+}
-+
-+static struct pci_device_id platform_pci_tbl[] __devinitdata = {
-+	{PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM,
-+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-+	{0,}
-+};
-+
-+MODULE_DEVICE_TABLE(pci, platform_pci_tbl);
-+
-+static struct pci_driver platform_driver = {
-+	.name =           DRV_NAME,
-+	.probe =          platform_pci_init,
-+	.id_table =       platform_pci_tbl,
-+#ifdef CONFIG_PM
-+	.resume_early =   platform_pci_resume,
-+#endif
-+};
-+
-+static int __init platform_pci_module_init(void)
-+{
-+	/* no unplug has been done, IGNORE hasn't been specified: just
-+	 * return now */
-+	if (!xen_platform_pci_unplug)
-+		return -ENODEV;
-+
-+	return pci_register_driver(&platform_driver);
-+}
-+
-+module_init(platform_pci_module_init);
 diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c
 index 88a60e0..ae5cb05 100644
 --- a/drivers/xen/sys-hypervisor.c
@@ -27092,7 +26192,7 @@
 index 649fcdf..3a83ba2 100644
 --- a/drivers/xen/xenbus/xenbus_probe.c
 +++ b/drivers/xen/xenbus/xenbus_probe.c
-@@ -49,31 +49,29 @@
+@@ -49,6 +49,8 @@
  #include <asm/page.h>
  #include <asm/pgtable.h>
  #include <asm/xen/hypervisor.h>
@@ -27101,12 +26201,7 @@
  #include <xen/xenbus.h>
  #include <xen/events.h>
  #include <xen/page.h>
- 
-+#include <xen/platform_pci.h>
-+#include <xen/hvm.h>
-+
- #include "xenbus_comms.h"
- #include "xenbus_probe.h"
+@@ -60,22 +63,15 @@
  
  
  int xen_store_evtchn;
@@ -27460,19 +26555,7 @@
  
  /* A flag to determine if xenstored is 'ready' (i.e. has started) */
  int xenstored_ready = 0;
-@@ -749,10 +646,7 @@ int register_xenstore_notifier(struct notifier_block *nb)
- {
- 	int ret = 0;
- 
--	if (xenstored_ready > 0)
--		ret = nb->notifier_call(nb, 0, NULL);
--	else
--		blocking_notifier_chain_register(&xenstore_chain, nb);
-+	blocking_notifier_chain_register(&xenstore_chain, nb);
- 
- 	return ret;
- }
-@@ -768,57 +662,93 @@ void xenbus_probe(struct work_struct *unused)
+@@ -768,11 +662,6 @@ void xenbus_probe(struct work_struct *unused)
  {
  	BUG_ON((xenstored_ready <= 0));
  
@@ -27484,24 +26567,8 @@
  	/* Notify others that xenstore is up */
  	blocking_notifier_call_chain(&xenstore_chain, 0, NULL);
  }
-+EXPORT_SYMBOL_GPL(xenbus_probe);
-+
-+static int __init xenbus_probe_initcall(void)
-+{
-+	if (!xen_domain())
-+		return -ENODEV;
-+
-+	if (xen_initial_domain() || xen_hvm_domain())
-+		return 0;
-+
-+	xenbus_probe(NULL);
-+	return 0;
-+}
-+
-+device_initcall(xenbus_probe_initcall);
- 
--static int __init xenbus_probe_init(void)
-+static int __init xenbus_init(void)
+@@ -781,28 +684,45 @@
+ static int __init xenbus_init(void)
  {
  	int err = 0;
 +	unsigned long page = 0;
@@ -27553,30 +26620,19 @@
 +
 +		xen_store_interface = mfn_to_virt(xen_store_mfn);
  	} else {
- 		xenstored_ready = 1;
--		xen_store_evtchn = xen_start_info->store_evtchn;
--		xen_store_mfn = xen_start_info->store_mfn;
-+		if (xen_hvm_domain()) {
-+			uint64_t v = 0;
-+			err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
-+			if (err)
-+				goto out_error;
-+			xen_store_evtchn = (int)v;
-+			err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
-+			if (err)
-+				goto out_error;
-+			xen_store_mfn = (unsigned long)v;
-+			xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE);
-+		} else {
-+			xen_store_evtchn = xen_start_info->store_evtchn;
-+			xen_store_mfn = xen_start_info->store_mfn;
-+			xen_store_interface = mfn_to_virt(xen_store_mfn);
-+		}
++		xenstored_ready = 1;
+ 		if (xen_hvm_domain()) {
+ 			uint64_t v = 0;
+ 			err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
+@@ -739,7 +739,6 @@ static int __init xenbus_init(void)
+ 			xen_store_mfn = xen_start_info->store_mfn;
+ 			xen_store_interface = mfn_to_virt(xen_store_mfn);
+ 		}
+-		xenstored_ready = 1;
  	}
--	xen_store_interface = mfn_to_virt(xen_store_mfn);
  
  	/* Initialize the interface to xenstore. */
- 	err = xs_init();
+@@ -813,7 +746,7 @@
  	if (err) {
  		printk(KERN_WARNING
  		       "XENBUS: Error initializing xenstore comms: %i\n", err);
@@ -27584,13 +26640,8 @@
 +		goto out_error;
  	}
  
--	if (!xen_initial_domain())
--		xenbus_probe(NULL);
--
  #ifdef CONFIG_XEN_COMPAT_XENFS
- 	/*
- 	 * Create xenfs mountpoint in /proc for compatibility with
-@@ -829,128 +759,13 @@ static int __init xenbus_probe_init(void)
+@@ -829,131 +759,13 @@ static int __init xenbus_probe_init(void)
  
  	return 0;
  
@@ -27607,8 +26658,7 @@
  	return err;
  }
  
--postcore_initcall(xenbus_probe_init);
-+postcore_initcall(xenbus_init);
+ postcore_initcall(xenbus_init);
  
  MODULE_LICENSE("GPL");
 -
@@ -27716,6 +26766,9 @@
 -#ifndef MODULE
 -static int __init boot_wait_for_devices(void)
 -{
+-	if (xen_hvm_domain() && !xen_platform_pci_unplug)
+-		return -ENODEV;
+-
 -	ready_to_wait_for_devices = 1;
 -	wait_for_devices(NULL);
 -	return 0;
@@ -29036,11 +28089,11 @@
  }
  
  static int xenfs_get_sb(struct file_system_type *fs_type,
-@@ -63,11 +137,25 @@ static struct file_system_type xenfs_type = {
+@@ -63,15 +137,29 @@ static struct file_system_type xenfs_type = {
  
  static int __init xenfs_init(void)
  {
--	if (xen_pv_domain())
+-	if (xen_domain())
 -		return register_filesystem(&xenfs_type);
 +	int err;
 +	if (!xen_pv_domain()) {
@@ -29066,6 +28119,11 @@
  }
  
  static void __exit xenfs_exit(void)
+ {
+-	if (xen_domain())
++	if (xen_pv_domain())
+ 		unregister_filesystem(&xenfs_type);
+ }
 diff --git a/drivers/xen/xenfs/xenbus.c b/drivers/xen/xenfs/xenbus.c
 index 6c4269b..64b3be4 100644
 --- a/drivers/xen/xenfs/xenbus.c
@@ -29531,17 +28589,6 @@
  #endif
  
  #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
-diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
-index 67325bf..c398cc3 100644
---- a/include/linux/pci_ids.h
-+++ b/include/linux/pci_ids.h
-@@ -2712,3 +2712,6 @@
- #define PCI_DEVICE_ID_RME_DIGI32	0x9896
- #define PCI_DEVICE_ID_RME_DIGI32_PRO	0x9897
- #define PCI_DEVICE_ID_RME_DIGI32_8	0x9898
-+
-+#define PCI_VENDOR_ID_XEN		0x5853
-+#define PCI_DEVICE_ID_XEN_PLATFORM	0x0001
 diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
 index 73b1f1c..113585a 100644
 --- a/include/linux/swiotlb.h
@@ -29981,7 +29028,7 @@
  
  /*
   * Common unbind function for all event sources. Takes IRQ to unbind from.
-@@ -53,7 +61,42 @@ bool xen_test_irq_pending(int irq);
+@@ -53,9 +61,37 @@ bool xen_test_irq_pending(int irq);
     irq will be disabled so it won't deliver an interrupt. */
  void xen_poll_irq(int irq);
  
@@ -30016,14 +29063,9 @@
 +
 +/* Determine whether to ignore this IRQ if passed to a guest. */
 +int xen_ignore_irq(int irq);
-+/* Xen HVM evtchn vector callback */
-+extern void xen_hvm_callback_vector(void);
-+extern int xen_have_vector_callback;
-+int xen_set_callback_via(uint64_t via);
-+void xen_evtchn_do_upcall(struct pt_regs *regs);
-+void xen_hvm_evtchn_do_upcall(void);
-+
- #endif	/* _XEN_EVENTS_H */
+ /* Xen HVM evtchn vector callback */
+ extern void xen_hvm_callback_vector(void);
+ extern int xen_have_vector_callback;
 diff --git a/include/xen/gntdev.h b/include/xen/gntdev.h
 new file mode 100644
 index 0000000..8bd1467
@@ -30171,16 +29213,15 @@
  /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
  #define NR_GRANT_FRAMES 4
  
-@@ -51,6 +57,9 @@ struct gnttab_free_callback {
+@@ -51,6 +57,8 @@ struct gnttab_free_callback {
  	u16 count;
  };
  
 +void gnttab_reset_grant_page(struct page *page);
 +
-+int gnttab_init(void);
+ int gnttab_init(void);
  int gnttab_suspend(void);
  int gnttab_resume(void);
- 
 @@ -80,6 +89,8 @@ unsigned long gnttab_end_foreign_transfer(grant_ref_t ref);
  
  int gnttab_query_foreign_access(grant_ref_t ref);
@@ -30190,7 +29231,7 @@
  /*
   * operations on reserved batches of grant references
   */
-@@ -106,12 +117,46 @@ void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
+@@ -106,6 +117,37 @@ void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
  void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
  				       unsigned long pfn);
  
@@ -30228,80 +29269,10 @@
  int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
  			   unsigned long max_nr_gframes,
  			   struct grant_entry **__shared);
- void arch_gnttab_unmap_shared(struct grant_entry *shared,
- 			      unsigned long nr_gframes);
- 
-+extern unsigned long xen_hvm_resume_frames;
-+unsigned int gnttab_max_grant_frames(void);
-+
- #define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))
- 
- #endif /* __ASM_GNTTAB_H__ */
-diff --git a/include/xen/hvm.h b/include/xen/hvm.h
-new file mode 100644
-index 0000000..b193fa2
---- /dev/null
-+++ b/include/xen/hvm.h
-@@ -0,0 +1,30 @@
-+/* Simple wrappers around HVM functions */
-+#ifndef XEN_HVM_H__
-+#define XEN_HVM_H__
-+
-+#include <xen/interface/hvm/params.h>
-+#include <asm/xen/hypercall.h>
-+
-+static inline int hvm_get_parameter(int idx, uint64_t *value)
-+{
-+	struct xen_hvm_param xhv;
-+	int r;
-+
-+	xhv.domid = DOMID_SELF;
-+	xhv.index = idx;
-+	r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
-+	if (r < 0) {
-+		printk(KERN_ERR "Cannot get hvm parameter %d: %d!\n",
-+			idx, r);
-+		return r;
-+	}
-+	*value = xhv.value;
-+	return r;
-+}
-+
-+#define HVM_CALLBACK_VIA_TYPE_VECTOR 0x2
-+#define HVM_CALLBACK_VIA_TYPE_SHIFT 56
-+#define HVM_CALLBACK_VECTOR(x) (((uint64_t)HVM_CALLBACK_VIA_TYPE_VECTOR)<<\
-+		HVM_CALLBACK_VIA_TYPE_SHIFT | (x))
-+
-+#endif /* XEN_HVM_H__ */
-diff --git a/include/xen/interface/features.h b/include/xen/interface/features.h
-index f51b641..70d2563 100644
---- a/include/xen/interface/features.h
-+++ b/include/xen/interface/features.h
-@@ -41,6 +41,12 @@
- /* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */
- #define XENFEAT_mmu_pt_update_preserve_ad  5
- 
-+/* x86: Does this Xen host support the HVM callback vector type? */
-+#define XENFEAT_hvm_callback_vector        8
-+
-+/* x86: pvclock algorithm is safe to use on HVM */
-+#define XENFEAT_hvm_safe_pvclock           9
-+
- #define XENFEAT_NR_SUBMAPS 1
- 
- #endif /* __XEN_PUBLIC_FEATURES_H__ */
 diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h
 index 39da93c..c704fe5 100644
 --- a/include/xen/interface/grant_table.h
 +++ b/include/xen/interface/grant_table.h
-@@ -28,6 +28,7 @@
- #ifndef __XEN_PUBLIC_GRANT_TABLE_H__
- #define __XEN_PUBLIC_GRANT_TABLE_H__
- 
-+#include <xen/interface/xen.h>
- 
- /***********************************
-  * GRANT TABLE REPRESENTATION
 @@ -321,6 +322,28 @@ struct gnttab_query_size {
  DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_size);
  
@@ -30331,159 +29302,6 @@
   * Bitfield values for update_pin_status.flags.
   */
   /* Map the grant entry for access by I/O devices. */
-diff --git a/include/xen/interface/hvm/hvm_op.h b/include/xen/interface/hvm/hvm_op.h
-new file mode 100644
-index 0000000..a4827f4
---- /dev/null
-+++ b/include/xen/interface/hvm/hvm_op.h
-@@ -0,0 +1,46 @@
-+/*
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to
-+ * deal in the Software without restriction, including without limitation the
-+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-+ * sell copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ * DEALINGS IN THE SOFTWARE.
-+ */
-+
-+#ifndef __XEN_PUBLIC_HVM_HVM_OP_H__
-+#define __XEN_PUBLIC_HVM_HVM_OP_H__
-+
-+/* Get/set subcommands: the second argument of the hypercall is a
-+ * pointer to a xen_hvm_param struct. */
-+#define HVMOP_set_param           0
-+#define HVMOP_get_param           1
-+struct xen_hvm_param {
-+    domid_t  domid;    /* IN */
-+    uint32_t index;    /* IN */
-+    uint64_t value;    /* IN/OUT */
-+};
-+DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_param);
-+
-+/* Hint from PV drivers for pagetable destruction. */
-+#define HVMOP_pagetable_dying       9
-+struct xen_hvm_pagetable_dying {
-+    /* Domain with a pagetable about to be destroyed. */
-+    domid_t  domid;
-+    /* guest physical address of the toplevel pagetable dying */
-+    aligned_u64 gpa;
-+};
-+typedef struct xen_hvm_pagetable_dying xen_hvm_pagetable_dying_t;
-+DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_pagetable_dying_t);
-+ 
-+#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
-diff --git a/include/xen/interface/hvm/params.h b/include/xen/interface/hvm/params.h
-new file mode 100644
-index 0000000..1888d8c
---- /dev/null
-+++ b/include/xen/interface/hvm/params.h
-@@ -0,0 +1,95 @@
-+/*
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to
-+ * deal in the Software without restriction, including without limitation the
-+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-+ * sell copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ * DEALINGS IN THE SOFTWARE.
-+ */
-+
-+#ifndef __XEN_PUBLIC_HVM_PARAMS_H__
-+#define __XEN_PUBLIC_HVM_PARAMS_H__
-+
-+#include "hvm_op.h"
-+
-+/*
-+ * Parameter space for HVMOP_{set,get}_param.
-+ */
-+
-+/*
-+ * How should CPU0 event-channel notifications be delivered?
-+ * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt).
-+ * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows:
-+ *                  Domain = val[47:32], Bus  = val[31:16],
-+ *                  DevFn  = val[15: 8], IntX = val[ 1: 0]
-+ * val[63:56] == 2: val[7:0] is a vector number.
-+ * If val == 0 then CPU0 event-channel notifications are not delivered.
-+ */
-+#define HVM_PARAM_CALLBACK_IRQ 0
-+
-+#define HVM_PARAM_STORE_PFN    1
-+#define HVM_PARAM_STORE_EVTCHN 2
-+
-+#define HVM_PARAM_PAE_ENABLED  4
-+
-+#define HVM_PARAM_IOREQ_PFN    5
-+
-+#define HVM_PARAM_BUFIOREQ_PFN 6
-+
-+/*
-+ * Set mode for virtual timers (currently x86 only):
-+ *  delay_for_missed_ticks (default):
-+ *   Do not advance a vcpu's time beyond the correct delivery time for
-+ *   interrupts that have been missed due to preemption. Deliver missed
-+ *   interrupts when the vcpu is rescheduled and advance the vcpu's virtual
-+ *   time stepwise for each one.
-+ *  no_delay_for_missed_ticks:
-+ *   As above, missed interrupts are delivered, but guest time always tracks
-+ *   wallclock (i.e., real) time while doing so.
-+ *  no_missed_ticks_pending:
-+ *   No missed interrupts are held pending. Instead, to ensure ticks are
-+ *   delivered at some non-zero rate, if we detect missed ticks then the
-+ *   internal tick alarm is not disabled if the VCPU is preempted during the
-+ *   next tick period.
-+ *  one_missed_tick_pending:
-+ *   Missed interrupts are collapsed together and delivered as one 'late tick'.
-+ *   Guest time always tracks wallclock (i.e., real) time.
-+ */
-+#define HVM_PARAM_TIMER_MODE   10
-+#define HVMPTM_delay_for_missed_ticks    0
-+#define HVMPTM_no_delay_for_missed_ticks 1
-+#define HVMPTM_no_missed_ticks_pending   2
-+#define HVMPTM_one_missed_tick_pending   3
-+
-+/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */
-+#define HVM_PARAM_HPET_ENABLED 11
-+
-+/* Identity-map page directory used by Intel EPT when CR0.PG=0. */
-+#define HVM_PARAM_IDENT_PT     12
-+
-+/* Device Model domain, defaults to 0. */
-+#define HVM_PARAM_DM_DOMAIN    13
-+
-+/* ACPI S state: currently support S0 and S3 on x86. */
-+#define HVM_PARAM_ACPI_S_STATE 14
-+
-+/* TSS used on Intel when CR0.PE=0. */
-+#define HVM_PARAM_VM86_TSS     15
-+
-+/* Boolean: Enable aligning all periodic vpts to reduce interrupts */
-+#define HVM_PARAM_VPT_ALIGN    16
-+
-+#define HVM_NR_PARAMS          17
-+
-+#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
 diff --git a/include/xen/interface/io/netif.h b/include/xen/interface/io/netif.h
 index 518481c..8309344 100644
 --- a/include/xen/interface/io/netif.h
@@ -31817,61 +30635,6 @@
 +
 +extern void unregister_xen_pcpu_notifier(struct notifier_block *nb);
 +#endif
-diff --git a/include/xen/platform_pci.h b/include/xen/platform_pci.h
-new file mode 100644
-index 0000000..ce9d671
---- /dev/null
-+++ b/include/xen/platform_pci.h
-@@ -0,0 +1,49 @@
-+#ifndef _XEN_PLATFORM_PCI_H
-+#define _XEN_PLATFORM_PCI_H
-+
-+#define XEN_IOPORT_MAGIC_VAL 0x49d2
-+#define XEN_IOPORT_LINUX_PRODNUM 0x0003
-+#define XEN_IOPORT_LINUX_DRVVER  0x0001
-+
-+#define XEN_IOPORT_BASE 0x10
-+
-+#define XEN_IOPORT_PLATFLAGS	(XEN_IOPORT_BASE + 0) /* 1 byte access (R/W) */
-+#define XEN_IOPORT_MAGIC	(XEN_IOPORT_BASE + 0) /* 2 byte access (R) */
-+#define XEN_IOPORT_UNPLUG	(XEN_IOPORT_BASE + 0) /* 2 byte access (W) */
-+#define XEN_IOPORT_DRVVER	(XEN_IOPORT_BASE + 0) /* 4 byte access (W) */
-+
-+#define XEN_IOPORT_SYSLOG	(XEN_IOPORT_BASE + 2) /* 1 byte access (W) */
-+#define XEN_IOPORT_PROTOVER	(XEN_IOPORT_BASE + 2) /* 1 byte access (R) */
-+#define XEN_IOPORT_PRODNUM	(XEN_IOPORT_BASE + 2) /* 2 byte access (W) */
-+
-+#define XEN_UNPLUG_ALL_IDE_DISKS 1
-+#define XEN_UNPLUG_ALL_NICS 2
-+#define XEN_UNPLUG_AUX_IDE_DISKS 4
-+#define XEN_UNPLUG_ALL 7
-+#define XEN_UNPLUG_IGNORE 8
-+
-+static inline int xen_must_unplug_nics(void) {
-+#if (defined(CONFIG_XEN_NETDEV_FRONTEND) || \
-+		defined(CONFIG_XEN_NETDEV_FRONTEND_MODULE)) && \
-+		(defined(CONFIG_XEN_PLATFORM_PCI) || \
-+		 defined(CONFIG_XEN_PLATFORM_PCI_MODULE))
-+        return 1;
-+#else
-+        return 0;
-+#endif
-+}
-+
-+static inline int xen_must_unplug_disks(void) {
-+#if (defined(CONFIG_XEN_BLKDEV_FRONTEND) || \
-+		defined(CONFIG_XEN_BLKDEV_FRONTEND_MODULE)) && \
-+		(defined(CONFIG_XEN_PLATFORM_PCI) || \
-+		 defined(CONFIG_XEN_PLATFORM_PCI_MODULE))
-+        return 1;
-+#else
-+        return 0;
-+#endif
-+}
-+
-+extern int xen_platform_pci_unplug;
-+
-+#endif /* _XEN_PLATFORM_PCI_H */
 diff --git a/include/xen/privcmd.h b/include/xen/privcmd.h
 new file mode 100644
 index 0000000..b42cdfd
@@ -31962,15 +30725,7 @@
 index 883a21b..7058f8a 100644
 --- a/include/xen/xen-ops.h
 +++ b/include/xen/xen-ops.h
-@@ -7,6 +7,7 @@ DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
- 
- void xen_pre_suspend(void);
- void xen_post_suspend(int suspend_cancelled);
-+void xen_hvm_post_suspend(int suspend_cancelled);
- 
- void xen_mm_pin_all(void);
- void xen_mm_unpin_all(void);
-@@ -14,4 +15,16 @@ void xen_mm_unpin_all(void);
+@@ -14,6 +15,16 @@ void xen_mm_unpin_all(void);
  void xen_timer_resume(void);
  void xen_arch_resume(void);
  
@@ -31984,8 +30739,8 @@
 +				unsigned int address_bits);
 +
 +void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
-+int xen_setup_shutdown_event(void);
-+
+ int xen_setup_shutdown_event(void);
+ 
  #endif /* INCLUDE_XEN_OPS_H */
 diff --git a/include/xen/xen.h b/include/xen/xen.h
 new file mode 100644
@@ -34216,0 +32972,23 @@
+diff a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
+--- a/arch/x86/include/asm/setup.h
++++ b/arch/x86/include/asm/setup.h
+@@ -84,7 +84,7 @@ void *extend_brk(size_t size, size_t ali
+  * executable.)
+  */
+ #define RESERVE_BRK(name,sz)						\
+-	static void __section(.discard.text) __used			\
++	static void __section(.discard) __used				\
+ 	__brk_reservation_fn_##name##__(void) {				\
+ 		asm volatile (						\
+ 			".pushsection .brk_reservation,\"aw\",@nobits;" \
+diff a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -639,7 +639,6 @@
+ 	EXIT_DATA							\
+ 	EXIT_CALL							\
+ 	*(.discard)							\
+-	*(.discard.*)							\
+ 	}
+ 
+ /**
diff -u linux-2.6-2.6.32/debian/patches/series/21 linux-2.6-2.6.32/debian/patches/series/21
--- linux-2.6-2.6.32/debian/patches/series/21
+++ linux-2.6-2.6.32/debian/patches/series/21
@@ -10,0 +11,15 @@
+
++ features/all/xen/pvhvm/0001-xen-Add-support-for-HVM-hypercalls.patch
++ features/all/xen/pvhvm/0002-x86-early-PV-on-HVM-features-initialization.patch
++ features/all/xen/pvhvm/0003-x86-xen-event-channels-delivery-on-HVM.patch
++ features/all/xen/pvhvm/0004-xen-Xen-PCI-platform-device-driver.patch
++ features/all/xen/pvhvm/0005-xen-Add-suspend-resume-support-for-PV-on-HVM-guests.patch
++ features/all/xen/pvhvm/0006-xen-Fix-find_unbound_irq-in-presence-of-ioapic-irqs.patch
++ features/all/xen/pvhvm/0007-x86-Use-xen_vcpuop_clockevent-xen_clocksource-and.patch
++ features/all/xen/pvhvm/0008-x86-Unplug-emulated-disks-and-nics.patch
++ features/all/xen/pvhvm/0009-x86-Call-HVMOP_pagetable_dying-on-exit_mmap.patch
++ features/all/xen/pvhvm/0010-xenfs-enable-for-HVM-domains-too.patch
++ features/all/xen/pvhvm/0011-support-multiple-.discard.-sections-to-avoid-sectio.patch
++ features/all/xen/pvhvm/0012-blkfront-do-not-create-a-PV-cdrom-device-if-xen_hvm.patch
++ features/all/xen/pvhvm/0013-Introduce-CONFIG_XEN_PVHVM-compile-option.patch
++ features/all/xen/pvhvm/0014-pvops-do-not-notify-callers-from-register_xenstore_.patch
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0010-xenfs-enable-for-HVM-domains-too.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0010-xenfs-enable-for-HVM-domains-too.patch
@@ -0,0 +1,36 @@
+From 3b31f9a21623a5310b2fa87f62bab79a98445a66 Mon Sep 17 00:00:00 2001
+From: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+Date: Wed, 21 Jul 2010 22:51:39 -0700
+Subject: [PATCH] xenfs: enable for HVM domains too
+
+Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+(cherry picked from commit 43df95c44e71d009b5a73f104ff183f73af9526f)
+---
+ drivers/xen/xenfs/super.c |    4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/xen/xenfs/super.c b/drivers/xen/xenfs/super.c
+index 6559e0c..6c16685 100644
+--- a/drivers/xen/xenfs/super.c
++++ b/drivers/xen/xenfs/super.c
+@@ -63,7 +63,7 @@ static struct file_system_type xenfs_type = {
+ 
+ static int __init xenfs_init(void)
+ {
+-	if (xen_pv_domain())
++	if (xen_domain())
+ 		return register_filesystem(&xenfs_type);
+ 
+ 	printk(KERN_INFO "XENFS: not registering filesystem on non-xen platform\n");
+@@ -72,7 +72,7 @@ static int __init xenfs_init(void)
+ 
+ static void __exit xenfs_exit(void)
+ {
+-	if (xen_pv_domain())
++	if (xen_domain())
+ 		unregister_filesystem(&xenfs_type);
+ }
+ 
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0011-support-multiple-.discard.-sections-to-avoid-sectio.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0011-support-multiple-.discard.-sections-to-avoid-sectio.patch
@@ -0,0 +1,45 @@
+From bc068987ea67877f7c5378e6bc8cbd9771e3d829 Mon Sep 17 00:00:00 2001
+From: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+Date: Thu, 22 Jul 2010 22:58:01 -0700
+Subject: [PATCH] support multiple .discard.* sections to avoid section type conflicts
+
+gcc 4.4.4 will complain if you use a .discard section for both text and
+data ("causes a section type conflict").  Add support for ".discard.*"
+sections, and use .discard.text for a dummy function in the x86
+RESERVE_BRK() macro.
+
+Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+(cherry picked from commit c7f52cdc2f3e1733d3864e439ac2e92edd99ef31)
+---
+ arch/x86/include/asm/setup.h      |    2 +-
+ include/asm-generic/vmlinux.lds.h |    1 +
+ 2 files changed, 2 insertions(+), 1 deletions(-)
+
+diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
+index 18e496c..fee81d0 100644
+--- a/arch/x86/include/asm/setup.h
++++ b/arch/x86/include/asm/setup.h
+@@ -84,7 +84,7 @@ void *extend_brk(size_t size, size_t align);
+  * executable.)
+  */
+ #define RESERVE_BRK(name,sz)						\
+-	static void __section(.discard) __used				\
++	static void __section(.discard.text) __used			\
+ 	__brk_reservation_fn_##name##__(void) {				\
+ 		asm volatile (						\
+ 			".pushsection .brk_reservation,\"aw\",@nobits;" \
+diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
+index b6e818f..ca060ce 100644
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -639,6 +639,7 @@
+ 	EXIT_DATA							\
+ 	EXIT_CALL							\
+ 	*(.discard)							\
++	*(.discard.*)							\
+ 	}
+ 
+ /**
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0006-xen-Fix-find_unbound_irq-in-presence-of-ioapic-irqs.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0006-xen-Fix-find_unbound_irq-in-presence-of-ioapic-irqs.patch
@@ -0,0 +1,55 @@
+From 1c2d51c200fe12bf18ca5392da3ab4ce8d75bbec Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Date: Fri, 14 May 2010 12:41:20 +0100
+Subject: [PATCH] xen: Fix find_unbound_irq in presence of ioapic irqs.
+
+Don't break the assumption that the first 16 irqs are ISA irqs;
+make sure that the irq is actually free before using it.
+
+Use dynamic_irq_init_keep_chip_data instead of
+dynamic_irq_init so that chip_data is not NULL (a NULL chip_data breaks
+setup_vector_irq).
+
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+(cherry picked from commit 99ad198c4978036bb9f7ebd11618b225b77046da)
+---
+ drivers/xen/events.c |   13 +++++++++++--
+ 1 files changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/xen/events.c b/drivers/xen/events.c
+index 9d99c9a..da01209 100644
+--- a/drivers/xen/events.c
++++ b/drivers/xen/events.c
+@@ -338,9 +338,18 @@ static int find_unbound_irq(void)
+ 	int irq;
+ 	struct irq_desc *desc;
+ 
+-	for (irq = 0; irq < nr_irqs; irq++)
++	for (irq = 0; irq < nr_irqs; irq++) {
++		desc = irq_to_desc(irq);
++		/* only 0->15 have init'd desc; handle irq > 16 */
++		if (desc == NULL)
++			break;
++		if (desc->chip == &no_irq_chip)
++			break;
++		if (desc->chip != &xen_dynamic_chip)
++			continue;
+ 		if (irq_info[irq].type == IRQT_UNBOUND)
+ 			break;
++	}
+ 
+ 	if (irq == nr_irqs)
+ 		panic("No available IRQ to bind to: increase nr_irqs!\n");
+@@ -349,7 +358,7 @@ static int find_unbound_irq(void)
+ 	if (WARN_ON(desc == NULL))
+ 		return -1;
+ 
+-	dynamic_irq_init(irq);
++	dynamic_irq_init_keep_chip_data(irq);
+ 
+ 	return irq;
+ }
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0002-x86-early-PV-on-HVM-features-initialization.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0002-x86-early-PV-on-HVM-features-initialization.patch
@@ -0,0 +1,242 @@
+From 4ff272652d56f0c00c1f0be7a5c750794ff515a3 Mon Sep 17 00:00:00 2001
+From: Sheng Yang <sheng@linux.intel.com>
+Date: Fri, 14 May 2010 12:39:33 +0100
+Subject: [PATCH] x86: early PV on HVM features initialization.
+
+Initialize basic pv on hvm features in xen_hvm_guest_init.
+
+Don't try to initialize xen-kbdfront and xen-fbfront when running on HVM
+because the backends are not available.
+
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Signed-off-by: Sheng Yang <sheng@linux.intel.com>
+Signed-off-by: Yaozu (Eddie) Dong <eddie.dong@intel.com>
+(cherry picked from commit bee6ab53e652a414af20392899879b58cd80d033 and
+adjusted to not use the generic hypervisor detection routines which are not in
+this kernel)
+---
+ arch/x86/include/asm/xen/hypervisor.h |    2 +
+ arch/x86/kernel/setup.c               |    2 +
+ arch/x86/xen/enlighten.c              |   82 +++++++++++++++++++++++++++++++++
+ drivers/input/xen-kbdfront.c          |    2 +-
+ drivers/video/xen-fbfront.c           |    2 +-
+ drivers/xen/xenbus/xenbus_probe.c     |   21 +++++++-
+ 6 files changed, 106 insertions(+), 5 deletions(-)
+
+diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h
+index d5b7e90..5d298fd 100644
+--- a/arch/x86/include/asm/xen/hypervisor.h
++++ b/arch/x86/include/asm/xen/hypervisor.h
+@@ -45,8 +45,10 @@ enum xen_domain_type {
+ 
+ #ifdef CONFIG_XEN
+ extern enum xen_domain_type xen_domain_type;
++extern void __init xen_hvm_guest_init(void);
+ #else
+ #define xen_domain_type		XEN_NATIVE
++#define xen_hvm_guest_init() do { } while (0)
+ #endif
+ 
+ #define xen_domain()		(xen_domain_type != XEN_NATIVE)
+diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
+index d7a0888..c852868 100644
+--- a/arch/x86/kernel/setup.c
++++ b/arch/x86/kernel/setup.c
+@@ -102,6 +102,7 @@
+ 
+ #include <asm/paravirt.h>
+ #include <asm/hypervisor.h>
++#include <asm/xen/hypervisor.h>
+ 
+ #include <asm/percpu.h>
+ #include <asm/topology.h>
+@@ -1034,6 +1035,7 @@ void __init setup_arch(char **cmdline_p)
+ 	probe_nr_irqs_gsi();
+ 
+ 	kvm_guest_init();
++	xen_hvm_guest_init();
+ 
+ 	e820_reserve_resources();
+ 	e820_mark_nosave_regions(max_low_pfn);
+diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
+index 942ccf1..b05e426 100644
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -32,6 +32,7 @@
+ #include <xen/interface/version.h>
+ #include <xen/interface/physdev.h>
+ #include <xen/interface/vcpu.h>
++#include <xen/interface/memory.h>
+ #include <xen/features.h>
+ #include <xen/page.h>
+ #include <xen/hvc-console.h>
+@@ -52,7 +53,9 @@
+ #include <asm/pgtable.h>
+ #include <asm/tlbflush.h>
+ #include <asm/reboot.h>
++#include <asm/setup.h>
+ #include <asm/stackprotector.h>
++#include <asm/hypervisor.h>
+ 
+ #include "xen-ops.h"
+ #include "mmu.h"
+@@ -73,6 +76,8 @@ struct shared_info xen_dummy_shared_info;
+ 
+ void *xen_initial_gdt;
+ 
++RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
++
+ /*
+  * Point at some empty memory to start with. We map the real shared_info
+  * page as soon as fixmap is up and running.
+@@ -1197,3 +1202,80 @@ asmlinkage void __init xen_start_kernel(void)
+ 	x86_64_start_reservations((char *)__pa_symbol(&boot_params));
+ #endif
+ }
++
++static uint32_t xen_cpuid_base(void)
++{
++	uint32_t base, eax, ebx, ecx, edx;
++	char signature[13];
++
++	for (base = 0x40000000; base < 0x40010000; base += 0x100) {
++		cpuid(base, &eax, &ebx, &ecx, &edx);
++		*(uint32_t *)(signature + 0) = ebx;
++		*(uint32_t *)(signature + 4) = ecx;
++		*(uint32_t *)(signature + 8) = edx;
++		signature[12] = 0;
++
++		if (!strcmp("XenVMMXenVMM", signature) && ((eax - base) >= 2))
++			return base;
++	}
++
++	return 0;
++}
++
++static int init_hvm_pv_info(int *major, int *minor)
++{
++	uint32_t eax, ebx, ecx, edx, pages, msr, base;
++	u64 pfn;
++
++	base = xen_cpuid_base();
++	cpuid(base + 1, &eax, &ebx, &ecx, &edx);
++
++	*major = eax >> 16;
++	*minor = eax & 0xffff;
++	printk(KERN_INFO "Xen version %d.%d.\n", *major, *minor);
++
++	cpuid(base + 2, &pages, &msr, &ecx, &edx);
++
++	pfn = __pa(hypercall_page);
++	wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
++
++	xen_setup_features();
++
++	pv_info = xen_info;
++	pv_info.kernel_rpl = 0;
++
++	xen_domain_type = XEN_HVM_DOMAIN;
++
++	return 0;
++}
++
++static void __init init_shared_info(void)
++{
++	struct xen_add_to_physmap xatp;
++	struct shared_info *shared_info_page;
++
++	shared_info_page = (struct shared_info *)
++		extend_brk(PAGE_SIZE, PAGE_SIZE);
++	xatp.domid = DOMID_SELF;
++	xatp.idx = 0;
++	xatp.space = XENMAPSPACE_shared_info;
++	xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
++	if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
++		BUG();
++
++	HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
++
++	per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
++}
++
++void __init xen_hvm_guest_init(void)
++{
++	int r;
++	int major, minor;
++
++	r = init_hvm_pv_info(&major, &minor);
++	if (r < 0)
++		return;
++
++	init_shared_info();
++}
+diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
+index b115726..8ec2201 100644
+--- a/drivers/input/xen-kbdfront.c
++++ b/drivers/input/xen-kbdfront.c
+@@ -335,7 +335,7 @@ static struct xenbus_driver xenkbd_driver = {
+ 
+ static int __init xenkbd_init(void)
+ {
+-	if (!xen_domain())
++	if (!xen_pv_domain())
+ 		return -ENODEV;
+ 
+ 	/* Nothing to do if running in dom0. */
+diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
+index 54cd916..450f958 100644
+--- a/drivers/video/xen-fbfront.c
++++ b/drivers/video/xen-fbfront.c
+@@ -680,7 +680,7 @@ static struct xenbus_driver xenfb_driver = {
+ 
+ static int __init xenfb_init(void)
+ {
+-	if (!xen_domain())
++	if (!xen_pv_domain())
+ 		return -ENODEV;
+ 
+ 	/* Nothing to do if running in dom0. */
+diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
+index 649fcdf..568d14d 100644
+--- a/drivers/xen/xenbus/xenbus_probe.c
++++ b/drivers/xen/xenbus/xenbus_probe.c
+@@ -53,6 +53,8 @@
+ #include <xen/events.h>
+ #include <xen/page.h>
+ 
++#include <xen/hvm.h>
++
+ #include "xenbus_comms.h"
+ #include "xenbus_probe.h"
+ 
+@@ -802,11 +804,24 @@ static int __init xenbus_probe_init(void)
+ 	if (xen_initial_domain()) {
+ 		/* dom0 not yet supported */
+ 	} else {
++		if (xen_hvm_domain()) {
++			uint64_t v = 0;
++			err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
++			if (err)
++				goto out_error;
++			xen_store_evtchn = (int)v;
++			err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
++			if (err)
++				goto out_error;
++			xen_store_mfn = (unsigned long)v;
++			xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE);
++		} else {
++			xen_store_evtchn = xen_start_info->store_evtchn;
++			xen_store_mfn = xen_start_info->store_mfn;
++			xen_store_interface = mfn_to_virt(xen_store_mfn);
++		}
+ 		xenstored_ready = 1;
+-		xen_store_evtchn = xen_start_info->store_evtchn;
+-		xen_store_mfn = xen_start_info->store_mfn;
+ 	}
+-	xen_store_interface = mfn_to_virt(xen_store_mfn);
+ 
+ 	/* Initialize the interface to xenstore. */
+ 	err = xs_init();
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0009-x86-Call-HVMOP_pagetable_dying-on-exit_mmap.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0009-x86-Call-HVMOP_pagetable_dying-on-exit_mmap.patch
@@ -0,0 +1,112 @@
+From 1932fc689504974a54992051ba8cc2afd1855b7e Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Date: Thu, 17 Jun 2010 14:22:52 +0100
+Subject: [PATCH] x86: Call HVMOP_pagetable_dying on exit_mmap.
+
+When a pagetable is about to be destroyed, we notify Xen so that the
+hypervisor can clear the related shadow pagetable.
+
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+(cherry picked from commit 5915100106b8f14a38053ad6c03a664d208aeaa2)
+---
+ arch/x86/xen/enlighten.c           |    1 +
+ arch/x86/xen/mmu.c                 |   33 +++++++++++++++++++++++++++++++++
+ arch/x86/xen/mmu.h                 |    1 +
+ include/xen/interface/hvm/hvm_op.h |   11 +++++++++++
+ 4 files changed, 46 insertions(+), 0 deletions(-)
+
+diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
+index 4488de1..c05b5fe 100644
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -1308,4 +1308,5 @@ void __init xen_hvm_guest_init(void)
+ 	have_vcpu_info_placement = 0;
+ 	x86_init.irqs.intr_init = xen_init_IRQ;
+ 	xen_hvm_init_time_ops();
++	xen_hvm_init_mmu_ops();
+ }
+diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
+index 350a3de..f3ff12a 100644
+--- a/arch/x86/xen/mmu.c
++++ b/arch/x86/xen/mmu.c
+@@ -57,6 +57,7 @@
+ 
+ #include <xen/page.h>
+ #include <xen/interface/xen.h>
++#include <xen/interface/hvm/hvm_op.h>
+ #include <xen/interface/version.h>
+ #include <xen/hvc-console.h>
+ 
+@@ -1962,6 +1963,38 @@ void __init xen_init_mmu_ops(void)
+ 	pv_mmu_ops = xen_mmu_ops;
+ }
+ 
++static void xen_hvm_exit_mmap(struct mm_struct *mm)
++{
++	struct xen_hvm_pagetable_dying a;
++	int rc;
++
++	a.domid = DOMID_SELF;
++	a.gpa = __pa(mm->pgd);
++	rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
++	WARN_ON_ONCE(rc < 0);
++}
++
++static int is_pagetable_dying_supported(void)
++{
++	struct xen_hvm_pagetable_dying a;
++	int rc = 0;
++
++	a.domid = DOMID_SELF;
++	a.gpa = 0x00;
++	rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
++	if (rc < 0) {
++		printk(KERN_DEBUG "HVMOP_pagetable_dying not supported\n");
++		return 0;
++	}
++	return 1;
++}
++
++void __init xen_hvm_init_mmu_ops(void)
++{
++	if (is_pagetable_dying_supported())
++		pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap;
++}
++
+ #ifdef CONFIG_XEN_DEBUG_FS
+ 
+ static struct dentry *d_mmu_debug;
+diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h
+index 5fe6bc7..fa938c4 100644
+--- a/arch/x86/xen/mmu.h
++++ b/arch/x86/xen/mmu.h
+@@ -60,4 +60,5 @@ void  xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
+ unsigned long xen_read_cr2_direct(void);
+ 
+ extern void xen_init_mmu_ops(void);
++extern void xen_hvm_init_mmu_ops(void);
+ #endif	/* _XEN_MMU_H */
+diff --git a/include/xen/interface/hvm/hvm_op.h b/include/xen/interface/hvm/hvm_op.h
+index 73c8c7e..a4827f4 100644
+--- a/include/xen/interface/hvm/hvm_op.h
++++ b/include/xen/interface/hvm/hvm_op.h
+@@ -32,4 +32,15 @@ struct xen_hvm_param {
+ };
+ DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_param);
+ 
++/* Hint from PV drivers for pagetable destruction. */
++#define HVMOP_pagetable_dying       9
++struct xen_hvm_pagetable_dying {
++    /* Domain with a pagetable about to be destroyed. */
++    domid_t  domid;
++    /* guest physical address of the toplevel pagetable dying */
++    aligned_u64 gpa;
++};
++typedef struct xen_hvm_pagetable_dying xen_hvm_pagetable_dying_t;
++DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_pagetable_dying_t);
++ 
+ #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0013-Introduce-CONFIG_XEN_PVHVM-compile-option.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0013-Introduce-CONFIG_XEN_PVHVM-compile-option.patch
@@ -0,0 +1,147 @@
+From 9ab36ce03c4bf58865aec406b6b63defd386ff80 Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Date: Thu, 29 Jul 2010 14:37:48 +0100
+Subject: [PATCH] Introduce CONFIG_XEN_PVHVM compile option
+
+This patch introduce a CONFIG_XEN_PVHVM compile time option to
+enable/disable Xen PV on HVM support.
+
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+(cherry picked from commit 5b270b05c41c21b19c88617c3, updated for lack of
+hypervisor detection infrastructure)
+---
+ arch/x86/xen/Kconfig               |    5 +++++
+ arch/x86/xen/enlighten.c           |    2 ++
+ arch/x86/xen/mmu.c                 |    2 ++
+ arch/x86/xen/platform-pci-unplug.c |    2 ++
+ arch/x86/xen/time.c                |    3 ++-
+ drivers/xen/Kconfig                |    2 +-
+ drivers/xen/events.c               |    4 ++++
+ 7 files changed, 18 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
+index b83e119..68128a1 100644
+--- a/arch/x86/xen/Kconfig
++++ b/arch/x86/xen/Kconfig
+@@ -13,6 +13,11 @@ config XEN
+ 	  kernel to boot in a paravirtualized environment under the
+ 	  Xen hypervisor.
+ 
++config XEN_PVHVM
++	def_bool y
++	depends on XEN
++	depends on X86_LOCAL_APIC
++
+ config XEN_MAX_DOMAIN_MEMORY
+        int "Maximum allowed size of a domain in gigabytes"
+        default 8 if X86_32
+diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
+index c05b5fe..47dab58 100644
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -1272,6 +1272,7 @@ void xen_hvm_init_shared_info(void)
+ 	}
+ }
+ 
++#ifdef CONFIG_XEN_PVHVM
+ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
+ 				    unsigned long action, void *hcpu)
+ {
+@@ -1310,3 +1311,4 @@ void __init xen_hvm_guest_init(void)
+ 	xen_hvm_init_time_ops();
+ 	xen_hvm_init_mmu_ops();
+ }
++#endif
+diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
+index f3ff12a..971a405 100644
+--- a/arch/x86/xen/mmu.c
++++ b/arch/x86/xen/mmu.c
+@@ -1963,6 +1963,7 @@ void __init xen_init_mmu_ops(void)
+ 	pv_mmu_ops = xen_mmu_ops;
+ }
+ 
++#ifdef CONFIG_XEN_PVHVM
+ static void xen_hvm_exit_mmap(struct mm_struct *mm)
+ {
+ 	struct xen_hvm_pagetable_dying a;
+@@ -1994,6 +1995,7 @@ void __init xen_hvm_init_mmu_ops(void)
+ 	if (is_pagetable_dying_supported())
+ 		pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap;
+ }
++#endif
+ 
+ #ifdef CONFIG_XEN_DEBUG_FS
+ 
+diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c
+index 2f7f3fb..554c002 100644
+--- a/arch/x86/xen/platform-pci-unplug.c
++++ b/arch/x86/xen/platform-pci-unplug.c
+@@ -32,6 +32,7 @@
+ /* store the value of xen_emul_unplug after the unplug is done */
+ int xen_platform_pci_unplug;
+ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
++#ifdef CONFIG_XEN_PVHVM
+ static int xen_emul_unplug;
+ 
+ static int __init check_platform_magic(void)
+@@ -133,3 +134,4 @@ static int __init parse_xen_emul_unplug(char *arg)
+ 	return 0;
+ }
+ early_param("xen_emul_unplug", parse_xen_emul_unplug);
++#endif
+diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
+index 7e47d09..094c70a 100644
+--- a/arch/x86/xen/time.c
++++ b/arch/x86/xen/time.c
+@@ -476,6 +476,7 @@ __init void xen_init_time_ops(void)
+ 	x86_platform.set_wallclock = xen_set_wallclock;
+ }
+ 
++#ifdef CONFIG_XEN_PVHVM
+ static void xen_hvm_setup_cpu_clockevents(void)
+ {
+ 	int cpu = smp_processor_id();
+@@ -504,4 +505,4 @@ __init void xen_hvm_init_time_ops(void)
+ 	x86_platform.get_wallclock = xen_get_wallclock;
+ 	x86_platform.set_wallclock = xen_set_wallclock;
+ }
+-
++#endif
+diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
+index f65d2c9..96572e2 100644
+--- a/drivers/xen/Kconfig
++++ b/drivers/xen/Kconfig
+@@ -64,7 +64,7 @@ config XEN_SYS_HYPERVISOR
+ 
+ config XEN_PLATFORM_PCI
+ 	tristate "xen platform pci device driver"
+-	depends on XEN
++	depends on XEN_PVHVM
+ 	default m
+ 	help
+ 	  Driver for the Xen PCI Platform device: it is responsible for
+diff --git a/drivers/xen/events.c b/drivers/xen/events.c
+index da01209..5d25cdf 100644
+--- a/drivers/xen/events.c
++++ b/drivers/xen/events.c
+@@ -968,6 +968,7 @@ int xen_set_callback_via(uint64_t via)
+ }
+ EXPORT_SYMBOL_GPL(xen_set_callback_via);
+ 
++#ifdef CONFIG_XEN_PVHVM
+ /* Vector callbacks are better than PCI interrupts to receive event
+  * channel notifications because we can receive vector callbacks on any
+  * vcpu and we don't need PCI support or APIC interactions. */
+@@ -991,6 +992,9 @@ void xen_callback_vector(void)
+ 			alloc_intr_gate(XEN_HVM_EVTCHN_CALLBACK, xen_hvm_callback_vector);
+ 	}
+ }
++#else
++void xen_callback_vector(void) {}
++#endif
+ 
+ void __init xen_init_IRQ(void)
+ {
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0001-xen-Add-support-for-HVM-hypercalls.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0001-xen-Add-support-for-HVM-hypercalls.patch
@@ -0,0 +1,211 @@
+From f1d25fa1b16536b1dfe8ee41fd152b6960d618a1 Mon Sep 17 00:00:00 2001
+From: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+Date: Fri, 14 May 2010 12:38:24 +0100
+Subject: [PATCH] xen: Add support for HVM hypercalls.
+
+Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+Signed-off-by: Sheng Yang <sheng@linux.intel.com>
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+(cherry picked from commit 18f19aa62a267f2f759e278018f1032adf4c3774)
+---
+ arch/x86/include/asm/xen/hypercall.h |    6 ++
+ include/xen/hvm.h                    |   24 +++++++++
+ include/xen/interface/hvm/hvm_op.h   |   35 ++++++++++++
+ include/xen/interface/hvm/params.h   |   95 ++++++++++++++++++++++++++++++++++
+ 4 files changed, 160 insertions(+), 0 deletions(-)
+ create mode 100644 include/xen/hvm.h
+ create mode 100644 include/xen/interface/hvm/hvm_op.h
+ create mode 100644 include/xen/interface/hvm/params.h
+
+diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
+index 9c371e4..7fda040 100644
+--- a/arch/x86/include/asm/xen/hypercall.h
++++ b/arch/x86/include/asm/xen/hypercall.h
+@@ -417,6 +417,12 @@ HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
+ 	return _hypercall2(int, nmi_op, op, arg);
+ }
+ 
++static inline unsigned long __must_check
++HYPERVISOR_hvm_op(int op, void *arg)
++{
++       return _hypercall2(unsigned long, hvm_op, op, arg);
++}
++
+ static inline void
+ MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
+ {
+diff --git a/include/xen/hvm.h b/include/xen/hvm.h
+new file mode 100644
+index 0000000..5dfe8fb
+--- /dev/null
++++ b/include/xen/hvm.h
+@@ -0,0 +1,24 @@
++/* Simple wrappers around HVM functions */
++#ifndef XEN_HVM_H__
++#define XEN_HVM_H__
++
++#include <xen/interface/hvm/params.h>
++
++static inline int hvm_get_parameter(int idx, uint64_t *value)
++{
++	struct xen_hvm_param xhv;
++	int r;
++
++	xhv.domid = DOMID_SELF;
++	xhv.index = idx;
++	r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
++	if (r < 0) {
++		printk(KERN_ERR "Cannot get hvm parameter %d: %d!\n",
++			idx, r);
++		return r;
++	}
++	*value = xhv.value;
++	return r;
++}
++
++#endif /* XEN_HVM_H__ */
+diff --git a/include/xen/interface/hvm/hvm_op.h b/include/xen/interface/hvm/hvm_op.h
+new file mode 100644
+index 0000000..73c8c7e
+--- /dev/null
++++ b/include/xen/interface/hvm/hvm_op.h
+@@ -0,0 +1,35 @@
++/*
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __XEN_PUBLIC_HVM_HVM_OP_H__
++#define __XEN_PUBLIC_HVM_HVM_OP_H__
++
++/* Get/set subcommands: the second argument of the hypercall is a
++ * pointer to a xen_hvm_param struct. */
++#define HVMOP_set_param           0
++#define HVMOP_get_param           1
++struct xen_hvm_param {
++    domid_t  domid;    /* IN */
++    uint32_t index;    /* IN */
++    uint64_t value;    /* IN/OUT */
++};
++DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_param);
++
++#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
+diff --git a/include/xen/interface/hvm/params.h b/include/xen/interface/hvm/params.h
+new file mode 100644
+index 0000000..1888d8c
+--- /dev/null
++++ b/include/xen/interface/hvm/params.h
+@@ -0,0 +1,95 @@
++/*
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __XEN_PUBLIC_HVM_PARAMS_H__
++#define __XEN_PUBLIC_HVM_PARAMS_H__
++
++#include "hvm_op.h"
++
++/*
++ * Parameter space for HVMOP_{set,get}_param.
++ */
++
++/*
++ * How should CPU0 event-channel notifications be delivered?
++ * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt).
++ * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows:
++ *                  Domain = val[47:32], Bus  = val[31:16],
++ *                  DevFn  = val[15: 8], IntX = val[ 1: 0]
++ * val[63:56] == 2: val[7:0] is a vector number.
++ * If val == 0 then CPU0 event-channel notifications are not delivered.
++ */
++#define HVM_PARAM_CALLBACK_IRQ 0
++
++#define HVM_PARAM_STORE_PFN    1
++#define HVM_PARAM_STORE_EVTCHN 2
++
++#define HVM_PARAM_PAE_ENABLED  4
++
++#define HVM_PARAM_IOREQ_PFN    5
++
++#define HVM_PARAM_BUFIOREQ_PFN 6
++
++/*
++ * Set mode for virtual timers (currently x86 only):
++ *  delay_for_missed_ticks (default):
++ *   Do not advance a vcpu's time beyond the correct delivery time for
++ *   interrupts that have been missed due to preemption. Deliver missed
++ *   interrupts when the vcpu is rescheduled and advance the vcpu's virtual
++ *   time stepwise for each one.
++ *  no_delay_for_missed_ticks:
++ *   As above, missed interrupts are delivered, but guest time always tracks
++ *   wallclock (i.e., real) time while doing so.
++ *  no_missed_ticks_pending:
++ *   No missed interrupts are held pending. Instead, to ensure ticks are
++ *   delivered at some non-zero rate, if we detect missed ticks then the
++ *   internal tick alarm is not disabled if the VCPU is preempted during the
++ *   next tick period.
++ *  one_missed_tick_pending:
++ *   Missed interrupts are collapsed together and delivered as one 'late tick'.
++ *   Guest time always tracks wallclock (i.e., real) time.
++ */
++#define HVM_PARAM_TIMER_MODE   10
++#define HVMPTM_delay_for_missed_ticks    0
++#define HVMPTM_no_delay_for_missed_ticks 1
++#define HVMPTM_no_missed_ticks_pending   2
++#define HVMPTM_one_missed_tick_pending   3
++
++/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */
++#define HVM_PARAM_HPET_ENABLED 11
++
++/* Identity-map page directory used by Intel EPT when CR0.PG=0. */
++#define HVM_PARAM_IDENT_PT     12
++
++/* Device Model domain, defaults to 0. */
++#define HVM_PARAM_DM_DOMAIN    13
++
++/* ACPI S state: currently support S0 and S3 on x86. */
++#define HVM_PARAM_ACPI_S_STATE 14
++
++/* TSS used on Intel when CR0.PE=0. */
++#define HVM_PARAM_VM86_TSS     15
++
++/* Boolean: Enable aligning all periodic vpts to reduce interrupts */
++#define HVM_PARAM_VPT_ALIGN    16
++
++#define HVM_NR_PARAMS          17
++
++#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0014-pvops-do-not-notify-callers-from-register_xenstore_.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0014-pvops-do-not-notify-callers-from-register_xenstore_.patch
@@ -0,0 +1,40 @@
+From abba540857dfa5e583dbcab78887b139f2e79cc3 Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Date: Fri, 16 Jul 2010 17:30:19 +0100
+Subject: [PATCH] pvops: do not notify callers from register_xenstore_notifier
+
+Currently register_xenstore_notifier notifies the caller during the
+registration itself if xenstore is believed to be ready. This behaviour
+causes problems to PV on HVM guests, in which case callers should be
+notified by xenbus_probe only after the platform pci driver is loaded.
+We already make sure xenbus_probe is called at the right time, calling
+it either from device_initcall (PV case) or from the platform pci
+driver initialization (HVM case) so we don't need this additional
+notification.
+
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+(cherry picked from commit 31de189f7d02da163f77d46a86d9e655a2d83124)
+---
+ drivers/xen/xenbus/xenbus_probe.c |    5 +----
+ 1 files changed, 1 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
+index 840c9ff..f52baf3 100644
+--- a/drivers/xen/xenbus/xenbus_probe.c
++++ b/drivers/xen/xenbus/xenbus_probe.c
+@@ -752,10 +752,7 @@ int register_xenstore_notifier(struct notifier_block *nb)
+ {
+ 	int ret = 0;
+ 
+-	if (xenstored_ready > 0)
+-		ret = nb->notifier_call(nb, 0, NULL);
+-	else
+-		blocking_notifier_chain_register(&xenstore_chain, nb);
++	blocking_notifier_chain_register(&xenstore_chain, nb);
+ 
+ 	return ret;
+ }
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0007-x86-Use-xen_vcpuop_clockevent-xen_clocksource-and.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0007-x86-Use-xen_vcpuop_clockevent-xen_clocksource-and.patch
@@ -0,0 +1,227 @@
+From 4d1f4d2b8923a2a94f70e3efb9002eaa50ee7e24 Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Date: Fri, 14 May 2010 12:48:19 +0100
+Subject: [PATCH] x86: Use xen_vcpuop_clockevent, xen_clocksource and xen wallclock.
+
+Use xen_vcpuop_clockevent instead of hpet and APIC timers as main
+clockevent device on all vcpus, use the xen wallclock time as wallclock
+instead of rtc and use xen_clocksource as clocksource.
+The pv clock algorithm needs to work correctly for the xen_clocksource
+and xen wallclock to be usable, only modern Xen versions offer a
+reliable pv clock in HVM guests (XENFEAT_hvm_safe_pvclock).
+
+Using the hpet as clocksource means a VMEXIT every time we read/write to
+the hpet mmio addresses, pvclock give us a better rating without
+VMEXITs. Same goes for the xen wallclock and xen_vcpuop_clockevent
+
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Signed-off-by: Don Dutile <ddutile@redhat.com>
+Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+(cherry picked from commit 409771d258e9dd71c30f3c9520fd2b796ffc40f0, conflict
+resolution arising from addition of 8a22b9996b001c88f2bfb54c6de6a05fc39e177a to
+2.6.32.18)
+---
+ arch/x86/xen/enlighten.c         |   14 +--------
+ arch/x86/xen/suspend.c           |    6 ++++
+ arch/x86/xen/time.c              |   56 +++++++++++++++++++++++++++++++++++---
+ arch/x86/xen/xen-ops.h           |    7 +---
+ include/xen/interface/features.h |    3 ++
+ 5 files changed, 65 insertions(+), 21 deletions(-)
+
+diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
+index 18205eb..97901b1 100644
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -931,10 +931,6 @@ static const struct pv_init_ops xen_init_ops __initdata = {
+ 	.patch = xen_patch,
+ };
+ 
+-static const struct pv_time_ops xen_time_ops __initdata = {
+-	.sched_clock = xen_clocksource_read,
+-};
+-
+ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
+ 	.cpuid = xen_cpuid,
+ 
+@@ -1072,7 +1068,6 @@ asmlinkage void __init xen_start_kernel(void)
+ 	/* Install Xen paravirt ops */
+ 	pv_info = xen_info;
+ 	pv_init_ops = xen_init_ops;
+-	pv_time_ops = xen_time_ops;
+ 	pv_cpu_ops = xen_cpu_ops;
+ 	pv_apic_ops = xen_apic_ops;
+ 
+@@ -1080,13 +1075,7 @@ asmlinkage void __init xen_start_kernel(void)
+ 	x86_init.oem.arch_setup = xen_arch_setup;
+ 	x86_init.oem.banner = xen_banner;
+ 
+-	x86_init.timers.timer_init = xen_time_init;
+-	x86_init.timers.setup_percpu_clockev = x86_init_noop;
+-	x86_cpuinit.setup_percpu_clockev = x86_init_noop;
+-
+-	x86_platform.calibrate_tsc = xen_tsc_khz;
+-	x86_platform.get_wallclock = xen_get_wallclock;
+-	x86_platform.set_wallclock = xen_set_wallclock;
++	xen_init_time_ops();
+ 
+ 	/*
+ 	 * Set up some pagetable state before starting to set any ptes.
+@@ -1317,4 +1306,5 @@ void __init xen_hvm_guest_init(void)
+ 	register_cpu_notifier(&xen_hvm_cpu_notifier);
+ 	have_vcpu_info_placement = 0;
+ 	x86_init.irqs.intr_init = xen_init_IRQ;
++	xen_hvm_init_time_ops();
+ }
+diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
+index d07479c..1d789d5 100644
+--- a/arch/x86/xen/suspend.c
++++ b/arch/x86/xen/suspend.c
+@@ -28,8 +28,14 @@ void xen_pre_suspend(void)
+ 
+ void xen_hvm_post_suspend(int suspend_cancelled)
+ {
++	int cpu;
+ 	xen_hvm_init_shared_info();
+ 	xen_callback_vector();
++	if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
++		for_each_online_cpu(cpu) {
++			xen_setup_runstate_info(cpu);
++		}
++	}
+ }
+ 
+ void xen_post_suspend(int suspend_cancelled)
+diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
+index 8e04980..7e47d09 100644
+--- a/arch/x86/xen/time.c
++++ b/arch/x86/xen/time.c
+@@ -19,6 +19,7 @@
+ #include <asm/xen/hypercall.h>
+ 
+ #include <xen/events.h>
++#include <xen/features.h>
+ #include <xen/interface/xen.h>
+ #include <xen/interface/vcpu.h>
+ 
+@@ -155,7 +156,7 @@ static void do_stolen_accounting(void)
+ }
+ 
+ /* Get the TSC speed from Xen */
+-unsigned long xen_tsc_khz(void)
++static unsigned long xen_tsc_khz(void)
+ {
+ 	struct pvclock_vcpu_time_info *info =
+ 		&HYPERVISOR_shared_info->vcpu_info[0].time;
+@@ -190,7 +191,7 @@ static void xen_read_wallclock(struct timespec *ts)
+ 	put_cpu_var(xen_vcpu);
+ }
+ 
+-unsigned long xen_get_wallclock(void)
++static unsigned long xen_get_wallclock(void)
+ {
+ 	struct timespec ts;
+ 
+@@ -198,7 +199,7 @@ unsigned long xen_get_wallclock(void)
+ 	return ts.tv_sec;
+ }
+ 
+-int xen_set_wallclock(unsigned long now)
++static int xen_set_wallclock(unsigned long now)
+ {
+ 	/* do nothing for domU */
+ 	return -1;
+@@ -433,7 +434,11 @@ void xen_timer_resume(void)
+ 	}
+ }
+ 
+-__init void xen_time_init(void)
++static const struct pv_time_ops xen_time_ops __initdata = {
++	.sched_clock = xen_clocksource_read,
++};
++
++static __init void xen_time_init(void)
+ {
+ 	int cpu = smp_processor_id();
+ 
+@@ -457,3 +462,46 @@ __init void xen_time_init(void)
+ 	xen_setup_timer(cpu);
+ 	xen_setup_cpu_clockevents();
+ }
++
++__init void xen_init_time_ops(void)
++{
++	pv_time_ops = xen_time_ops;
++
++	x86_init.timers.timer_init = xen_time_init;
++	x86_init.timers.setup_percpu_clockev = x86_init_noop;
++	x86_cpuinit.setup_percpu_clockev = x86_init_noop;
++
++	x86_platform.calibrate_tsc = xen_tsc_khz;
++	x86_platform.get_wallclock = xen_get_wallclock;
++	x86_platform.set_wallclock = xen_set_wallclock;
++}
++
++static void xen_hvm_setup_cpu_clockevents(void)
++{
++	int cpu = smp_processor_id();
++	xen_setup_runstate_info(cpu);
++	xen_setup_timer(cpu);
++	xen_setup_cpu_clockevents();
++}
++
++__init void xen_hvm_init_time_ops(void)
++{
++	/* vector callback is needed otherwise we cannot receive interrupts
++	 * on cpu > 0 */
++	if (!xen_have_vector_callback && num_present_cpus() > 1)
++		return;
++	if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
++		printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
++				"disable pv timer\n");
++		return;
++	}
++
++	pv_time_ops = xen_time_ops;
++	x86_init.timers.setup_percpu_clockev = xen_time_init;
++	x86_cpuinit.setup_percpu_clockev = xen_hvm_setup_cpu_clockevents;
++
++	x86_platform.calibrate_tsc = xen_tsc_khz;
++	x86_platform.get_wallclock = xen_get_wallclock;
++	x86_platform.set_wallclock = xen_set_wallclock;
++}
++
+diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
+index 01c9dd3..089d189 100644
+--- a/arch/x86/xen/xen-ops.h
++++ b/arch/x86/xen/xen-ops.h
+@@ -49,11 +49,8 @@ void xen_setup_runstate_info(int cpu);
+ void xen_teardown_timer(int cpu);
+ cycle_t xen_clocksource_read(void);
+ void xen_setup_cpu_clockevents(void);
+-unsigned long xen_tsc_khz(void);
+-void __init xen_time_init(void);
+-unsigned long xen_get_wallclock(void);
+-int xen_set_wallclock(unsigned long time);
+-unsigned long long xen_sched_clock(void);
++void __init xen_init_time_ops(void);
++void __init xen_hvm_init_time_ops(void);
+ 
+ irqreturn_t xen_debug_interrupt(int irq, void *dev_id);
+ 
+diff --git a/include/xen/interface/features.h b/include/xen/interface/features.h
+index 8ab08b9..70d2563 100644
+--- a/include/xen/interface/features.h
++++ b/include/xen/interface/features.h
+@@ -44,6 +44,9 @@
+ /* x86: Does this Xen host support the HVM callback vector type? */
+ #define XENFEAT_hvm_callback_vector        8
+ 
++/* x86: pvclock algorithm is safe to use on HVM */
++#define XENFEAT_hvm_safe_pvclock           9
++
+ #define XENFEAT_NR_SUBMAPS 1
+ 
+ #endif /* __XEN_PUBLIC_FEATURES_H__ */
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0003-x86-xen-event-channels-delivery-on-HVM.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0003-x86-xen-event-channels-delivery-on-HVM.patch
@@ -0,0 +1,334 @@
+From 28f65216d1a39d9e6c6b2e8e6565b4b1f72ff34f Mon Sep 17 00:00:00 2001
+From: Sheng Yang <sheng@linux.intel.com>
+Date: Fri, 14 May 2010 12:40:51 +0100
+Subject: [PATCH] x86/xen: event channels delivery on HVM.
+
+Set the callback to receive evtchns from Xen, using the
+callback vector delivery mechanism.
+
+The traditional way for receiving event channel notifications from Xen
+is via the interrupts from the platform PCI device.
+The callback vector is a newer alternative that allow us to receive
+notifications on any vcpu and doesn't need any PCI support: we allocate
+a vector exclusively to receive events, in the vector handler we don't
+need to interact with the vlapic, therefore we avoid a VMEXIT.
+
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Signed-off-by: Sheng Yang <sheng@linux.intel.com>
+Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+(cherry picked from commit 38e20b07efd541a959de367dc90a17f92ce2e8a6 with
+trivial merge conflicts resolved in arch/x86/include/asm/irq_vectors.h
+arch/x86/xen/enlighten.c)
+---
+ arch/x86/include/asm/irq_vectors.h |    3 ++
+ arch/x86/kernel/entry_32.S         |    3 ++
+ arch/x86/kernel/entry_64.S         |    3 ++
+ arch/x86/xen/enlighten.c           |   28 ++++++++++++++
+ arch/x86/xen/xen-ops.h             |    2 +
+ drivers/xen/events.c               |   69 ++++++++++++++++++++++++++++++++----
+ include/xen/events.h               |    7 ++++
+ include/xen/hvm.h                  |    6 +++
+ include/xen/interface/features.h   |    3 ++
+ 9 files changed, 117 insertions(+), 7 deletions(-)
+
+diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
+index 6e90a04..893179f 100644
+--- a/arch/x86/include/asm/irq_vectors.h
++++ b/arch/x86/include/asm/irq_vectors.h
+@@ -120,6 +120,9 @@
+  */
+ #define MCE_SELF_VECTOR			0xeb
+ 
++/* Xen vector callback to receive events in a HVM domain */
++#define XEN_HVM_EVTCHN_CALLBACK		0xe9
++
+ /*
+  * First APIC vector available to drivers: (vectors 0x30-0xee) we
+  * start at 0x31(0x41) to spread out vectors evenly between priority
+diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
+index c097e7d..7764118 100644
+--- a/arch/x86/kernel/entry_32.S
++++ b/arch/x86/kernel/entry_32.S
+@@ -1088,6 +1088,9 @@ ENTRY(xen_failsafe_callback)
+ .previous
+ ENDPROC(xen_failsafe_callback)
+ 
++BUILD_INTERRUPT3(xen_hvm_callback_vector, XEN_HVM_EVTCHN_CALLBACK,
++		xen_evtchn_do_upcall)
++
+ #endif	/* CONFIG_XEN */
+ 
+ #ifdef CONFIG_FUNCTION_TRACER
+diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
+index b5c061f..a626344 100644
+--- a/arch/x86/kernel/entry_64.S
++++ b/arch/x86/kernel/entry_64.S
+@@ -1364,6 +1364,9 @@ ENTRY(xen_failsafe_callback)
+ 	CFI_ENDPROC
+ END(xen_failsafe_callback)
+ 
++apicinterrupt XEN_HVM_EVTCHN_CALLBACK \
++	xen_hvm_callback_vector xen_evtchn_do_upcall
++
+ #endif /* CONFIG_XEN */
+ 
+ /*
+diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
+index b05e426..eeea6f4 100644
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -11,6 +11,7 @@
+  * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007
+  */
+ 
++#include <linux/cpu.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/smp.h>
+@@ -35,6 +36,7 @@
+ #include <xen/interface/memory.h>
+ #include <xen/features.h>
+ #include <xen/page.h>
++#include <xen/hvm.h>
+ #include <xen/hvc-console.h>
+ 
+ #include <asm/paravirt.h>
+@@ -77,6 +79,8 @@ struct shared_info xen_dummy_shared_info;
+ void *xen_initial_gdt;
+ 
+ RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
++__read_mostly int xen_have_vector_callback;
++EXPORT_SYMBOL_GPL(xen_have_vector_callback);
+ 
+ /*
+  * Point at some empty memory to start with. We map the real shared_info
+@@ -1268,6 +1272,24 @@ static void __init init_shared_info(void)
+ 	per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
+ }
+ 
++static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
++				    unsigned long action, void *hcpu)
++{
++	int cpu = (long)hcpu;
++	switch (action) {
++	case CPU_UP_PREPARE:
++		per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
++		break;
++	default:
++		break;
++	}
++	return NOTIFY_OK;
++}
++
++static struct notifier_block __cpuinitdata xen_hvm_cpu_notifier = {
++	.notifier_call	= xen_hvm_cpu_notify,
++};
++
+ void __init xen_hvm_guest_init(void)
+ {
+ 	int r;
+@@ -1278,4 +1300,10 @@ void __init xen_hvm_guest_init(void)
+ 		return;
+ 
+ 	init_shared_info();
++
++	if (xen_feature(XENFEAT_hvm_callback_vector))
++		xen_have_vector_callback = 1;
++	register_cpu_notifier(&xen_hvm_cpu_notifier);
++	have_vcpu_info_placement = 0;
++	x86_init.irqs.intr_init = xen_init_IRQ;
+ }
+diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
+index f9153a3..0d0e0e6 100644
+--- a/arch/x86/xen/xen-ops.h
++++ b/arch/x86/xen/xen-ops.h
+@@ -38,6 +38,8 @@ void xen_enable_sysenter(void);
+ void xen_enable_syscall(void);
+ void xen_vcpu_restore(void);
+ 
++void xen_callback_vector(void);
++
+ void __init xen_build_dynamic_phys_to_machine(void);
+ 
+ void xen_init_irq_ops(void);
+diff --git a/drivers/xen/events.c b/drivers/xen/events.c
+index 30e0467..9b03dcd 100644
+--- a/drivers/xen/events.c
++++ b/drivers/xen/events.c
+@@ -28,6 +28,7 @@
+ #include <linux/string.h>
+ #include <linux/bootmem.h>
+ 
++#include <asm/desc.h>
+ #include <asm/ptrace.h>
+ #include <asm/irq.h>
+ #include <asm/idle.h>
+@@ -35,10 +36,13 @@
+ #include <asm/xen/hypercall.h>
+ #include <asm/xen/hypervisor.h>
+ 
++#include <xen/hvm.h>
+ #include <xen/xen-ops.h>
+ #include <xen/events.h>
+ #include <xen/interface/xen.h>
+ #include <xen/interface/event_channel.h>
++#include <xen/interface/hvm/hvm_op.h>
++#include <xen/interface/hvm/params.h>
+ 
+ /*
+  * This lock protects updates to the following mapping and reference-count
+@@ -617,17 +621,13 @@ static DEFINE_PER_CPU(unsigned, xed_nesting_count);
+  * a bitset of words which contain pending event bits.  The second
+  * level is a bitset of pending events themselves.
+  */
+-void xen_evtchn_do_upcall(struct pt_regs *regs)
++static void __xen_evtchn_do_upcall(struct pt_regs *regs)
+ {
+ 	int cpu = get_cpu();
+-	struct pt_regs *old_regs = set_irq_regs(regs);
+ 	struct shared_info *s = HYPERVISOR_shared_info;
+ 	struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
+  	unsigned count;
+ 
+-	exit_idle();
+-	irq_enter();
+-
+ 	do {
+ 		unsigned long pending_words;
+ 
+@@ -663,10 +663,26 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
+ 	} while(count != 1);
+ 
+ out:
++
++	put_cpu();
++}
++
++void xen_evtchn_do_upcall(struct pt_regs *regs)
++{
++	struct pt_regs *old_regs = set_irq_regs(regs);
++
++	exit_idle();
++	irq_enter();
++
++	__xen_evtchn_do_upcall(regs);
++
+ 	irq_exit();
+ 	set_irq_regs(old_regs);
++}
+ 
+-	put_cpu();
++void xen_hvm_evtchn_do_upcall(void)
++{
++	__xen_evtchn_do_upcall(get_irq_regs());
+ }
+ 
+ /* Rebind a new event channel to an existing irq. */
+@@ -929,6 +945,40 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
+ 	.retrigger	= retrigger_dynirq,
+ };
+ 
++int xen_set_callback_via(uint64_t via)
++{
++	struct xen_hvm_param a;
++	a.domid = DOMID_SELF;
++	a.index = HVM_PARAM_CALLBACK_IRQ;
++	a.value = via;
++	return HYPERVISOR_hvm_op(HVMOP_set_param, &a);
++}
++EXPORT_SYMBOL_GPL(xen_set_callback_via);
++
++/* Vector callbacks are better than PCI interrupts to receive event
++ * channel notifications because we can receive vector callbacks on any
++ * vcpu and we don't need PCI support or APIC interactions. */
++void xen_callback_vector(void)
++{
++	int rc;
++	uint64_t callback_via;
++	if (xen_have_vector_callback) {
++		callback_via = HVM_CALLBACK_VECTOR(XEN_HVM_EVTCHN_CALLBACK);
++		rc = xen_set_callback_via(callback_via);
++		if (rc) {
++			printk(KERN_ERR "Request for Xen HVM callback vector"
++					" failed.\n");
++			xen_have_vector_callback = 0;
++			return;
++		}
++		printk(KERN_INFO "Xen HVM callback vector for event delivery is "
++				"enabled\n");
++		/* in the restore case the vector has already been allocated */
++		if (!test_bit(XEN_HVM_EVTCHN_CALLBACK, used_vectors))
++			alloc_intr_gate(XEN_HVM_EVTCHN_CALLBACK, xen_hvm_callback_vector);
++	}
++}
++
+ void __init xen_init_IRQ(void)
+ {
+ 	int i;
+@@ -943,5 +993,10 @@ void __init xen_init_IRQ(void)
+ 	for (i = 0; i < NR_EVENT_CHANNELS; i++)
+ 		mask_evtchn(i);
+ 
+-	irq_ctx_init(smp_processor_id());
++	if (xen_hvm_domain()) {
++		xen_callback_vector();
++		native_init_IRQ();
++	} else {
++		irq_ctx_init(smp_processor_id());
++	}
+ }
+diff --git a/include/xen/events.h b/include/xen/events.h
+index e68d59a..a15d932 100644
+--- a/include/xen/events.h
++++ b/include/xen/events.h
+@@ -56,4 +56,11 @@ void xen_poll_irq(int irq);
+ /* Determine the IRQ which is bound to an event channel */
+ unsigned irq_from_evtchn(unsigned int evtchn);
+ 
++/* Xen HVM evtchn vector callback */
++extern void xen_hvm_callback_vector(void);
++extern int xen_have_vector_callback;
++int xen_set_callback_via(uint64_t via);
++void xen_evtchn_do_upcall(struct pt_regs *regs);
++void xen_hvm_evtchn_do_upcall(void);
++
+ #endif	/* _XEN_EVENTS_H */
+diff --git a/include/xen/hvm.h b/include/xen/hvm.h
+index 5dfe8fb..b193fa2 100644
+--- a/include/xen/hvm.h
++++ b/include/xen/hvm.h
+@@ -3,6 +3,7 @@
+ #define XEN_HVM_H__
+ 
+ #include <xen/interface/hvm/params.h>
++#include <asm/xen/hypercall.h>
+ 
+ static inline int hvm_get_parameter(int idx, uint64_t *value)
+ {
+@@ -21,4 +22,9 @@ static inline int hvm_get_parameter(int idx, uint64_t *value)
+ 	return r;
+ }
+ 
++#define HVM_CALLBACK_VIA_TYPE_VECTOR 0x2
++#define HVM_CALLBACK_VIA_TYPE_SHIFT 56
++#define HVM_CALLBACK_VECTOR(x) (((uint64_t)HVM_CALLBACK_VIA_TYPE_VECTOR)<<\
++		HVM_CALLBACK_VIA_TYPE_SHIFT | (x))
++
+ #endif /* XEN_HVM_H__ */
+diff --git a/include/xen/interface/features.h b/include/xen/interface/features.h
+index f51b641..8ab08b9 100644
+--- a/include/xen/interface/features.h
++++ b/include/xen/interface/features.h
+@@ -41,6 +41,9 @@
+ /* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */
+ #define XENFEAT_mmu_pt_update_preserve_ad  5
+ 
++/* x86: Does this Xen host support the HVM callback vector type? */
++#define XENFEAT_hvm_callback_vector        8
++
+ #define XENFEAT_NR_SUBMAPS 1
+ 
+ #endif /* __XEN_PUBLIC_FEATURES_H__ */
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0004-xen-Xen-PCI-platform-device-driver.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0004-xen-Xen-PCI-platform-device-driver.patch
@@ -0,0 +1,564 @@
+From 6276c48133ff6cd2dade40da4e89d1e45d374b39 Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Date: Mon, 17 May 2010 17:08:21 +0100
+Subject: [PATCH] xen: Xen PCI platform device driver.
+
+Add the xen pci platform device driver that is responsible
+for initializing the grant table and xenbus in PV on HVM mode.
+Few changes to xenbus and grant table are necessary to allow the delayed
+initialization in HVM mode.
+Grant table needs few additional modifications to work in HVM mode.
+
+The Xen PCI platform device raises an irq every time an event has been
+delivered to us. However these interrupts are only delivered to vcpu 0.
+The Xen PCI platform interrupt handler calls xen_hvm_evtchn_do_upcall
+that is a little wrapper around __xen_evtchn_do_upcall, the traditional
+Xen upcall handler, the very same used with traditional PV guests.
+
+When running on HVM the event channel upcall is never called while in
+progress because it is a normal Linux irq handler (and we cannot switch
+the irq chip wholesale to the Xen PV ones as we are running QEMU and
+might have passed in PCI devices), therefore we cannot be sure that
+evtchn_upcall_pending is 0 when returning.
+For this reason if evtchn_upcall_pending is set by Xen we need to loop
+again on the event channels set pending otherwise we might loose some
+event channel deliveries.
+
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Signed-off-by: Sheng Yang <sheng@linux.intel.com>
+Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+(cherry picked from commit 183d03cc4ff39e0f0d952c09aa96d0abfd6e0c3c with
+trivial merge conflict resolved in drivers/xen/Kconfig)
+---
+ drivers/xen/Kconfig                 |   12 ++-
+ drivers/xen/Makefile                |    3 +-
+ drivers/xen/events.c                |    8 +-
+ drivers/xen/grant-table.c           |   77 +++++++++++++--
+ drivers/xen/manage.c                |    1 +
+ drivers/xen/platform-pci.c          |  181 +++++++++++++++++++++++++++++++++++
+ drivers/xen/xenbus/xenbus_probe.c   |   22 ++++-
+ include/linux/pci_ids.h             |    3 +
+ include/xen/grant_table.h           |    4 +
+ include/xen/interface/grant_table.h |    1 +
+ 10 files changed, 293 insertions(+), 19 deletions(-)
+ create mode 100644 drivers/xen/platform-pci.c
+
+diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
+index cab100a..f65d2c9 100644
+--- a/drivers/xen/Kconfig
++++ b/drivers/xen/Kconfig
+@@ -60,4 +60,14 @@ config XEN_SYS_HYPERVISOR
+          Create entries under /sys/hypervisor describing the Xen
+ 	 hypervisor environment.  When running native or in another
+ 	 virtual environment, /sys/hypervisor will still be present,
+-	 but will have no xen contents.
+\ No newline at end of file
++	 but will have no xen contents.
++
++config XEN_PLATFORM_PCI
++	tristate "xen platform pci device driver"
++	depends on XEN
++	default m
++	help
++	  Driver for the Xen PCI Platform device: it is responsible for
++	  initializing xenbus and grant_table when running in a Xen HVM
++	  domain. As a consequence this driver is required to run any Xen PV
++	  frontend on Xen HVM.
+diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
+index 7c28434..e392fb7 100644
+--- a/drivers/xen/Makefile
++++ b/drivers/xen/Makefile
+@@ -9,4 +9,5 @@ obj-$(CONFIG_XEN_XENCOMM)	+= xencomm.o
+ obj-$(CONFIG_XEN_BALLOON)	+= balloon.o
+ obj-$(CONFIG_XEN_DEV_EVTCHN)	+= evtchn.o
+ obj-$(CONFIG_XENFS)		+= xenfs/
+-obj-$(CONFIG_XEN_SYS_HYPERVISOR)	+= sys-hypervisor.o
+\ No newline at end of file
++obj-$(CONFIG_XEN_SYS_HYPERVISOR)	+= sys-hypervisor.o
++obj-$(CONFIG_XEN_PLATFORM_PCI)	+= platform-pci.o
+diff --git a/drivers/xen/events.c b/drivers/xen/events.c
+index 9b03dcd..9d99c9a 100644
+--- a/drivers/xen/events.c
++++ b/drivers/xen/events.c
+@@ -660,7 +660,7 @@ static void __xen_evtchn_do_upcall(struct pt_regs *regs)
+ 
+ 		count = __get_cpu_var(xed_nesting_count);
+ 		__get_cpu_var(xed_nesting_count) = 0;
+-	} while(count != 1);
++	} while (count != 1 || vcpu_info->evtchn_upcall_pending);
+ 
+ out:
+ 
+@@ -684,6 +684,7 @@ void xen_hvm_evtchn_do_upcall(void)
+ {
+ 	__xen_evtchn_do_upcall(get_irq_regs());
+ }
++EXPORT_SYMBOL_GPL(xen_hvm_evtchn_do_upcall);
+ 
+ /* Rebind a new event channel to an existing irq. */
+ void rebind_evtchn_irq(int evtchn, int irq)
+@@ -720,7 +721,10 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
+ 	struct evtchn_bind_vcpu bind_vcpu;
+ 	int evtchn = evtchn_from_irq(irq);
+ 
+-	if (!VALID_EVTCHN(evtchn))
++	/* events delivered via platform PCI interrupts are always
++	 * routed to vcpu 0 */
++	if (!VALID_EVTCHN(evtchn) ||
++		(xen_hvm_domain() && !xen_have_vector_callback))
+ 		return -1;
+ 
+ 	/* Send future instances of this interrupt to other vcpu. */
+diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
+index 7d8f531..6652ce9 100644
+--- a/drivers/xen/grant-table.c
++++ b/drivers/xen/grant-table.c
+@@ -36,10 +36,12 @@
+ #include <linux/mm.h>
+ #include <linux/vmalloc.h>
+ #include <linux/uaccess.h>
++#include <linux/io.h>
+ 
+ #include <xen/interface/xen.h>
+ #include <xen/page.h>
+ #include <xen/grant_table.h>
++#include <xen/interface/memory.h>
+ #include <asm/xen/hypercall.h>
+ 
+ #include <asm/pgtable.h>
+@@ -57,6 +59,8 @@ static unsigned int boot_max_nr_grant_frames;
+ static int gnttab_free_count;
+ static grant_ref_t gnttab_free_head;
+ static DEFINE_SPINLOCK(gnttab_list_lock);
++unsigned long xen_hvm_resume_frames;
++EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
+ 
+ static struct grant_entry *shared;
+ 
+@@ -431,7 +435,7 @@ static unsigned int __max_nr_grant_frames(void)
+ 	return query.max_nr_frames;
+ }
+ 
+-static inline unsigned int max_nr_grant_frames(void)
++unsigned int gnttab_max_grant_frames(void)
+ {
+ 	unsigned int xen_max = __max_nr_grant_frames();
+ 
+@@ -439,6 +443,7 @@ static inline unsigned int max_nr_grant_frames(void)
+ 		return boot_max_nr_grant_frames;
+ 	return xen_max;
+ }
++EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
+ 
+ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+ {
+@@ -447,6 +452,30 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+ 	unsigned int nr_gframes = end_idx + 1;
+ 	int rc;
+ 
++	if (xen_hvm_domain()) {
++		struct xen_add_to_physmap xatp;
++		unsigned int i = end_idx;
++		rc = 0;
++		/*
++		 * Loop backwards, so that the first hypercall has the largest
++		 * index, ensuring that the table will grow only once.
++		 */
++		do {
++			xatp.domid = DOMID_SELF;
++			xatp.idx = i;
++			xatp.space = XENMAPSPACE_grant_table;
++			xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i;
++			rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
++			if (rc != 0) {
++				printk(KERN_WARNING
++						"grant table add_to_physmap failed, err=%d\n", rc);
++				break;
++			}
++		} while (i-- > start_idx);
++
++		return rc;
++	}
++
+ 	frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
+ 	if (!frames)
+ 		return -ENOMEM;
+@@ -463,7 +492,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+ 
+ 	BUG_ON(rc || setup.status);
+ 
+-	rc = arch_gnttab_map_shared(frames, nr_gframes, max_nr_grant_frames(),
++	rc = arch_gnttab_map_shared(frames, nr_gframes, gnttab_max_grant_frames(),
+ 				    &shared);
+ 	BUG_ON(rc);
+ 
+@@ -474,9 +503,27 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+ 
+ int gnttab_resume(void)
+ {
+-	if (max_nr_grant_frames() < nr_grant_frames)
++	unsigned int max_nr_gframes;
++
++	max_nr_gframes = gnttab_max_grant_frames();
++	if (max_nr_gframes < nr_grant_frames)
+ 		return -ENOSYS;
+-	return gnttab_map(0, nr_grant_frames - 1);
++
++	if (xen_pv_domain())
++		return gnttab_map(0, nr_grant_frames - 1);
++
++	if (!shared) {
++		shared = ioremap(xen_hvm_resume_frames, PAGE_SIZE * max_nr_gframes);
++		if (shared == NULL) {
++			printk(KERN_WARNING
++					"Failed to ioremap gnttab share frames!");
++			return -ENOMEM;
++		}
++	}
++
++	gnttab_map(0, nr_grant_frames - 1);
++
++	return 0;
+ }
+ 
+ int gnttab_suspend(void)
+@@ -493,7 +540,7 @@ static int gnttab_expand(unsigned int req_entries)
+ 	cur = nr_grant_frames;
+ 	extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
+ 		 GREFS_PER_GRANT_FRAME);
+-	if (cur + extra > max_nr_grant_frames())
++	if (cur + extra > gnttab_max_grant_frames())
+ 		return -ENOSPC;
+ 
+ 	rc = gnttab_map(cur, cur + extra - 1);
+@@ -503,15 +550,12 @@ static int gnttab_expand(unsigned int req_entries)
+ 	return rc;
+ }
+ 
+-static int __devinit gnttab_init(void)
++int gnttab_init(void)
+ {
+ 	int i;
+ 	unsigned int max_nr_glist_frames, nr_glist_frames;
+ 	unsigned int nr_init_grefs;
+ 
+-	if (!xen_domain())
+-		return -ENODEV;
+-
+ 	nr_grant_frames = 1;
+ 	boot_max_nr_grant_frames = __max_nr_grant_frames();
+ 
+@@ -554,5 +598,18 @@ static int __devinit gnttab_init(void)
+ 	kfree(gnttab_list);
+ 	return -ENOMEM;
+ }
++EXPORT_SYMBOL_GPL(gnttab_init);
++
++static int __devinit __gnttab_init(void)
++{
++	/* Delay grant-table initialization in the PV on HVM case */
++	if (xen_hvm_domain())
++		return 0;
++
++	if (!xen_pv_domain())
++		return -ENODEV;
++
++	return gnttab_init();
++}
+ 
+-core_initcall(gnttab_init);
++core_initcall(__gnttab_init);
+diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
+index 5d42d55..95e7b32 100644
+--- a/drivers/xen/manage.c
++++ b/drivers/xen/manage.c
+@@ -269,5 +269,6 @@ static int __init setup_shutdown_event(void)
+ 
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
+ 
+ subsys_initcall(setup_shutdown_event);
+diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
+new file mode 100644
+index 0000000..a0ee5d0
+--- /dev/null
++++ b/drivers/xen/platform-pci.c
+@@ -0,0 +1,181 @@
++/******************************************************************************
++ * platform-pci.c
++ *
++ * Xen platform PCI device driver
++ * Copyright (c) 2005, Intel Corporation.
++ * Copyright (c) 2007, XenSource Inc.
++ * Copyright (c) 2010, Citrix
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
++ * Place - Suite 330, Boston, MA 02111-1307 USA.
++ *
++ */
++
++
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++
++#include <xen/grant_table.h>
++#include <xen/xenbus.h>
++#include <xen/events.h>
++#include <xen/hvm.h>
++
++#define DRV_NAME    "xen-platform-pci"
++
++MODULE_AUTHOR("ssmith@xensource.com and stefano.stabellini@eu.citrix.com");
++MODULE_DESCRIPTION("Xen platform PCI device");
++MODULE_LICENSE("GPL");
++
++static unsigned long platform_mmio;
++static unsigned long platform_mmio_alloc;
++static unsigned long platform_mmiolen;
++
++unsigned long alloc_xen_mmio(unsigned long len)
++{
++	unsigned long addr;
++
++	addr = platform_mmio + platform_mmio_alloc;
++	platform_mmio_alloc += len;
++	BUG_ON(platform_mmio_alloc > platform_mmiolen);
++
++	return addr;
++}
++
++static uint64_t get_callback_via(struct pci_dev *pdev)
++{
++	u8 pin;
++	int irq;
++
++	irq = pdev->irq;
++	if (irq < 16)
++		return irq; /* ISA IRQ */
++
++	pin = pdev->pin;
++
++	/* We don't know the GSI. Specify the PCI INTx line instead. */
++	return ((uint64_t)0x01 << 56) | /* PCI INTx identifier */
++		((uint64_t)pci_domain_nr(pdev->bus) << 32) |
++		((uint64_t)pdev->bus->number << 16) |
++		((uint64_t)(pdev->devfn & 0xff) << 8) |
++		((uint64_t)(pin - 1) & 3);
++}
++
++static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id)
++{
++	xen_hvm_evtchn_do_upcall();
++	return IRQ_HANDLED;
++}
++
++static int xen_allocate_irq(struct pci_dev *pdev)
++{
++	return request_irq(pdev->irq, do_hvm_evtchn_intr,
++			IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
++			"xen-platform-pci", pdev);
++}
++
++static int __devinit platform_pci_init(struct pci_dev *pdev,
++				       const struct pci_device_id *ent)
++{
++	int i, ret;
++	long ioaddr, iolen;
++	long mmio_addr, mmio_len;
++	uint64_t callback_via;
++	unsigned int max_nr_gframes;
++
++	i = pci_enable_device(pdev);
++	if (i)
++		return i;
++
++	ioaddr = pci_resource_start(pdev, 0);
++	iolen = pci_resource_len(pdev, 0);
++
++	mmio_addr = pci_resource_start(pdev, 1);
++	mmio_len = pci_resource_len(pdev, 1);
++
++	if (mmio_addr == 0 || ioaddr == 0) {
++		dev_err(&pdev->dev, "no resources found\n");
++		ret = -ENOENT;
++		goto pci_out;
++	}
++
++	if (request_mem_region(mmio_addr, mmio_len, DRV_NAME) == NULL) {
++		dev_err(&pdev->dev, "MEM I/O resource 0x%lx @ 0x%lx busy\n",
++		       mmio_addr, mmio_len);
++		ret = -EBUSY;
++		goto pci_out;
++	}
++
++	if (request_region(ioaddr, iolen, DRV_NAME) == NULL) {
++		dev_err(&pdev->dev, "I/O resource 0x%lx @ 0x%lx busy\n",
++		       iolen, ioaddr);
++		ret = -EBUSY;
++		goto mem_out;
++	}
++
++	platform_mmio = mmio_addr;
++	platform_mmiolen = mmio_len;
++
++	if (!xen_have_vector_callback) {
++		ret = xen_allocate_irq(pdev);
++		if (ret) {
++			dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret);
++			goto out;
++		}
++		callback_via = get_callback_via(pdev);
++		ret = xen_set_callback_via(callback_via);
++		if (ret) {
++			dev_warn(&pdev->dev, "Unable to set the evtchn callback "
++					 "err=%d\n", ret);
++			goto out;
++		}
++	}
++
++	max_nr_gframes = gnttab_max_grant_frames();
++	xen_hvm_resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
++	ret = gnttab_init();
++	if (ret)
++		goto out;
++	xenbus_probe(NULL);
++	return 0;
++
++out:
++	release_region(ioaddr, iolen);
++mem_out:
++	release_mem_region(mmio_addr, mmio_len);
++pci_out:
++	pci_disable_device(pdev);
++	return ret;
++}
++
++static struct pci_device_id platform_pci_tbl[] __devinitdata = {
++	{PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM,
++		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
++	{0,}
++};
++
++MODULE_DEVICE_TABLE(pci, platform_pci_tbl);
++
++static struct pci_driver platform_driver = {
++	.name =           DRV_NAME,
++	.probe =          platform_pci_init,
++	.id_table =       platform_pci_tbl,
++};
++
++static int __init platform_pci_module_init(void)
++{
++	return pci_register_driver(&platform_driver);
++}
++
++module_init(platform_pci_module_init);
+diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
+index 568d14d..e8169db 100644
+--- a/drivers/xen/xenbus/xenbus_probe.c
++++ b/drivers/xen/xenbus/xenbus_probe.c
+@@ -778,8 +778,23 @@ void xenbus_probe(struct work_struct *unused)
+ 	/* Notify others that xenstore is up */
+ 	blocking_notifier_call_chain(&xenstore_chain, 0, NULL);
+ }
++EXPORT_SYMBOL_GPL(xenbus_probe);
+ 
+-static int __init xenbus_probe_init(void)
++static int __init xenbus_probe_initcall(void)
++{
++	if (!xen_domain())
++		return -ENODEV;
++
++	if (xen_initial_domain() || xen_hvm_domain())
++		return 0;
++
++	xenbus_probe(NULL);
++	return 0;
++}
++
++device_initcall(xenbus_probe_initcall);
++
++static int __init xenbus_init(void)
+ {
+ 	int err = 0;
+ 
+@@ -831,9 +846,6 @@ static int __init xenbus_probe_init(void)
+ 		goto out_unreg_back;
+ 	}
+ 
+-	if (!xen_initial_domain())
+-		xenbus_probe(NULL);
+-
+ #ifdef CONFIG_XEN_COMPAT_XENFS
+ 	/*
+ 	 * Create xenfs mountpoint in /proc for compatibility with
+@@ -854,7 +866,7 @@ static int __init xenbus_probe_init(void)
+ 	return err;
+ }
+ 
+-postcore_initcall(xenbus_probe_init);
++postcore_initcall(xenbus_init);
+ 
+ MODULE_LICENSE("GPL");
+ 
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index 67325bf..c398cc3 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -2712,3 +2712,6 @@
+ #define PCI_DEVICE_ID_RME_DIGI32	0x9896
+ #define PCI_DEVICE_ID_RME_DIGI32_PRO	0x9897
+ #define PCI_DEVICE_ID_RME_DIGI32_8	0x9898
++
++#define PCI_VENDOR_ID_XEN		0x5853
++#define PCI_DEVICE_ID_XEN_PLATFORM	0x0001
+diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
+index a40f1cd..9a73170 100644
+--- a/include/xen/grant_table.h
++++ b/include/xen/grant_table.h
+@@ -51,6 +51,7 @@ struct gnttab_free_callback {
+ 	u16 count;
+ };
+ 
++int gnttab_init(void);
+ int gnttab_suspend(void);
+ int gnttab_resume(void);
+ 
+@@ -112,6 +113,9 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+ void arch_gnttab_unmap_shared(struct grant_entry *shared,
+ 			      unsigned long nr_gframes);
+ 
++extern unsigned long xen_hvm_resume_frames;
++unsigned int gnttab_max_grant_frames(void);
++
+ #define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))
+ 
+ #endif /* __ASM_GNTTAB_H__ */
+diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h
+index 39da93c..39e5717 100644
+--- a/include/xen/interface/grant_table.h
++++ b/include/xen/interface/grant_table.h
+@@ -28,6 +28,7 @@
+ #ifndef __XEN_PUBLIC_GRANT_TABLE_H__
+ #define __XEN_PUBLIC_GRANT_TABLE_H__
+ 
++#include <xen/interface/xen.h>
+ 
+ /***********************************
+  * GRANT TABLE REPRESENTATION
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0008-x86-Unplug-emulated-disks-and-nics.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0008-x86-Unplug-emulated-disks-and-nics.patch
@@ -0,0 +1,378 @@
+From 58ca6e935cb9a7bf8f612feb7bfc6dcf4d531c19 Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Date: Fri, 14 May 2010 12:44:30 +0100
+Subject: [PATCH] x86: Unplug emulated disks and nics.
+
+Add a xen_emul_unplug command line option to the kernel to unplug
+xen emulated disks and nics.
+
+Set the default value of xen_emul_unplug depending on whether or
+not the Xen PV frontends and the Xen platform PCI driver have
+been compiled for this kernel (modules or built-in are both OK).
+
+The user can specify xen_emul_unplug=ignore to enable PV drivers on HVM
+even if the host platform doesn't support unplug.
+
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+(cherry picked from commit c1c5413ad58cb73267d328e6020268aa2e50d8ca)
+---
+ Documentation/kernel-parameters.txt |   11 +++
+ arch/x86/xen/Makefile               |    2 +-
+ arch/x86/xen/enlighten.c            |    1 +
+ arch/x86/xen/platform-pci-unplug.c  |  135 +++++++++++++++++++++++++++++++++++
+ arch/x86/xen/xen-ops.h              |    1 +
+ drivers/block/xen-blkfront.c        |   17 +++++
+ drivers/xen/platform-pci.c          |    6 ++
+ drivers/xen/xenbus/xenbus_probe.c   |    4 +
+ include/xen/platform_pci.h          |   49 +++++++++++++
+ 9 files changed, 225 insertions(+), 1 deletions(-)
+ create mode 100644 arch/x86/xen/platform-pci-unplug.c
+ create mode 100644 include/xen/platform_pci.h
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 5f6aa11..3e30e60 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -113,6 +113,7 @@ parameter is applicable:
+ 			More X86-64 boot options can be found in
+ 			Documentation/x86/x86_64/boot-options.txt .
+ 	X86	Either 32bit or 64bit x86 (same as X86-32+X86-64)
++	XEN	Xen support is enabled
+ 
+ In addition, the following text indicates that the option:
+ 
+@@ -2760,6 +2761,16 @@ and is between 256 and 4096 characters. It is defined in the file
+ 	xd=		[HW,XT] Original XT pre-IDE (RLL encoded) disks.
+ 	xd_geo=		See header of drivers/block/xd.c.
+ 
++	xen_emul_unplug=		[HW,X86,XEN]
++			Unplug Xen emulated devices
++			Format: [unplug0,][unplug1]
++			ide-disks -- unplug primary master IDE devices
++			aux-ide-disks -- unplug non-primary-master IDE devices
++			nics -- unplug network devices
++			all -- unplug all emulated devices (NICs and IDE disks)
++			ignore -- continue loading the Xen platform PCI driver even
++				if the version check failed
++
+ 	xirc2ps_cs=	[NET,PCMCIA]
+ 			Format:
+ 			<irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
+diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
+index 3bb4fc2..9309546 100644
+--- a/arch/x86/xen/Makefile
++++ b/arch/x86/xen/Makefile
+@@ -12,7 +12,7 @@ CFLAGS_mmu.o			:= $(nostackp)
+ 
+ obj-y		:= enlighten.o setup.o multicalls.o mmu.o irq.o \
+ 			time.o xen-asm.o xen-asm_$(BITS).o \
+-			grant-table.o suspend.o
++			grant-table.o suspend.o platform-pci-unplug.o
+ 
+ obj-$(CONFIG_SMP)		+= smp.o
+ obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
+diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
+index 97901b1..4488de1 100644
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -1304,6 +1304,7 @@ void __init xen_hvm_guest_init(void)
+ 	if (xen_feature(XENFEAT_hvm_callback_vector))
+ 		xen_have_vector_callback = 1;
+ 	register_cpu_notifier(&xen_hvm_cpu_notifier);
++	xen_unplug_emulated_devices();
+ 	have_vcpu_info_placement = 0;
+ 	x86_init.irqs.intr_init = xen_init_IRQ;
+ 	xen_hvm_init_time_ops();
+diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c
+new file mode 100644
+index 0000000..2f7f3fb
+--- /dev/null
++++ b/arch/x86/xen/platform-pci-unplug.c
+@@ -0,0 +1,135 @@
++/******************************************************************************
++ * platform-pci-unplug.c
++ *
++ * Xen platform PCI device driver
++ * Copyright (c) 2010, Citrix
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
++ * Place - Suite 330, Boston, MA 02111-1307 USA.
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/module.h>
++
++#include <xen/platform_pci.h>
++
++#define XEN_PLATFORM_ERR_MAGIC -1
++#define XEN_PLATFORM_ERR_PROTOCOL -2
++#define XEN_PLATFORM_ERR_BLACKLIST -3
++
++/* store the value of xen_emul_unplug after the unplug is done */
++int xen_platform_pci_unplug;
++EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
++static int xen_emul_unplug;
++
++static int __init check_platform_magic(void)
++{
++	short magic;
++	char protocol;
++
++	magic = inw(XEN_IOPORT_MAGIC);
++	if (magic != XEN_IOPORT_MAGIC_VAL) {
++		printk(KERN_ERR "Xen Platform PCI: unrecognised magic value\n");
++		return XEN_PLATFORM_ERR_MAGIC;
++	}
++
++	protocol = inb(XEN_IOPORT_PROTOVER);
++
++	printk(KERN_DEBUG "Xen Platform PCI: I/O protocol version %d\n",
++			protocol);
++
++	switch (protocol) {
++	case 1:
++		outw(XEN_IOPORT_LINUX_PRODNUM, XEN_IOPORT_PRODNUM);
++		outl(XEN_IOPORT_LINUX_DRVVER, XEN_IOPORT_DRVVER);
++		if (inw(XEN_IOPORT_MAGIC) != XEN_IOPORT_MAGIC_VAL) {
++			printk(KERN_ERR "Xen Platform: blacklisted by host\n");
++			return XEN_PLATFORM_ERR_BLACKLIST;
++		}
++		break;
++	default:
++		printk(KERN_WARNING "Xen Platform PCI: unknown I/O protocol version");
++		return XEN_PLATFORM_ERR_PROTOCOL;
++	}
++
++	return 0;
++}
++
++void __init xen_unplug_emulated_devices(void)
++{
++	int r;
++
++	/* check the version of the xen platform PCI device */
++	r = check_platform_magic();
++	/* If the version matches enable the Xen platform PCI driver.
++	 * Also enable the Xen platform PCI driver if the version is really old
++	 * and the user told us to ignore it. */
++	if (r && !(r == XEN_PLATFORM_ERR_MAGIC &&
++			(xen_emul_unplug & XEN_UNPLUG_IGNORE)))
++		return;
++	/* Set the default value of xen_emul_unplug depending on whether or
++	 * not the Xen PV frontends and the Xen platform PCI driver have
++	 * been compiled for this kernel (modules or built-in are both OK). */
++	if (!xen_emul_unplug) {
++		if (xen_must_unplug_nics()) {
++			printk(KERN_INFO "Netfront and the Xen platform PCI driver have "
++					"been compiled for this kernel: unplug emulated NICs.\n");
++			xen_emul_unplug |= XEN_UNPLUG_ALL_NICS;
++		}
++		if (xen_must_unplug_disks()) {
++			printk(KERN_INFO "Blkfront and the Xen platform PCI driver have "
++					"been compiled for this kernel: unplug emulated disks.\n"
++					"You might have to change the root device\n"
++					"from /dev/hd[a-d] to /dev/xvd[a-d]\n"
++					"in your root= kernel command line option\n");
++			xen_emul_unplug |= XEN_UNPLUG_ALL_IDE_DISKS;
++		}
++	}
++	/* Now unplug the emulated devices */
++	if (!(xen_emul_unplug & XEN_UNPLUG_IGNORE))
++		outw(xen_emul_unplug, XEN_IOPORT_UNPLUG);
++	xen_platform_pci_unplug = xen_emul_unplug;
++}
++
++static int __init parse_xen_emul_unplug(char *arg)
++{
++	char *p, *q;
++	int l;
++
++	for (p = arg; p; p = q) {
++		q = strchr(p, ',');
++		if (q) {
++			l = q - p;
++			q++;
++		} else {
++			l = strlen(p);
++		}
++		if (!strncmp(p, "all", l))
++			xen_emul_unplug |= XEN_UNPLUG_ALL;
++		else if (!strncmp(p, "ide-disks", l))
++			xen_emul_unplug |= XEN_UNPLUG_ALL_IDE_DISKS;
++		else if (!strncmp(p, "aux-ide-disks", l))
++			xen_emul_unplug |= XEN_UNPLUG_AUX_IDE_DISKS;
++		else if (!strncmp(p, "nics", l))
++			xen_emul_unplug |= XEN_UNPLUG_ALL_NICS;
++		else if (!strncmp(p, "ignore", l))
++			xen_emul_unplug |= XEN_UNPLUG_IGNORE;
++		else
++			printk(KERN_WARNING "unrecognised option '%s' "
++				 "in parameter 'xen_emul_unplug'\n", p);
++	}
++	return 0;
++}
++early_param("xen_emul_unplug", parse_xen_emul_unplug);
+diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
+index 089d189..ed77694 100644
+--- a/arch/x86/xen/xen-ops.h
++++ b/arch/x86/xen/xen-ops.h
+@@ -40,6 +40,7 @@ void xen_vcpu_restore(void);
+ 
+ void xen_callback_vector(void);
+ void xen_hvm_init_shared_info(void);
++void __init xen_unplug_emulated_devices(void);
+ 
+ void __init xen_build_dynamic_phys_to_machine(void);
+ 
+diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
+index b8578bb..151c560 100644
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -46,6 +46,7 @@
+ #include <xen/grant_table.h>
+ #include <xen/events.h>
+ #include <xen/page.h>
++#include <xen/platform_pci.h>
+ 
+ #include <xen/interface/grant_table.h>
+ #include <xen/interface/io/blkif.h>
+@@ -736,6 +737,22 @@ static int blkfront_probe(struct xenbus_device *dev,
+ 		}
+ 	}
+ 
++	/* no unplug has been done: do not hook devices != xen vbds */
++	if (xen_hvm_domain() && (xen_platform_pci_unplug & XEN_UNPLUG_IGNORE)) {
++		int major;
++
++		if (!VDEV_IS_EXTENDED(vdevice))
++			major = BLKIF_MAJOR(vdevice);
++		else
++			major = XENVBD_MAJOR;
++
++		if (major != XENVBD_MAJOR) {
++			printk(KERN_INFO
++					"%s: HVM does not support vbd %d as xen block device\n",
++					__FUNCTION__, vdevice);
++			return -ENODEV;
++		}
++	}
+ 	info = kzalloc(sizeof(*info), GFP_KERNEL);
+ 	if (!info) {
+ 		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
+index bdb44f2..c01b5dd 100644
+--- a/drivers/xen/platform-pci.c
++++ b/drivers/xen/platform-pci.c
+@@ -27,6 +27,7 @@
+ #include <linux/module.h>
+ #include <linux/pci.h>
+ 
++#include <xen/platform_pci.h>
+ #include <xen/grant_table.h>
+ #include <xen/xenbus.h>
+ #include <xen/events.h>
+@@ -195,6 +196,11 @@ static struct pci_driver platform_driver = {
+ 
+ static int __init platform_pci_module_init(void)
+ {
++	/* no unplug has been done, IGNORE hasn't been specified: just
++	 * return now */
++	if (!xen_platform_pci_unplug)
++		return -ENODEV;
++
+ 	return pci_register_driver(&platform_driver);
+ }
+ 
+diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
+index e8169db..840c9ff 100644
+--- a/drivers/xen/xenbus/xenbus_probe.c
++++ b/drivers/xen/xenbus/xenbus_probe.c
+@@ -53,6 +53,7 @@
+ #include <xen/events.h>
+ #include <xen/page.h>
+ 
++#include <xen/platform_pci.h>
+ #include <xen/hvm.h>
+ 
+ #include "xenbus_comms.h"
+@@ -974,6 +975,9 @@ static void wait_for_devices(struct xenbus_driver *xendrv)
+ #ifndef MODULE
+ static int __init boot_wait_for_devices(void)
+ {
++	if (xen_hvm_domain() && !xen_platform_pci_unplug)
++		return -ENODEV;
++
+ 	ready_to_wait_for_devices = 1;
+ 	wait_for_devices(NULL);
+ 	return 0;
+diff --git a/include/xen/platform_pci.h b/include/xen/platform_pci.h
+new file mode 100644
+index 0000000..ce9d671
+--- /dev/null
++++ b/include/xen/platform_pci.h
+@@ -0,0 +1,49 @@
++#ifndef _XEN_PLATFORM_PCI_H
++#define _XEN_PLATFORM_PCI_H
++
++#define XEN_IOPORT_MAGIC_VAL 0x49d2
++#define XEN_IOPORT_LINUX_PRODNUM 0x0003
++#define XEN_IOPORT_LINUX_DRVVER  0x0001
++
++#define XEN_IOPORT_BASE 0x10
++
++#define XEN_IOPORT_PLATFLAGS	(XEN_IOPORT_BASE + 0) /* 1 byte access (R/W) */
++#define XEN_IOPORT_MAGIC	(XEN_IOPORT_BASE + 0) /* 2 byte access (R) */
++#define XEN_IOPORT_UNPLUG	(XEN_IOPORT_BASE + 0) /* 2 byte access (W) */
++#define XEN_IOPORT_DRVVER	(XEN_IOPORT_BASE + 0) /* 4 byte access (W) */
++
++#define XEN_IOPORT_SYSLOG	(XEN_IOPORT_BASE + 2) /* 1 byte access (W) */
++#define XEN_IOPORT_PROTOVER	(XEN_IOPORT_BASE + 2) /* 1 byte access (R) */
++#define XEN_IOPORT_PRODNUM	(XEN_IOPORT_BASE + 2) /* 2 byte access (W) */
++
++#define XEN_UNPLUG_ALL_IDE_DISKS 1
++#define XEN_UNPLUG_ALL_NICS 2
++#define XEN_UNPLUG_AUX_IDE_DISKS 4
++#define XEN_UNPLUG_ALL 7
++#define XEN_UNPLUG_IGNORE 8
++
++static inline int xen_must_unplug_nics(void) {
++#if (defined(CONFIG_XEN_NETDEV_FRONTEND) || \
++		defined(CONFIG_XEN_NETDEV_FRONTEND_MODULE)) && \
++		(defined(CONFIG_XEN_PLATFORM_PCI) || \
++		 defined(CONFIG_XEN_PLATFORM_PCI_MODULE))
++        return 1;
++#else
++        return 0;
++#endif
++}
++
++static inline int xen_must_unplug_disks(void) {
++#if (defined(CONFIG_XEN_BLKDEV_FRONTEND) || \
++		defined(CONFIG_XEN_BLKDEV_FRONTEND_MODULE)) && \
++		(defined(CONFIG_XEN_PLATFORM_PCI) || \
++		 defined(CONFIG_XEN_PLATFORM_PCI_MODULE))
++        return 1;
++#else
++        return 0;
++#endif
++}
++
++extern int xen_platform_pci_unplug;
++
++#endif /* _XEN_PLATFORM_PCI_H */
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0012-blkfront-do-not-create-a-PV-cdrom-device-if-xen_hvm.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0012-blkfront-do-not-create-a-PV-cdrom-device-if-xen_hvm.patch
@@ -0,0 +1,70 @@
+From 9432f61005cc8bd9b62a5ab58d41ad0cb1672456 Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Date: Thu, 29 Jul 2010 14:53:16 +0100
+Subject: [PATCH] blkfront: do not create a PV cdrom device if xen_hvm_guest
+
+It is not possible to unplug emulated cdrom devices, and PV cdroms don't
+handle media insert, eject and stream, so we are better off disabling PV
+cdroms when running as a Xen HVM guest.
+
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+(cherry picked from commit b98a409b80ac510c95b4f1bafdef28edaeabd3e7)
+---
+ drivers/block/xen-blkfront.c |   39 ++++++++++++++++++++++++++-------------
+ 1 files changed, 26 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
+index 151c560..ac692c5 100644
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -737,21 +737,34 @@ static int blkfront_probe(struct xenbus_device *dev,
+ 		}
+ 	}
+ 
+-	/* no unplug has been done: do not hook devices != xen vbds */
+-	if (xen_hvm_domain() && (xen_platform_pci_unplug & XEN_UNPLUG_IGNORE)) {
+-		int major;
+-
+-		if (!VDEV_IS_EXTENDED(vdevice))
+-			major = BLKIF_MAJOR(vdevice);
+-		else
+-			major = XENVBD_MAJOR;
+-
+-		if (major != XENVBD_MAJOR) {
+-			printk(KERN_INFO
+-					"%s: HVM does not support vbd %d as xen block device\n",
+-					__FUNCTION__, vdevice);
++	if (xen_hvm_domain()) {
++		char *type;
++		int len;
++		/* no unplug has been done: do not hook devices != xen vbds */
++		if (xen_platform_pci_unplug & XEN_UNPLUG_IGNORE) {
++			int major;
++
++			if (!VDEV_IS_EXTENDED(vdevice))
++				major = BLKIF_MAJOR(vdevice);
++			else
++				major = XENVBD_MAJOR;
++
++			if (major != XENVBD_MAJOR) {
++				printk(KERN_INFO
++						"%s: HVM does not support vbd %d as xen block device\n",
++						__FUNCTION__, vdevice);
++				return -ENODEV;
++			}
++		}
++		/* do not create a PV cdrom device if we are an HVM guest */
++		type = xenbus_read(XBT_NIL, dev->nodename, "device-type", &len);
++		if (IS_ERR(type))
++			return -ENODEV;
++		if (strncmp(type, "cdrom", 5) == 0) {
++			kfree(type);
+ 			return -ENODEV;
+ 		}
++		kfree(type);
+ 	}
+ 	info = kzalloc(sizeof(*info), GFP_KERNEL);
+ 	if (!info) {
+-- 
+1.5.6.5
+
only in patch2:
unchanged:
--- linux-2.6-2.6.32.orig/debian/patches/features/all/xen/pvhvm/0005-xen-Add-suspend-resume-support-for-PV-on-HVM-guests.patch
+++ linux-2.6-2.6.32/debian/patches/features/all/xen/pvhvm/0005-xen-Add-suspend-resume-support-for-PV-on-HVM-guests.patch
@@ -0,0 +1,283 @@
+From f8d5e4640007b9e92595af70c8dcea83642ffbd2 Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Date: Fri, 14 May 2010 12:45:07 +0100
+Subject: [PATCH] xen: Add suspend/resume support for PV on HVM guests.
+
+Suspend/resume requires few different things on HVM: the suspend
+hypercall is different; we don't need to save/restore memory related
+settings; except the shared info page and the callback mechanism.
+
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+(cherry picked from commit 016b6f5fe8398b0291cece60b749d7c930a2e09c,
+ adusted for lack of hypervisor detection infrastructure)
+---
+ arch/x86/xen/enlighten.c   |   25 ++++++++++++++++++-------
+ arch/x86/xen/suspend.c     |    6 ++++++
+ arch/x86/xen/xen-ops.h     |    1 +
+ drivers/xen/manage.c       |   44 ++++++++++++++++++++++++++++++++++++++++----
+ drivers/xen/platform-pci.c |   22 +++++++++++++++++++++-
+ include/xen/xen-ops.h      |    3 +++
+ 6 files changed, 89 insertions(+), 12 deletions(-)
+
+diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
+index eeea6f4..18205eb 100644
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -78,7 +78,6 @@ struct shared_info xen_dummy_shared_info;
+ 
+ void *xen_initial_gdt;
+ 
+-RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
+ __read_mostly int xen_have_vector_callback;
+ EXPORT_SYMBOL_GPL(xen_have_vector_callback);
+ 
+@@ -1253,13 +1252,15 @@ static int init_hvm_pv_info(int *major, int *minor)
+ 	return 0;
+ }
+ 
+-static void __init init_shared_info(void)
++void xen_hvm_init_shared_info(void)
+ {
++	int cpu;
+ 	struct xen_add_to_physmap xatp;
+-	struct shared_info *shared_info_page;
++	static struct shared_info *shared_info_page = 0;
++
++	if (!shared_info_page)
++		shared_info_page = (struct shared_info *) alloc_bootmem_pages(PAGE_SIZE);
+ 
+-	shared_info_page = (struct shared_info *)
+-		extend_brk(PAGE_SIZE, PAGE_SIZE);
+ 	xatp.domid = DOMID_SELF;
+ 	xatp.idx = 0;
+ 	xatp.space = XENMAPSPACE_shared_info;
+@@ -1269,7 +1270,17 @@ static void __init init_shared_info(void)
+ 
+ 	HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
+ 
+-	per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
++	/* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
++	 * page, we use it in the event channel upcall and in some pvclock
++	 * related functions. We don't need the vcpu_info placement
++	 * optimizations because we don't use any pv_mmu or pv_irq op on
++	 * HVM.
++	 * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is
++	 * online but xen_hvm_init_shared_info is run at resume time too and
++	 * in that case multiple vcpus might be online. */
++	for_each_online_cpu(cpu) {
++		per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
++	}
+ }
+ 
+ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
+@@ -1299,7 +1310,7 @@ void __init xen_hvm_guest_init(void)
+ 	if (r < 0)
+ 		return;
+ 
+-	init_shared_info();
++	xen_hvm_init_shared_info();
+ 
+ 	if (xen_feature(XENFEAT_hvm_callback_vector))
+ 		xen_have_vector_callback = 1;
+diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
+index a9c6611..d07479c 100644
+--- a/arch/x86/xen/suspend.c
++++ b/arch/x86/xen/suspend.c
+@@ -26,6 +26,12 @@ void xen_pre_suspend(void)
+ 		BUG();
+ }
+ 
++void xen_hvm_post_suspend(int suspend_cancelled)
++{
++	xen_hvm_init_shared_info();
++	xen_callback_vector();
++}
++
+ void xen_post_suspend(int suspend_cancelled)
+ {
+ 	xen_build_mfn_list_list();
+diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
+index 0d0e0e6..01c9dd3 100644
+--- a/arch/x86/xen/xen-ops.h
++++ b/arch/x86/xen/xen-ops.h
+@@ -39,6 +39,7 @@ void xen_enable_syscall(void);
+ void xen_vcpu_restore(void);
+ 
+ void xen_callback_vector(void);
++void xen_hvm_init_shared_info(void);
+ 
+ void __init xen_build_dynamic_phys_to_machine(void);
+ 
+diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
+index 95e7b32..aee1f59 100644
+--- a/drivers/xen/manage.c
++++ b/drivers/xen/manage.c
+@@ -16,6 +16,7 @@
+ 
+ #include <asm/xen/hypercall.h>
+ #include <asm/xen/page.h>
++#include <asm/xen/hypervisor.h>
+ 
+ enum shutdown_state {
+ 	SHUTDOWN_INVALID = -1,
+@@ -32,10 +33,30 @@ enum shutdown_state {
+ static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
+ 
+ #ifdef CONFIG_PM_SLEEP
+-static int xen_suspend(void *data)
++static int xen_hvm_suspend(void *data)
+ {
++	struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
+ 	int *cancelled = data;
++
++	BUG_ON(!irqs_disabled());
++
++	*cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
++
++	xen_hvm_post_suspend(*cancelled);
++	gnttab_resume();
++
++	if (!*cancelled) {
++		xen_irq_resume();
++		xen_timer_resume();
++	}
++
++	return 0;
++}
++
++static int xen_suspend(void *data)
++{
+ 	int err;
++	int *cancelled = data;
+ 
+ 	BUG_ON(!irqs_disabled());
+ 
+@@ -111,7 +132,10 @@ static void do_suspend(void)
+ 		goto out_resume;
+ 	}
+ 
+-	err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
++	if (xen_hvm_domain())
++		err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0));
++	else
++		err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
+ 
+ 	dpm_resume_noirq(PMSG_RESUME);
+ 
+@@ -260,7 +284,19 @@ static int shutdown_event(struct notifier_block *notifier,
+ 	return NOTIFY_DONE;
+ }
+ 
+-static int __init setup_shutdown_event(void)
++static int __init __setup_shutdown_event(void)
++{
++	/* Delay initialization in the PV on HVM case */
++	if (xen_hvm_domain())
++		return 0;
++
++	if (!xen_pv_domain())
++		return -ENODEV;
++
++	return xen_setup_shutdown_event();
++}
++
++int xen_setup_shutdown_event(void)
+ {
+ 	static struct notifier_block xenstore_notifier = {
+ 		.notifier_call = shutdown_event
+@@ -271,4 +307,4 @@ static int __init setup_shutdown_event(void)
+ }
+ EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
+ 
+-subsys_initcall(setup_shutdown_event);
++subsys_initcall(__setup_shutdown_event);
+diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
+index a0ee5d0..bdb44f2 100644
+--- a/drivers/xen/platform-pci.c
++++ b/drivers/xen/platform-pci.c
+@@ -31,6 +31,7 @@
+ #include <xen/xenbus.h>
+ #include <xen/events.h>
+ #include <xen/hvm.h>
++#include <xen/xen-ops.h>
+ 
+ #define DRV_NAME    "xen-platform-pci"
+ 
+@@ -41,6 +42,7 @@ MODULE_LICENSE("GPL");
+ static unsigned long platform_mmio;
+ static unsigned long platform_mmio_alloc;
+ static unsigned long platform_mmiolen;
++static uint64_t callback_via;
+ 
+ unsigned long alloc_xen_mmio(unsigned long len)
+ {
+@@ -85,13 +87,25 @@ static int xen_allocate_irq(struct pci_dev *pdev)
+ 			"xen-platform-pci", pdev);
+ }
+ 
++static int platform_pci_resume(struct pci_dev *pdev)
++{
++	int err;
++	if (xen_have_vector_callback)
++		return 0;
++	err = xen_set_callback_via(callback_via);
++	if (err) {
++		dev_err(&pdev->dev, "platform_pci_resume failure!\n");
++		return err;
++	}
++	return 0;
++}
++
+ static int __devinit platform_pci_init(struct pci_dev *pdev,
+ 				       const struct pci_device_id *ent)
+ {
+ 	int i, ret;
+ 	long ioaddr, iolen;
+ 	long mmio_addr, mmio_len;
+-	uint64_t callback_via;
+ 	unsigned int max_nr_gframes;
+ 
+ 	i = pci_enable_device(pdev);
+@@ -148,6 +162,9 @@ static int __devinit platform_pci_init(struct pci_dev *pdev,
+ 	if (ret)
+ 		goto out;
+ 	xenbus_probe(NULL);
++	ret = xen_setup_shutdown_event();
++	if (ret)
++		goto out;
+ 	return 0;
+ 
+ out:
+@@ -171,6 +188,9 @@ static struct pci_driver platform_driver = {
+ 	.name =           DRV_NAME,
+ 	.probe =          platform_pci_init,
+ 	.id_table =       platform_pci_tbl,
++#ifdef CONFIG_PM
++	.resume_early =   platform_pci_resume,
++#endif
+ };
+ 
+ static int __init platform_pci_module_init(void)
+diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
+index 883a21b..46bc81e 100644
+--- a/include/xen/xen-ops.h
++++ b/include/xen/xen-ops.h
+@@ -7,6 +7,7 @@ DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
+ 
+ void xen_pre_suspend(void);
+ void xen_post_suspend(int suspend_cancelled);
++void xen_hvm_post_suspend(int suspend_cancelled);
+ 
+ void xen_mm_pin_all(void);
+ void xen_mm_unpin_all(void);
+@@ -14,4 +15,6 @@ void xen_mm_unpin_all(void);
+ void xen_timer_resume(void);
+ void xen_arch_resume(void);
+ 
++int xen_setup_shutdown_event(void);
++
+ #endif /* INCLUDE_XEN_OPS_H */
+-- 
+1.5.6.5
+

Reply to: