[kernel] r15663 - in dists/sid/linux-2.6/debian: . patches/features/all/xen
Bastian Blank
waldi at alioth.debian.org
Wed May 12 08:01:24 UTC 2010
Author: waldi
Date: Wed May 12 08:01:16 2010
New Revision: 15663
Log:
* debian/changelog: Update.
* patches/features/all/xen/pvops.patch: Update to b1cb4e89c3d2.
Modified:
dists/sid/linux-2.6/debian/changelog
dists/sid/linux-2.6/debian/patches/features/all/xen/pvops.patch
Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog Wed May 12 00:10:49 2010 (r15662)
+++ dists/sid/linux-2.6/debian/changelog Wed May 12 08:01:16 2010 (r15663)
@@ -34,6 +34,7 @@
[ Bastian Blank ]
* Fix symlinks in several packages.
+ * Update Xen patch.
-- Frederik Schüler <fs at debian.org> Wed, 05 May 2010 17:54:01 +0200
Modified: dists/sid/linux-2.6/debian/patches/features/all/xen/pvops.patch
==============================================================================
--- dists/sid/linux-2.6/debian/patches/features/all/xen/pvops.patch Wed May 12 00:10:49 2010 (r15662)
+++ dists/sid/linux-2.6/debian/patches/features/all/xen/pvops.patch Wed May 12 08:01:16 2010 (r15663)
@@ -1,4 +1,4 @@
-Patch based on commit b1cb4e89c3d22864b169acb4574e950f87df8d5a of
+Patch based on commit ba739f9abd3f659b907a824af1161926b420a2ce of
git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git.
diff --git a/Documentation/x86/x86_64/boot-options.txt b/Documentation/x86/x86_64/boot-options.txt
@@ -257,6 +257,69 @@
static inline int is_hpet_enabled(void) { return 0; }
#define hpet_readl(a) 0
+diff --git a/arch/x86/include/asm/hugetlb.h b/arch/x86/include/asm/hugetlb.h
+index 439a9ac..4cfd4de 100644
+--- a/arch/x86/include/asm/hugetlb.h
++++ b/arch/x86/include/asm/hugetlb.h
+@@ -36,16 +36,24 @@ static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
+ free_pgd_range(tlb, addr, end, floor, ceiling);
+ }
+
++static inline pte_t huge_ptep_get(pte_t *ptep)
++{
++ return *ptep;
++}
++
+ static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+ {
+- set_pte_at(mm, addr, ptep, pte);
++ set_pmd((pmd_t *)ptep, __pmd(pte_val(pte)));
+ }
+
+ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+ {
+- return ptep_get_and_clear(mm, addr, ptep);
++ pte_t pte = huge_ptep_get(ptep);
++
++ set_huge_pte_at(mm, addr, ptep, __pte(0));
++ return pte;
+ }
+
+ static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+@@ -66,19 +74,25 @@ static inline pte_t huge_pte_wrprotect(pte_t pte)
+ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+ {
+- ptep_set_wrprotect(mm, addr, ptep);
++ pte_t pte = huge_ptep_get(ptep);
++
++ pte = pte_wrprotect(pte);
++ set_huge_pte_at(mm, addr, ptep, pte);
+ }
+
+ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t pte, int dirty)
+ {
+- return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+-}
++ pte_t oldpte = huge_ptep_get(ptep);
++ int changed = !pte_same(oldpte, pte);
+
+-static inline pte_t huge_ptep_get(pte_t *ptep)
+-{
+- return *ptep;
++ if (changed && dirty) {
++ set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
++ flush_tlb_page(vma, addr);
++ }
++
++ return changed;
+ }
+
+ static inline int arch_prepare_hugepage(struct page *page)
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 7373932..49ee1a9 100644
--- a/arch/x86/include/asm/io.h
@@ -659,18 +722,19 @@
extern struct x86_init_ops x86_init;
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
-index 9c371e4..3da450b 100644
+index 9c371e4..41c4be0 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
-@@ -45,6 +45,7 @@
+@@ -45,6 +45,8 @@
#include <xen/interface/xen.h>
#include <xen/interface/sched.h>
#include <xen/interface/physdev.h>
+#include <xen/interface/platform.h>
++#include <xen/interface/xen-mca.h>
/*
* The hypercall asms have to meet several constraints:
-@@ -200,6 +201,23 @@ extern struct { char _entry[32]; } hypercall_page[];
+@@ -200,6 +202,23 @@ extern struct { char _entry[32]; } hypercall_page[];
(type)__res; \
})
@@ -694,10 +758,17 @@
static inline int
HYPERVISOR_set_trap_table(struct trap_info *table)
{
-@@ -282,6 +300,13 @@ HYPERVISOR_set_timer_op(u64 timeout)
+@@ -282,6 +301,20 @@ HYPERVISOR_set_timer_op(u64 timeout)
}
static inline int
++HYPERVISOR_mca(struct xen_mc *mc_op)
++{
++ mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
++ return _hypercall1(int, mca, mc_op);
++}
++
++static inline int
+HYPERVISOR_dom0_op(struct xen_platform_op *platform_op)
+{
+ platform_op->interface_version = XENPF_INTERFACE_VERSION;
@@ -708,7 +779,20 @@
HYPERVISOR_set_debugreg(int reg, unsigned long value)
{
return _hypercall2(int, set_debugreg, reg, value);
-@@ -424,6 +449,14 @@ MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
+@@ -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;
}
@@ -723,7 +807,7 @@
static inline void
MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
pte_t new_val, unsigned long flags)
-@@ -432,12 +465,11 @@ MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
+@@ -432,12 +479,11 @@ MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
mcl->args[0] = va;
if (sizeof(new_val) == sizeof(long)) {
mcl->args[1] = new_val.pte;
@@ -738,10 +822,10 @@
static inline void
diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h
-index d5b7e90..396ff4c 100644
+index d5b7e90..8d5e15a 100644
--- a/arch/x86/include/asm/xen/hypervisor.h
+++ b/arch/x86/include/asm/xen/hypervisor.h
-@@ -37,31 +37,4 @@
+@@ -37,31 +37,10 @@
extern struct shared_info *HYPERVISOR_shared_info;
extern struct start_info *xen_start_info;
@@ -751,12 +835,14 @@
- XEN_HVM_DOMAIN, /* running in a Xen hvm domain */
-};
-
--#ifdef CONFIG_XEN
+ #ifdef CONFIG_XEN
-extern enum xen_domain_type xen_domain_type;
--#else
++extern void xen_guest_init(void);
+ #else
-#define xen_domain_type XEN_NATIVE
--#endif
--
++#define xen_guest_init() do { } while (0)
+ #endif
+
-#define xen_domain() (xen_domain_type != XEN_NATIVE)
-#define xen_pv_domain() (xen_domain() && \
- xen_domain_type == XEN_PV_DOMAIN)
@@ -1789,6 +1875,18 @@
+ pat_init();
+ }
+}
+diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
+index ff95824..ebd4c51 100644
+--- a/arch/x86/kernel/crash.c
++++ b/arch/x86/kernel/crash.c
+@@ -28,7 +28,6 @@
+ #include <asm/reboot.h>
+ #include <asm/virtext.h>
+
+-
+ #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
+
+ static void kdump_nmi_callback(int cpu, struct die_args *args)
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 74f5a3f..b69c4e8 100644
--- a/arch/x86/kernel/hpet.c
@@ -2689,7 +2787,7 @@
}
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
-index 8425f7e..9f1d581 100644
+index 8425f7e..abd6489 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -89,6 +89,7 @@
@@ -2700,7 +2798,15 @@
#include <asm/system.h>
#include <asm/vsyscall.h>
-@@ -955,6 +956,9 @@ void __init setup_arch(char **cmdline_p)
+@@ -102,6 +103,7 @@
+
+ #include <asm/paravirt.h>
+ #include <asm/hypervisor.h>
++#include <asm/xen/hypervisor.h>
+
+ #include <asm/percpu.h>
+ #include <asm/topology.h>
+@@ -955,6 +957,9 @@ void __init setup_arch(char **cmdline_p)
initmem_init(0, max_pfn);
@@ -2710,6 +2816,14 @@
#ifdef CONFIG_ACPI_SLEEP
/*
* Reserve low memory region for sleep support.
+@@ -1023,6 +1028,7 @@ void __init setup_arch(char **cmdline_p)
+ probe_nr_irqs_gsi();
+
+ kvm_guest_init();
++ xen_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
@@ -3009,7 +3123,7 @@
#endif
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
new file mode 100644
-index 0000000..9606bfa
+index 0000000..67fa926
--- /dev/null
+++ b/arch/x86/pci/xen.c
@@ -0,0 +1,154 @@
@@ -3049,7 +3163,6 @@
+ struct msi_desc *msidesc;
+ int *v;
+
-+
+ /* Dom0 has another mechanism for this. The exit path
+ * (xen_pci_teardown_msi_irq) is shared with Dom0.
+ */
@@ -3079,6 +3192,7 @@
+ ret = set_irq_msi(irq, msidesc);
+ if (ret)
+ goto error_while;
++ i++;
+ }
+ kfree(v);
+ return 0;
@@ -3266,10 +3380,10 @@
+#endif
+}
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
-index 3578688..cc0c7ed 100644
+index 3578688..e6a9f9f 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
-@@ -28,6 +28,7 @@
+@@ -28,12 +28,19 @@
#include <linux/highmem.h>
#include <linux/console.h>
@@ -3277,7 +3391,19 @@
#include <xen/interface/xen.h>
#include <xen/interface/version.h>
#include <xen/interface/physdev.h>
-@@ -66,6 +67,11 @@ DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
+ #include <xen/interface/vcpu.h>
++#include <xen/interface/memory.h>
++#include <xen/interface/hvm/hvm_op.h>
++#include <xen/interface/hvm/params.h>
++#include <xen/interface/platform_pci.h>
+ #include <xen/features.h>
+ #include <xen/page.h>
++#include <xen/hvm.h>
++#include <xen/events.h>
+ #include <xen/hvc-console.h>
+
+ #include <asm/paravirt.h>
+@@ -66,6 +73,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);
@@ -3289,7 +3415,17 @@
struct start_info *xen_start_info;
EXPORT_SYMBOL_GPL(xen_start_info);
-@@ -167,13 +173,16 @@ static void __init xen_banner(void)
+@@ -73,6 +85,9 @@ struct shared_info xen_dummy_shared_info;
+
+ void *xen_initial_gdt;
+
++int xen_have_vector_callback;
++int unplug;
++
+ /*
+ * Point at some empty memory to start with. We map the real shared_info
+ * page as soon as fixmap is up and running.
+@@ -167,13 +182,16 @@ static void __init xen_banner(void)
printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
pv_info.name);
@@ -3308,7 +3444,7 @@
static void xen_cpuid(unsigned int *ax, unsigned int *bx,
unsigned int *cx, unsigned int *dx)
-@@ -187,7 +196,7 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
+@@ -187,7 +205,7 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
* unsupported kernel subsystems as possible.
*/
switch (*ax) {
@@ -3317,7 +3453,7 @@
maskecx = cpuid_leaf1_ecx_mask;
maskedx = cpuid_leaf1_edx_mask;
break;
-@@ -196,6 +205,10 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
+@@ -196,6 +214,10 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
/* Suppress extended topology stuff */
maskebx = 0;
break;
@@ -3328,16 +3464,27 @@
}
asm(XEN_EMULATE_PREFIX "cpuid"
-@@ -219,6 +232,8 @@ static __init void xen_init_cpuid_mask(void)
- (1 << X86_FEATURE_MCA) | /* disable MCA */
- (1 << X86_FEATURE_ACC)); /* thermal monitoring */
+@@ -215,13 +237,15 @@ static __init void xen_init_cpuid_mask(void)
+ unsigned int ax, bx, cx, dx;
-+ cpuid_leaf81_edx_mask = ~(1 << (X86_FEATURE_GBPAGES % 32));
+ cpuid_leaf1_edx_mask =
+- ~((1 << X86_FEATURE_MCE) | /* disable MCE */
+- (1 << X86_FEATURE_MCA) | /* disable MCA */
+- (1 << X86_FEATURE_ACC)); /* thermal monitoring */
++ ~(1 << X86_FEATURE_ACC); /* thermal monitoring */
+
++ cpuid_leaf81_edx_mask = ~(1 << (X86_FEATURE_GBPAGES % 32));
+
if (!xen_initial_domain())
cpuid_leaf1_edx_mask &=
- ~((1 << X86_FEATURE_APIC) | /* disable local APIC */
-@@ -406,7 +421,7 @@ static __init void xen_load_gdt_boot(const struct desc_ptr *dtr)
+- ~((1 << X86_FEATURE_APIC) | /* disable local APIC */
++ ~((1 << X86_FEATURE_MCE) | /* disable MCE */
++ (1 << X86_FEATURE_MCA) | /* disable MCA */
++ (1 << X86_FEATURE_APIC) | /* disable local APIC */
+ (1 << X86_FEATURE_ACPI)); /* disable ACPI */
+
+ ax = 1;
+@@ -406,7 +430,7 @@ static __init void xen_load_gdt_boot(const struct desc_ptr *dtr)
pte = pfn_pte(pfn, PAGE_KERNEL_RO);
@@ -3346,9 +3493,13 @@
BUG();
frames[f] = mfn;
-@@ -519,11 +534,10 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
- } else if (addr == (unsigned long)machine_check) {
+@@ -517,13 +541,13 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
return 0;
+ #ifdef CONFIG_X86_MCE
+ } else if (addr == (unsigned long)machine_check) {
+- return 0;
++ /* We can use the original machine_check handler,
++ despite IST. */
#endif
- } else {
- /* Some other trap using IST? */
@@ -3362,7 +3513,7 @@
#endif /* CONFIG_X86_64 */
info->address = addr;
-@@ -679,6 +693,18 @@ static void xen_set_iopl_mask(unsigned mask)
+@@ -679,6 +703,18 @@ static void xen_set_iopl_mask(unsigned mask)
HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
}
@@ -3381,7 +3532,7 @@
static void xen_io_delay(void)
{
}
-@@ -716,7 +742,7 @@ static u32 xen_safe_apic_wait_icr_idle(void)
+@@ -716,7 +752,7 @@ static u32 xen_safe_apic_wait_icr_idle(void)
return 0;
}
@@ -3390,7 +3541,7 @@
{
apic->read = xen_apic_read;
apic->write = xen_apic_write;
-@@ -728,7 +754,6 @@ static void set_xen_basic_apic_ops(void)
+@@ -728,7 +764,6 @@ static void set_xen_basic_apic_ops(void)
#endif
@@ -3398,7 +3549,7 @@
static void xen_clts(void)
{
struct multicall_space mcs;
-@@ -811,6 +836,11 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
+@@ -811,6 +846,11 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
Xen console noise. */
break;
@@ -3410,7 +3561,7 @@
default:
ret = native_write_msr_safe(msr, low, high);
}
-@@ -978,6 +1008,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
+@@ -978,6 +1018,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
.load_sp0 = xen_load_sp0,
.set_iopl_mask = xen_set_iopl_mask,
@@ -3418,7 +3569,7 @@
.io_delay = xen_io_delay,
/* Xen takes care of %gs when switching to usermode for us */
-@@ -1020,6 +1051,14 @@ static void xen_machine_halt(void)
+@@ -1020,6 +1061,14 @@ static void xen_machine_halt(void)
xen_reboot(SHUTDOWN_poweroff);
}
@@ -3433,7 +3584,7 @@
static void xen_crash_shutdown(struct pt_regs *regs)
{
xen_reboot(SHUTDOWN_crash);
-@@ -1028,7 +1067,7 @@ static void xen_crash_shutdown(struct pt_regs *regs)
+@@ -1028,7 +1077,7 @@ static void xen_crash_shutdown(struct pt_regs *regs)
static const struct machine_ops __initdata xen_machine_ops = {
.restart = xen_restart,
.halt = xen_machine_halt,
@@ -3442,7 +3593,7 @@
.shutdown = xen_machine_halt,
.crash_shutdown = xen_crash_shutdown,
.emergency_restart = xen_emergency_restart,
-@@ -1061,6 +1100,8 @@ asmlinkage void __init xen_start_kernel(void)
+@@ -1061,6 +1110,8 @@ asmlinkage void __init xen_start_kernel(void)
xen_domain_type = XEN_PV_DOMAIN;
@@ -3451,7 +3602,7 @@
/* Install Xen paravirt ops */
pv_info = xen_info;
pv_init_ops = xen_init_ops;
-@@ -1086,6 +1127,12 @@ asmlinkage void __init xen_start_kernel(void)
+@@ -1086,6 +1137,12 @@ asmlinkage void __init xen_start_kernel(void)
xen_init_mmu_ops();
@@ -3464,7 +3615,7 @@
/* Prevent unwanted bits from being set in PTEs. */
__supported_pte_mask &= ~_PAGE_GLOBAL;
if (!xen_initial_domain())
-@@ -1116,6 +1163,10 @@ asmlinkage void __init xen_start_kernel(void)
+@@ -1116,6 +1173,10 @@ asmlinkage void __init xen_start_kernel(void)
*/
xen_setup_stackprotector();
@@ -3475,7 +3626,7 @@
xen_init_irq_ops();
xen_init_cpuid_mask();
-@@ -1144,6 +1195,8 @@ asmlinkage void __init xen_start_kernel(void)
+@@ -1144,6 +1205,8 @@ asmlinkage void __init xen_start_kernel(void)
pgd = (pgd_t *)xen_start_info->pt_base;
@@ -3484,7 +3635,7 @@
/* Don't do the full vcpu_info placement stuff until we have a
possible map and a non-dummy shared_info. */
per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
-@@ -1153,6 +1206,7 @@ asmlinkage void __init xen_start_kernel(void)
+@@ -1153,6 +1216,7 @@ asmlinkage void __init xen_start_kernel(void)
xen_raw_console_write("mapping kernel into physical memory\n");
pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages);
@@ -3492,7 +3643,7 @@
init_mm.pgd = pgd;
-@@ -1162,6 +1216,14 @@ asmlinkage void __init xen_start_kernel(void)
+@@ -1162,6 +1226,14 @@ asmlinkage void __init xen_start_kernel(void)
if (xen_feature(XENFEAT_supervisor_mode_kernel))
pv_info.kernel_rpl = 0;
@@ -3507,7 +3658,7 @@
/* set the limit of our address space */
xen_reserve_top();
-@@ -1184,6 +1246,16 @@ asmlinkage void __init xen_start_kernel(void)
+@@ -1184,6 +1256,16 @@ asmlinkage void __init xen_start_kernel(void)
add_preferred_console("xenboot", 0, NULL);
add_preferred_console("tty", 0, NULL);
add_preferred_console("hvc", 0, NULL);
@@ -3524,6 +3675,149 @@
}
xen_raw_console_write("about to get started...\n");
+@@ -1197,3 +1279,142 @@ 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();
++ 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;
++}
++
++static void init_shared_info(void)
++{
++ 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;
++
++ /* Don't do the full vcpu_info placement stuff until we have a
++ possible map and a non-dummy shared_info. */
++ per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
++}
++
++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);
++}
++
++void do_hvm_pv_evtchn_intr(void)
++{
++ xen_hvm_evtchn_do_upcall(get_irq_regs());
++}
++
++void xen_guest_init(void)
++{
++ int r;
++ int major, minor;
++ uint64_t callback_via;
++
++ if (xen_pv_domain())
++ return;
++
++ r = init_hvm_pv_info(&major, &minor);
++ if (r < 0)
++ return;
++
++ init_shared_info();
++
++ if (xen_feature(XENFEAT_hvm_callback_vector)) {
++ callback_via = HVM_CALLBACK_VECTOR(GENERIC_INTERRUPT_VECTOR);
++ xen_set_callback_via(callback_via);
++ generic_interrupt_extension = do_hvm_pv_evtchn_intr;
++ xen_have_vector_callback = 1;
++ }
++ if (unplug) {
++ /* unplug emulated devices */
++ outw(UNPLUG_ALL, XEN_IOPORT_UNPLUG);
++ }
++ have_vcpu_info_placement = 0;
++ x86_init.irqs.intr_init = xen_init_IRQ;
++ machine_ops = xen_machine_ops;
++}
++
++static int __init parse_unplug(char *arg)
++{
++ char *p, *q;
++
++ for (p = arg; p; p = q) {
++ q = strchr(arg, ',');
++ if (q)
++ *q++ = '\0';
++ if (!strcmp(p, "all"))
++ unplug |= UNPLUG_ALL;
++ else if (!strcmp(p, "ide-disks"))
++ unplug |= UNPLUG_ALL_IDE_DISKS;
++ else if (!strcmp(p, "aux-ide-disks"))
++ unplug |= UNPLUG_AUX_IDE_DISKS;
++ else if (!strcmp(p, "nics"))
++ unplug |= UNPLUG_ALL_NICS;
++ else
++ printk(KERN_WARNING "unrecognised option '%s' "
++ "in module parameter 'dev_unplug'\n", p);
++ }
++ return 0;
++}
++early_param("xen_unplug", parse_unplug);
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 350a3de..8c6a858 100644
--- a/arch/x86/xen/mmu.c
@@ -4613,7 +4907,7 @@
+}
+EXPORT_SYMBOL(xen_unregister_device_domain_owner);
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
-index ad0047f..3c16973 100644
+index ad0047f..f008629 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -10,6 +10,7 @@
@@ -4634,7 +4928,7 @@
#include <xen/features.h>
#include "xen-ops.h"
-@@ -32,25 +35,125 @@ extern void xen_sysenter_target(void);
+@@ -32,25 +35,131 @@ extern void xen_sysenter_target(void);
extern void xen_syscall_target(void);
extern void xen_syscall32_target(void);
@@ -4683,18 +4977,24 @@
+ return len;
+}
+
-+static unsigned long __init xen_return_unused_memory(const struct e820map *e820)
++static unsigned long __init xen_return_unused_memory(unsigned long max_pfn,
++ const struct e820map *e820)
+{
++ phys_addr_t max_addr = PFN_PHYS(max_pfn);
+ phys_addr_t last_end = 0;
+ unsigned long released = 0;
+ int i;
+
-+ for (i = 0; i < e820->nr_map; i++) {
-+ released += xen_release_chunk(last_end, e820->map[i].addr);
++ for (i = 0; i < e820->nr_map && last_end < max_addr; i++) {
++ phys_addr_t end = e820->map[i].addr;
++ end = min(max_addr, end);
++
++ released += xen_release_chunk(last_end, end);
+ last_end = e820->map[i].addr + e820->map[i].size;
+ }
+
-+ released += xen_release_chunk(last_end, PFN_PHYS(xen_start_info->nr_pages));
++ if (last_end < max_addr)
++ released += xen_release_chunk(last_end, max_addr);
+
+ printk(KERN_INFO "released %ld pages of unused memory\n", released);
+ return released;
@@ -4763,16 +5063,16 @@
*/
e820_add_region(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS,
E820_RESERVED);
-@@ -67,6 +170,8 @@ char * __init xen_memory_setup(void)
+@@ -67,6 +176,8 @@ char * __init xen_memory_setup(void)
sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
-+ xen_return_unused_memory(&e820);
++ xen_return_unused_memory(xen_start_info->nr_pages, &e820);
+
return "Xen";
}
-@@ -182,13 +287,17 @@ void __init xen_arch_setup(void)
+@@ -182,13 +293,17 @@ void __init xen_arch_setup(void)
}
#endif
@@ -6637,7 +6937,7 @@
}
EXPORT_SYMBOL(ttm_fbdev_mmap);
diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
-index b115726..0859bb0 100644
+index b115726..80a072e 100644
--- a/drivers/input/xen-kbdfront.c
+++ b/drivers/input/xen-kbdfront.c
@@ -21,7 +21,10 @@
@@ -6660,6 +6960,15 @@
case XenbusStateUnknown:
case XenbusStateClosed:
break;
+@@ -335,7 +340,7 @@ static struct xenbus_driver xenkbd_driver = {
+
+ static int __init xenkbd_init(void)
+ {
+- if (!xen_domain())
++ if (!xen_domain() || xen_hvm_domain())
+ return -ENODEV;
+
+ /* Nothing to do if running in dom0. */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b2f71f7..b7feb84 100644
--- a/drivers/net/Kconfig
@@ -7142,7 +7451,7 @@
+
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
new file mode 100644
-index 0000000..2c36004
+index 0000000..360eccf
--- /dev/null
+++ b/drivers/pci/xen-pcifront.c
@@ -0,0 +1,1156 @@
@@ -7440,7 +7749,7 @@
+ if (likely(!op.value)) {
+ /* we get the result */
+ for (i = 0; i < nvec; i++)
-+ *vector[i] = op.msix_entries[i].vector;
++ *(*vector+i) = op.msix_entries[i].vector;
+ return 0;
+ } else {
+ printk(KERN_DEBUG "enable msix get value %x\n",
@@ -7486,7 +7795,7 @@
+
+ err = do_pci_op(pdev, &op);
+ if (likely(!err)) {
-+ *vector[0] = op.value;
++ *(*vector) = op.value;
+ } else {
+ dev_err(&dev->dev, "pci frontend enable msi failed for dev "
+ "%x:%x \n", op.bus, op.devfn);
@@ -8369,7 +8678,7 @@
info->fbdefio = &metronomefb_defio;
fb_deferred_io_init(info);
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
-index 54cd916..7ec2c90 100644
+index 54cd916..dc72563 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -25,7 +25,10 @@
@@ -8401,8 +8710,17 @@
case XenbusStateUnknown:
case XenbusStateClosed:
break;
+@@ -680,7 +685,7 @@ static struct xenbus_driver xenfb_driver = {
+
+ static int __init xenfb_init(void)
+ {
+- if (!xen_domain())
++ if (!xen_domain() || xen_hvm_domain())
+ return -ENODEV;
+
+ /* Nothing to do if running in dom0. */
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
-index cab100a..d6d6f3e 100644
+index cab100a..c63eeae 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -28,6 +28,110 @@ config XEN_DEV_EVTCHN
@@ -8516,7 +8834,7 @@
config XENFS
tristate "Xen filesystem"
depends on XEN
-@@ -60,4 +164,23 @@ config XEN_SYS_HYPERVISOR
+@@ -60,4 +164,36 @@ 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,
@@ -8524,6 +8842,19 @@
\ 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
++ 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.
++
++config XEN_MCE
++ def_bool y
++ depends on XEN_DOM0 && X86_64 && X86_MCE_INTEL
++
+config XEN_XENBUS_FRONTEND
+ tristate
+
@@ -8543,10 +8874,10 @@
+ depends on XEN_DOM0 && ACPI_PROCESSOR && CPU_FREQ
+ default y
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
-index 7c28434..23bc06e 100644
+index 7c28434..5771359 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
-@@ -1,12 +1,24 @@
+@@ -1,12 +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/
@@ -8573,6 +8904,9 @@
+obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/
+obj-$(CONFIG_XENFS) += xenfs/
+obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
++obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o
++obj-$(CONFIG_XEN_MCE) += mce.o
++
+obj-$(CONFIG_XEN_S3) += acpi.o
+obj-$(CONFIG_ACPI_PROCESSOR_XEN) += acpi_processor.o
+obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += xen_acpi_memhotplug.o
@@ -14539,7 +14873,7 @@
#include <asm/xen/hypervisor.h>
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
-index ce602dd..660774a 100644
+index ce602dd..9c8ad5c 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -16,7 +16,7 @@
@@ -14551,7 +14885,7 @@
*
* Jeremy Fitzhardinge <jeremy at xensource.com>, XenSource Inc, 2007
*/
-@@ -27,19 +27,27 @@
+@@ -27,19 +27,28 @@
#include <linux/module.h>
#include <linux/string.h>
#include <linux/bootmem.h>
@@ -14569,6 +14903,7 @@
#include <asm/xen/hypervisor.h>
+#include <asm/xen/pci.h>
++#include <xen/hvm.h>
#include <xen/xen-ops.h>
#include <xen/events.h>
#include <xen/interface/xen.h>
@@ -14579,7 +14914,7 @@
/*
* This lock protects updates to the following mapping and reference-count
* arrays. The lock does not need to be acquired to read the mapping tables.
-@@ -67,7 +75,7 @@ enum xen_irq_type {
+@@ -67,7 +76,7 @@ enum xen_irq_type {
* event channel - irq->event channel mapping
* cpu - cpu this event channel is bound to
* index - type-specific information:
@@ -14588,7 +14923,7 @@
* VIRQ - virq number
* IPI - IPI vector
* EVTCHN -
-@@ -83,20 +91,27 @@ struct irq_info
+@@ -83,20 +92,27 @@ struct irq_info
enum ipi_vector ipi;
struct {
unsigned short gsi;
@@ -14622,7 +14957,7 @@
static inline unsigned long *cpu_evtchn_mask(int cpu)
{
return cpu_evtchn_mask_p[cpu].bits;
-@@ -106,6 +121,7 @@ static inline unsigned long *cpu_evtchn_mask(int cpu)
+@@ -106,6 +122,7 @@ static inline unsigned long *cpu_evtchn_mask(int cpu)
#define VALID_EVTCHN(chn) ((chn) != 0)
static struct irq_chip xen_dynamic_chip;
@@ -14630,7 +14965,7 @@
/* Constructor for packed IRQ information. */
static struct irq_info mk_unbound_info(void)
-@@ -135,7 +151,8 @@ static struct irq_info mk_pirq_info(unsigned short evtchn,
+@@ -135,7 +152,8 @@ static struct irq_info mk_pirq_info(unsigned short evtchn,
unsigned short gsi, unsigned short vector)
{
return (struct irq_info) { .type = IRQT_PIRQ, .evtchn = evtchn,
@@ -14640,7 +14975,7 @@
}
/*
-@@ -218,6 +235,15 @@ static unsigned int cpu_from_evtchn(unsigned int evtchn)
+@@ -218,6 +236,15 @@ static unsigned int cpu_from_evtchn(unsigned int evtchn)
return ret;
}
@@ -14656,7 +14991,7 @@
static inline unsigned long active_evtchns(unsigned int cpu,
struct shared_info *sh,
unsigned int idx)
-@@ -329,17 +355,33 @@ static void unmask_evtchn(int port)
+@@ -329,17 +356,42 @@ static void unmask_evtchn(int port)
put_cpu();
}
@@ -14682,9 +15017,18 @@
+ goto no_irqs;
+
+ /* nr_irqs is a magic value. Must not use it.*/
-+ for (irq = nr_irqs-1; irq > start; irq--)
++ 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;
if (irq_info[irq].type == IRQT_UNBOUND)
break;
++ }
- if (irq == nr_irqs)
- panic("No available IRQ to bind to: increase nr_irqs!\n");
@@ -14693,7 +15037,7 @@
desc = irq_to_desc_alloc_node(irq, 0);
if (WARN_ON(desc == NULL))
-@@ -348,8 +390,324 @@ static int find_unbound_irq(void)
+@@ -348,8 +400,324 @@ static int find_unbound_irq(void)
dynamic_irq_init(irq);
return irq;
@@ -14733,8 +15077,8 @@
+ info->u.pirq.flags &= ~PIRQ_NEEDS_EOI;
+ if (irq_status.flags & XENIRQSTAT_needs_eoi)
+ info->u.pirq.flags |= PIRQ_NEEDS_EOI;
- }
-
++}
++
+static bool probing_irq(int irq)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
@@ -14805,8 +15149,8 @@
+static void enable_pirq(unsigned int irq)
+{
+ startup_pirq(irq);
-+}
-+
+ }
+
+static void disable_pirq(unsigned int irq)
+{
+}
@@ -15018,7 +15362,7 @@
int bind_evtchn_to_irq(unsigned int evtchn)
{
int irq;
-@@ -409,8 +767,23 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
+@@ -409,8 +777,23 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
return irq;
}
@@ -15027,11 +15371,11 @@
+{
+ struct evtchn_bind_interdomain bind_interdomain;
+ int err;
-+
-+ bind_interdomain.remote_dom = remote_domain;
-+ bind_interdomain.remote_port = remote_port;
-static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
++ bind_interdomain.remote_dom = remote_domain;
++ bind_interdomain.remote_port = remote_port;
++
+ err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
+ &bind_interdomain);
+
@@ -15043,7 +15387,7 @@
{
struct evtchn_bind_virq bind_virq;
int evtchn, irq;
-@@ -504,6 +877,29 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn,
+@@ -504,6 +887,29 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn,
}
EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler);
@@ -15073,7 +15417,7 @@
int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
irq_handler_t handler,
unsigned long irqflags, const char *devname, void *dev_id)
-@@ -535,6 +931,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi,
+@@ -535,6 +941,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi,
if (irq < 0)
return irq;
@@ -15081,7 +15425,26 @@
retval = request_irq(irq, handler, irqflags, devname, dev_id);
if (retval != 0) {
unbind_from_irq(irq);
-@@ -649,9 +1046,13 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
+@@ -616,17 +1023,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)
++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 +1052,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;
int irq = evtchn_to_irq[port];
@@ -15097,7 +15460,44 @@
}
}
-@@ -855,7 +1256,7 @@ void xen_clear_irq_pending(int irq)
+@@ -662,10 +1069,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(struct pt_regs *regs)
++{
++ __xen_evtchn_do_upcall(regs);
+ }
+
+ /* Rebind a new event channel to an existing irq. */
+@@ -703,7 +1126,7 @@ 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))
++ if (!VALID_EVTCHN(evtchn) || xen_hvm_domain())
+ return -1;
+
+ /* Send future instances of this interrupt to other vcpu. */
+@@ -855,7 +1278,7 @@ void xen_clear_irq_pending(int irq)
if (VALID_EVTCHN(evtchn))
clear_evtchn(evtchn);
}
@@ -15106,7 +15506,7 @@
void xen_set_irq_pending(int irq)
{
int evtchn = evtchn_from_irq(irq);
-@@ -875,9 +1276,9 @@ bool xen_test_irq_pending(int irq)
+@@ -875,9 +1298,9 @@ bool xen_test_irq_pending(int irq)
return ret;
}
@@ -15118,7 +15518,7 @@
{
evtchn_port_t evtchn = evtchn_from_irq(irq);
-@@ -885,13 +1286,20 @@ void xen_poll_irq(int irq)
+@@ -885,13 +1308,33 @@ void xen_poll_irq(int irq)
struct sched_poll poll;
poll.nr_ports = 1;
@@ -15137,10 +15537,23 @@
+{
+ xen_poll_irq_timeout(irq, 0 /* no timeout */);
+}
++
++/* Check whether the IRQ line is shared with other guests. */
++int xen_ignore_irq(int irq)
++{
++ struct irq_info *info = info_for_irq(irq);
++ struct physdev_irq_status_query irq_status = { .irq =
++ info->u.pirq.gsi };
++
++ if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
++ return 0;
++ return !(irq_status.flags & XENIRQSTAT_shared);
++}
++EXPORT_SYMBOL_GPL(xen_ignore_irq);
void xen_irq_resume(void)
{
-@@ -928,13 +1336,38 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
+@@ -928,13 +1371,38 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
.retrigger = retrigger_dynirq,
};
@@ -15180,10 +15593,15 @@
init_evtchn_cpu_bindings();
-@@ -943,4 +1376,6 @@ void __init xen_init_IRQ(void)
+@@ -942,5 +1410,10 @@ void __init xen_init_IRQ(void)
+ for (i = 0; i < NR_EVENT_CHANNELS; i++)
mask_evtchn(i);
- irq_ctx_init(smp_processor_id());
+- irq_ctx_init(smp_processor_id());
++ if (xen_hvm_domain())
++ native_init_IRQ();
++ else
++ irq_ctx_init(smp_processor_id());
+
+ xen_setup_pirqs();
}
@@ -16012,18 +16430,64 @@
+
+/* ------------------------------------------------------------------ */
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
-index 7d8f531..76fe621 100644
+index 7d8f531..8df6ae0 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
-@@ -37,6 +37,7 @@
+@@ -36,10 +36,14 @@
+ #include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
++#include <linux/io.h>
+#include <xen/xen.h>
#include <xen/interface/xen.h>
#include <xen/page.h>
#include <xen/grant_table.h>
-@@ -472,6 +473,111 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
++#include <xen/platform_pci.h>
++#include <xen/interface/memory.h>
+ #include <asm/xen/hypercall.h>
+
+ #include <asm/pgtable.h>
+@@ -57,6 +61,7 @@ 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);
++static unsigned long hvm_pv_resume_frames;
+
+ static struct grant_entry *shared;
+
+@@ -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 = (hvm_pv_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;
+@@ -472,11 +501,135 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
return 0;
}
@@ -16134,56 +16598,494 @@
+
int gnttab_resume(void)
{
- if (max_nr_grant_frames() < nr_grant_frames)
-diff --git a/drivers/xen/netback/Makefile b/drivers/xen/netback/Makefile
-new file mode 100644
-index 0000000..e346e81
---- /dev/null
-+++ b/drivers/xen/netback/Makefile
-@@ -0,0 +1,3 @@
-+obj-$(CONFIG_XEN_NETDEV_BACKEND) := xen-netback.o
+- if (max_nr_grant_frames() < nr_grant_frames)
++ unsigned int max_nr_gframes;
+
-+xen-netback-y := netback.o xenbus.o interface.o
-diff --git a/drivers/xen/netback/common.h b/drivers/xen/netback/common.h
-new file mode 100644
-index 0000000..51f97c0
---- /dev/null
-+++ b/drivers/xen/netback/common.h
-@@ -0,0 +1,227 @@
-+/******************************************************************************
-+ * arch/xen/drivers/netif/backend/common.h
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License version 2
-+ * as published by the Free Software Foundation; or, when distributed
-+ * separately from the Linux kernel or incorporated into other
-+ * software packages, subject to the following license:
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this source file (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.
-+ */
++ max_nr_gframes = max_nr_grant_frames();
++ if (max_nr_gframes < nr_grant_frames)
+ return -ENOSYS;
+- return gnttab_map(0, nr_grant_frames - 1);
+
-+#ifndef __NETIF__BACKEND__COMMON_H__
-+#define __NETIF__BACKEND__COMMON_H__
++ if (xen_pv_domain())
++ return gnttab_map(0, nr_grant_frames - 1);
+
-+#include <linux/version.h>
-+#include <linux/module.h>
-+#include <linux/interrupt.h>
++ if (!hvm_pv_resume_frames) {
++ hvm_pv_resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
++ shared = ioremap(hvm_pv_resume_frames, PAGE_SIZE * max_nr_gframes);
++ if (shared == NULL) {
++ printk(KERN_WARNING
++ "Fail to ioremap gnttab share frames\n");
++ return -ENOMEM;
++ }
++ }
++
++ gnttab_map(0, nr_grant_frames - 1);
++
++ return 0;
+ }
+
+ int gnttab_suspend(void)
+@@ -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();
+
+@@ -555,4 +705,16 @@ static int __devinit gnttab_init(void)
+ return -ENOMEM;
+ }
+
+-core_initcall(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);
+diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
+index 5d42d55..004b1dd 100644
+--- a/drivers/xen/manage.c
++++ b/drivers/xen/manage.c
+@@ -7,15 +7,19 @@
+ #include <linux/sysrq.h>
+ #include <linux/stop_machine.h>
+ #include <linux/freezer.h>
++#include <linux/pci.h>
++#include <linux/cpumask.h>
+
+ #include <xen/xenbus.h>
+ #include <xen/grant_table.h>
+ #include <xen/events.h>
+ #include <xen/hvc-console.h>
+ #include <xen/xen-ops.h>
++#include <xen/platform_pci.h>
+
+ #include <asm/xen/hypercall.h>
+ #include <asm/xen/page.h>
++#include <asm/xen/hypervisor.h>
+
+ enum shutdown_state {
+ SHUTDOWN_INVALID = -1,
+@@ -32,10 +36,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_guest_init();
++ gnttab_resume();
++
++ if (!*cancelled) {
++ xen_irq_resume();
++ platform_pci_resume();
++ }
++
++ return 0;
++}
++
++static int xen_suspend(void *data)
++{
+ int err;
++ int *cancelled = data;
+
+ BUG_ON(!irqs_disabled());
+
+@@ -72,6 +96,59 @@ static int xen_suspend(void *data)
+ return 0;
+ }
+
++static void do_hvm_suspend(void)
++{
++ int err;
++ int cancelled = 1;
++
++ shutting_down = SHUTDOWN_SUSPEND;
++
++ err = stop_machine_create();
++ if (err) {
++ printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err);
++ goto out;
++ }
++
++#ifdef CONFIG_PREEMPT
++ /* If the kernel is preemptible, we need to freeze all the processes
++ to prevent them from being in the middle of a pagetable update
++ during suspend. */
++ err = freeze_processes();
++ if (err) {
++ printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
++ goto out_destroy_sm;
++ }
++#endif
++
++ printk(KERN_DEBUG "suspending xenstore... ");
++ xenbus_suspend();
++ printk(KERN_DEBUG "xenstore suspended\n");
++ platform_pci_disable_irq();
++
++ err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0));
++ if (err) {
++ printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
++ cancelled = 1;
++ }
++
++ platform_pci_enable_irq();
++
++ if (!cancelled) {
++ xen_arch_resume();
++ xenbus_resume();
++ } else
++ xs_suspend_cancel();
++
++ /* Make sure timer events get retriggered on all CPUs */
++ clock_was_set();
++
++out_destroy_sm:
++ stop_machine_destroy();
++
++out:
++ shutting_down = SHUTDOWN_INVALID;
++}
++
+ static void do_suspend(void)
+ {
+ int err;
+@@ -184,7 +261,10 @@ static void shutdown_handler(struct xenbus_watch *watch,
+ ctrl_alt_del();
+ #ifdef CONFIG_PM_SLEEP
+ } else if (strcmp(str, "suspend") == 0) {
+- do_suspend();
++ if (xen_hvm_domain())
++ do_hvm_suspend();
++ else
++ do_suspend();
+ #endif
+ } else {
+ printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
+@@ -260,7 +340,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
+@@ -270,4 +362,4 @@ static int __init setup_shutdown_event(void)
+ return 0;
+ }
+
+-subsys_initcall(setup_shutdown_event);
++subsys_initcall(__setup_shutdown_event);
+diff --git a/drivers/xen/mce.c b/drivers/xen/mce.c
+new file mode 100644
+index 0000000..da566a5
+--- /dev/null
++++ b/drivers/xen/mce.c
+@@ -0,0 +1,216 @@
++/******************************************************************************
++ * mce.c
++ * Add Machine Check event Logging support in DOM0
++ *
++ * Driver for receiving and logging machine check event
++ *
++ * Copyright (c) 2008, 2009 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (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.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <xen/interface/xen.h>
++#include <asm/xen/hypervisor.h>
++#include <xen/events.h>
++#include <xen/interface/vcpu.h>
++#include <asm/xen/hypercall.h>
++#include <asm/mce.h>
++#include <xen/xen.h>
++
++static mc_info_t *g_mi;
++static mcinfo_logical_cpu_t *g_physinfo;
++static uint32_t ncpus;
++
++static int convert_log(struct mc_info *mi)
++{
++ struct mcinfo_common *mic = NULL;
++ struct mcinfo_global *mc_global;
++ struct mcinfo_bank *mc_bank;
++ struct mce m;
++ int i, found = 0;
++
++ x86_mcinfo_lookup(&mic, mi, MC_TYPE_GLOBAL);
++ WARN_ON(!mic);
++
++ mce_setup(&m);
++ mc_global = (struct mcinfo_global *)mic;
++ m.mcgstatus = mc_global->mc_gstatus;
++ m.apicid = mc_global->mc_apicid;
++ for (i = 0; i < ncpus; i++) {
++ if (g_physinfo[i].mc_apicid == m.apicid) {
++ found = 1;
++ break;
++ }
++ }
++ WARN_ON(!found);
++
++ m.socketid = g_physinfo[i].mc_chipid;
++ m.cpu = m.extcpu = g_physinfo[i].mc_cpunr;
++ m.cpuvendor = (__u8)g_physinfo[i].mc_vendor;
++ m.mcgcap = g_physinfo[i].mc_msrvalues[0].value;
++ x86_mcinfo_lookup(&mic, mi, MC_TYPE_BANK);
++ do {
++ if (mic == NULL || mic->size == 0)
++ break;
++ if (mic->type == MC_TYPE_BANK) {
++ mc_bank = (struct mcinfo_bank *)mic;
++ m.misc = mc_bank->mc_misc;
++ m.status = mc_bank->mc_status;
++ m.addr = mc_bank->mc_addr;
++ m.tsc = mc_bank->mc_tsc;
++ m.bank = mc_bank->mc_bank;
++ m.finished = 1;
++ /*log this record*/
++ mce_log(&m);
++ }
++ mic = x86_mcinfo_next(mic);
++ } while (1);
++
++ return 0;
++}
++
++/*pv_ops domain mce virq handler, logging physical mce error info*/
++static irqreturn_t mce_dom_interrupt(int irq, void *dev_id)
++{
++ xen_mc_t mc_op;
++ int result = 0;
++
++ mc_op.cmd = XEN_MC_fetch;
++ mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
++ set_xen_guest_handle(mc_op.u.mc_fetch.data, g_mi);
++urgent:
++ mc_op.u.mc_fetch.flags = XEN_MC_URGENT;
++ result = HYPERVISOR_mca(&mc_op);
++ if (result || mc_op.u.mc_fetch.flags & XEN_MC_NODATA ||
++ mc_op.u.mc_fetch.flags & XEN_MC_FETCHFAILED)
++ goto nonurgent;
++ else {
++ result = convert_log(g_mi);
++ if (result)
++ goto end;
++ /* After fetching the error event log entry from DOM0,
++ * we need to dec the refcnt and release the entry.
++ * The entry is reserved and inc refcnt when filling
++ * the error log entry.
++ */
++ mc_op.u.mc_fetch.flags = XEN_MC_URGENT | XEN_MC_ACK;
++ result = HYPERVISOR_mca(&mc_op);
++ goto urgent;
++ }
++nonurgent:
++ mc_op.u.mc_fetch.flags = XEN_MC_NONURGENT;
++ result = HYPERVISOR_mca(&mc_op);
++ if (result || mc_op.u.mc_fetch.flags & XEN_MC_NODATA ||
++ mc_op.u.mc_fetch.flags & XEN_MC_FETCHFAILED)
++ goto end;
++ else {
++ result = convert_log(g_mi);
++ if (result)
++ goto end;
++ /* After fetching the error event log entry from DOM0,
++ * we need to dec the refcnt and release the entry. The
++ * entry is reserved and inc refcnt when filling the
++ * error log entry.
++ */
++ mc_op.u.mc_fetch.flags = XEN_MC_NONURGENT | XEN_MC_ACK;
++ result = HYPERVISOR_mca(&mc_op);
++ goto nonurgent;
++ }
++end:
++ return IRQ_HANDLED;
++}
++
++static int bind_virq_for_mce(void)
++{
++ int ret;
++ xen_mc_t mc_op;
++
++ g_mi = kmalloc(sizeof(struct mc_info), GFP_KERNEL);
++
++ if (!g_mi)
++ return -ENOMEM;
++
++ /* Fetch physical CPU Numbers */
++ mc_op.cmd = XEN_MC_physcpuinfo;
++ mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
++ set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, g_physinfo);
++ ret = HYPERVISOR_mca(&mc_op);
++ if (ret) {
++ printk(KERN_ERR "MCE_DOM0_LOG: Fail to get physical CPU numbers\n");
++ kfree(g_mi);
++ return ret;
++ }
++
++ /* Fetch each CPU Physical Info for later reference*/
++ ncpus = mc_op.u.mc_physcpuinfo.ncpus;
++ g_physinfo = kmalloc(sizeof(struct mcinfo_logical_cpu)*ncpus,
++ GFP_KERNEL);
++ if (!g_physinfo) {
++ kfree(g_mi);
++ return -ENOMEM;
++ }
++ set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, g_physinfo);
++ ret = HYPERVISOR_mca(&mc_op);
++ if (ret) {
++ printk(KERN_ERR "MCE_DOM0_LOG: Fail to get physical CPUs info\n");
++ kfree(g_mi);
++ kfree(g_physinfo);
++ return ret;
++ }
++
++ ret = bind_virq_to_irqhandler(VIRQ_MCA, 0,
++ mce_dom_interrupt, 0, "mce", NULL);
++
++ if (ret < 0) {
++ printk(KERN_ERR "MCE_DOM0_LOG: bind_virq for DOM0 failed\n");
++ return ret;
++ }
++
++ return 0;
++}
++
++static int __init mcelog_init(void)
++{
++ /* Only DOM0 is responsible for MCE logging */
++ if (xen_initial_domain())
++ return bind_virq_for_mce();
++
++ return 0;
++}
++
++
++static void __exit mcelog_cleanup(void)
++{
++ kfree(g_mi);
++ kfree(g_physinfo);
++}
++module_init(mcelog_init);
++module_exit(mcelog_cleanup);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/xen/netback/Makefile b/drivers/xen/netback/Makefile
+new file mode 100644
+index 0000000..e346e81
+--- /dev/null
++++ b/drivers/xen/netback/Makefile
+@@ -0,0 +1,3 @@
++obj-$(CONFIG_XEN_NETDEV_BACKEND) := xen-netback.o
++
++xen-netback-y := netback.o xenbus.o interface.o
+diff --git a/drivers/xen/netback/common.h b/drivers/xen/netback/common.h
+new file mode 100644
+index 0000000..51f97c0
+--- /dev/null
++++ b/drivers/xen/netback/common.h
+@@ -0,0 +1,227 @@
++/******************************************************************************
++ * arch/xen/drivers/netif/backend/common.h
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (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 __NETIF__BACKEND__COMMON_H__
++#define __NETIF__BACKEND__COMMON_H__
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/ip.h>
+#include <linux/in.h>
@@ -19773,10 +20675,10 @@
+#endif
diff --git a/drivers/xen/pciback/conf_space_capability_msi.c b/drivers/xen/pciback/conf_space_capability_msi.c
new file mode 100644
-index 0000000..b70ea8b
+index 0000000..b15131e
--- /dev/null
+++ b/drivers/xen/pciback/conf_space_capability_msi.c
-@@ -0,0 +1,84 @@
+@@ -0,0 +1,110 @@
+/*
+ * PCI Backend -- Configuration overlay for MSI capability
+ */
@@ -19791,9 +20693,13 @@
+int pciback_enable_msi(struct pciback_device *pdev,
+ struct pci_dev *dev, struct xen_pci_op *op)
+{
++ struct pciback_dev_data *dev_data;
+ int otherend = pdev->xdev->otherend_id;
+ int status;
+
++ if (unlikely(verbose_request))
++ printk(KERN_DEBUG "pciback: %s: enable MSI\n", pci_name(dev));
++
+ status = pci_enable_msi(dev);
+
+ if (status) {
@@ -19806,24 +20712,38 @@
+ /* The value the guest needs is actually the IDT vector, not the
+ * the local domain's IRQ number. */
+ op->value = xen_gsi_from_irq(dev->irq);
++ dev_data = pci_get_drvdata(dev);
++ if (dev_data)
++ dev_data->ack_intr = 0;
++
+ return 0;
+}
+
+int pciback_disable_msi(struct pciback_device *pdev,
+ struct pci_dev *dev, struct xen_pci_op *op)
+{
++ struct pciback_dev_data *dev_data;
++
++ if (unlikely(verbose_request))
++ printk(KERN_DEBUG "pciback: %s: disable MSI\n", pci_name(dev));
+ pci_disable_msi(dev);
+
+ op->value = xen_gsi_from_irq(dev->irq);
++ dev_data = pci_get_drvdata(dev);
++ if (dev_data)
++ dev_data->ack_intr = 1;
+ return 0;
+}
+
+int pciback_enable_msix(struct pciback_device *pdev,
+ struct pci_dev *dev, struct xen_pci_op *op)
+{
++ struct pciback_dev_data *dev_data;
+ int i, result;
+ struct msix_entry *entries;
+
++ if (unlikely(verbose_request))
++ printk(KERN_DEBUG "pciback: %s: enable MSI-X\n", pci_name(dev));
+ if (op->value > SH_INFO_MAX_VEC)
+ return -EINVAL;
+
@@ -19847,6 +20767,9 @@
+ kfree(entries);
+
+ op->value = result;
++ dev_data = pci_get_drvdata(dev);
++ if (dev_data)
++ dev_data->ack_intr = 0;
+
+ return result;
+}
@@ -19854,10 +20777,15 @@
+int pciback_disable_msix(struct pciback_device *pdev,
+ struct pci_dev *dev, struct xen_pci_op *op)
+{
-+
++ struct pciback_dev_data *dev_data;
++ if (unlikely(verbose_request))
++ printk(KERN_DEBUG "pciback: %s: disable MSI-X\n", pci_name(dev));
+ pci_disable_msix(dev);
+
+ op->value = xen_gsi_from_irq(dev->irq);
++ dev_data = pci_get_drvdata(dev);
++ if (dev_data)
++ dev_data->ack_intr = 1;
+ return 0;
+}
+
@@ -20028,10 +20956,10 @@
+};
diff --git a/drivers/xen/pciback/conf_space_header.c b/drivers/xen/pciback/conf_space_header.c
new file mode 100644
-index 0000000..1f4f86e
+index 0000000..cb450f4
--- /dev/null
+++ b/drivers/xen/pciback/conf_space_header.c
-@@ -0,0 +1,379 @@
+@@ -0,0 +1,385 @@
+/*
+ * PCI Backend - Handles the virtual fields in the configuration space headers.
+ *
@@ -20073,8 +21001,10 @@
+
+static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
+{
++ struct pciback_dev_data *dev_data;
+ int err;
+
++ dev_data = pci_get_drvdata(dev);
+ if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
+ if (unlikely(verbose_request))
+ printk(KERN_DEBUG "pciback: %s: enable\n",
@@ -20082,11 +21012,15 @@
+ err = pci_enable_device(dev);
+ if (err)
+ return err;
++ if (dev_data)
++ dev_data->enable_intx = 1;
+ } else if (pci_is_enabled(dev) && !is_enable_cmd(value)) {
+ if (unlikely(verbose_request))
+ printk(KERN_DEBUG "pciback: %s: disable\n",
+ pci_name(dev));
+ pci_disable_device(dev);
++ if (dev_data)
++ dev_data->enable_intx = 0;
+ }
+
+ if (!dev->is_busmaster && is_master_cmd(value)) {
@@ -21232,10 +22166,10 @@
+}
diff --git a/drivers/xen/pciback/pci_stub.c b/drivers/xen/pciback/pci_stub.c
new file mode 100644
-index 0000000..02178e2
+index 0000000..88c7ca1
--- /dev/null
+++ b/drivers/xen/pciback/pci_stub.c
-@@ -0,0 +1,1287 @@
+@@ -0,0 +1,1370 @@
+/*
+ * PCI Stub Driver - Grabs devices in backend to be exported later
+ *
@@ -21259,6 +22193,8 @@
+#include "conf_space.h"
+#include "conf_space_quirks.h"
+
++#define DRV_NAME "pciback"
++
+static char *pci_devs_to_hide;
+wait_queue_head_t aer_wait_queue;
+/*Add sem for sync AER handling and pciback remove/reconfigue ops,
@@ -21528,13 +22464,20 @@
+ * would need to be called somewhere to free the memory allocated
+ * here and then to call kfree(pci_get_drvdata(psdev->dev)).
+ */
-+ dev_data = kzalloc(sizeof(*dev_data), GFP_ATOMIC);
++ dev_data = kzalloc(sizeof(*dev_data) + strlen(DRV_NAME "[]")
++ + strlen(pci_name(dev)) + 1, GFP_ATOMIC);
+ if (!dev_data) {
+ err = -ENOMEM;
+ goto out;
+ }
+ pci_set_drvdata(dev, dev_data);
+
++ /*
++ * Setup name for fake IRQ handler. It will only be enabled
++ * once the device is turned on by the guest.
++ */
++ sprintf(dev_data->irq_name, DRV_NAME "[%s]", pci_name(dev));
++
+ dev_dbg(&dev->dev, "initializing config\n");
+
+ init_waitqueue_head(&aer_wait_queue);
@@ -22075,7 +23018,7 @@
+ */
+
+static struct pci_driver pciback_pci_driver = {
-+ .name = "pciback",
++ .name = DRV_NAME,
+ .id_table = pcistub_ids,
+ .probe = pcistub_probe,
+ .remove = pcistub_remove,
@@ -22267,6 +23210,71 @@
+
+DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL);
+
++static ssize_t pcistub_irq_handler_show(struct device_driver *drv, char *buf)
++{
++ struct pcistub_device *psdev;
++ struct pciback_dev_data *dev_data;
++ size_t count = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&pcistub_devices_lock, flags);
++ list_for_each_entry(psdev, &pcistub_devices, dev_list) {
++ if (count >= PAGE_SIZE)
++ break;
++ if (!psdev->dev)
++ continue;
++ dev_data = pci_get_drvdata(psdev->dev);
++ if (!dev_data)
++ continue;
++ count +=
++ scnprintf(buf + count, PAGE_SIZE - count, "%s:%s:%sing:%ld\n",
++ pci_name(psdev->dev),
++ dev_data->isr_on ? "on" : "off",
++ dev_data->ack_intr ? "ack" : "not ack",
++ dev_data->handled);
++ }
++ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++ return count;
++}
++
++DRIVER_ATTR(irq_handlers, S_IRUSR, pcistub_irq_handler_show, NULL);
++
++static ssize_t pcistub_irq_handler_switch(struct device_driver *drv,
++ const char *buf,
++ size_t count)
++{
++ struct pcistub_device *psdev;
++ struct pciback_dev_data *dev_data;
++ int domain, bus, slot, func;
++ int err = -ENOENT;
++
++ err = str_to_slot(buf, &domain, &bus, &slot, &func);
++ if (err)
++ goto out;
++
++ psdev = pcistub_device_find(domain, bus, slot, func);
++
++ if (!psdev)
++ goto out;
++
++ dev_data = pci_get_drvdata(psdev->dev);
++ if (!dev_data)
++ goto out;
++
++ dev_dbg(&psdev->dev->dev, "%s fake irq handler: %d->%d\n",
++ dev_data->irq_name, dev_data->isr_on,
++ !dev_data->isr_on);
++
++ dev_data->isr_on = !(dev_data->isr_on);
++ if (dev_data->isr_on)
++ dev_data->ack_intr = 1;
++out:
++ if (!err)
++ err = count;
++ return err;
++}
++DRIVER_ATTR(irq_handler_state, S_IWUSR, NULL, pcistub_irq_handler_switch);
++
+static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf,
+ size_t count)
+{
@@ -22406,7 +23414,10 @@
+ driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots);
+ driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks);
+ driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive);
-+
++ driver_remove_file(&pciback_pci_driver.driver,
++ &driver_attr_irq_handlers);
++ driver_remove_file(&pciback_pci_driver.driver,
++ &driver_attr_irq_handler_state);
+ pci_unregister_driver(&pciback_pci_driver);
+}
+
@@ -22465,6 +23476,12 @@
+ err = driver_create_file(&pciback_pci_driver.driver,
+ &driver_attr_permissive);
+
++ if (!err)
++ err = driver_create_file(&pciback_pci_driver.driver,
++ &driver_attr_irq_handlers);
++ if (!err)
++ err = driver_create_file(&pciback_pci_driver.driver,
++ &driver_attr_irq_handler_state);
+ if (err)
+ pcistub_exit();
+
@@ -22525,10 +23542,10 @@
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/xen/pciback/pciback.h b/drivers/xen/pciback/pciback.h
new file mode 100644
-index 0000000..98e2912
+index 0000000..fc31052
--- /dev/null
+++ b/drivers/xen/pciback/pciback.h
-@@ -0,0 +1,133 @@
+@@ -0,0 +1,142 @@
+/*
+ * PCI Backend Common Data Structures & Function Declarations
+ *
@@ -22576,8 +23593,14 @@
+
+struct pciback_dev_data {
+ struct list_head config_fields;
-+ int permissive;
-+ int warned_on_write;
++ unsigned int permissive : 1;
++ unsigned int warned_on_write : 1;
++ unsigned int enable_intx : 1;
++ unsigned int isr_on : 1; /* Whether the IRQ handler is installed. */
++ unsigned int ack_intr : 1; /* .. and ACK-ing */
++ unsigned long handled;
++ unsigned int irq; /* Saved in case device transitions to MSI/MSI-X */
++ char irq_name[0]; /* pciback[000:04:00.0] */
+};
+
+/* Used by XenBus and pciback_ops.c */
@@ -22662,12 +23685,15 @@
+void test_and_schedule_op(struct pciback_device *pdev);
+#endif
+
++/* Handles shared IRQs that can to device domain and control domain. */
++void pciback_irq_handler(struct pci_dev *dev, int reset);
++irqreturn_t pciback_guest_interrupt(int irq, void *dev_id);
diff --git a/drivers/xen/pciback/pciback_ops.c b/drivers/xen/pciback/pciback_ops.c
new file mode 100644
-index 0000000..011db67
+index 0000000..5543881
--- /dev/null
+++ b/drivers/xen/pciback/pciback_ops.c
-@@ -0,0 +1,139 @@
+@@ -0,0 +1,242 @@
+/*
+ * PCI Backend Operations - respond to PCI requests from Frontend
+ *
@@ -22683,6 +23709,78 @@
+int verbose_request;
+module_param(verbose_request, int, 0644);
+
++/* Ensure a device is has the fake IRQ handler "turned on/off" and is
++ * ready to be exported. This MUST be run after pciback_reset_device
++ * which does the actual PCI device enable/disable.
++ */
++void pciback_control_isr(struct pci_dev *dev, int reset)
++{
++ struct pciback_dev_data *dev_data;
++ int rc;
++ int enable = 0;
++
++ dev_data = pci_get_drvdata(dev);
++ if (!dev_data)
++ return;
++
++ /* We don't deal with bridges */
++ if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL)
++ return;
++
++ if (reset) {
++ dev_data->enable_intx = 0;
++ dev_data->ack_intr = 0;
++ }
++ enable = dev_data->enable_intx;
++
++ /* Asked to disable, but ISR isn't runnig */
++ if (!enable && !dev_data->isr_on)
++ return;
++
++ /* Squirrel away the IRQs in the dev_data. We need this
++ * b/c when device transitions to MSI, the dev->irq is
++ * overwritten with the MSI vector.
++ */
++ if (enable)
++ dev_data->irq = dev->irq;
++
++ dev_dbg(&dev->dev, "%s: #%d %s %s%s %s-> %s\n",
++ dev_data->irq_name,
++ dev_data->irq,
++ pci_is_enabled(dev) ? "on" : "off",
++ dev->msi_enabled ? "MSI" : "",
++ dev->msix_enabled ? "MSI/X" : "",
++ dev_data->isr_on ? "enable" : "disable",
++ enable ? "enable" : "disable");
++
++ if (enable) {
++ rc = request_irq(dev_data->irq,
++ pciback_guest_interrupt, IRQF_SHARED,
++ dev_data->irq_name, dev);
++ if (rc) {
++ dev_err(&dev->dev, "%s: failed to install fake IRQ " \
++ "handler for IRQ %d! (rc:%d)\n", dev_data->irq_name,
++ dev_data->irq, rc);
++ goto out;
++ }
++ }
++ else {
++ free_irq(dev_data->irq, dev);
++ dev_data->irq = 0;
++ }
++ dev_data->isr_on = enable;
++ dev_data->ack_intr = enable;
++out:
++ dev_dbg(&dev->dev, "%s: #%d %s %s%s %s\n",
++ dev_data->irq_name,
++ dev_data->irq,
++ pci_is_enabled(dev) ? "on" : "off",
++ dev->msi_enabled ? "MSI" : "",
++ dev->msix_enabled ? "MSI/X" : "",
++ enable ? (dev_data->isr_on ? "enabled" : "failed to enable") :
++ (dev_data->isr_on ? "failed to disable" : "disabled"));
++}
++
+/* Ensure a device is "turned off" and ready to be exported.
+ * (Also see pciback_config_reset to ensure virtual configuration space is
+ * ready to be re-exported)
@@ -22691,6 +23789,8 @@
+{
+ u16 cmd;
+
++ pciback_control_isr(dev, 1 /* reset device */);
++
+ /* Disable devices (but not bridges) */
+ if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
+#ifdef CONFIG_PCI_MSI
@@ -22748,13 +23848,18 @@
+ struct pciback_device *pdev =
+ container_of(data, struct pciback_device, op_work);
+ struct pci_dev *dev;
++ struct pciback_dev_data *dev_data = NULL;
+ struct xen_pci_op *op = &pdev->sh_info->op;
++ int test_intx = 0;
+
+ dev = pciback_get_pci_dev(pdev, op->domain, op->bus, op->devfn);
+
+ if (dev == NULL)
+ op->err = XEN_PCI_ERR_dev_not_found;
+ else {
++ dev_data = pci_get_drvdata(dev);
++ if (dev_data)
++ test_intx = dev_data->enable_intx;
+ switch (op->cmd) {
+ case XEN_PCI_OP_conf_read:
+ op->err = pciback_config_read(dev,
@@ -22779,10 +23884,15 @@
+ break;
+#endif
+ default:
-+ op->err = XEN_PCI_ERR_not_implemented;
++ op->err = XEN_PCI_ERR_not_implemented;
+ break;
+ }
+ }
++ if (!op->err && dev && dev_data) {
++ /* Transition detected */
++ if ((dev_data->enable_intx != test_intx))
++ pciback_control_isr(dev, 0 /* no reset */);
++ }
+ /* Tell the driver domain that we're done. */
+ wmb();
+ clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
@@ -22807,6 +23917,25 @@
+
+ return IRQ_HANDLED;
+}
++irqreturn_t pciback_guest_interrupt(int irq, void *dev_id)
++{
++ struct pci_dev *dev = (struct pci_dev *)dev_id;
++ struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
++
++ if (dev_data->isr_on && dev_data->ack_intr) {
++ dev_data->handled++;
++ if ((dev_data->handled % 1000) == 0) {
++ if (xen_ignore_irq(irq)) {
++ printk(KERN_INFO "%s IRQ line is not shared "
++ "with other domains. Turning ISR off\n",
++ dev_data->irq_name);
++ dev_data->ack_intr = 0;
++ }
++ }
++ return IRQ_HANDLED;
++ }
++ return IRQ_NONE;
++}
diff --git a/drivers/xen/pciback/slot.c b/drivers/xen/pciback/slot.c
new file mode 100644
index 0000000..efb922d
@@ -24408,6 +25537,271 @@
+}
+
+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..a33074e
+--- /dev/null
++++ b/drivers/xen/platform-pci.c
+@@ -0,0 +1,259 @@
++/******************************************************************************
++ * 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 <asm/io.h>
++
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++
++#include <xen/grant_table.h>
++#include <xen/platform_pci.h>
++#include <xen/interface/platform_pci.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 at xensource.com and stefano.stabellini at 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;
++struct pci_dev *xen_platform_pdev;
++
++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(get_irq_regs());
++ return IRQ_HANDLED;
++}
++
++static int xen_allocate_irq(struct pci_dev *pdev)
++{
++ __set_irq_handler(pdev->irq, handle_edge_irq, 0, NULL);
++ return request_irq(pdev->irq, do_hvm_evtchn_intr,
++ IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
++ "xen-platform-pci", pdev);
++}
++
++void platform_pci_disable_irq(void)
++{
++ printk(KERN_DEBUG "platform_pci_disable_irq\n");
++ disable_irq(xen_platform_pdev->irq);
++}
++
++void platform_pci_enable_irq(void)
++{
++ printk(KERN_DEBUG "platform_pci_enable_irq\n");
++ enable_irq(xen_platform_pdev->irq);
++}
++
++void platform_pci_resume(void)
++{
++ if (xen_set_callback_via(callback_via)) {
++ printk("platform_pci_resume failure!\n");
++ return;
++ }
++}
++
++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;
++ xen_platform_pdev = pdev;
++
++ 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;
++ }
++
++ 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;
++ }
++
++ 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 out;
++ }
++
++ platform_mmio = mmio_addr;
++ platform_mmiolen = mmio_len;
++
++ if (!xen_have_vector_callback) {
++ ret = xen_allocate_irq(pdev);
++ if (ret) {
++ printk(KERN_WARNING "request_irq failed err=%d\n", ret);
++ goto out;
++ }
++ callback_via = get_callback_via(pdev);
++ ret = xen_set_callback_via(callback_via);
++ if (ret) {
++ printk(KERN_WARNING
++ "Unable to set the evtchn callback err=%d\n", ret);
++ goto out;
++ }
++ }
++ ret = gnttab_init();
++ if (ret)
++ goto out;
++ ret = xenbus_probe_init();
++ if (ret)
++ goto out;
++ ret = xen_setup_shutdown_event();
++ if (ret)
++ goto out;
++
++
++out:
++ if (ret) {
++ release_mem_region(mmio_addr, mmio_len);
++ release_region(ioaddr, iolen);
++ pci_disable_device(pdev);
++ }
++
++ return ret;
++}
++
++#define XEN_PLATFORM_VENDOR_ID 0x5853
++#define XEN_PLATFORM_DEVICE_ID 0x0001
++static struct pci_device_id platform_pci_tbl[] __devinitdata = {
++ {XEN_PLATFORM_VENDOR_ID, XEN_PLATFORM_DEVICE_ID,
++ 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 check_platform_magic(void)
++{
++ short magic;
++ char protocol, *err;
++
++ magic = inw(XEN_IOPORT_MAGIC);
++
++ if (magic != XEN_IOPORT_MAGIC_VAL) {
++ err = "unrecognised magic value";
++ goto no_dev;
++ }
++
++ protocol = inb(XEN_IOPORT_PROTOVER);
++
++ printk(KERN_DEBUG DRV_NAME "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 DRV_NAME "blacklisted by host\n");
++ return -ENODEV;
++ }
++ break;
++ default:
++ err = "unknown I/O protocol version";
++ goto no_dev;
++ }
++
++ return 0;
++
++ no_dev:
++ printk(KERN_WARNING DRV_NAME "failed backend handshake: %s\n", err);
++ return -ENODEV;
++}
++
++static int __init platform_pci_module_init(void)
++{
++ int rc;
++
++ rc = check_platform_magic();
++ if (rc < 0)
++ return rc;
++
++ rc = pci_register_driver(&platform_driver);
++ if (rc) {
++ printk(KERN_INFO DRV_NAME
++ ": No platform pci device model found\n");
++ return rc;
++ }
++
++ return 0;
++}
++
++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
@@ -24662,10 +26056,10 @@
return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
}
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
-index 649fcdf..ab04a1b 100644
+index 649fcdf..57fb749 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
-@@ -49,6 +49,8 @@
+@@ -49,31 +49,28 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/xen/hypervisor.h>
@@ -24674,7 +26068,11 @@
#include <xen/xenbus.h>
#include <xen/events.h>
#include <xen/page.h>
-@@ -58,22 +60,15 @@
+
++#include <xen/hvm.h>
++
+ #include "xenbus_comms.h"
+ #include "xenbus_probe.h"
int xen_store_evtchn;
@@ -24700,7 +26098,7 @@
/* If something in array of ids matches this device, return it. */
static const struct xenbus_device_id *
match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
-@@ -94,34 +89,7 @@ int xenbus_match(struct device *_dev, struct device_driver *_drv)
+@@ -94,34 +91,7 @@ int xenbus_match(struct device *_dev, struct device_driver *_drv)
return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
}
@@ -24736,7 +26134,7 @@
static void free_otherend_details(struct xenbus_device *dev)
-@@ -141,7 +109,28 @@ static void free_otherend_watch(struct xenbus_device *dev)
+@@ -141,7 +111,28 @@ static void free_otherend_watch(struct xenbus_device *dev)
}
@@ -24766,7 +26164,7 @@
char *id_node, char *path_node)
{
int err = xenbus_gather(XBT_NIL, xendev->nodename,
-@@ -166,39 +155,11 @@ int read_otherend_details(struct xenbus_device *xendev,
+@@ -166,39 +157,11 @@ int read_otherend_details(struct xenbus_device *xendev,
return 0;
}
@@ -24810,7 +26208,7 @@
{
struct xenbus_device *dev =
container_of(watch, struct xenbus_device, otherend_watch);
-@@ -226,11 +187,7 @@ static void otherend_changed(struct xenbus_watch *watch,
+@@ -226,11 +189,7 @@ static void otherend_changed(struct xenbus_watch *watch,
* work that can fail e.g., when the rootfs is gone.
*/
if (system_state > SYSTEM_RUNNING) {
@@ -24823,7 +26221,7 @@
xenbus_frontend_closed(dev);
return;
}
-@@ -238,25 +195,7 @@ static void otherend_changed(struct xenbus_watch *watch,
+@@ -238,25 +197,7 @@ static void otherend_changed(struct xenbus_watch *watch,
if (drv->otherend_changed)
drv->otherend_changed(dev, state);
}
@@ -24850,7 +26248,7 @@
int xenbus_dev_probe(struct device *_dev)
{
-@@ -300,8 +239,9 @@ int xenbus_dev_probe(struct device *_dev)
+@@ -300,8 +241,9 @@ int xenbus_dev_probe(struct device *_dev)
fail:
xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename);
xenbus_switch_state(dev, XenbusStateClosed);
@@ -24861,7 +26259,7 @@
int xenbus_dev_remove(struct device *_dev)
{
-@@ -319,8 +259,9 @@ int xenbus_dev_remove(struct device *_dev)
+@@ -319,8 +261,9 @@ int xenbus_dev_remove(struct device *_dev)
xenbus_switch_state(dev, XenbusStateClosed);
return 0;
}
@@ -24872,7 +26270,7 @@
{
struct xenbus_device *dev = to_xenbus_device(_dev);
unsigned long timeout = 5*HZ;
-@@ -341,6 +282,7 @@ static void xenbus_dev_shutdown(struct device *_dev)
+@@ -341,6 +284,7 @@ static void xenbus_dev_shutdown(struct device *_dev)
out:
put_device(&dev->dev);
}
@@ -24880,7 +26278,7 @@
int xenbus_register_driver_common(struct xenbus_driver *drv,
struct xen_bus_type *bus,
-@@ -354,25 +296,7 @@ int xenbus_register_driver_common(struct xenbus_driver *drv,
+@@ -354,25 +298,7 @@ int xenbus_register_driver_common(struct xenbus_driver *drv,
return driver_register(&drv->driver);
}
@@ -24907,7 +26305,7 @@
void xenbus_unregister_driver(struct xenbus_driver *drv)
{
-@@ -543,24 +467,7 @@ fail:
+@@ -543,24 +469,7 @@ fail:
kfree(xendev);
return err;
}
@@ -24933,7 +26331,7 @@
static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type)
{
-@@ -574,10 +481,11 @@ static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type)
+@@ -574,10 +483,11 @@ static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type)
return PTR_ERR(dir);
for (i = 0; i < dir_n; i++) {
@@ -24946,7 +26344,7 @@
kfree(dir);
return err;
}
-@@ -597,9 +505,11 @@ int xenbus_probe_devices(struct xen_bus_type *bus)
+@@ -597,9 +507,11 @@ int xenbus_probe_devices(struct xen_bus_type *bus)
if (err)
break;
}
@@ -24958,7 +26356,7 @@
static unsigned int char_count(const char *str, char c)
{
-@@ -662,32 +572,17 @@ void xenbus_dev_changed(const char *node, struct xen_bus_type *bus)
+@@ -662,32 +574,17 @@ void xenbus_dev_changed(const char *node, struct xen_bus_type *bus)
}
EXPORT_SYMBOL_GPL(xenbus_dev_changed);
@@ -24994,7 +26392,7 @@
if (drv->suspend)
err = drv->suspend(xdev, state);
if (err)
-@@ -695,21 +590,19 @@ static int xenbus_dev_suspend(struct device *dev, pm_message_t state)
+@@ -695,21 +592,19 @@ static int xenbus_dev_suspend(struct device *dev, pm_message_t state)
"xenbus: suspend %s failed: %i\n", dev_name(dev), err);
return 0;
}
@@ -25020,7 +26418,7 @@
err = talk_to_otherend(xdev);
if (err) {
printk(KERN_WARNING
-@@ -740,6 +633,7 @@ static int xenbus_dev_resume(struct device *dev)
+@@ -740,6 +635,7 @@ static int xenbus_dev_resume(struct device *dev)
return 0;
}
@@ -25028,7 +26426,7 @@
/* A flag to determine if xenstored is 'ready' (i.e. has started) */
int xenstored_ready = 0;
-@@ -768,11 +662,6 @@ void xenbus_probe(struct work_struct *unused)
+@@ -768,52 +664,78 @@ void xenbus_probe(struct work_struct *unused)
{
BUG_ON((xenstored_ready <= 0));
@@ -25040,27 +26438,39 @@
/* Notify others that xenstore is up */
blocking_notifier_call_chain(&xenstore_chain, 0, NULL);
}
-@@ -780,27 +669,43 @@ void xenbus_probe(struct work_struct *unused)
- static int __init xenbus_probe_init(void)
+
+-static int __init xenbus_probe_init(void)
++static int __init __xenbus_probe_init(void)
{
- int err = 0;
-+ unsigned long page = 0;
+- int err = 0;
++ /* Delay initialization in the PV on HVM case */
++ if (xen_hvm_domain())
++ return 0;
- DPRINTK("");
+- DPRINTK("");
++ if (!xen_pv_domain())
++ return -ENODEV;
- err = -ENODEV;
- if (!xen_domain())
+- err = -ENODEV;
+- if (!xen_domain())
- goto out_error;
--
++ return xenbus_probe_init();
++}
+
- /* Register ourselves with the kernel bus subsystem */
- err = bus_register(&xenbus_frontend.bus);
- if (err)
- goto out_error;
--
++int xenbus_probe_init(void)
++{
++ int err = 0;
++ unsigned long page = 0;
++
++ DPRINTK("");
+
- err = xenbus_backend_bus_register();
- if (err)
- goto out_unreg_front;
-+ return err;
/*
* Domain0 doesn't have a store_evtchn or store_mfn yet.
@@ -25094,8 +26504,22 @@
+ xen_store_interface = mfn_to_virt(xen_store_mfn);
} else {
xenstored_ready = 1;
- xen_store_evtchn = xen_start_info->store_evtchn;
-@@ -813,7 +718,7 @@ static int __init xenbus_probe_init(void)
+- xen_store_evtchn = xen_start_info->store_evtchn;
+- xen_store_mfn = xen_start_info->store_mfn;
++ if (xen_hvm_domain()) {
++ xen_store_evtchn = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN);
++ xen_store_mfn = hvm_get_parameter(HVM_PARAM_STORE_PFN);
++ 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);
++ }
+ }
+- xen_store_interface = mfn_to_virt(xen_store_mfn);
+
+ /* Initialize the interface to xenstore. */
+ err = xs_init();
if (err) {
printk(KERN_WARNING
"XENBUS: Error initializing xenstore comms: %i\n", err);
@@ -25104,7 +26528,7 @@
}
if (!xen_initial_domain())
-@@ -829,128 +734,13 @@ static int __init xenbus_probe_init(void)
+@@ -829,128 +751,13 @@ static int __init xenbus_probe_init(void)
return 0;
@@ -25121,7 +26545,8 @@
return err;
}
- postcore_initcall(xenbus_probe_init);
+-postcore_initcall(xenbus_probe_init);
++postcore_initcall(__xenbus_probe_init);
MODULE_LICENSE("GPL");
-
@@ -25587,10 +27012,10 @@
+subsys_initcall(xenbus_probe_backend_init);
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
new file mode 100644
-index 0000000..77af5c3
+index 0000000..54e4d70
--- /dev/null
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
-@@ -0,0 +1,287 @@
+@@ -0,0 +1,314 @@
+#define DPRINTK(fmt, args...) \
+ pr_debug("xenbus_probe (%s:%d) " fmt ".\n", \
+ __func__, __LINE__, ##args)
@@ -25845,6 +27270,33 @@
+ return NOTIFY_DONE;
+}
+
++static int dev_suspend(struct device *dev, void *data)
++{
++ return xenbus_dev_suspend(dev, PMSG_SUSPEND);
++}
++
++static int dev_resume(struct device *dev, void *data)
++{
++ return xenbus_dev_resume(dev);
++}
++
++void xenbus_suspend(void)
++{
++ DPRINTK("");
++
++ bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, dev_suspend);
++ xs_suspend();
++}
++EXPORT_SYMBOL_GPL(xenbus_suspend);
++
++void xenbus_resume(void)
++{
++ DPRINTK("");
++
++ xs_resume();
++ bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, dev_resume);
++}
++EXPORT_SYMBOL_GPL(xenbus_resume);
+
+static int __init xenbus_probe_frontend_init(void)
+{
@@ -27297,7 +28749,7 @@
+
+#endif /* __XEN_BLKIF_H__ */
diff --git a/include/xen/events.h b/include/xen/events.h
-index e68d59a..c9034af 100644
+index e68d59a..699108a 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -12,6 +12,8 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn,
@@ -27322,7 +28774,7 @@
/*
* Common unbind function for all event sources. Takes IRQ to unbind from.
-@@ -53,7 +61,33 @@ bool xen_test_irq_pending(int irq);
+@@ -53,7 +61,39 @@ bool xen_test_irq_pending(int irq);
irq will be disabled so it won't deliver an interrupt. */
void xen_poll_irq(int irq);
@@ -27355,6 +28807,12 @@
+}
+#endif
+
++/* Determine whether to ignore this IRQ if passed to a guest. */
++int xen_ignore_irq(int irq);
++
++void xen_evtchn_do_upcall(struct pt_regs *regs);
++void xen_hvm_evtchn_do_upcall(struct pt_regs *regs);
++
#endif /* _XEN_EVENTS_H */
diff --git a/include/xen/gntdev.h b/include/xen/gntdev.h
new file mode 100644
@@ -27482,7 +28940,7 @@
+
+#endif /* __LINUX_PUBLIC_GNTDEV_H__ */
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
-index a40f1cd..9e54167 100644
+index a40f1cd..7f8c7c8 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -37,10 +37,16 @@
@@ -27503,16 +28961,17 @@
/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
#define NR_GRANT_FRAMES 4
-@@ -51,6 +57,8 @@ struct gnttab_free_callback {
+@@ -51,6 +57,9 @@ struct gnttab_free_callback {
u16 count;
};
++int gnttab_init(void);
+void gnttab_reset_grant_page(struct page *page);
+
int gnttab_suspend(void);
int gnttab_resume(void);
-@@ -80,6 +88,8 @@ unsigned long gnttab_end_foreign_transfer(grant_ref_t ref);
+@@ -80,6 +89,8 @@ unsigned long gnttab_end_foreign_transfer(grant_ref_t ref);
int gnttab_query_foreign_access(grant_ref_t ref);
@@ -27521,7 +28980,7 @@
/*
* operations on reserved batches of grant references
*/
-@@ -106,6 +116,37 @@ 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);
@@ -27559,11 +29018,71 @@
int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
unsigned long max_nr_gframes,
struct grant_entry **__shared);
+diff --git a/include/xen/hvm.h b/include/xen/hvm.h
+new file mode 100644
+index 0000000..a80c7b9
+--- /dev/null
++++ b/include/xen/hvm.h
+@@ -0,0 +1,32 @@
++/* 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 unsigned long hvm_get_parameter(int idx)
++{
++ 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 0;
++ }
++ return xhv.value;
++}
++
++int xen_set_callback_via(uint64_t via);
++extern int xen_have_vector_callback;
++
++#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__ */
diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h
-index 39da93c..8211af8 100644
+index 39da93c..c704fe5 100644
--- a/include/xen/interface/grant_table.h
+++ b/include/xen/interface/grant_table.h
-@@ -321,6 +321,28 @@ struct gnttab_query_size {
+@@ -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);
/*
@@ -27592,6 +29111,202 @@
* 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..7c74ba4
+--- /dev/null
++++ b/include/xen/interface/hvm/hvm_op.h
+@@ -0,0 +1,72 @@
++/*
++ * 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: extra argument == pointer to 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);
++
++/* Set the logical level of one of a domain's PCI INTx wires. */
++#define HVMOP_set_pci_intx_level 2
++struct xen_hvm_set_pci_intx_level {
++ /* Domain to be updated. */
++ domid_t domid;
++ /* PCI INTx identification in PCI topology (domain:bus:device:intx). */
++ uint8_t domain, bus, device, intx;
++ /* Assertion level (0 = unasserted, 1 = asserted). */
++ uint8_t level;
++};
++DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_set_pci_intx_level);
++
++/* Set the logical level of one of a domain's ISA IRQ wires. */
++#define HVMOP_set_isa_irq_level 3
++struct xen_hvm_set_isa_irq_level {
++ /* Domain to be updated. */
++ domid_t domid;
++ /* ISA device identification, by ISA IRQ (0-15). */
++ uint8_t isa_irq;
++ /* Assertion level (0 = unasserted, 1 = asserted). */
++ uint8_t level;
++};
++DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_set_isa_irq_level);
++
++#define HVMOP_set_pci_link_route 4
++struct xen_hvm_set_pci_link_route {
++ /* Domain to be updated. */
++ domid_t domid;
++ /* PCI link identifier (0-3). */
++ uint8_t link;
++ /* ISA IRQ (1-15), or 0 (disable link). */
++ uint8_t isa_irq;
++};
++DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_set_pci_link_route);
++
++/* Flushes all VCPU TLBs: @arg must be NULL. */
++#define HVMOP_flush_tlbs 5
++
++#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..aa9efd8
+--- /dev/null
++++ b/include/xen/interface/hvm/params.h
+@@ -0,0 +1,112 @@
++/*
++ * 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
++
++/*
++ * These are not used by Xen. They are here for convenience of HVM-guest
++ * xenbus implementations.
++ */
++#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
++
++#ifdef __ia64__
++
++#define HVM_PARAM_NVRAM_FD 7
++#define HVM_PARAM_VHPT_SIZE 8
++#define HVM_PARAM_BUFPIOREQ_PFN 9
++
++#elif defined(__i386__) || defined(__x86_64__)
++
++/* Expose Viridian interfaces to this HVM guest? */
++#define HVM_PARAM_VIRIDIAN 9
++
++#endif
++
++/*
++ * 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/pciif.h b/include/xen/interface/io/pciif.h
new file mode 100644
index 0000000..c4177f3
@@ -28351,6 +30066,492 @@
+DEFINE_GUEST_HANDLE_STRUCT(xen_platform_op_t);
+
+#endif /* __XEN_PUBLIC_PLATFORM_H__ */
+diff --git a/include/xen/interface/platform_pci.h b/include/xen/interface/platform_pci.h
+new file mode 100644
+index 0000000..bc230cd
+--- /dev/null
++++ b/include/xen/interface/platform_pci.h
+@@ -0,0 +1,45 @@
++/******************************************************************************
++ * platform_pci.h
++ *
++ * Interface for granting foreign access to page frames, and receiving
++ * page-ownership transfers.
++ *
++ * 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_PLATFORM_PCI_H__
++#define __XEN_PUBLIC_PLATFORM_PCI_H__
++
++#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 UNPLUG_ALL_IDE_DISKS 1
++#define UNPLUG_ALL_NICS 2
++#define UNPLUG_AUX_IDE_DISKS 4
++#define UNPLUG_ALL 7
++
++#endif /* __XEN_PUBLIC_PLATFORM_PCI_H__ */
+diff --git a/include/xen/interface/xen-mca.h b/include/xen/interface/xen-mca.h
+new file mode 100644
+index 0000000..f31fdab
+--- /dev/null
++++ b/include/xen/interface/xen-mca.h
+@@ -0,0 +1,429 @@
++/******************************************************************************
++ * arch-x86/mca.h
++ *
++ * Contributed by Advanced Micro Devices, Inc.
++ * Author: Christoph Egger <Christoph.Egger at amd.com>
++ *
++ * Guest OS machine check interface to x86 Xen.
++ *
++ * 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.
++ */
++
++/* Full MCA functionality has the following Usecases from the guest side:
++ *
++ * Must have's:
++ * 1. Dom0 and DomU register machine check trap callback handlers
++ * (already done via "set_trap_table" hypercall)
++ * 2. Dom0 registers machine check event callback handler
++ * (doable via EVTCHNOP_bind_virq)
++ * 3. Dom0 and DomU fetches machine check data
++ * 4. Dom0 wants Xen to notify a DomU
++ * 5. Dom0 gets DomU ID from physical address
++ * 6. Dom0 wants Xen to kill DomU (already done for "xm destroy")
++ *
++ * Nice to have's:
++ * 7. Dom0 wants Xen to deactivate a physical CPU
++ * This is better done as separate task, physical CPU hotplugging,
++ * and hypercall(s) should be sysctl's
++ * 8. Page migration proposed from Xen NUMA work, where Dom0 can tell Xen to
++ * move a DomU (or Dom0 itself) away from a malicious page
++ * producing correctable errors.
++ * 9. offlining physical page:
++ * Xen free's and never re-uses a certain physical page.
++ * 10. Testfacility: Allow Dom0 to write values into machine check MSR's
++ * and tell Xen to trigger a machine check
++ */
++
++#ifndef __XEN_PUBLIC_ARCH_X86_MCA_H__
++#define __XEN_PUBLIC_ARCH_X86_MCA_H__
++
++/* Hypercall */
++#define __HYPERVISOR_mca __HYPERVISOR_arch_0
++
++/*
++ * The xen-unstable repo has interface version 0x03000001; out interface
++ * is incompatible with that and any future minor revisions, so we
++ * choose a different version number range that is numerically less
++ * than that used in xen-unstable.
++ */
++#define XEN_MCA_INTERFACE_VERSION 0x01ecc003
++
++/* IN: Dom0 calls hypercall to retrieve nonurgent error log entry */
++#define XEN_MC_NONURGENT 0x0001
++/* IN: Dom0/DomU calls hypercall to retrieve urgent error log entry */
++#define XEN_MC_URGENT 0x0002
++/* IN: Dom0 acknowledges previosly-fetched error log entry */
++#define XEN_MC_ACK 0x0004
++
++/* OUT: All is ok */
++#define XEN_MC_OK 0x0
++/* OUT: Domain could not fetch data. */
++#define XEN_MC_FETCHFAILED 0x1
++/* OUT: There was no machine check data to fetch. */
++#define XEN_MC_NODATA 0x2
++/* OUT: Between notification time and this hypercall an other
++ * (most likely) correctable error happened. The fetched data,
++ * does not match the original machine check data. */
++#define XEN_MC_NOMATCH 0x4
++
++/* OUT: DomU did not register MC NMI handler. Try something else. */
++#define XEN_MC_CANNOTHANDLE 0x8
++/* OUT: Notifying DomU failed. Retry later or try something else. */
++#define XEN_MC_NOTDELIVERED 0x10
++/* Note, XEN_MC_CANNOTHANDLE and XEN_MC_NOTDELIVERED are mutually exclusive. */
++
++
++#ifndef __ASSEMBLY__
++
++#define VIRQ_MCA VIRQ_ARCH_0 /* G. (DOM0) Machine Check Architecture */
++
++/*
++ * Machine Check Architecure:
++ * structs are read-only and used to report all kinds of
++ * correctable and uncorrectable errors detected by the HW.
++ * Dom0 and DomU: register a handler to get notified.
++ * Dom0 only: Correctable errors are reported via VIRQ_MCA
++ */
++#define MC_TYPE_GLOBAL 0
++#define MC_TYPE_BANK 1
++#define MC_TYPE_EXTENDED 2
++#define MC_TYPE_RECOVERY 3
++
++struct mcinfo_common {
++ uint16_t type; /* structure type */
++ uint16_t size; /* size of this struct in bytes */
++};
++
++
++#define MC_FLAG_CORRECTABLE (1 << 0)
++#define MC_FLAG_UNCORRECTABLE (1 << 1)
++#define MC_FLAG_RECOVERABLE (1 << 2)
++#define MC_FLAG_POLLED (1 << 3)
++#define MC_FLAG_RESET (1 << 4)
++#define MC_FLAG_CMCI (1 << 5)
++#define MC_FLAG_MCE (1 << 6)
++/* contains global x86 mc information */
++struct mcinfo_global {
++ struct mcinfo_common common;
++
++ /* running domain at the time in error (most likely
++ * the impacted one) */
++ uint16_t mc_domid;
++ uint16_t mc_vcpuid; /* virtual cpu scheduled for mc_domid */
++ uint32_t mc_socketid; /* physical socket of the physical core */
++ uint16_t mc_coreid; /* physical impacted core */
++ uint16_t mc_core_threadid; /* core thread of physical core */
++ uint32_t mc_apicid;
++ uint32_t mc_flags;
++ uint64_t mc_gstatus; /* global status */
++};
++
++/* contains bank local x86 mc information */
++struct mcinfo_bank {
++ struct mcinfo_common common;
++
++ uint16_t mc_bank; /* bank nr */
++ uint16_t mc_domid; /* Usecase 5: domain referenced by mc_addr on
++ * privileged pv-ops dom and if mc_addr is valid.
++ * Never valid on DomU. */
++ uint64_t mc_status; /* bank status */
++ uint64_t mc_addr; /* bank address, only valid
++ * if addr bit is set in mc_status */
++ uint64_t mc_misc;
++ uint64_t mc_ctrl2;
++ uint64_t mc_tsc;
++};
++
++
++struct mcinfo_msr {
++ uint64_t reg; /* MSR */
++ uint64_t value; /* MSR value */
++};
++
++/* contains mc information from other
++ * or additional mc MSRs */
++struct mcinfo_extended {
++ struct mcinfo_common common;
++
++ /* You can fill up to five registers.
++ * If you need more, then use this structure
++ * multiple times. */
++
++ uint32_t mc_msrs; /* Number of msr with valid values. */
++ /*
++ * Currently Intel extended MSR (32/64) include all gp registers
++ * and E(R)FLAGS, E(R)IP, E(R)MISC, up to 11/19 of them might be
++ * useful at present. So expand this array to 16/32 to leave room.
++ */
++ struct mcinfo_msr mc_msr[sizeof(void *) * 4];
++};
++
++/* Recovery Action flags. Giving recovery result information to DOM0 */
++
++/* Xen takes successful recovery action, the error is recovered */
++#define REC_ACTION_RECOVERED (0x1 << 0)
++/* No action is performed by XEN */
++#define REC_ACTION_NONE (0x1 << 1)
++/* It's possible DOM0 might take action ownership in some case */
++#define REC_ACTION_NEED_RESET (0x1 << 2)
++
++/* Different Recovery Action types, if the action is performed successfully,
++ * REC_ACTION_RECOVERED flag will be returned.
++ */
++
++/* Page Offline Action */
++#define MC_ACTION_PAGE_OFFLINE (0x1 << 0)
++/* CPU offline Action */
++#define MC_ACTION_CPU_OFFLINE (0x1 << 1)
++/* L3 cache disable Action */
++#define MC_ACTION_CACHE_SHRINK (0x1 << 2)
++
++/* Below interface used between XEN/DOM0 for passing XEN's recovery action
++ * information to DOM0.
++ * usage Senario: After offlining broken page, XEN might pass its page offline
++ * recovery action result to DOM0. DOM0 will save the information in
++ * non-volatile memory for further proactive actions, such as offlining the
++ * easy broken page earlier when doing next reboot.
++*/
++struct page_offline_action {
++ /* Params for passing the offlined page number to DOM0 */
++ uint64_t mfn;
++ uint64_t status;
++};
++
++struct cpu_offline_action {
++ /* Params for passing the identity of the offlined CPU to DOM0 */
++ uint32_t mc_socketid;
++ uint16_t mc_coreid;
++ uint16_t mc_core_threadid;
++};
++
++#define MAX_UNION_SIZE 16
++struct mcinfo_recovery {
++ struct mcinfo_common common;
++ uint16_t mc_bank; /* bank nr */
++ /* Recovery Action Flags defined above such as REC_ACTION_DONE */
++ uint8_t action_flags;
++ /* Recovery Action types defined above such as MC_ACTION_PAGE_OFFLINE */
++ uint8_t action_types;
++ /* In future if more than one recovery action permitted per error bank,
++ * a mcinfo_recovery data array will be returned
++ */
++ union {
++ struct page_offline_action page_retire;
++ struct cpu_offline_action cpu_offline;
++ uint8_t pad[MAX_UNION_SIZE];
++ } action_info;
++};
++
++
++#define MCINFO_HYPERCALLSIZE 1024
++#define MCINFO_MAXSIZE 768
++
++struct mc_info {
++ /* Number of mcinfo_* entries in mi_data */
++ uint32_t mi_nentries;
++ uint32_t _pad0;
++ uint64_t mi_data[(MCINFO_MAXSIZE - 1) / 8];
++};
++typedef struct mc_info mc_info_t;
++DEFINE_GUEST_HANDLE_STRUCT(mc_info);
++
++#define __MC_MSR_ARRAYSIZE 8
++#define __MC_NMSRS 1
++#define MC_NCAPS 7 /* 7 CPU feature flag words */
++#define MC_CAPS_STD_EDX 0 /* cpuid level 0x00000001 (%edx) */
++#define MC_CAPS_AMD_EDX 1 /* cpuid level 0x80000001 (%edx) */
++#define MC_CAPS_TM 2 /* cpuid level 0x80860001 (TransMeta) */
++#define MC_CAPS_LINUX 3 /* Linux-defined */
++#define MC_CAPS_STD_ECX 4 /* cpuid level 0x00000001 (%ecx) */
++#define MC_CAPS_VIA 5 /* cpuid level 0xc0000001 */
++#define MC_CAPS_AMD_ECX 6 /* cpuid level 0x80000001 (%ecx) */
++
++struct mcinfo_logical_cpu {
++ uint32_t mc_cpunr;
++ uint32_t mc_chipid;
++ uint16_t mc_coreid;
++ uint16_t mc_threadid;
++ uint32_t mc_apicid;
++ uint32_t mc_clusterid;
++ uint32_t mc_ncores;
++ uint32_t mc_ncores_active;
++ uint32_t mc_nthreads;
++ int32_t mc_cpuid_level;
++ uint32_t mc_family;
++ uint32_t mc_vendor;
++ uint32_t mc_model;
++ uint32_t mc_step;
++ char mc_vendorid[16];
++ char mc_brandid[64];
++ uint32_t mc_cpu_caps[MC_NCAPS];
++ uint32_t mc_cache_size;
++ uint32_t mc_cache_alignment;
++ int32_t mc_nmsrvals;
++ struct mcinfo_msr mc_msrvalues[__MC_MSR_ARRAYSIZE];
++};
++typedef struct mcinfo_logical_cpu mcinfo_logical_cpu_t;
++DEFINE_GUEST_HANDLE_STRUCT(mcinfo_logical_cpu);
++
++
++/*
++ * OS's should use these instead of writing their own lookup function
++ * each with its own bugs and drawbacks.
++ * We use macros instead of static inline functions to allow guests
++ * to include this header in assembly files (*.S).
++ */
++/* Prototype:
++ * uint32_t x86_mcinfo_nentries(struct mc_info *mi);
++ */
++#define x86_mcinfo_nentries(_mi) \
++ ((_mi)->mi_nentries)
++/* Prototype:
++ * struct mcinfo_common *x86_mcinfo_first(struct mc_info *mi);
++ */
++#define x86_mcinfo_first(_mi) \
++ ((struct mcinfo_common *)(_mi)->mi_data)
++/* Prototype:
++ * struct mcinfo_common *x86_mcinfo_next(struct mcinfo_common *mic);
++ */
++#define x86_mcinfo_next(_mic) \
++ ((struct mcinfo_common *)((uint8_t *)(_mic) + (_mic)->size))
++
++/* Prototype:
++ * void x86_mcinfo_lookup(void *ret, struct mc_info *mi, uint16_t type);
++ */
++
++static inline void x86_mcinfo_lookup
++ (struct mcinfo_common **ret, struct mc_info *mi, uint16_t type)
++{
++ uint32_t found = 0, i;
++ struct mcinfo_common *mic;
++
++ *ret = NULL;
++ if (!mi)
++ return;
++ mic = x86_mcinfo_first(mi);
++
++ for (i = 0; i < x86_mcinfo_nentries(mi); i++) {
++ if (mic->type == type) {
++ found = 1;
++ break;
++ }
++ mic = x86_mcinfo_next(mic);
++ }
++
++ *ret = found ? mic : NULL;
++}
++/* Usecase 1
++ * Register machine check trap callback handler
++ * (already done via "set_trap_table" hypercall)
++ */
++
++/* Usecase 2
++ * Dom0 registers machine check event callback handler
++ * done by EVTCHNOP_bind_virq
++ */
++
++/* Usecase 3
++ * Fetch machine check data from hypervisor.
++ * Note, this hypercall is special, because both Dom0 and DomU must use this.
++ */
++#define XEN_MC_fetch 1
++struct xen_mc_fetch {
++ /* IN/OUT variables.
++ * IN: XEN_MC_NONURGENT, XEN_MC_URGENT,
++ * XEN_MC_ACK if ack'king an earlier fetch
++ * OUT: XEN_MC_OK, XEN_MC_FETCHAILED,
++ * XEN_MC_NODATA, XEN_MC_NOMATCH
++ */
++ uint32_t flags;
++ uint32_t _pad0;
++ /* OUT: id for ack, IN: id we are ack'ing */
++ uint64_t fetch_id;
++
++ /* OUT variables. */
++ GUEST_HANDLE(mc_info) data;
++};
++typedef struct xen_mc_fetch xen_mc_fetch_t;
++DEFINE_GUEST_HANDLE_STRUCT(xen_mc_fetch);
++
++
++/* Usecase 4
++ * This tells the hypervisor to notify a DomU about the machine check error
++ */
++#define XEN_MC_notifydomain 2
++struct xen_mc_notifydomain {
++ /* IN variables. */
++ uint16_t mc_domid;/* The unprivileged domain to notify. */
++ uint16_t mc_vcpuid;/* The vcpu in mc_domid to notify.
++ * Usually echo'd value from the fetch hypercall. */
++
++ /* IN/OUT variables. */
++ uint32_t flags;
++
++/* OUT: XEN_MC_OK, XEN_MC_CANNOTHANDLE, XEN_MC_NOTDELIVERED, XEN_MC_NOMATCH */
++};
++typedef struct xen_mc_notifydomain xen_mc_notifydomain_t;
++DEFINE_GUEST_HANDLE_STRUCT(xen_mc_notifydomain);
++
++#define XEN_MC_physcpuinfo 3
++struct xen_mc_physcpuinfo {
++ /* IN/OUT */
++ uint32_t ncpus;
++ uint32_t _pad0;
++ /* OUT */
++ GUEST_HANDLE(mcinfo_logical_cpu) info;
++};
++
++#define XEN_MC_msrinject 4
++#define MC_MSRINJ_MAXMSRS 8
++struct xen_mc_msrinject {
++ /* IN */
++ uint32_t mcinj_cpunr;/* target processor id */
++ uint32_t mcinj_flags;/* see MC_MSRINJ_F_* below */
++ uint32_t mcinj_count;/* 0 .. count-1 in array are valid */
++ uint32_t _pad0;
++ struct mcinfo_msr mcinj_msr[MC_MSRINJ_MAXMSRS];
++};
++
++/* Flags for mcinj_flags above; bits 16-31 are reserved */
++#define MC_MSRINJ_F_INTERPOSE 0x1
++
++#define XEN_MC_mceinject 5
++struct xen_mc_mceinject {
++ unsigned int mceinj_cpunr; /* target processor id */
++};
++
++struct xen_mc {
++ uint32_t cmd;
++ uint32_t interface_version; /* XEN_MCA_INTERFACE_VERSION */
++ union {
++ struct xen_mc_fetch mc_fetch;
++ struct xen_mc_notifydomain mc_notifydomain;
++ struct xen_mc_physcpuinfo mc_physcpuinfo;
++ struct xen_mc_msrinject mc_msrinject;
++ struct xen_mc_mceinject mc_mceinject;
++ } u;
++};
++typedef struct xen_mc xen_mc_t;
++DEFINE_GUEST_HANDLE_STRUCT(xen_mc);
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __XEN_PUBLIC_ARCH_X86_MCA_H__ */
diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h
index 2befa3e..9ffaee0 100644
--- a/include/xen/interface/xen.h
@@ -28467,6 +30668,59 @@
+
+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..ced434d
+--- /dev/null
++++ b/include/xen/platform_pci.h
+@@ -0,0 +1,47 @@
++/******************************************************************************
++ * platform-pci.h
++ *
++ * Xen platform PCI device driver
++ * Copyright (c) 2004, Intel Corporation. <xiaofeng.ling at intel.com>
++ * 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.
++ */
++
++#ifndef _XEN_PLATFORM_PCI_H
++#define _XEN_PLATFORM_PCI_H
++
++#include <linux/version.h>
++
++#define XEN_IOPORT_MAGIC_VAL 0x49d2
++#define XEN_IOPORT_LINUX_PRODNUM 0xffff
++#define XEN_IOPORT_LINUX_DRVVER ((LINUX_VERSION_CODE << 8) + 0x0)
++
++#ifdef CONFIG_XEN_PLATFORM_PCI
++unsigned long alloc_xen_mmio(unsigned long len);
++void platform_pci_resume(void);
++void platform_pci_disable_irq(void);
++void platform_pci_enable_irq(void);
++#else
++static inline unsigned long alloc_xen_mmio(unsigned long len)
++{
++ return ~0UL;
++}
++static inline void platform_pci_resume(void) {}
++static inline void platform_pci_disable_irq(void) {}
++static inline void platform_pci_enable_irq(void) {}
++#endif
++
++#endif /* _XEN_PLATFORM_PCI_H */
diff --git a/include/xen/privcmd.h b/include/xen/privcmd.h
new file mode 100644
index 0000000..b42cdfd
@@ -28554,13 +30808,15 @@
+
+#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
-index 883a21b..c7b3ce9 100644
+index 883a21b..323121a 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
-@@ -14,4 +14,15 @@ void xen_mm_unpin_all(void);
+@@ -14,4 +14,17 @@ void xen_mm_unpin_all(void);
void xen_timer_resume(void);
void xen_arch_resume(void);
++int xen_setup_shutdown_event(void);
++
+int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
+ unsigned long addr,
+ unsigned long mfn, int nr,
@@ -28612,7 +30868,7 @@
+
+#endif /* _XEN_XEN_H */
diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
-index b9763ba..542ca7c 100644
+index b9763ba..a7d13ff 100644
--- a/include/xen/xenbus.h
+++ b/include/xen/xenbus.h
@@ -93,7 +93,7 @@ struct xenbus_driver {
@@ -28624,6 +30880,14 @@
struct device_driver driver;
int (*read_otherend_details)(struct xenbus_device *dev);
int (*is_ready)(struct xenbus_device *dev);
+@@ -173,6 +173,7 @@ void unregister_xenbus_watch(struct xenbus_watch *watch);
+ void xs_suspend(void);
+ void xs_resume(void);
+ void xs_suspend_cancel(void);
++int xenbus_probe_init(void);
+
+ /* Used by xenbus_dev to borrow kernel's store connection. */
+ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 986519e..cae345b 100644
--- a/kernel/irq/manage.c
More information about the Kernel-svn-changes
mailing list