static int setup_shutdown_watcher(void) { int err; (void)xenbus_scanf(XBT_NIL, "control", "platform-feature-multiprocessor-suspend", "%d", &fast_suspend); err = register_xenbus_watch(&shutdown_watch); if (err) { printk(KERN_ERR "Failed to set shutdown watcher\n"); return err; } err = register_xenbus_watch(&sysrq_watch); if (err) { printk(KERN_ERR "Failed to set sysrq watcher\n"); return err; } /* suspend event channel */ err = setup_suspend_evtchn(); if (err) { printk(KERN_ERR "Failed to register suspend event channel\n"); return err; } return 0; }
static int xen_suspend(void *__unused) { int err, old_state; daemonize("suspend"); err = set_cpus_allowed(current, cpumask_of_cpu(0)); if (err) { printk(KERN_ERR "Xen suspend can't run on CPU0 (%d)\n", err); goto fail; } do { err = __xen_suspend(fast_suspend, xen_resume_notifier); if (err) { printk(KERN_ERR "Xen suspend failed (%d)\n", err); goto fail; } if (!suspend_cancelled) setup_suspend_evtchn(); old_state = cmpxchg( &shutting_down, SHUTDOWN_RESUMING, SHUTDOWN_INVALID); } while (old_state == SHUTDOWN_SUSPEND); switch (old_state) { case SHUTDOWN_INVALID: case SHUTDOWN_SUSPEND: BUG(); case SHUTDOWN_RESUMING: break; default: schedule_work(&shutdown_work); break; } return 0; fail: old_state = xchg(&shutting_down, SHUTDOWN_INVALID); BUG_ON(old_state != SHUTDOWN_SUSPEND); return 0; }
/* open a checkpoint session to guest domid */ int checkpoint_open(checkpoint_state* s, unsigned int domid) { xc_dominfo_t dominfo; unsigned long pvirq; s->domid = domid; s->xch = xc_interface_open(); if (s->xch < 0) { s->errstr = "could not open control interface (are you root?)"; return -1; } s->xsh = xs_daemon_open(); if (!s->xsh) { checkpoint_close(s); s->errstr = "could not open xenstore handle"; return -1; } s->xce = xc_evtchn_open(); if (s->xce < 0) { checkpoint_close(s); s->errstr = "could not open event channel handle"; return -1; } if (xc_domain_getinfo(s->xch, s->domid, 1, &dominfo) < 0) { checkpoint_close(s); s->errstr = "could not get domain info"; return -1; } if (dominfo.hvm) { if (xc_get_hvm_param(s->xch, s->domid, HVM_PARAM_CALLBACK_IRQ, &pvirq)) { checkpoint_close(s); s->errstr = "could not get HVM callback IRQ"; return -1; } s->domtype = pvirq ? dt_pvhvm : dt_hvm; } else s->domtype = dt_pv; if (setup_shutdown_watch(s) < 0) { checkpoint_close(s); return -1; } if (s->domtype == dt_pv) { if (setup_suspend_evtchn(s) < 0) { fprintf(stderr, "WARNING: suspend event channel unavailable, " "falling back to slow xenstore signalling\n"); } } else if (s->domtype == dt_pvhvm) { checkpoint_close(s); s->errstr = "PV-on-HVM is unsupported"; return -1; } return 0; }