ia64/linux-2.6.18-xen.hg

view drivers/xen/core/machine_kexec.c @ 685:b54652ee29ef

xen: fix kdump kernel crash on Xen3.2

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>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Oct 02 11:29:02 2008 +0100 (2008-10-02)
parents 32a80b65ddad
children
line source
1 /*
2 * drivers/xen/core/machine_kexec.c
3 * handle transition of Linux booting another kernel
4 */
6 #include <linux/kexec.h>
7 #include <xen/interface/kexec.h>
8 #include <linux/mm.h>
9 #include <linux/bootmem.h>
11 extern void machine_kexec_setup_load_arg(xen_kexec_image_t *xki,
12 struct kimage *image);
13 extern int machine_kexec_setup_resources(struct resource *hypervisor,
14 struct resource *phys_cpus,
15 int nr_phys_cpus);
16 extern void machine_kexec_register_resources(struct resource *res);
18 static int __initdata xen_max_nr_phys_cpus;
19 static struct resource xen_hypervisor_res;
20 static struct resource *xen_phys_cpus;
22 size_t vmcoreinfo_size_xen;
23 unsigned long paddr_vmcoreinfo_xen;
25 void __init xen_machine_kexec_setup_resources(void)
26 {
27 xen_kexec_range_t range;
28 struct resource *res;
29 int k = 0;
30 int rc;
32 if (!is_initial_xendomain())
33 return;
35 /* determine maximum number of physical cpus */
37 while (1) {
38 memset(&range, 0, sizeof(range));
39 range.range = KEXEC_RANGE_MA_CPU;
40 range.nr = k;
42 if(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
43 break;
45 k++;
46 }
48 if (k == 0)
49 return;
51 xen_max_nr_phys_cpus = k;
53 /* allocate xen_phys_cpus */
55 xen_phys_cpus = alloc_bootmem_low(k * sizeof(struct resource));
56 BUG_ON(xen_phys_cpus == NULL);
58 /* fill in xen_phys_cpus with per-cpu crash note information */
60 for (k = 0; k < xen_max_nr_phys_cpus; k++) {
61 memset(&range, 0, sizeof(range));
62 range.range = KEXEC_RANGE_MA_CPU;
63 range.nr = k;
65 if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
66 goto err;
68 res = xen_phys_cpus + k;
70 memset(res, 0, sizeof(*res));
71 res->name = "Crash note";
72 res->start = range.start;
73 res->end = range.start + range.size - 1;
74 res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
75 }
77 /* fill in xen_hypervisor_res with hypervisor machine address range */
79 memset(&range, 0, sizeof(range));
80 range.range = KEXEC_RANGE_MA_XEN;
82 if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
83 goto err;
85 xen_hypervisor_res.name = "Hypervisor code and data";
86 xen_hypervisor_res.start = range.start;
87 xen_hypervisor_res.end = range.start + range.size - 1;
88 xen_hypervisor_res.flags = IORESOURCE_BUSY | IORESOURCE_MEM;
90 /* fill in crashk_res if range is reserved by hypervisor */
92 memset(&range, 0, sizeof(range));
93 range.range = KEXEC_RANGE_MA_CRASH;
95 if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
96 goto err;
98 if (range.size) {
99 crashk_res.start = range.start;
100 crashk_res.end = range.start + range.size - 1;
101 }
103 /* get physical address of vmcoreinfo */
104 memset(&range, 0, sizeof(range));
105 range.range = KEXEC_RANGE_MA_VMCOREINFO;
107 rc = HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range);
109 if (rc == 0) {
110 /* Hypercall succeeded */
111 vmcoreinfo_size_xen = range.size;
112 paddr_vmcoreinfo_xen = range.start;
114 } else {
115 /* Hypercall failed.
116 * Indicate not to create sysfs file by resetting globals
117 */
118 vmcoreinfo_size_xen = 0;
119 paddr_vmcoreinfo_xen = 0;
121 /* The KEXEC_CMD_kexec_get_range hypercall did not implement
122 * KEXEC_RANGE_MA_VMCOREINFO until Xen 3.3.
123 * Do not bail out if it fails for this reason.
124 */
125 if (rc != -EINVAL)
126 return;
127 }
129 if (machine_kexec_setup_resources(&xen_hypervisor_res, xen_phys_cpus,
130 xen_max_nr_phys_cpus))
131 goto err;
133 return;
135 err:
136 /*
137 * It isn't possible to free xen_phys_cpus this early in the
138 * boot. Failure at this stage is unexpected and the amount of
139 * memory is small therefore we tolerate the potential leak.
140 */
141 xen_max_nr_phys_cpus = 0;
142 return;
143 }
145 void __init xen_machine_kexec_register_resources(struct resource *res)
146 {
147 request_resource(res, &xen_hypervisor_res);
148 machine_kexec_register_resources(res);
149 }
151 static void setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
152 {
153 machine_kexec_setup_load_arg(xki, image);
155 xki->indirection_page = image->head;
156 xki->start_address = image->start;
157 }
159 /*
160 * Load the image into xen so xen can kdump itself
161 * This might have been done in prepare, but prepare
162 * is currently called too early. It might make sense
163 * to move prepare, but for now, just add an extra hook.
164 */
165 int xen_machine_kexec_load(struct kimage *image)
166 {
167 xen_kexec_load_t xkl;
169 memset(&xkl, 0, sizeof(xkl));
170 xkl.type = image->type;
171 setup_load_arg(&xkl.image, image);
172 return HYPERVISOR_kexec_op(KEXEC_CMD_kexec_load, &xkl);
173 }
175 /*
176 * Unload the image that was stored by machine_kexec_load()
177 * This might have been done in machine_kexec_cleanup() but it
178 * is called too late, and its possible xen could try and kdump
179 * using resources that have been freed.
180 */
181 void xen_machine_kexec_unload(struct kimage *image)
182 {
183 xen_kexec_load_t xkl;
185 memset(&xkl, 0, sizeof(xkl));
186 xkl.type = image->type;
187 WARN_ON(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_unload, &xkl));
188 }
190 /*
191 * Do not allocate memory (or fail in any way) in machine_kexec().
192 * We are past the point of no return, committed to rebooting now.
193 *
194 * This has the hypervisor move to the prefered reboot CPU,
195 * stop all CPUs and kexec. That is it combines machine_shutdown()
196 * and machine_kexec() in Linux kexec terms.
197 */
198 NORET_TYPE void machine_kexec(struct kimage *image)
199 {
200 xen_kexec_exec_t xke;
202 memset(&xke, 0, sizeof(xke));
203 xke.type = image->type;
204 VOID(HYPERVISOR_kexec_op(KEXEC_CMD_kexec, &xke));
205 panic("KEXEC_CMD_kexec hypercall should not return\n");
206 }
208 void machine_shutdown(void)
209 {
210 /* do nothing */
211 }
214 /*
215 * Local variables:
216 * c-file-style: "linux"
217 * indent-tabs-mode: t
218 * c-indent-level: 8
219 * c-basic-offset: 8
220 * tab-width: 8
221 * End:
222 */