---
  arch/x86/xen/enlighten_pvh.c | 74 ++++++++++++++++++++++++++++++++------------
  1 file changed, 55 insertions(+), 19 deletions(-)
diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c
index 98ab176..d93f711 100644
--- a/arch/x86/xen/enlighten_pvh.c
+++ b/arch/x86/xen/enlighten_pvh.c
@@ -31,21 +31,46 @@ static void xen_pvh_arch_setup(void)
                acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
  }
  
-static void __init init_pvh_bootparams(void)
+static void __init init_pvh_bootparams(bool xen_guest)
  {
        struct xen_memory_map memmap;
        int rc;
  
  	memset(&pvh_bootparams, 0, sizeof(pvh_bootparams));
  
-	memmap.nr_entries = ARRAY_SIZE(pvh_bootparams.e820_table);
-       set_xen_guest_handle(memmap.buffer, pvh_bootparams.e820_table);
-       rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
-       if (rc) {
-               xen_raw_printk("XENMEM_memory_map failed (%d)\n", rc);
-               BUG();
+       if (xen_guest) {
+               memmap.nr_entries = ARRAY_SIZE(pvh_bootparams.e820_table);
+               set_xen_guest_handle(memmap.buffer, pvh_bootparams.e820_table);
+               rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
+               if (rc) {
+                       xen_raw_printk("XENMEM_memory_map failed (%d)\n", rc);
+                       BUG();
+               }
+               pvh_bootparams.e820_entries = memmap.nr_entries;
+       } else if (pvh_start_info.nr_modules > 1) {
+               /* The second module should be the e820 data for KVM guests */
+               struct hvm_modlist_entry *modaddr;
+               char e820_sig[] = "e820 data";
+               struct boot_e820_entry *ep;
+               struct e820_table *tp;
+               char *cmdline_str;
+               int idx;
+
+               modaddr = __va(pvh_start_info.modlist_paddr +
+                              sizeof(struct hvm_modlist_entry));
+               cmdline_str = __va(modaddr->cmdline_paddr);
+
+               if ((modaddr->cmdline_paddr) &&
+                   (!strncmp(e820_sig, cmdline_str, sizeof(e820_sig)))) {
+                       tp = __va(modaddr->paddr);
+                       ep = (struct boot_e820_entry *)tp->entries;
+
+                       pvh_bootparams.e820_entries = tp->nr_entries;
+
+                       for (idx = 0; idx < tp->nr_entries ; idx++, ep++)
+                               pvh_bootparams.e820_table[idx] = *ep;
+               }
        }
-       pvh_bootparams.e820_entries = memmap.nr_entries;
  
  	if (pvh_bootparams.e820_entries < E820_MAX_ENTRIES_ZEROPAGE - 1) {
                pvh_bootparams.e820_table[pvh_bootparams.e820_entries].addr =
@@ -55,8 +80,9 @@ static void __init init_pvh_bootparams(void)
                pvh_bootparams.e820_table[pvh_bootparams.e820_entries].type =
                        E820_TYPE_RESERVED;
                pvh_bootparams.e820_entries++;
-       } else
+       } else if (xen_guest) {
                xen_raw_printk("Warning: Can fit ISA range into e820\n");
+       }
  
  	pvh_bootparams.hdr.cmd_line_ptr =
                pvh_start_info.cmdline_paddr;
@@ -76,7 +102,7 @@ static void __init init_pvh_bootparams(void)
         * environment (i.e. hardware_subarch 0).
         */
        pvh_bootparams.hdr.version = 0x212;
-       pvh_bootparams.hdr.type_of_loader = (9 << 4) | 0; /* Xen loader */
+       pvh_bootparams.hdr.type_of_loader = ((xen_guest ? 0x9 : 0xb) << 4) | 0;
  }
  
  /*
@@ -85,22 +111,32 @@ static void __init init_pvh_bootparams(void)
   */
  void __init xen_prepare_pvh(void)
  {
-       u32 msr;
+
+       u32 msr = xen_cpuid_base();
        u64 pfn;
+       bool xen_guest = msr ? true : false;
  
  	if (pvh_start_info.magic != XEN_HVM_START_MAGIC_VALUE) {
-               xen_raw_printk("Error: Unexpected magic value (0x%08x)\n",
-                               pvh_start_info.magic);
+               if (xen_guest)
+                       xen_raw_printk("Error: Unexpected magic value 
(0x%08x)\n",
+                                       pvh_start_info.magic);
                BUG();
        }
  
-	xen_pvh = 1;
+       if (xen_guest) {
+               xen_pvh = 1;
+
+               msr = cpuid_ebx(msr + 2);
+               pfn = __pa(hypercall_page);
+               wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
+
+       } else if (!hypervisor_cpuid_base("KVMKVMKVM\0\0\0", 0)) {
+               BUG();
+       }
  
-	msr = cpuid_ebx(xen_cpuid_base() + 2);
-       pfn = __pa(hypercall_page);
-       wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
+       init_pvh_bootparams(xen_guest);
  
-	init_pvh_bootparams();
+       if (xen_guest)
+               x86_init.oem.arch_setup = xen_pvh_arch_setup;
  
-	x86_init.oem.arch_setup = xen_pvh_arch_setup;
  }