]>
Commit | Line | Data |
---|---|---|
cc90b958 BS |
1 | From: jbeulich@novell.com |
2 | Subject: use base kernel suspend/resume infrastructure | |
3 | Patch-mainline: obsolete | |
4 | ||
5 | ... rather than calling just a few functions explicitly. | |
6 | ||
7 | Index: head-2008-12-01/arch/x86/kernel/time_32-xen.c | |
8 | =================================================================== | |
9 | --- head-2008-12-01.orig/arch/x86/kernel/time_32-xen.c 2008-12-01 12:07:15.000000000 +0100 | |
10 | +++ head-2008-12-01/arch/x86/kernel/time_32-xen.c 2008-12-01 12:07:30.000000000 +0100 | |
11 | @@ -88,6 +88,10 @@ static DEFINE_PER_CPU(struct vcpu_runsta | |
12 | /* Must be signed, as it's compared with s64 quantities which can be -ve. */ | |
13 | #define NS_PER_TICK (1000000000LL/HZ) | |
14 | ||
15 | +static struct vcpu_set_periodic_timer xen_set_periodic_tick = { | |
16 | + .period_ns = NS_PER_TICK | |
17 | +}; | |
18 | + | |
19 | static void __clock_was_set(struct work_struct *unused) | |
20 | { | |
21 | clock_was_set(); | |
22 | @@ -599,6 +603,25 @@ void mark_tsc_unstable(char *reason) | |
23 | } | |
24 | EXPORT_SYMBOL_GPL(mark_tsc_unstable); | |
25 | ||
26 | +static void init_missing_ticks_accounting(unsigned int cpu) | |
27 | +{ | |
28 | + struct vcpu_register_runstate_memory_area area; | |
29 | + struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu); | |
30 | + int rc; | |
31 | + | |
32 | + memset(runstate, 0, sizeof(*runstate)); | |
33 | + | |
34 | + area.addr.v = runstate; | |
35 | + rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu, &area); | |
36 | + WARN_ON(rc && rc != -ENOSYS); | |
37 | + | |
38 | + per_cpu(processed_blocked_time, cpu) = | |
39 | + runstate->time[RUNSTATE_blocked]; | |
40 | + per_cpu(processed_stolen_time, cpu) = | |
41 | + runstate->time[RUNSTATE_runnable] + | |
42 | + runstate->time[RUNSTATE_offline]; | |
43 | +} | |
44 | + | |
45 | static cycle_t cs_last; | |
46 | ||
47 | static cycle_t xen_clocksource_read(void) | |
48 | @@ -635,11 +658,34 @@ static cycle_t xen_clocksource_read(void | |
49 | #endif | |
50 | } | |
51 | ||
52 | +/* No locking required. Interrupts are disabled on all CPUs. */ | |
53 | static void xen_clocksource_resume(void) | |
54 | { | |
55 | - extern void time_resume(void); | |
56 | + unsigned int cpu; | |
57 | + | |
58 | + init_cpu_khz(); | |
59 | + | |
60 | + for_each_online_cpu(cpu) { | |
61 | + switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu, | |
62 | + &xen_set_periodic_tick)) { | |
63 | + case 0: | |
64 | +#if CONFIG_XEN_COMPAT <= 0x030004 | |
65 | + case -ENOSYS: | |
66 | +#endif | |
67 | + break; | |
68 | + default: | |
69 | + BUG(); | |
70 | + } | |
71 | + get_time_values_from_xen(cpu); | |
72 | + per_cpu(processed_system_time, cpu) = | |
73 | + per_cpu(shadow_time, 0).system_timestamp; | |
74 | + init_missing_ticks_accounting(cpu); | |
75 | + } | |
76 | + | |
77 | + processed_system_time = per_cpu(shadow_time, 0).system_timestamp; | |
78 | + | |
79 | + update_wallclock(); | |
80 | ||
81 | - time_resume(); | |
82 | cs_last = local_clock(); | |
83 | } | |
84 | ||
85 | @@ -654,25 +700,6 @@ static struct clocksource clocksource_xe | |
86 | .resume = xen_clocksource_resume, | |
87 | }; | |
88 | ||
89 | -static void init_missing_ticks_accounting(unsigned int cpu) | |
90 | -{ | |
91 | - struct vcpu_register_runstate_memory_area area; | |
92 | - struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu); | |
93 | - int rc; | |
94 | - | |
95 | - memset(runstate, 0, sizeof(*runstate)); | |
96 | - | |
97 | - area.addr.v = runstate; | |
98 | - rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu, &area); | |
99 | - WARN_ON(rc && rc != -ENOSYS); | |
100 | - | |
101 | - per_cpu(processed_blocked_time, cpu) = | |
102 | - runstate->time[RUNSTATE_blocked]; | |
103 | - per_cpu(processed_stolen_time, cpu) = | |
104 | - runstate->time[RUNSTATE_runnable] + | |
105 | - runstate->time[RUNSTATE_offline]; | |
106 | -} | |
107 | - | |
108 | unsigned long xen_read_persistent_clock(void) | |
109 | { | |
110 | const shared_info_t *s = HYPERVISOR_shared_info; | |
111 | @@ -717,10 +744,6 @@ static void __init setup_cpu0_timer_irq( | |
112 | BUG_ON(per_cpu(timer_irq, 0) < 0); | |
113 | } | |
114 | ||
115 | -static struct vcpu_set_periodic_timer xen_set_periodic_tick = { | |
116 | - .period_ns = NS_PER_TICK | |
117 | -}; | |
118 | - | |
119 | void __init time_init(void) | |
120 | { | |
121 | init_cpu_khz(); | |
122 | @@ -844,35 +867,6 @@ void xen_halt(void) | |
123 | } | |
124 | EXPORT_SYMBOL(xen_halt); | |
125 | ||
126 | -/* No locking required. Interrupts are disabled on all CPUs. */ | |
127 | -void time_resume(void) | |
128 | -{ | |
129 | - unsigned int cpu; | |
130 | - | |
131 | - init_cpu_khz(); | |
132 | - | |
133 | - for_each_online_cpu(cpu) { | |
134 | - switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu, | |
135 | - &xen_set_periodic_tick)) { | |
136 | - case 0: | |
137 | -#if CONFIG_XEN_COMPAT <= 0x030004 | |
138 | - case -ENOSYS: | |
139 | -#endif | |
140 | - break; | |
141 | - default: | |
142 | - BUG(); | |
143 | - } | |
144 | - get_time_values_from_xen(cpu); | |
145 | - per_cpu(processed_system_time, cpu) = | |
146 | - per_cpu(shadow_time, 0).system_timestamp; | |
147 | - init_missing_ticks_accounting(cpu); | |
148 | - } | |
149 | - | |
150 | - processed_system_time = per_cpu(shadow_time, 0).system_timestamp; | |
151 | - | |
152 | - update_wallclock(); | |
153 | -} | |
154 | - | |
155 | #ifdef CONFIG_SMP | |
156 | static char timer_name[NR_CPUS][15]; | |
157 | ||
158 | Index: head-2008-12-01/drivers/xen/core/evtchn.c | |
159 | =================================================================== | |
160 | --- head-2008-12-01.orig/drivers/xen/core/evtchn.c 2008-12-02 09:11:31.000000000 +0100 | |
161 | +++ head-2008-12-01/drivers/xen/core/evtchn.c 2008-12-02 09:23:09.000000000 +0100 | |
162 | @@ -35,6 +35,7 @@ | |
163 | #include <linux/interrupt.h> | |
164 | #include <linux/sched.h> | |
165 | #include <linux/kernel_stat.h> | |
166 | +#include <linux/sysdev.h> | |
167 | #include <linux/version.h> | |
168 | #include <asm/atomic.h> | |
169 | #include <asm/system.h> | |
170 | @@ -1061,9 +1062,20 @@ static void restore_cpu_ipis(unsigned in | |
171 | } | |
172 | } | |
173 | ||
174 | -void irq_resume(void) | |
175 | +static int evtchn_resume(struct sys_device *dev) | |
176 | { | |
177 | unsigned int cpu, irq, evtchn; | |
178 | + struct evtchn_status status; | |
179 | + | |
180 | + /* Avoid doing anything in the 'suspend cancelled' case. */ | |
181 | + status.dom = DOMID_SELF; | |
182 | + status.port = evtchn_from_irq(__get_cpu_var(virq_to_irq)[VIRQ_TIMER]); | |
183 | + if (HYPERVISOR_event_channel_op(EVTCHNOP_status, &status)) | |
184 | + BUG(); | |
185 | + if (status.status == EVTCHNSTAT_virq | |
186 | + && status.vcpu == smp_processor_id() | |
187 | + && status.u.virq == VIRQ_TIMER) | |
188 | + return 0; | |
189 | ||
190 | init_evtchn_cpu_bindings(); | |
191 | ||
192 | @@ -1094,7 +1106,32 @@ void irq_resume(void) | |
193 | restore_cpu_ipis(cpu); | |
194 | } | |
195 | ||
196 | + return 0; | |
197 | +} | |
198 | + | |
199 | +static struct sysdev_class evtchn_sysclass = { | |
200 | + .name = "evtchn", | |
201 | + .resume = evtchn_resume, | |
202 | +}; | |
203 | + | |
204 | +static struct sys_device device_evtchn = { | |
205 | + .id = 0, | |
206 | + .cls = &evtchn_sysclass, | |
207 | +}; | |
208 | + | |
209 | +static int __init evtchn_register(void) | |
210 | +{ | |
211 | + int err; | |
212 | + | |
213 | + if (is_initial_xendomain()) | |
214 | + return 0; | |
215 | + | |
216 | + err = sysdev_class_register(&evtchn_sysclass); | |
217 | + if (!err) | |
218 | + err = sysdev_register(&device_evtchn); | |
219 | + return err; | |
220 | } | |
221 | +core_initcall(evtchn_register); | |
222 | #endif | |
223 | ||
224 | #if defined(CONFIG_X86_IO_APIC) | |
225 | Index: head-2008-12-01/drivers/xen/core/gnttab.c | |
226 | =================================================================== | |
227 | --- head-2008-12-01.orig/drivers/xen/core/gnttab.c 2008-12-02 09:26:17.000000000 +0100 | |
228 | +++ head-2008-12-01/drivers/xen/core/gnttab.c 2008-12-02 09:26:51.000000000 +0100 | |
229 | @@ -35,6 +35,7 @@ | |
230 | #include <linux/sched.h> | |
231 | #include <linux/mm.h> | |
232 | #include <linux/seqlock.h> | |
233 | +#include <linux/sysdev.h> | |
234 | #include <xen/interface/xen.h> | |
235 | #include <xen/gnttab.h> | |
236 | #include <asm/pgtable.h> | |
237 | @@ -704,23 +705,37 @@ EXPORT_SYMBOL(gnttab_post_map_adjust); | |
238 | ||
239 | #endif /* __HAVE_ARCH_PTE_SPECIAL */ | |
240 | ||
241 | -int gnttab_resume(void) | |
242 | +static int gnttab_resume(struct sys_device *dev) | |
243 | { | |
244 | if (max_nr_grant_frames() < nr_grant_frames) | |
245 | return -ENOSYS; | |
246 | return gnttab_map(0, nr_grant_frames - 1); | |
247 | } | |
248 | +#define gnttab_resume() gnttab_resume(NULL) | |
249 | ||
250 | #ifdef CONFIG_PM_SLEEP | |
251 | -int gnttab_suspend(void) | |
252 | -{ | |
253 | #ifdef CONFIG_X86 | |
254 | +static int gnttab_suspend(struct sys_device *dev, pm_message_t state) | |
255 | +{ | |
256 | apply_to_page_range(&init_mm, (unsigned long)shared, | |
257 | PAGE_SIZE * nr_grant_frames, | |
258 | unmap_pte_fn, NULL); | |
259 | -#endif | |
260 | return 0; | |
261 | } | |
262 | +#else | |
263 | +#define gnttab_suspend NULL | |
264 | +#endif | |
265 | + | |
266 | +static struct sysdev_class gnttab_sysclass = { | |
267 | + .name = "gnttab", | |
268 | + .resume = gnttab_resume, | |
269 | + .suspend = gnttab_suspend, | |
270 | +}; | |
271 | + | |
272 | +static struct sys_device device_gnttab = { | |
273 | + .id = 0, | |
274 | + .cls = &gnttab_sysclass, | |
275 | +}; | |
276 | #endif | |
277 | ||
278 | #else /* !CONFIG_XEN */ | |
279 | @@ -800,6 +815,17 @@ int __devinit gnttab_init(void) | |
280 | if (!is_running_on_xen()) | |
281 | return -ENODEV; | |
282 | ||
283 | +#if defined(CONFIG_XEN) && defined(CONFIG_PM_SLEEP) | |
284 | + if (!is_initial_xendomain()) { | |
285 | + int err = sysdev_class_register(&gnttab_sysclass); | |
286 | + | |
287 | + if (!err) | |
288 | + err = sysdev_register(&device_gnttab); | |
289 | + if (err) | |
290 | + return err; | |
291 | + } | |
292 | +#endif | |
293 | + | |
294 | nr_grant_frames = 1; | |
295 | boot_max_nr_grant_frames = __max_nr_grant_frames(); | |
296 | ||
297 | Index: head-2008-12-01/drivers/xen/core/machine_reboot.c | |
298 | =================================================================== | |
299 | --- head-2008-12-01.orig/drivers/xen/core/machine_reboot.c 2008-12-01 11:49:07.000000000 +0100 | |
300 | +++ head-2008-12-01/drivers/xen/core/machine_reboot.c 2008-12-01 12:07:30.000000000 +0100 | |
301 | @@ -17,6 +17,7 @@ | |
302 | #include <xen/xencons.h> | |
303 | #include <xen/cpu_hotplug.h> | |
304 | #include <xen/interface/vcpu.h> | |
305 | +#include "../../base/base.h" | |
306 | ||
307 | #if defined(__i386__) || defined(__x86_64__) | |
308 | ||
309 | @@ -149,7 +150,6 @@ static int take_machine_down(void *_susp | |
310 | { | |
311 | struct suspend *suspend = _suspend; | |
312 | int suspend_cancelled, err; | |
313 | - extern void time_resume(void); | |
314 | ||
315 | if (suspend->fast_suspend) { | |
316 | BUG_ON(!irqs_disabled()); | |
317 | @@ -175,20 +175,23 @@ static int take_machine_down(void *_susp | |
318 | } | |
319 | ||
320 | mm_pin_all(); | |
321 | - gnttab_suspend(); | |
322 | - pre_suspend(); | |
323 | - | |
324 | - /* | |
325 | - * This hypercall returns 1 if suspend was cancelled or the domain was | |
326 | - * merely checkpointed, and 0 if it is resuming in a new domain. | |
327 | - */ | |
328 | - suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); | |
329 | + suspend_cancelled = sysdev_suspend(PMSG_FREEZE); | |
330 | + if (!suspend_cancelled) { | |
331 | + pre_suspend(); | |
332 | ||
333 | + /* | |
334 | + * This hypercall returns 1 if suspend was cancelled or the domain was | |
335 | + * merely checkpointed, and 0 if it is resuming in a new domain. | |
336 | + */ | |
337 | + suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); | |
338 | + } else | |
339 | + BUG_ON(suspend_cancelled > 0); | |
340 | suspend->resume_notifier(suspend_cancelled); | |
341 | - post_suspend(suspend_cancelled); | |
342 | - gnttab_resume(); | |
343 | + if (suspend_cancelled >= 0) { | |
344 | + post_suspend(suspend_cancelled); | |
345 | + sysdev_resume(); | |
346 | + } | |
347 | if (!suspend_cancelled) { | |
348 | - irq_resume(); | |
349 | #ifdef __x86_64__ | |
350 | /* | |
351 | * Older versions of Xen do not save/restore the user %cr3. | |
352 | @@ -200,7 +203,6 @@ static int take_machine_down(void *_susp | |
353 | current->active_mm->pgd))); | |
354 | #endif | |
355 | } | |
356 | - time_resume(); | |
357 | ||
358 | if (!suspend->fast_suspend) | |
359 | local_irq_enable(); | |
360 | Index: head-2008-12-01/include/xen/evtchn.h | |
361 | =================================================================== | |
362 | --- head-2008-12-01.orig/include/xen/evtchn.h 2008-12-02 09:25:52.000000000 +0100 | |
363 | +++ head-2008-12-01/include/xen/evtchn.h 2008-12-01 12:07:30.000000000 +0100 | |
364 | @@ -93,7 +93,9 @@ int bind_ipi_to_irqhandler( | |
365 | */ | |
366 | void unbind_from_irqhandler(unsigned int irq, void *dev_id); | |
367 | ||
368 | +#ifndef CONFIG_XEN | |
369 | void irq_resume(void); | |
370 | +#endif | |
371 | ||
372 | /* Entry point for notifications into Linux subsystems. */ | |
373 | asmlinkage void evtchn_do_upcall(struct pt_regs *regs); | |
374 | Index: head-2008-12-01/include/xen/gnttab.h | |
375 | =================================================================== | |
376 | --- head-2008-12-01.orig/include/xen/gnttab.h 2008-12-02 09:25:52.000000000 +0100 | |
377 | +++ head-2008-12-01/include/xen/gnttab.h 2008-12-01 12:07:30.000000000 +0100 | |
378 | @@ -110,8 +110,9 @@ static inline void __gnttab_dma_unmap_pa | |
379 | ||
380 | void gnttab_reset_grant_page(struct page *page); | |
381 | ||
382 | -int gnttab_suspend(void); | |
383 | +#ifndef CONFIG_XEN | |
384 | int gnttab_resume(void); | |
385 | +#endif | |
386 | ||
387 | void *arch_gnttab_alloc_shared(unsigned long *frames); | |
388 |