]> xenbits.xensource.com Git - xenclient/kernel.git/commitdiff
xen: fix kdump kernel crash on Xen3.2 qparent
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 2 Oct 2008 10:29:02 +0000 (11:29 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 2 Oct 2008 10:29:02 +0000 (11:29 +0100)
The kernel is supposed to create some "Crash note" resources (children
of the "Hypervisor code and data" resource in /proc/iomem).  However,
when running on Xen 3.2, xen_machine_kexec_setup_resources()
encounters an error and returns prior to doing this.

The error occurs when it calls the "kexec_get_range" hypercall to
determine the location of the "vmcoreinfo".  This was only implemented
in Xen 3.3.

This patch makes the kernel handle this error gracefully by simply not
creating the sysfs file "hypervisor/vmcoreinfo" if the hypervisor is
unable to provide the info - rather than bailing out of
xen_machine_kexec_setup_resources() early.

Signed-off-by: Alex Zeffertt <alex.zeffertt@eu.citrix.com>
drivers/xen/core/machine_kexec.c
drivers/xen/core/xen_sysfs.c
include/xen/interface/kexec.h

index 3edea503df1b6c103c9f40ee5361ae75e50f1fe3..b42fe05d83ce401eb66048660185e77aabeb02f5 100644 (file)
@@ -27,6 +27,7 @@ void __init xen_machine_kexec_setup_resources(void)
        xen_kexec_range_t range;
        struct resource *res;
        int k = 0;
+       int rc;
 
        if (!is_initial_xendomain())
                return;
@@ -103,12 +104,26 @@ void __init xen_machine_kexec_setup_resources(void)
        memset(&range, 0, sizeof(range));
        range.range = KEXEC_RANGE_MA_VMCOREINFO;
 
-       if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
-               return;
+       rc = HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range);
 
-       if (range.size) {
-               paddr_vmcoreinfo_xen = range.start;
+       if (rc == 0) {
+               /* Hypercall succeeded */
                vmcoreinfo_size_xen = range.size;
+               paddr_vmcoreinfo_xen = range.start;
+
+       } else {
+               /* Hypercall failed.
+                * Indicate not to create sysfs file by resetting globals
+                */
+               vmcoreinfo_size_xen = 0;
+               paddr_vmcoreinfo_xen = 0;
+               
+               /* The KEXEC_CMD_kexec_get_range hypercall did not implement
+                * KEXEC_RANGE_MA_VMCOREINFO until Xen 3.3.
+                * Do not bail out if it fails for this reason.
+                */
+               if (rc != -EINVAL)
+                       return;
        }
 
        if (machine_kexec_setup_resources(&xen_hypervisor_res, xen_phys_cpus,
index 3288008ad52b3eb8ca80b851546228d43f674773..287635f091037fd87df86bed976a4262338f843c 100644 (file)
@@ -339,9 +339,6 @@ static void xen_properties_destroy(void)
 
 static ssize_t vmcoreinfo_show(struct hyp_sysfs_attr *attr, char *page)
 {
-       extern size_t vmcoreinfo_size_xen;
-       extern unsigned long paddr_vmcoreinfo_xen;
-
        return sprintf(page, "%lx %zx\n",
                paddr_vmcoreinfo_xen, vmcoreinfo_size_xen);
 }
@@ -359,11 +356,6 @@ static void xen_sysfs_vmcoreinfo_destroy(void)
        sysfs_remove_file(&hypervisor_subsys.kset.kobj, &vmcoreinfo_attr.attr);
 }
 
-#else
-
-#define xen_sysfs_vmcoreinfo_init()    0
-#define xen_sysfs_vmcoreinfo_destroy() ((void)0)
-
 #endif
 
 static int __init hyper_sysfs_init(void)
@@ -388,10 +380,19 @@ static int __init hyper_sysfs_init(void)
        ret = xen_properties_init();
        if (ret)
                goto prop_out;
-       ret = xen_sysfs_vmcoreinfo_init();
-       if (!ret)
-               goto out;
+#ifdef CONFIG_KEXEC
+       if (vmcoreinfo_size_xen != 0) {
+               ret = xen_sysfs_vmcoreinfo_init();
+               if (ret)
+                       goto vmcoreinfo_out;
+       }
+#endif
+
+       goto out;
 
+#ifdef CONFIG_KEXEC
+vmcoreinfo_out:
+#endif
        xen_properties_destroy();
 prop_out:
        xen_sysfs_uuid_destroy();
@@ -407,7 +408,10 @@ out:
 
 static void __exit hyper_sysfs_exit(void)
 {
-       xen_sysfs_vmcoreinfo_destroy();
+#ifdef CONFIG_KEXEC
+       if (vmcoreinfo_size_xen != 0)
+               xen_sysfs_vmcoreinfo_destroy();
+#endif
        xen_properties_destroy();
        xen_compilation_destroy();
        xen_sysfs_uuid_destroy();
index fc19f2fe50847f0c4e1d179816016c12fd878c65..8977a8330236d9622e2d974261109c80dfec1aca 100644 (file)
@@ -175,6 +175,8 @@ void vmcoreinfo_append_str(const char *fmt, ...)
 #define VMCOREINFO_OFFSET_ALIAS(name, field, alias) \
        vmcoreinfo_append_str("OFFSET(%s.%s)=%lu\n", #name, #alias, \
                              (unsigned long)offsetof(struct name, field))
+extern size_t vmcoreinfo_size_xen;
+extern unsigned long paddr_vmcoreinfo_xen;
 
 #endif /* _XEN_PUBLIC_KEXEC_H */