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