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

[Xen-devel] [PATCH] linux-2.6.18: kexec adjustments



- fix error path after retrieving vmcoreinfo (must no directly return,
  special casing -EINVAL should only happen if absolutely needed)
- improve detection of number of CPUs (utilize platform hypercall)
- clean up in error path as far as possible (only after possibly having
  inserted some or all resources it would be problematic to free the
  allocated space)
- leverage the fact that alloc_bootmem() already clears the memory

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

--- a/drivers/xen/core/machine_kexec.c
+++ b/drivers/xen/core/machine_kexec.c
@@ -5,6 +5,7 @@
 
 #include <linux/kexec.h>
 #include <xen/interface/kexec.h>
+#include <xen/interface/platform.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
 
@@ -17,7 +18,7 @@ extern void machine_kexec_register_resou
 
 static int __initdata xen_max_nr_phys_cpus;
 static struct resource xen_hypervisor_res;
-static struct resource *xen_phys_cpus;
+static struct resource *__initdata xen_phys_cpus;
 
 size_t vmcoreinfo_size_xen;
 unsigned long paddr_vmcoreinfo_xen;
@@ -25,16 +26,21 @@ unsigned long paddr_vmcoreinfo_xen;
 void __init xen_machine_kexec_setup_resources(void)
 {
        xen_kexec_range_t range;
+       xen_platform_op_t op;
        struct resource *res;
-       int k = 0;
+       unsigned int k = 0, nr = 0;
        int rc;
 
        if (!is_initial_xendomain())
                return;
 
        /* determine maximum number of physical cpus */
-
-       while (1) {
+       op.cmd = XENPF_get_cpuinfo;
+       op.u.pcpu_info.xen_cpuid = 0;
+       if (HYPERVISOR_platform_op(&op) == 0)
+               k = op.u.pcpu_info.max_present + 1;
+#if CONFIG_XEN_COMPAT < 0x040000
+       else while (1) {
                memset(&range, 0, sizeof(range));
                range.range = KEXEC_RANGE_MA_CPU;
                range.nr = k;
@@ -44,6 +50,7 @@ void __init xen_machine_kexec_setup_reso
 
                k++;
        }
+#endif
 
        if (k == 0)
                return;
@@ -62,25 +69,27 @@ void __init xen_machine_kexec_setup_reso
                range.range = KEXEC_RANGE_MA_CPU;
                range.nr = k;
 
-               if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
-                       goto err;
-
-               res = xen_phys_cpus + k;
+               if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range)
+                   || range.size == 0)
+                       continue;
 
-               memset(res, 0, sizeof(*res));
+               res = xen_phys_cpus + nr++;
                res->name = "Crash note";
                res->start = range.start;
                res->end = range.start + range.size - 1;
                res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
        }
 
+       if (nr == 0)
+               goto free;
+
        /* fill in xen_hypervisor_res with hypervisor machine address range */
 
        memset(&range, 0, sizeof(range));
        range.range = KEXEC_RANGE_MA_XEN;
 
        if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
-               goto err;
+               goto free;
 
        xen_hypervisor_res.name = "Hypervisor code and data";
        xen_hypervisor_res.start = range.start;
@@ -93,7 +102,7 @@ void __init xen_machine_kexec_setup_reso
        range.range = KEXEC_RANGE_MA_CRASH;
 
        if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
-               goto err;
+               goto free;
 
        if (range.size) {
                crashk_res.start = range.start;
@@ -118,28 +127,35 @@ void __init xen_machine_kexec_setup_reso
                vmcoreinfo_size_xen = 0;
                paddr_vmcoreinfo_xen = 0;
                
+#if CONFIG_XEN_COMPAT < 0x030300
                /* 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;
+#endif
+                       goto free;
        }
 
        if (machine_kexec_setup_resources(&xen_hypervisor_res, xen_phys_cpus,
-                                         xen_max_nr_phys_cpus))
+                                         nr)) {
+               /*
+                * It's too cumbersome to properly free xen_phys_cpus here.
+                * Failure at this stage is unexpected and the amount of
+                * memory is small therefore we tolerate the potential leak.
+                */
                goto err;
+       }
+
+       xen_max_nr_phys_cpus = nr;
 
        return;
 
+ free:
+       free_bootmem(__pa(xen_phys_cpus),
+                    xen_max_nr_phys_cpus * sizeof(*xen_phys_cpus));
  err:
-       /*
-        * It isn't possible to free xen_phys_cpus this early in the
-        * boot. Failure at this stage is unexpected and the amount of
-        * memory is small therefore we tolerate the potential leak.
-         */
        xen_max_nr_phys_cpus = 0;
-       return;
 }
 
 void __init xen_machine_kexec_register_resources(struct resource *res)


Attachment: xen-kexec-cleanup.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.