add_preferred_console("hvc", 0, NULL);
}
+static struct shared_info *shared_info_page;
+
+int xen_register_shared_info(void)
+{
+ struct xen_add_to_physmap xatp;
+
+ /*
+ * This function is called on boot and on restore. On boot we
+ * allocate this page immediately before calling this function
+ * and bail on failure. On resume that allocation must have
+ * succeeded or we couldn't be doing a save/restore.
+ */
+ BUG_ON(!shared_info_page);
+
+ xatp.domid = DOMID_SELF;
+ xatp.idx = 0;
+ xatp.space = XENMAPSPACE_shared_info;
+ xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
+ if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
+ BUG();
+
+ HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
+
+ return 0;
+}
+
+void xen_vcpu_restore(void)
+{
+ xen_percpu_init();
+
+ /* XXX TODO: xen_setup_runstate_info(cpu); */
+}
+
static void __init xen_acpi_guest_init(void)
{
#ifdef CONFIG_ACPI
static int __init xen_guest_init(void)
{
- struct xen_add_to_physmap xatp;
- struct shared_info *shared_info_page = NULL;
int cpu;
if (!xen_domain())
pr_err("not enough memory\n");
return -ENOMEM;
}
- xatp.domid = DOMID_SELF;
- xatp.idx = 0;
- xatp.space = XENMAPSPACE_shared_info;
- xatp.gpfn = virt_to_gfn(shared_info_page);
- if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
- BUG();
- HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
+ xen_register_shared_info();
/* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
* page, we use it in the event channel upcall and in some pvclock
late_initcall(xen_pm_init);
-/* empty stubs */
-void xen_arch_pre_suspend(void) { }
-void xen_arch_post_suspend(int suspend_cancelled) { }
-void xen_timer_resume(void) { }
-void xen_arch_resume(void) { }
-void xen_arch_suspend(void) { }
-
-
/* In the hypercall.S file. */
EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op);
EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op);
--- /dev/null
+#include <linux/types.h>
+#include <linux/tick.h>
+
+#include <xen/interface/xen.h>
+
+#include <asm/xen/hypercall.h>
+
+#include "xen-ops.h"
+
+void xen_arch_pre_suspend(void) {
+ /* Nothing to do */
+}
+
+void xen_arch_post_suspend(int suspend_cancelled)
+{
+ xen_register_shared_info();
+ if (!suspend_cancelled)
+ xen_vcpu_restore();
+}
+
+static void xen_vcpu_notify_suspend(void *data)
+{
+ tick_suspend_local();
+}
+
+static void xen_vcpu_notify_resume(void *data)
+{
+ int suspend_cancelled = *(int *)data;
+
+ if (smp_processor_id() == 0)
+ return;
+
+ /* Boot processor done in post_suspend */
+ if (!suspend_cancelled)
+ xen_vcpu_restore();
+
+ /* Boot processor notified via generic timekeeping_resume() */
+ tick_resume_local();
+}
+
+void xen_arch_suspend(void)
+{
+ on_each_cpu(xen_vcpu_notify_suspend, NULL, 1);
+}
+
+void xen_arch_resume(int suspend_cancelled)
+{
+ on_each_cpu(xen_vcpu_notify_resume, &suspend_cancelled, 1);
+}
+
+void xen_timer_resume(void)
+{
+ /* Nothing to do */
+}