From: jbeulich@novell.com Subject: use base kernel suspend/resume infrastructure Patch-mainline: obsolete ... rather than calling just a few functions explicitly. --- sle11-2009-03-24.orig/arch/x86/kernel/time_32-xen.c 2009-03-24 10:22:14.000000000 +0100 +++ sle11-2009-03-24/arch/x86/kernel/time_32-xen.c 2009-03-24 10:22:24.000000000 +0100 @@ -88,6 +88,10 @@ static DEFINE_PER_CPU(struct vcpu_runsta /* Must be signed, as it's compared with s64 quantities which can be -ve. */ #define NS_PER_TICK (1000000000LL/HZ) +static struct vcpu_set_periodic_timer xen_set_periodic_tick = { + .period_ns = NS_PER_TICK +}; + static void __clock_was_set(struct work_struct *unused) { clock_was_set(); @@ -597,6 +601,25 @@ void mark_tsc_unstable(char *reason) } EXPORT_SYMBOL_GPL(mark_tsc_unstable); +static void init_missing_ticks_accounting(unsigned int cpu) +{ + struct vcpu_register_runstate_memory_area area; + struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu); + int rc; + + memset(runstate, 0, sizeof(*runstate)); + + area.addr.v = runstate; + rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu, &area); + WARN_ON(rc && rc != -ENOSYS); + + per_cpu(processed_blocked_time, cpu) = + runstate->time[RUNSTATE_blocked]; + per_cpu(processed_stolen_time, cpu) = + runstate->time[RUNSTATE_runnable] + + runstate->time[RUNSTATE_offline]; +} + static cycle_t cs_last; static cycle_t xen_clocksource_read(void) @@ -633,11 +656,32 @@ static cycle_t xen_clocksource_read(void #endif } +/* No locking required. Interrupts are disabled on all CPUs. */ static void xen_clocksource_resume(void) { - extern void time_resume(void); + unsigned int cpu; + + init_cpu_khz(); + + for_each_online_cpu(cpu) { + switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu, + &xen_set_periodic_tick)) { + case 0: +#if CONFIG_XEN_COMPAT <= 0x030004 + case -ENOSYS: +#endif + break; + default: + BUG(); + } + get_time_values_from_xen(cpu); + per_cpu(processed_system_time, cpu) = + per_cpu(shadow_time, 0).system_timestamp; + init_missing_ticks_accounting(cpu); + } + + processed_system_time = per_cpu(shadow_time, 0).system_timestamp; - time_resume(); cs_last = local_clock(); } @@ -652,25 +696,6 @@ static struct clocksource clocksource_xe .resume = xen_clocksource_resume, }; -static void init_missing_ticks_accounting(unsigned int cpu) -{ - struct vcpu_register_runstate_memory_area area; - struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu); - int rc; - - memset(runstate, 0, sizeof(*runstate)); - - area.addr.v = runstate; - rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu, &area); - WARN_ON(rc && rc != -ENOSYS); - - per_cpu(processed_blocked_time, cpu) = - runstate->time[RUNSTATE_blocked]; - per_cpu(processed_stolen_time, cpu) = - runstate->time[RUNSTATE_runnable] + - runstate->time[RUNSTATE_offline]; -} - unsigned long xen_read_persistent_clock(void) { const shared_info_t *s = HYPERVISOR_shared_info; @@ -715,10 +740,6 @@ static void __init setup_cpu0_timer_irq( BUG_ON(per_cpu(timer_irq, 0) < 0); } -static struct vcpu_set_periodic_timer xen_set_periodic_tick = { - .period_ns = NS_PER_TICK -}; - void __init time_init(void) { init_cpu_khz(); @@ -842,35 +863,6 @@ void xen_halt(void) } EXPORT_SYMBOL(xen_halt); -/* No locking required. Interrupts are disabled on all CPUs. */ -void time_resume(void) -{ - unsigned int cpu; - - init_cpu_khz(); - - for_each_online_cpu(cpu) { - switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu, - &xen_set_periodic_tick)) { - case 0: -#if CONFIG_XEN_COMPAT <= 0x030004 - case -ENOSYS: -#endif - break; - default: - BUG(); - } - get_time_values_from_xen(cpu); - per_cpu(processed_system_time, cpu) = - per_cpu(shadow_time, 0).system_timestamp; - init_missing_ticks_accounting(cpu); - } - - processed_system_time = per_cpu(shadow_time, 0).system_timestamp; - - update_wallclock(); -} - #ifdef CONFIG_SMP static char timer_name[NR_CPUS][15]; --- sle11-2009-03-24.orig/drivers/xen/core/evtchn.c 2009-03-16 16:38:16.000000000 +0100 +++ sle11-2009-03-24/drivers/xen/core/evtchn.c 2009-01-14 14:57:55.000000000 +0100 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -1070,9 +1071,20 @@ static void restore_cpu_ipis(unsigned in } } -void irq_resume(void) +static int evtchn_resume(struct sys_device *dev) { unsigned int cpu, irq, evtchn; + struct evtchn_status status; + + /* Avoid doing anything in the 'suspend cancelled' case. */ + status.dom = DOMID_SELF; + status.port = evtchn_from_irq(__get_cpu_var(virq_to_irq)[VIRQ_TIMER]); + if (HYPERVISOR_event_channel_op(EVTCHNOP_status, &status)) + BUG(); + if (status.status == EVTCHNSTAT_virq + && status.vcpu == smp_processor_id() + && status.u.virq == VIRQ_TIMER) + return 0; init_evtchn_cpu_bindings(); @@ -1103,7 +1115,32 @@ void irq_resume(void) restore_cpu_ipis(cpu); } + return 0; +} + +static struct sysdev_class evtchn_sysclass = { + .name = "evtchn", + .resume = evtchn_resume, +}; + +static struct sys_device device_evtchn = { + .id = 0, + .cls = &evtchn_sysclass, +}; + +static int __init evtchn_register(void) +{ + int err; + + if (is_initial_xendomain()) + return 0; + + err = sysdev_class_register(&evtchn_sysclass); + if (!err) + err = sysdev_register(&device_evtchn); + return err; } +core_initcall(evtchn_register); #endif #if defined(CONFIG_X86_IO_APIC) --- sle11-2009-03-24.orig/drivers/xen/core/gnttab.c 2009-03-16 16:38:16.000000000 +0100 +++ sle11-2009-03-24/drivers/xen/core/gnttab.c 2008-12-15 11:32:52.000000000 +0100 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -704,23 +705,37 @@ EXPORT_SYMBOL(gnttab_post_map_adjust); #endif /* __HAVE_ARCH_PTE_SPECIAL */ -int gnttab_resume(void) +static int gnttab_resume(struct sys_device *dev) { if (max_nr_grant_frames() < nr_grant_frames) return -ENOSYS; return gnttab_map(0, nr_grant_frames - 1); } +#define gnttab_resume() gnttab_resume(NULL) #ifdef CONFIG_PM_SLEEP -int gnttab_suspend(void) -{ #ifdef CONFIG_X86 +static int gnttab_suspend(struct sys_device *dev, pm_message_t state) +{ apply_to_page_range(&init_mm, (unsigned long)shared, PAGE_SIZE * nr_grant_frames, unmap_pte_fn, NULL); -#endif return 0; } +#else +#define gnttab_suspend NULL +#endif + +static struct sysdev_class gnttab_sysclass = { + .name = "gnttab", + .resume = gnttab_resume, + .suspend = gnttab_suspend, +}; + +static struct sys_device device_gnttab = { + .id = 0, + .cls = &gnttab_sysclass, +}; #endif #else /* !CONFIG_XEN */ @@ -800,6 +815,17 @@ int __devinit gnttab_init(void) if (!is_running_on_xen()) return -ENODEV; +#if defined(CONFIG_XEN) && defined(CONFIG_PM_SLEEP) + if (!is_initial_xendomain()) { + int err = sysdev_class_register(&gnttab_sysclass); + + if (!err) + err = sysdev_register(&device_gnttab); + if (err) + return err; + } +#endif + nr_grant_frames = 1; boot_max_nr_grant_frames = __max_nr_grant_frames(); --- sle11-2009-03-24.orig/drivers/xen/core/machine_reboot.c 2009-03-16 16:38:16.000000000 +0100 +++ sle11-2009-03-24/drivers/xen/core/machine_reboot.c 2009-02-17 12:23:48.000000000 +0100 @@ -17,6 +17,7 @@ #include #include #include +#include "../../base/base.h" #if defined(__i386__) || defined(__x86_64__) @@ -141,7 +142,6 @@ static int take_machine_down(void *_susp { struct suspend *suspend = _suspend; int suspend_cancelled, err; - extern void time_resume(void); if (suspend->fast_suspend) { BUG_ON(!irqs_disabled()); @@ -167,20 +167,23 @@ static int take_machine_down(void *_susp } mm_pin_all(); - gnttab_suspend(); - pre_suspend(); - - /* - * This hypercall returns 1 if suspend was cancelled or the domain was - * merely checkpointed, and 0 if it is resuming in a new domain. - */ - suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); + suspend_cancelled = sysdev_suspend(PMSG_FREEZE); + if (!suspend_cancelled) { + pre_suspend(); + /* + * This hypercall returns 1 if suspend was cancelled or the domain was + * merely checkpointed, and 0 if it is resuming in a new domain. + */ + suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); + } else + BUG_ON(suspend_cancelled > 0); suspend->resume_notifier(suspend_cancelled); - post_suspend(suspend_cancelled); - gnttab_resume(); + if (suspend_cancelled >= 0) { + post_suspend(suspend_cancelled); + sysdev_resume(); + } if (!suspend_cancelled) { - irq_resume(); #ifdef __x86_64__ /* * Older versions of Xen do not save/restore the user %cr3. @@ -192,7 +195,6 @@ static int take_machine_down(void *_susp current->active_mm->pgd))); #endif } - time_resume(); if (!suspend->fast_suspend) local_irq_enable(); --- sle11-2009-03-24.orig/include/xen/evtchn.h 2009-03-16 16:33:40.000000000 +0100 +++ sle11-2009-03-24/include/xen/evtchn.h 2008-12-15 11:32:52.000000000 +0100 @@ -93,7 +93,9 @@ int bind_ipi_to_irqhandler( */ void unbind_from_irqhandler(unsigned int irq, void *dev_id); +#ifndef CONFIG_XEN void irq_resume(void); +#endif /* Entry point for notifications into Linux subsystems. */ asmlinkage void evtchn_do_upcall(struct pt_regs *regs); --- sle11-2009-03-24.orig/include/xen/gnttab.h 2009-03-24 10:00:14.000000000 +0100 +++ sle11-2009-03-24/include/xen/gnttab.h 2008-12-15 11:32:52.000000000 +0100 @@ -110,8 +110,9 @@ static inline void __gnttab_dma_unmap_pa void gnttab_reset_grant_page(struct page *page); -int gnttab_suspend(void); +#ifndef CONFIG_XEN int gnttab_resume(void); +#endif void *arch_gnttab_alloc_shared(unsigned long *frames);