source: trunk/packages/xen-3.1/xen-3.1/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 4.4 KB
Line 
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 <xen/interface/kexec.h>
8#include <linux/mm.h>
9#include <linux/bootmem.h>
10
11extern void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, 
12                                         struct kimage *image);
13
14int xen_max_nr_phys_cpus;
15struct resource xen_hypervisor_res;
16struct resource *xen_phys_cpus;
17
18void xen_machine_kexec_setup_resources(void)
19{
20        xen_kexec_range_t range;
21        struct resource *res;
22        int k = 0;
23
24        if (!is_initial_xendomain())
25                return;
26
27        /* determine maximum number of physical cpus */
28
29        while (1) {
30                memset(&range, 0, sizeof(range));
31                range.range = KEXEC_RANGE_MA_CPU;
32                range.nr = k;
33
34                if(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
35                        break;
36
37                k++;
38        }
39
40        if (k == 0)
41                return;
42
43        xen_max_nr_phys_cpus = k;
44
45        /* allocate xen_phys_cpus */
46
47        xen_phys_cpus = alloc_bootmem_low(k * sizeof(struct resource));
48        BUG_ON(xen_phys_cpus == NULL);
49
50        /* fill in xen_phys_cpus with per-cpu crash note information */
51
52        for (k = 0; k < xen_max_nr_phys_cpus; k++) {
53                memset(&range, 0, sizeof(range));
54                range.range = KEXEC_RANGE_MA_CPU;
55                range.nr = k;
56
57                if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
58                        goto err;
59
60                res = xen_phys_cpus + k;
61
62                memset(res, 0, sizeof(*res));
63                res->name = "Crash note";
64                res->start = range.start;
65                res->end = range.start + range.size - 1;
66                res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
67        }
68
69        /* fill in xen_hypervisor_res with hypervisor machine address range */
70
71        memset(&range, 0, sizeof(range));
72        range.range = KEXEC_RANGE_MA_XEN;
73
74        if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
75                goto err;
76
77        xen_hypervisor_res.name = "Hypervisor code and data";
78        xen_hypervisor_res.start = range.start;
79        xen_hypervisor_res.end = range.start + range.size - 1;
80        xen_hypervisor_res.flags = IORESOURCE_BUSY | IORESOURCE_MEM;
81
82        /* fill in crashk_res if range is reserved by hypervisor */
83
84        memset(&range, 0, sizeof(range));
85        range.range = KEXEC_RANGE_MA_CRASH;
86
87        if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
88                return;
89
90        if (range.size) {
91                crashk_res.start = range.start;
92                crashk_res.end = range.start + range.size - 1;
93        }
94
95        return;
96
97 err:
98        /*
99         * It isn't possible to free xen_phys_cpus this early in the
100         * boot. Failure at this stage is unexpected and the amount of
101         * memory is small therefore we tolerate the potential leak.
102         */
103        xen_max_nr_phys_cpus = 0;
104        return;
105}
106
107void xen_machine_kexec_register_resources(struct resource *res)
108{
109        int k;
110
111        request_resource(res, &xen_hypervisor_res);
112
113        for (k = 0; k < xen_max_nr_phys_cpus; k++)
114                request_resource(&xen_hypervisor_res, xen_phys_cpus + k);
115
116}
117
118static void setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
119{
120        machine_kexec_setup_load_arg(xki, image);
121
122        xki->indirection_page = image->head;
123        xki->start_address = image->start;
124}
125
126/*
127 * Load the image into xen so xen can kdump itself
128 * This might have been done in prepare, but prepare
129 * is currently called too early. It might make sense
130 * to move prepare, but for now, just add an extra hook.
131 */
132int xen_machine_kexec_load(struct kimage *image)
133{
134        xen_kexec_load_t xkl;
135
136        memset(&xkl, 0, sizeof(xkl));
137        xkl.type = image->type;
138        setup_load_arg(&xkl.image, image);
139        return HYPERVISOR_kexec_op(KEXEC_CMD_kexec_load, &xkl);
140}
141
142/*
143 * Unload the image that was stored by machine_kexec_load()
144 * This might have been done in machine_kexec_cleanup() but it
145 * is called too late, and its possible xen could try and kdump
146 * using resources that have been freed.
147 */
148void xen_machine_kexec_unload(struct kimage *image)
149{
150        xen_kexec_load_t xkl;
151
152        memset(&xkl, 0, sizeof(xkl));
153        xkl.type = image->type;
154        HYPERVISOR_kexec_op(KEXEC_CMD_kexec_unload, &xkl);
155}
156
157/*
158 * Do not allocate memory (or fail in any way) in machine_kexec().
159 * We are past the point of no return, committed to rebooting now.
160 *
161 * This has the hypervisor move to the prefered reboot CPU,
162 * stop all CPUs and kexec. That is it combines machine_shutdown()
163 * and machine_kexec() in Linux kexec terms.
164 */
165NORET_TYPE void machine_kexec(struct kimage *image)
166{
167        xen_kexec_exec_t xke;
168
169        memset(&xke, 0, sizeof(xke));
170        xke.type = image->type;
171        HYPERVISOR_kexec_op(KEXEC_CMD_kexec, &xke);
172        panic("KEXEC_CMD_kexec hypercall should not return\n");
173}
174
175void machine_shutdown(void)
176{
177        /* do nothing */
178}
179
180
181/*
182 * Local variables:
183 *  c-file-style: "linux"
184 *  indent-tabs-mode: t
185 *  c-indent-level: 8
186 *  c-basic-offset: 8
187 *  tab-width: 8
188 * End:
189 */
Note: See TracBrowser for help on using the repository browser.