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