Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / core / machine_kexec.c
1 /*
2  * drivers/xen/core/machine_kexec.c 
3  * handle transition of Linux booting another kernel
4  */
5
6 #include <linux/kexec.h>
7 #include <linux/slab.h>
8 #include <xen/interface/kexec.h>
9 #include <xen/interface/platform.h>
10 #include <linux/reboot.h>
11 #include <linux/mm.h>
12 #include <linux/bootmem.h>
13 #include <xen/pcpu.h>
14
15 extern void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, 
16                                          struct kimage *image);
17 extern int machine_kexec_setup_resources(struct resource *hypervisor,
18                                          struct resource *phys_cpus,
19                                          int nr_phys_cpus);
20 extern int machine_kexec_setup_resource(struct resource *hypervisor,
21                                         struct resource *phys_cpu);
22 extern void machine_kexec_register_resources(struct resource *res);
23
24 static unsigned int xen_nr_phys_cpus, xen_max_nr_phys_cpus;
25 static struct resource xen_hypervisor_res;
26 static struct resource *xen_phys_cpus;
27 static struct xen_phys_cpu_entry {
28         struct xen_phys_cpu_entry *next;
29         struct resource res;
30 } *xen_phys_cpu_list;
31
32 size_t vmcoreinfo_size_xen;
33 unsigned long paddr_vmcoreinfo_xen;
34
35 static int fill_crash_res(struct resource *res, unsigned int cpu)
36 {
37         xen_kexec_range_t range = {
38                 .range = KEXEC_RANGE_MA_CPU,
39                 .nr = cpu
40         };
41         int rc = HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range);
42
43         if (!rc && !range.size)
44                 rc = -ENODEV;
45         if (!rc) {
46                 res->name = "Crash note";
47                 res->start = range.start;
48                 res->end = range.start + range.size - 1;
49                 res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
50         }
51
52         return rc;
53 }
54
55 static struct resource *find_crash_res(const struct resource *r,
56                                        unsigned int *idx)
57 {
58         unsigned int i;
59         struct xen_phys_cpu_entry *ent;
60
61         for (i = 0; i < xen_max_nr_phys_cpus; ++i) {
62                 struct resource *res = xen_phys_cpus + i;
63
64                 if (res->parent && res->start == r->start
65                     && res->end == r->end) {
66                         if (idx)
67                                 *idx = i;
68                         return res;
69                 }
70         }
71
72         for (ent = xen_phys_cpu_list; ent; ent = ent->next, ++i)
73                 if (ent->res.parent && ent->res.start == r->start
74                     && ent->res.end == r->end) {
75                         if (idx)
76                                 *idx = i;
77                         return &ent->res;
78                 }
79
80         return NULL;
81 }
82
83 static int kexec_cpu_callback(struct notifier_block *nfb,
84                               unsigned long action, void *hcpu)
85 {
86         unsigned int i, cpu = (unsigned long)hcpu;
87         struct xen_phys_cpu_entry *ent;
88         struct resource *res = NULL, r;
89
90         if (xen_nr_phys_cpus < xen_max_nr_phys_cpus)
91                 xen_nr_phys_cpus = xen_max_nr_phys_cpus;
92         switch (action) {
93         case CPU_ONLINE:
94                 for (i = 0; i < xen_max_nr_phys_cpus; ++i)
95                         if (!xen_phys_cpus[i].parent) {
96                                 res = xen_phys_cpus + i;
97                                 break;
98                         }
99                 if (!res)
100                         for (ent = xen_phys_cpu_list; ent; ent = ent->next)
101                                 if (!ent->res.parent) {
102                                         res = &ent->res;
103                                         break;
104                                 }
105                 if (!res) {
106                         ent = kmalloc(sizeof(*ent), GFP_KERNEL);
107                         res = ent ? &ent->res : NULL;
108                 } else
109                         ent = NULL;
110                 if (res && !fill_crash_res(res, cpu)
111                     && !machine_kexec_setup_resource(&xen_hypervisor_res,
112                                                      res)) {
113                         if (ent) {
114                                 ent->next = xen_phys_cpu_list;
115                                 xen_phys_cpu_list = ent;
116                                 ++xen_nr_phys_cpus;
117                         }
118                 } else {
119                         pr_warn("Could not set up crash note for pCPU#%u\n",
120                                 cpu);
121                         kfree(ent);
122                 }
123                 break;
124
125         case CPU_DEAD:
126                 if (!fill_crash_res(&r, cpu))
127                         res = find_crash_res(&r, NULL);
128                 if (!res) {
129                         unsigned long *map;
130                         xen_platform_op_t op;
131
132                         map = kcalloc(BITS_TO_LONGS(xen_nr_phys_cpus),
133                                       sizeof(long), GFP_KERNEL);
134                         if (!map)
135                                 break;
136
137                         op.cmd = XENPF_get_cpuinfo;
138                         op.u.pcpu_info.xen_cpuid = 0;
139                         if (HYPERVISOR_platform_op(&op) == 0)
140                                 i = op.u.pcpu_info.max_present + 1;
141                         else
142                                 i = xen_nr_phys_cpus;
143
144                         for (cpu = 0; cpu < i; ++cpu) {
145                                 unsigned int idx;
146
147                                 if (fill_crash_res(&r, cpu))
148                                         continue;
149                                 if (find_crash_res(&r, &idx)) {
150                                         BUG_ON(idx >= xen_nr_phys_cpus);
151                                         __set_bit(idx, map);
152                                 }
153                         }
154
155                         for (i = 0; i < xen_max_nr_phys_cpus; ++i)
156                                 if (xen_phys_cpus[i].parent && !test_bit(i, map)) {
157                                         res = xen_phys_cpus + i;
158                                         break;
159                                 }
160                         for (ent = xen_phys_cpu_list; !res && ent;
161                              ent = ent->next, ++i)
162                                 if (ent->res.parent && !test_bit(i, map))
163                                         res = &ent->res;
164                         kfree(map);
165                 }
166                 if (res)
167                         release_resource(res);
168                 break;
169         }
170
171         return NOTIFY_OK;
172 }
173
174 static struct notifier_block kexec_cpu_notifier = {
175         .notifier_call = kexec_cpu_callback
176 };
177
178 void __init xen_machine_kexec_setup_resources(void)
179 {
180         xen_kexec_range_t range;
181         xen_platform_op_t op;
182         unsigned int k = 0, nr = 0;
183         int rc;
184
185         if (strstr(boot_command_line, "crashkernel="))
186                 pr_warning("Ignoring crashkernel command line, "
187                            "parameter will be supplied by xen\n");
188
189         if (!is_initial_xendomain())
190                 return;
191
192         /* fill in crashk_res if range is reserved by hypervisor */
193         memset(&range, 0, sizeof(range));
194         range.range = KEXEC_RANGE_MA_CRASH;
195
196         if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range)
197             || !range.size)
198                 return;
199
200         crashk_res.start = range.start;
201         crashk_res.end = range.start + range.size - 1;
202
203         /* determine maximum number of physical cpus */
204         op.cmd = XENPF_get_cpuinfo;
205         op.u.pcpu_info.xen_cpuid = 0;
206         if (HYPERVISOR_platform_op(&op) == 0)
207                 k = op.u.pcpu_info.max_present + 1;
208 #if CONFIG_XEN_COMPAT < 0x040000
209         else while (1) {
210                 memset(&range, 0, sizeof(range));
211                 range.range = KEXEC_RANGE_MA_CPU;
212                 range.nr = k;
213
214                 if(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
215                         break;
216
217                 k++;
218         }
219 #endif
220
221         if (k == 0)
222                 return;
223
224         xen_max_nr_phys_cpus = k;
225
226         /* allocate xen_phys_cpus */
227
228         xen_phys_cpus = alloc_bootmem(k * sizeof(struct resource));
229
230         /* fill in xen_phys_cpus with per-cpu crash note information */
231
232         for (k = 0; k < xen_max_nr_phys_cpus; k++)
233                 if (!fill_crash_res(xen_phys_cpus + nr, k))
234                         ++nr;
235
236         if (nr == 0)
237                 goto free;
238
239         /* fill in xen_hypervisor_res with hypervisor machine address range */
240
241         memset(&range, 0, sizeof(range));
242         range.range = KEXEC_RANGE_MA_XEN;
243
244         if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
245                 goto free;
246
247         xen_hypervisor_res.name = "Hypervisor code and data";
248         xen_hypervisor_res.start = range.start;
249         xen_hypervisor_res.end = range.start + range.size - 1;
250         xen_hypervisor_res.flags = IORESOURCE_BUSY | IORESOURCE_MEM;
251
252         /* get physical address of vmcoreinfo */
253         memset(&range, 0, sizeof(range));
254         range.range = KEXEC_RANGE_MA_VMCOREINFO;
255
256         rc = HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range);
257
258         if (rc == 0) {
259                 /* Hypercall succeeded */
260                 vmcoreinfo_size_xen = range.size;
261                 paddr_vmcoreinfo_xen = range.start;
262
263         } else {
264                 /* Hypercall failed.
265                  * Indicate not to create sysfs file by resetting globals
266                  */
267                 vmcoreinfo_size_xen = 0;
268                 paddr_vmcoreinfo_xen = 0;
269                 
270 #if CONFIG_XEN_COMPAT < 0x030300
271                 /* The KEXEC_CMD_kexec_get_range hypercall did not implement
272                  * KEXEC_RANGE_MA_VMCOREINFO until Xen 3.3.
273                  * Do not bail out if it fails for this reason.
274                  */
275                 if (rc != -EINVAL)
276 #endif
277                         goto free;
278         }
279
280         if (machine_kexec_setup_resources(&xen_hypervisor_res, xen_phys_cpus,
281                                           nr)) {
282                 /*
283                  * It's too cumbersome to properly free xen_phys_cpus here.
284                  * Failure at this stage is unexpected and the amount of
285                  * memory is small therefore we tolerate the potential leak.
286                  */
287                 goto err;
288         }
289
290         xen_nr_phys_cpus = nr;
291         rc = register_pcpu_notifier(&kexec_cpu_notifier);
292         if (rc)
293                 pr_warn("kexec: pCPU notifier registration failed (%d)\n", rc);
294
295         return;
296
297  free:
298         free_bootmem(__pa(xen_phys_cpus),
299                      xen_max_nr_phys_cpus * sizeof(*xen_phys_cpus));
300  err:
301         xen_nr_phys_cpus = 0;
302 }
303
304 #ifndef CONFIG_X86
305 void __init xen_machine_kexec_register_resources(struct resource *res)
306 {
307         int k;
308         struct resource *r;
309
310         request_resource(res, &xen_hypervisor_res);
311         for (k = 0; k < xen_nr_phys_cpus; k++) {
312                 r = xen_phys_cpus + k;
313                 if (r->parent == NULL) /* out of xen_hypervisor_res range */
314                         request_resource(res, r);
315         } 
316         machine_kexec_register_resources(res);
317 }
318 #endif
319
320 static void setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
321 {
322         machine_kexec_setup_load_arg(xki, image);
323
324         xki->indirection_page = image->head;
325         xki->start_address = image->start;
326 }
327
328 /*
329  * Load the image into xen so xen can kdump itself
330  * This might have been done in prepare, but prepare
331  * is currently called too early. It might make sense
332  * to move prepare, but for now, just add an extra hook.
333  */
334 int xen_machine_kexec_load(struct kimage *image)
335 {
336         xen_kexec_load_t xkl;
337
338         memset(&xkl, 0, sizeof(xkl));
339         xkl.type = image->type;
340         setup_load_arg(&xkl.image, image);
341         return HYPERVISOR_kexec_op(KEXEC_CMD_kexec_load, &xkl);
342 }
343
344 /*
345  * Unload the image that was stored by machine_kexec_load()
346  * This might have been done in machine_kexec_cleanup() but it
347  * is called too late, and its possible xen could try and kdump
348  * using resources that have been freed.
349  */
350 void xen_machine_kexec_unload(struct kimage *image)
351 {
352         xen_kexec_load_t xkl;
353
354         memset(&xkl, 0, sizeof(xkl));
355         xkl.type = image->type;
356         WARN_ON(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_unload, &xkl));
357 }
358
359 /*
360  * Do not allocate memory (or fail in any way) in machine_kexec().
361  * We are past the point of no return, committed to rebooting now.
362  *
363  * This has the hypervisor move to the prefered reboot CPU, 
364  * stop all CPUs and kexec. That is it combines machine_shutdown()
365  * and machine_kexec() in Linux kexec terms.
366  */
367 void __noreturn machine_kexec(struct kimage *image)
368 {
369         xen_kexec_exec_t xke;
370
371         memset(&xke, 0, sizeof(xke));
372         xke.type = image->type;
373         VOID(HYPERVISOR_kexec_op(KEXEC_CMD_kexec, &xke));
374         panic("KEXEC_CMD_kexec hypercall should not return\n");
375 }
376
377 #ifdef CONFIG_X86
378 unsigned long paddr_vmcoreinfo_note(void)
379 {
380         return virt_to_machine(&vmcoreinfo_note);
381 }
382 #endif
383
384 void machine_shutdown(void)
385 {
386         /* do nothing */
387 }
388
389 void machine_crash_shutdown(struct pt_regs *regs)
390 {
391         /* The kernel is broken so disable interrupts */
392         local_irq_disable();
393 }
394
395 /*
396  * Local variables:
397  *  c-file-style: "linux"
398  *  indent-tabs-mode: t
399  *  c-indent-level: 8
400  *  c-basic-offset: 8
401  *  tab-width: 8
402  * End:
403  */