direct-io.hg

view linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c @ 12733:0bea8e773508

[LINUX] The crash note resource should be nested inside the hypervisor
resource.

This was exposed by 12709:98413fa7826c which corrected the length of
the hypervisor resource.

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
author Ian Campbell <ian.campbell@xensource.com>
date Tue Dec 05 17:01:34 2006 +0000 (2006-12-05)
parents d7f71de58c4b
children 7c3dee5ff185
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>
10 #include <asm/hypercall.h>
12 extern void machine_kexec_setup_load_arg(xen_kexec_image_t *xki,
13 struct kimage *image);
15 int xen_max_nr_phys_cpus;
16 struct resource xen_hypervisor_res;
17 struct resource *xen_phys_cpus;
19 void xen_machine_kexec_setup_resources(void)
20 {
21 xen_kexec_range_t range;
22 struct resource *res;
23 int err, k = 0;
25 if (!is_initial_xendomain())
26 return;
28 /* determine maximum number of physical cpus */
30 while (1) {
31 memset(&range, 0, sizeof(range));
32 range.range = KEXEC_RANGE_MA_CPU;
33 range.nr = k;
35 /*
36 * Anything other than EINVAL or success indictates
37 * that we are not running on a hypervisor which
38 * supports kexec.
39 */
40 err = HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range);
41 if (err == -EINVAL)
42 break;
43 else if (err)
44 return;
46 k++;
47 }
49 xen_max_nr_phys_cpus = k;
51 /* allocate xen_phys_cpus */
53 xen_phys_cpus = alloc_bootmem_low(k * sizeof(struct resource));
54 BUG_ON(!xen_phys_cpus);
56 /* fill in xen_phys_cpus with per-cpu crash note information */
58 for (k = 0; k < xen_max_nr_phys_cpus; k++) {
59 memset(&range, 0, sizeof(range));
60 range.range = KEXEC_RANGE_MA_CPU;
61 range.nr = k;
63 if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
64 BUG();
66 res = xen_phys_cpus + k;
68 memset(res, 0, sizeof(*res));
69 res->name = "Crash note";
70 res->start = range.start;
71 res->end = range.start + range.size - 1;
72 res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
73 }
75 /* fill in xen_hypervisor_res with hypervisor machine address range */
77 memset(&range, 0, sizeof(range));
78 range.range = KEXEC_RANGE_MA_XEN;
80 if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
81 BUG();
83 xen_hypervisor_res.name = "Hypervisor code and data";
84 xen_hypervisor_res.start = range.start;
85 xen_hypervisor_res.end = range.start + range.size - 1;
86 xen_hypervisor_res.flags = IORESOURCE_BUSY | IORESOURCE_MEM;
88 /* fill in crashk_res if range is reserved by hypervisor */
90 memset(&range, 0, sizeof(range));
91 range.range = KEXEC_RANGE_MA_CRASH;
93 if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
94 BUG();
96 if (range.size) {
97 crashk_res.start = range.start;
98 crashk_res.end = range.start + range.size - 1;
99 }
100 }
102 void xen_machine_kexec_register_resources(struct resource *res)
103 {
104 int k;
106 request_resource(res, &xen_hypervisor_res);
108 for (k = 0; k < xen_max_nr_phys_cpus; k++)
109 request_resource(&xen_hypervisor_res, xen_phys_cpus + k);
111 }
113 static void setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
114 {
115 machine_kexec_setup_load_arg(xki, image);
117 xki->indirection_page = image->head;
118 xki->start_address = image->start;
119 }
121 /*
122 * Load the image into xen so xen can kdump itself
123 * This might have been done in prepare, but prepare
124 * is currently called too early. It might make sense
125 * to move prepare, but for now, just add an extra hook.
126 */
127 int xen_machine_kexec_load(struct kimage *image)
128 {
129 xen_kexec_load_t xkl;
131 memset(&xkl, 0, sizeof(xkl));
132 xkl.type = image->type;
133 setup_load_arg(&xkl.image, image);
134 return HYPERVISOR_kexec_op(KEXEC_CMD_kexec_load, &xkl);
135 }
137 /*
138 * Unload the image that was stored by machine_kexec_load()
139 * This might have been done in machine_kexec_cleanup() but it
140 * is called too late, and its possible xen could try and kdump
141 * using resources that have been freed.
142 */
143 void xen_machine_kexec_unload(struct kimage *image)
144 {
145 xen_kexec_load_t xkl;
147 memset(&xkl, 0, sizeof(xkl));
148 xkl.type = image->type;
149 HYPERVISOR_kexec_op(KEXEC_CMD_kexec_unload, &xkl);
150 }
152 /*
153 * Do not allocate memory (or fail in any way) in machine_kexec().
154 * We are past the point of no return, committed to rebooting now.
155 *
156 * This has the hypervisor move to the prefered reboot CPU,
157 * stop all CPUs and kexec. That is it combines machine_shutdown()
158 * and machine_kexec() in Linux kexec terms.
159 */
160 NORET_TYPE void xen_machine_kexec(struct kimage *image)
161 {
162 xen_kexec_exec_t xke;
164 memset(&xke, 0, sizeof(xke));
165 xke.type = image->type;
166 HYPERVISOR_kexec_op(KEXEC_CMD_kexec, &xke);
167 panic("KEXEC_CMD_kexec hypercall should not return\n");
168 }
170 void machine_shutdown(void)
171 {
172 /* do nothing */
173 }
176 /*
177 * Local variables:
178 * c-file-style: "linux"
179 * indent-tabs-mode: t
180 * c-indent-level: 8
181 * c-basic-offset: 8
182 * tab-width: 8
183 * End:
184 */