ia64/linux-2.6.18-xen.hg

view drivers/xen/core/machine_kexec.c @ 450:b7f980c60a61

kexec: add xen_machine_kexec_register_resources() and machine_kexec_register_resources()

Add xen_machine_kexec_register_resources() and
machine_kexec_register_resources() to allow architecture specific
handling of iomem resources.

At this time xen_machine_kexec_register_resources() does the
same parenting of per-cpu resources on all architectures.
And machine_kexec_register_resources does nothing on all
architectures.

Signed-off-by: Simon Horman <horms@verge.net.au>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Feb 28 10:54:20 2008 +0000 (2008-02-28)
parents 621ce063ad83
children 32a80b65ddad
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 void __init xen_machine_kexec_setup_resources(void)
23 {
24 xen_kexec_range_t range;
25 struct resource *res;
26 int k = 0;
28 if (!is_initial_xendomain())
29 return;
31 /* determine maximum number of physical cpus */
33 while (1) {
34 memset(&range, 0, sizeof(range));
35 range.range = KEXEC_RANGE_MA_CPU;
36 range.nr = k;
38 if(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
39 break;
41 k++;
42 }
44 if (k == 0)
45 return;
47 xen_max_nr_phys_cpus = k;
49 /* allocate xen_phys_cpus */
51 xen_phys_cpus = alloc_bootmem_low(k * sizeof(struct resource));
52 BUG_ON(xen_phys_cpus == NULL);
54 /* fill in xen_phys_cpus with per-cpu crash note information */
56 for (k = 0; k < xen_max_nr_phys_cpus; k++) {
57 memset(&range, 0, sizeof(range));
58 range.range = KEXEC_RANGE_MA_CPU;
59 range.nr = k;
61 if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
62 goto err;
64 res = xen_phys_cpus + k;
66 memset(res, 0, sizeof(*res));
67 res->name = "Crash note";
68 res->start = range.start;
69 res->end = range.start + range.size - 1;
70 res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
71 }
73 /* fill in xen_hypervisor_res with hypervisor machine address range */
75 memset(&range, 0, sizeof(range));
76 range.range = KEXEC_RANGE_MA_XEN;
78 if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
79 goto err;
81 xen_hypervisor_res.name = "Hypervisor code and data";
82 xen_hypervisor_res.start = range.start;
83 xen_hypervisor_res.end = range.start + range.size - 1;
84 xen_hypervisor_res.flags = IORESOURCE_BUSY | IORESOURCE_MEM;
86 /* fill in crashk_res if range is reserved by hypervisor */
88 memset(&range, 0, sizeof(range));
89 range.range = KEXEC_RANGE_MA_CRASH;
91 if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
92 goto err;
94 if (range.size) {
95 crashk_res.start = range.start;
96 crashk_res.end = range.start + range.size - 1;
97 }
99 if (machine_kexec_setup_resources(&xen_hypervisor_res, xen_phys_cpus,
100 xen_max_nr_phys_cpus))
101 goto err;
103 return;
105 err:
106 /*
107 * It isn't possible to free xen_phys_cpus this early in the
108 * boot. Failure at this stage is unexpected and the amount of
109 * memory is small therefore we tolerate the potential leak.
110 */
111 xen_max_nr_phys_cpus = 0;
112 return;
113 }
115 void __init xen_machine_kexec_register_resources(struct resource *res)
116 {
117 request_resource(res, &xen_hypervisor_res);
118 machine_kexec_register_resources(res);
119 }
121 static void setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
122 {
123 machine_kexec_setup_load_arg(xki, image);
125 xki->indirection_page = image->head;
126 xki->start_address = image->start;
127 }
129 /*
130 * Load the image into xen so xen can kdump itself
131 * This might have been done in prepare, but prepare
132 * is currently called too early. It might make sense
133 * to move prepare, but for now, just add an extra hook.
134 */
135 int xen_machine_kexec_load(struct kimage *image)
136 {
137 xen_kexec_load_t xkl;
139 memset(&xkl, 0, sizeof(xkl));
140 xkl.type = image->type;
141 setup_load_arg(&xkl.image, image);
142 return HYPERVISOR_kexec_op(KEXEC_CMD_kexec_load, &xkl);
143 }
145 /*
146 * Unload the image that was stored by machine_kexec_load()
147 * This might have been done in machine_kexec_cleanup() but it
148 * is called too late, and its possible xen could try and kdump
149 * using resources that have been freed.
150 */
151 void xen_machine_kexec_unload(struct kimage *image)
152 {
153 xen_kexec_load_t xkl;
155 memset(&xkl, 0, sizeof(xkl));
156 xkl.type = image->type;
157 WARN_ON(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_unload, &xkl));
158 }
160 /*
161 * Do not allocate memory (or fail in any way) in machine_kexec().
162 * We are past the point of no return, committed to rebooting now.
163 *
164 * This has the hypervisor move to the prefered reboot CPU,
165 * stop all CPUs and kexec. That is it combines machine_shutdown()
166 * and machine_kexec() in Linux kexec terms.
167 */
168 NORET_TYPE void machine_kexec(struct kimage *image)
169 {
170 xen_kexec_exec_t xke;
172 memset(&xke, 0, sizeof(xke));
173 xke.type = image->type;
174 VOID(HYPERVISOR_kexec_op(KEXEC_CMD_kexec, &xke));
175 panic("KEXEC_CMD_kexec hypercall should not return\n");
176 }
178 void machine_shutdown(void)
179 {
180 /* do nothing */
181 }
184 /*
185 * Local variables:
186 * c-file-style: "linux"
187 * indent-tabs-mode: t
188 * c-indent-level: 8
189 * c-basic-offset: 8
190 * tab-width: 8
191 * End:
192 */