xen/acpi: Move the xen_running_on_version_or_later function.
[pandora-kernel.git] / arch / x86 / xen / enlighten.c
index e3497f2..3325cd9 100644 (file)
@@ -81,8 +81,6 @@
 #include "smp.h"
 #include "multicalls.h"
 
-#include <xen/events.h>
-
 EXPORT_SYMBOL_GPL(hypercall_page);
 
 DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
@@ -225,6 +223,21 @@ static void __init xen_banner(void)
               version >> 16, version & 0xffff, extra.extraversion,
               xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
 }
+/* Check if running on Xen version (major, minor) or later */
+bool
+xen_running_on_version_or_later(unsigned int major, unsigned int minor)
+{
+       unsigned int version;
+
+       if (!xen_domain())
+               return false;
+
+       version = HYPERVISOR_xen_version(XENVER_version, NULL);
+       if ((((version >> 16) == major) && ((version & 0xffff) >= minor)) ||
+               ((version >> 16) > major))
+               return true;
+       return false;
+}
 
 #define CPUID_THERM_POWER_LEAF 6
 #define APERFMPERF_PRESENT 0
@@ -289,8 +302,7 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
 
 static bool __init xen_check_mwait(void)
 {
-#if defined(CONFIG_ACPI) && !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) && \
-       !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
+#ifdef CONFIG_ACPI
        struct xen_platform_op op = {
                .cmd                    = XENPF_set_processor_pminfo,
                .u.set_pminfo.id        = -1,
@@ -311,6 +323,13 @@ static bool __init xen_check_mwait(void)
        if (!xen_initial_domain())
                return false;
 
+       /*
+        * When running under platform earlier than Xen4.2, do not expose
+        * mwait, to avoid the risk of loading native acpi pad driver
+        */
+       if (!xen_running_on_version_or_later(4, 2))
+               return false;
+
        ax = 1;
        cx = 0;
 
@@ -1497,51 +1516,72 @@ asmlinkage void __init xen_start_kernel(void)
 #endif
 }
 
-void __ref xen_hvm_init_shared_info(void)
+#ifdef CONFIG_XEN_PVHVM
+#define HVM_SHARED_INFO_ADDR 0xFE700000UL
+static struct shared_info *xen_hvm_shared_info;
+static unsigned long xen_hvm_sip_phys;
+static int xen_major, xen_minor;
+
+static void xen_hvm_connect_shared_info(unsigned long pfn)
 {
-       int cpu;
        struct xen_add_to_physmap xatp;
-       static struct shared_info *shared_info_page = 0;
 
-       if (!shared_info_page)
-               shared_info_page = (struct shared_info *)
-                       extend_brk(PAGE_SIZE, PAGE_SIZE);
        xatp.domid = DOMID_SELF;
        xatp.idx = 0;
        xatp.space = XENMAPSPACE_shared_info;
-       xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
+       xatp.gpfn = pfn;
        if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
                BUG();
 
-       HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
+}
+static void __init xen_hvm_set_shared_info(struct shared_info *sip)
+{
+       int cpu;
+
+       HYPERVISOR_shared_info = sip;
 
        /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
         * page, we use it in the event channel upcall and in some pvclock
         * related functions. We don't need the vcpu_info placement
         * optimizations because we don't use any pv_mmu or pv_irq op on
-        * HVM.
-        * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is
-        * online but xen_hvm_init_shared_info is run at resume time too and
-        * in that case multiple vcpus might be online. */
-       for_each_online_cpu(cpu) {
+        * HVM. */
+       for_each_online_cpu(cpu)
                per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
+}
+
+/* Reconnect the shared_info pfn to a (new) mfn */
+void xen_hvm_resume_shared_info(void)
+{
+       xen_hvm_connect_shared_info(xen_hvm_sip_phys >> PAGE_SHIFT);
+}
+
+/* Xen tools prior to Xen 4 do not provide a E820_Reserved area for guest usage.
+ * On these old tools the shared info page will be placed in E820_Ram.
+ * Xen 4 provides a E820_Reserved area at 0xFC000000, and this code expects
+ * that nothing is mapped up to HVM_SHARED_INFO_ADDR.
+ * Xen 4.3+ provides an explicit 1MB area at HVM_SHARED_INFO_ADDR which is used
+ * here for the shared info page. */
+static void __init xen_hvm_init_shared_info(void)
+{
+       if (xen_major < 4) {
+               xen_hvm_shared_info = extend_brk(PAGE_SIZE, PAGE_SIZE);
+               xen_hvm_sip_phys = __pa(xen_hvm_shared_info);
+       } else {
+               xen_hvm_sip_phys = HVM_SHARED_INFO_ADDR;
+               set_fixmap(FIX_PARAVIRT_BOOTMAP, xen_hvm_sip_phys);
+               xen_hvm_shared_info =
+               (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP);
        }
+       xen_hvm_connect_shared_info(xen_hvm_sip_phys >> PAGE_SHIFT);
+       xen_hvm_set_shared_info(xen_hvm_shared_info);
 }
 
-#ifdef CONFIG_XEN_PVHVM
 static void __init init_hvm_pv_info(void)
 {
-       int major, minor;
        uint32_t eax, ebx, ecx, edx, pages, msr, base;
        u64 pfn;
 
        base = xen_cpuid_base();
-       cpuid(base + 1, &eax, &ebx, &ecx, &edx);
-
-       major = eax >> 16;
-       minor = eax & 0xffff;
-       printk(KERN_INFO "Xen version %d.%d.\n", major, minor);
-
        cpuid(base + 2, &pages, &msr, &ecx, &edx);
 
        pfn = __pa(hypercall_page);
@@ -1592,12 +1632,22 @@ static void __init xen_hvm_guest_init(void)
 
 static bool __init xen_hvm_platform(void)
 {
+       uint32_t eax, ebx, ecx, edx, base;
+
        if (xen_pv_domain())
                return false;
 
-       if (!xen_cpuid_base())
+       base = xen_cpuid_base();
+       if (!base)
                return false;
 
+       cpuid(base + 1, &eax, &ebx, &ecx, &edx);
+
+       xen_major = eax >> 16;
+       xen_minor = eax & 0xffff;
+
+       printk(KERN_INFO "Xen version %d.%d.\n", xen_major, xen_minor);
+
        return true;
 }