Okay, I've checked this one in as 12036:eb3fe0620e3d of xen-unstable.
Thanks!
Steven.
> Sorry, the previous patch had a problem on dom0 boot.
> I have modified the patch to fix it and tested xm reboot/shutdown/sysrq
> to both of PV and HVM domain.
>
> To make reboot on HVM domain work correctly, the following patch is needed:
> http://lists.xensource.com/archives/html/xen-devel/2006-10/msg01184.html
>
> Regards,
>
> Tetsu Yamamoto
>
> Signed-off-by: Tetsu Yamamoto <yamamoto.tetsu@xxxxxxxxxxxxxx>
>
> Tetsu Yamamoto wrote:
> > Hi Steven,
> >
> > Thank you for your comments.
> >
> > The attached is modified patch based on your comments.
> >
> > The functions which can not be used from the module on HVM domain are
> > moved to the new file machine_reboot.c, and several #ifdefs are removed.
> > However, reboot.c still has two parts of #ifdef CONFIG_XEN because some
> > functions called in common functions are not EXPORT_SYMBOL:
> > - sys_reboot
> > - Some functions called in __do_suspend
> >
> > Regards,
> >
> > Tetsu Yamamoto
> >
> > Signed-off-by: Tetsu Yamamoto <yamamoto.tetsu@xxxxxxxxxxxxxx>
> >
> > Steven Smith wrote:
> >>>>> This patch enhances 'xm reboot'/'xm shutdown' commands to
> >>>>> reboot/shutdown guest Linux on HVM domain as gracefully as para-Linux.
> >>>>> In addtion, sysrq key signal can be sent to HVM domain by 'xm sysrq'
> >>>>> command.
> >>>> Thanks, that's really useful. I have a couple of comments about the
> >>>> patch, though:
> >>>>
> >>>> -- It looks like you had some problems with ctrl_alt_del(), and instead
> >>>> used kill_proc(cad_pid, SIGINT, 1). What was the reason for this?
> >>> The symbol ctrl_alt_del() can't be found when it is used in loadable
> >>> module. On build, the warning message is shown that ctrl_alt_del() is
> >>> undefined, and on loading, the error message is shown that it is unknown
> >>> symbol. I'm not sure why this happens, but I tried kill_proc(), which
> >>> is called in ctrl_alt_del(), it works correctly.
> >> Ah, okay, ctrl_alt_del isn't an EXPORT_SYMBOL. That's unfortunate,
> >> and this looks like a sensible work-around.
> >>
> >>>> -- You've introduced a lot of #ifdefs into reboot.c. It might be
> >>>> easier to just split the file in two; did you look at this at all?
> >>> reboot.c has common process to deal with reboot/shutdown/sysrq for
> >>> para-linux (built in kernel) and full-linux (loadable module), so I
> >>> think that it would be better to be one file in consideration of code
> >>> maintenance.
> >> I'm not talking about duplicating the code. As far as I can see, you
> >> share the following functions with PV reboot.c:
> >>
> >> -- shutdown_process
> >> -- __shutdown_handler
> >> -- shutdown_handler
> >> -- sysrq_handler
> >> -- setup_shutdown_event
> >> -- setup_shutdown_watcher
> >>
> >> You don't share:
> >>
> >> -- machine_emergency_restart
> >> -- machine_restart
> >> -- machine_halt
> >> -- machine_power_off
> >> -- switch_idle_mm
> >> -- pre_suspend
> >> -- post_suspend
> >> -- __do_suspend
> >> -- kthread_create_on_cpu
> >>
> >> To put it another way, your patch #if's out more than half the file.
> >> Given that, I think the code would be more maintainable if you moved
> >> machine_* and __do_suspend to a new file, perhaps machine_reboot.c.
> >>
> >>>> -- You set reboot_module from within a xenbus transaction. I don't
> >>>> think that's necessary, since xenbus_writes are supposed to be
> >>>> atomic anyway.
> >>> The reason why I use xenbus_write is that I could not find other
> >>> interface to write xenstore through xenbus module for HVM. I'm not sure
> >>> which interface you suggest to use, but for example, xb_write() is not
> >>> exported, so it can not be called from reboot module. If I should use
> >>> other interface, please let me know.
> >> I'm not objecting to the use of xenbus_write, but the use of
> >> xenbus_transaction_start: you're only doing one write, so you can just
> >> go xenbus_write(XBT_NULL, "control", "reboot_module", "installed")
> >> rather than having the loop in setup_shutdown_event.
> >>
> >> I'm also not sure why this is #ifndef CONFIG_XEN. It seems like it
> >> would be a good idea to set reboot_module in PV domains as well, just
> >> for consistency.
> >>
> >>> +#ifndef CONFIG_XEN
> >>> +MODULE_LICENSE("Dual BSD/GPL");
> >>> +#endif /* !CONFIG_XEN */
> >> Does this actually need the #ifdefs? If we're CONFIG_XEN, we're not a
> >> module, so MODULE_LICENSE gets preprocessored away, doesn't it?
> >>
> >>> static int shutdown_process(void *__unused)
> >>> {
> >>> @@ -222,12 +232,17 @@ static int shutdown_process(void *__unus
> >>>
> >>> if ((shutting_down == SHUTDOWN_POWEROFF) ||
> >>> (shutting_down == SHUTDOWN_HALT)) {
> >>> +#ifdef CONFIG_XEN
> >>> if (execve("/sbin/poweroff", poweroff_argv, envp) < 0) {
> >>> sys_reboot(LINUX_REBOOT_MAGIC1,
> >>> LINUX_REBOOT_MAGIC2,
> >>> LINUX_REBOOT_CMD_POWER_OFF,
> >>> NULL);
> >>> }
> >>> +#else /* !CONFIG_XEN */
> >>> + call_usermodehelper_keys("/sbin/poweroff", poweroff_argv, envp,
> > NULL, 0);
> >>> +
> >>> +#endif /* !CONFIG_XEN */
> >> Hmm... it might make sense to use call_usermodehelper_keys in the
> >> CONFIG_XEN case. Did you try that?
> >>
> >>> static void __shutdown_handler(void *unused)
> >>> {
> >>> int err;
> >>>
> >>> +#ifdef CONFIG_XEN
> >>> if (shutting_down != SHUTDOWN_SUSPEND)
> >>> err = kernel_thread(shutdown_process, NULL,
> >>> CLONE_FS | CLONE_FILES);
> >>> else
> >>> err = kthread_create_on_cpu(__do_suspend, NULL, "suspend", 0);
> >>>
> >>> +#else /* !CONFIG_XEN */
> >>> + err = kernel_thread(shutdown_process, NULL,
> >>> + CLONE_FS | CLONE_FILES);
> >>> +#endif /* !CONFIG_XEN */
> >>> +
> >> I don't understand why this was necessary. Surely __do_suspend just
> >> returns an error if called from non-CONFIG_XEN?
> >>
> >> Steven.
> >
> >
> >
> > ------------------------------------------------------------------------
> >
> > diff -r 38f9bd7a4ce6 linux-2.6-xen-sparse/drivers/xen/core/Makefile
> > --- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile Tue Oct 03
> > 11:39:22 2006 +0100
> > +++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile Mon Oct 16
> > 19:43:51 2006 +0900
> > @@ -9,5 +9,5 @@ obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug
> > obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
> > obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
> > obj-$(CONFIG_XEN_SKBUFF) += skbuff.o
> > -obj-$(CONFIG_XEN_REBOOT) += reboot.o
> > +obj-$(CONFIG_XEN_REBOOT) += reboot.o machine_reboot.o
> > obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o
> > diff -r 38f9bd7a4ce6 linux-2.6-xen-sparse/drivers/xen/core/reboot.c
> > --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Tue Oct 03
> > 11:39:22 2006 +0100
> > +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Wed Oct 18
> > 15:46:31 2006 +0900
> > @@ -1,215 +1,19 @@
> > #define __KERNEL_SYSCALLS__
> > #include <linux/version.h>
> > #include <linux/kernel.h>
> > -#include <linux/mm.h>
> > #include <linux/unistd.h>
> > #include <linux/module.h>
> > #include <linux/reboot.h>
> > #include <linux/sysrq.h>
> > -#include <linux/stringify.h>
> > -#include <asm/irq.h>
> > -#include <asm/mmu_context.h>
> > -#include <xen/evtchn.h>
> > #include <asm/hypervisor.h>
> > -#include <xen/interface/dom0_ops.h>
> > #include <xen/xenbus.h>
> > -#include <linux/cpu.h>
> > #include <linux/kthread.h>
> > -#include <xen/gnttab.h>
> > -#include <xen/xencons.h>
> > -#include <xen/cpu_hotplug.h>
> > +#include <xen/reboot.h>
> >
> > -extern void ctrl_alt_del(void);
> > +MODULE_LICENSE("Dual BSD/GPL");
> >
> > -#define SHUTDOWN_INVALID -1
> > -#define SHUTDOWN_POWEROFF 0
> > -#define SHUTDOWN_SUSPEND 2
> > -/* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
> > - * report a crash, not be instructed to crash!
> > - * HALT is the same as POWEROFF, as far as we're concerned. The tools use
> > - * the distinction when we return the reason code to them.
> > - */
> > -#define SHUTDOWN_HALT 4
> > -
> > -#if defined(__i386__) || defined(__x86_64__)
> > -
> > -/*
> > - * Power off function, if any
> > - */
> > -void (*pm_power_off)(void);
> > -EXPORT_SYMBOL(pm_power_off);
> > -
> > -void machine_emergency_restart(void)
> > -{
> > - /* We really want to get pending console data out before we die. */
> > - xencons_force_flush();
> > - HYPERVISOR_shutdown(SHUTDOWN_reboot);
> > -}
> > -
> > -void machine_restart(char * __unused)
> > -{
> > - machine_emergency_restart();
> > -}
> > -
> > -void machine_halt(void)
> > -{
> > - machine_power_off();
> > -}
> > -
> > -void machine_power_off(void)
> > -{
> > - /* We really want to get pending console data out before we die. */
> > - xencons_force_flush();
> > - if (pm_power_off)
> > - pm_power_off();
> > - HYPERVISOR_shutdown(SHUTDOWN_poweroff);
> > -}
> > -
> > -int reboot_thru_bios = 0; /* for dmi_scan.c */
> > -EXPORT_SYMBOL(machine_restart);
> > -EXPORT_SYMBOL(machine_halt);
> > -EXPORT_SYMBOL(machine_power_off);
> > -
> > -#endif /* defined(__i386__) || defined(__x86_64__) */
> > -
> > -/******************************************************************************
> > - * Stop/pickle callback handling.
> > - */
> > -
> > -/* Ignore multiple shutdown requests. */
> > -static int shutting_down = SHUTDOWN_INVALID;
> > static void __shutdown_handler(void *unused);
> > static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
> > -
> > -#if defined(__i386__) || defined(__x86_64__)
> > -
> > -/* Ensure we run on the idle task page tables so that we will
> > - switch page tables before running user space. This is needed
> > - on architectures with separate kernel and user page tables
> > - because the user page table pointer is not saved/restored. */
> > -static void switch_idle_mm(void)
> > -{
> > - struct mm_struct *mm = current->active_mm;
> > -
> > - if (mm == &init_mm)
> > - return;
> > -
> > - atomic_inc(&init_mm.mm_count);
> > - switch_mm(mm, &init_mm, current);
> > - current->active_mm = &init_mm;
> > - mmdrop(mm);
> > -}
> > -
> > -static void pre_suspend(void)
> > -{
> > - HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
> > - clear_fixmap(FIX_SHARED_INFO);
> > -
> > - xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
> > - xen_start_info->console.domU.mfn =
> > - mfn_to_pfn(xen_start_info->console.domU.mfn);
> > -}
> > -
> > -static void post_suspend(void)
> > -{
> > - int i, j, k, fpp;
> > - extern unsigned long max_pfn;
> > - extern unsigned long *pfn_to_mfn_frame_list_list;
> > - extern unsigned long *pfn_to_mfn_frame_list[];
> > -
> > - set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
> > -
> > - HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
> > -
> > - memset(empty_zero_page, 0, PAGE_SIZE);
> > -
> > - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
> > - virt_to_mfn(pfn_to_mfn_frame_list_list);
> > -
> > - fpp = PAGE_SIZE/sizeof(unsigned long);
> > - for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
> > - if ((j % fpp) == 0) {
> > - k++;
> > - pfn_to_mfn_frame_list_list[k] =
> > - virt_to_mfn(pfn_to_mfn_frame_list[k]);
> > - j = 0;
> > - }
> > - pfn_to_mfn_frame_list[k][j] =
> > - virt_to_mfn(&phys_to_machine_mapping[i]);
> > - }
> > - HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
> > -}
> > -
> > -#else /* !(defined(__i386__) || defined(__x86_64__)) */
> > -
> > -#define switch_idle_mm() ((void)0)
> > -#define mm_pin_all() ((void)0)
> > -#define pre_suspend() ((void)0)
> > -#define post_suspend() ((void)0)
> > -
> > -#endif
> > -
> > -static int __do_suspend(void *ignore)
> > -{
> > - int err;
> > -
> > - extern void time_resume(void);
> > -
> > - BUG_ON(smp_processor_id() != 0);
> > - BUG_ON(in_interrupt());
> > -
> > -#if defined(__i386__) || defined(__x86_64__)
> > - if (xen_feature(XENFEAT_auto_translated_physmap)) {
> > - printk(KERN_WARNING "Cannot suspend in "
> > - "auto_translated_physmap mode.\n");
> > - return -EOPNOTSUPP;
> > - }
> > -#endif
> > -
> > - err = smp_suspend();
> > - if (err)
> > - return err;
> > -
> > - xenbus_suspend();
> > -
> > - preempt_disable();
> > -
> > - mm_pin_all();
> > - local_irq_disable();
> > - preempt_enable();
> > -
> > - gnttab_suspend();
> > -
> > - pre_suspend();
> > -
> > - /*
> > - * We'll stop somewhere inside this hypercall. When it returns,
> > - * we'll start resuming after the restore.
> > - */
> > - HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
> > -
> > - shutting_down = SHUTDOWN_INVALID;
> > -
> > - post_suspend();
> > -
> > - gnttab_resume();
> > -
> > - irq_resume();
> > -
> > - time_resume();
> > -
> > - switch_idle_mm();
> > -
> > - local_irq_enable();
> > -
> > - xencons_resume();
> > -
> > - xenbus_resume();
> > -
> > - smp_resume();
> > -
> > - return err;
> > -}
> >
> > static int shutdown_process(void *__unused)
> > {
> > @@ -222,11 +26,13 @@ static int shutdown_process(void *__unus
> >
> > if ((shutting_down == SHUTDOWN_POWEROFF) ||
> > (shutting_down == SHUTDOWN_HALT)) {
> > - if (execve("/sbin/poweroff", poweroff_argv, envp) < 0) {
> > + if (call_usermodehelper_keys("/sbin/poweroff", poweroff_argv,
> > envp, NULL, 0) < 0) {
> > +#ifdef CONFIG_XEN
> > sys_reboot(LINUX_REBOOT_MAGIC1,
> > LINUX_REBOOT_MAGIC2,
> > LINUX_REBOOT_CMD_POWER_OFF,
> > NULL);
> > +#endif /* CONFIG_XEN */
> > }
> > }
> >
> > @@ -235,29 +41,21 @@ static int shutdown_process(void *__unus
> > return 0;
> > }
> >
> > -static int kthread_create_on_cpu(int (*f)(void *arg),
> > - void *arg,
> > - const char *name,
> > - int cpu)
> > -{
> > - struct task_struct *p;
> > - p = kthread_create(f, arg, name);
> > - if (IS_ERR(p))
> > - return PTR_ERR(p);
> > - kthread_bind(p, cpu);
> > - wake_up_process(p);
> > - return 0;
> > -}
> >
> > static void __shutdown_handler(void *unused)
> > {
> > int err;
> >
> > +#ifdef CONFIG_XEN
> > if (shutting_down != SHUTDOWN_SUSPEND)
> > err = kernel_thread(shutdown_process, NULL,
> > CLONE_FS | CLONE_FILES);
> > else
> > err = kthread_create_on_cpu(__do_suspend, NULL, "suspend", 0);
> > +#else /* !CONFIG_XEN */
> > + err = kernel_thread(shutdown_process, NULL,
> > + CLONE_FS | CLONE_FILES);
> > +#endif /* !CONFIG_XEN */
> >
> > if (err < 0) {
> > printk(KERN_WARNING "Error creating shutdown process (%d): "
> > @@ -272,6 +70,8 @@ static void shutdown_handler(struct xenb
> > char *str;
> > struct xenbus_transaction xbt;
> > int err;
> > +
> > + int cad_pid = 1;
> >
> > if (shutting_down != SHUTDOWN_INVALID)
> > return;
> > @@ -298,7 +98,7 @@ static void shutdown_handler(struct xenb
> > if (strcmp(str, "poweroff") == 0)
> > shutting_down = SHUTDOWN_POWEROFF;
> > else if (strcmp(str, "reboot") == 0)
> > - ctrl_alt_del();
> > + kill_proc(cad_pid, SIGINT, 1);
> > else if (strcmp(str, "suspend") == 0)
> > shutting_down = SHUTDOWN_SUSPEND;
> > else if (strcmp(str, "halt") == 0)
> > @@ -378,6 +178,9 @@ static int __init setup_shutdown_event(v
> > .notifier_call = setup_shutdown_watcher
> > };
> > register_xenstore_notifier(&xenstore_notifier);
> > +
> > + xenbus_write(XBT_NIL, "control", "reboot_module", "installed");
> > +
> > return 0;
> > }
> >
> > diff -r 38f9bd7a4ce6 tools/python/xen/xend/image.py
> > --- a/tools/python/xen/xend/image.py Tue Oct 03 11:39:22 2006 +0100
> > +++ b/tools/python/xen/xend/image.py Mon Oct 16 18:52:49 2006 +0900
> > @@ -281,6 +281,7 @@ class HVMImageHandler(ImageHandler):
> > log.debug("apic = %d", self.apic)
> >
> > self.register_shutdown_watch()
> > + self.register_reboot_module_watch()
> >
> > return xc.hvm_build(dom = self.vm.getDomid(),
> > image = self.kernel,
> > @@ -383,6 +384,7 @@ class HVMImageHandler(ImageHandler):
> >
> > def destroy(self):
> > self.unregister_shutdown_watch();
> > + self.unregister_reboot_module_watch();
> > import signal
> > if not self.pid:
> > return
> > @@ -425,6 +427,39 @@ class HVMImageHandler(ImageHandler):
> > vm.refreshShutdown(vm.info)
> >
> > return 1 # Keep watching
> > +
> > + def register_reboot_module_watch(self):
> > + """ add xen store watch on control/reboot_module """
> > + self.rebootModuleWatch = xswatch(self.vm.dompath +
> > "/control/reboot_module", \
> > + self.hvm_reboot_module)
> > + log.debug("hvm reboot module watch registered")
> > +
> > + def unregister_reboot_module_watch(self):
> > + """Remove the watch on the control/reboot_module, if any. Nothrow
> > + guarantee."""
> > +
> > + try:
> > + if self.rebootModuleWatch:
> > + self.rebootModuleWatch.unwatch()
> > + except:
> > + log.exception("Unwatching hvm reboot module watch failed.")
> > + self.rebootModuleWatch = None
> > + log.debug("hvm reboot module watch unregistered")
> > +
> > + def hvm_reboot_module(self, _):
> > + """ watch call back on node control/reboot_module,
> > + if node changed, this function will be called
> > + """
> > + xd = xen.xend.XendDomain.instance()
> > + vm = xd.domain_lookup( self.vm.getDomid() )
> > +
> > + reboot_module_status = vm.readDom('control/reboot_module')
> > + log.debug("hvm_reboot_module fired, module status=%s",
> > reboot_module_status)
> > + if reboot_module_status == 'installed':
> > + self.unregister_shutdown_watch()
> > +
> > + return 1 # Keep watching
> > +
> >
> > class IA64_HVM_ImageHandler(HVMImageHandler):
> >
> > diff -r 38f9bd7a4ce6 unmodified_drivers/linux-2.6/Makefile
> > --- a/unmodified_drivers/linux-2.6/Makefile Tue Oct 03 11:39:22 2006 +0100
> > +++ b/unmodified_drivers/linux-2.6/Makefile Mon Oct 16 18:52:49 2006 +0900
> > @@ -4,3 +4,4 @@ obj-m += xenbus/
> > obj-m += xenbus/
> > obj-m += blkfront/
> > obj-m += netfront/
> > +obj-m += util/
> > diff -r 38f9bd7a4ce6 unmodified_drivers/linux-2.6/mkbuildtree
> > --- a/unmodified_drivers/linux-2.6/mkbuildtree Tue Oct 03 11:39:22
> > 2006 +0100
> > +++ b/unmodified_drivers/linux-2.6/mkbuildtree Mon Oct 16 18:52:49
> > 2006 +0900
> > @@ -14,6 +14,7 @@ ln -sf ${XL}/drivers/xen/core/gnttab.c p
> > ln -sf ${XL}/drivers/xen/core/gnttab.c platform-pci
> > ln -sf ${XL}/drivers/xen/core/features.c platform-pci
> > ln -sf ${XL}/drivers/xen/core/xen_proc.c xenbus
> > +ln -sf ${XL}/drivers/xen/core/reboot.c util
> >
> > mkdir -p include
> > mkdir -p include/xen
> > diff -r 38f9bd7a4ce6 linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c
> > --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> > +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c Mon Oct
> > 16 21:55:32 2006 +0900
> > @@ -0,0 +1,206 @@
> > +#define __KERNEL_SYSCALLS__
> > +#include <linux/version.h>
> > +#include <linux/kernel.h>
> > +#include <linux/mm.h>
> > +#include <linux/unistd.h>
> > +#include <linux/module.h>
> > +#include <linux/reboot.h>
> > +#include <linux/sysrq.h>
> > +#include <linux/stringify.h>
> > +#include <asm/irq.h>
> > +#include <asm/mmu_context.h>
> > +#include <xen/evtchn.h>
> > +#include <asm/hypervisor.h>
> > +#include <xen/interface/dom0_ops.h>
> > +#include <xen/xenbus.h>
> > +#include <linux/cpu.h>
> > +#include <linux/kthread.h>
> > +#include <xen/gnttab.h>
> > +#include <xen/xencons.h>
> > +#include <xen/cpu_hotplug.h>
> > +#include <xen/reboot.h>
> > +
> > +#if defined(__i386__) || defined(__x86_64__)
> > +
> > +/*
> > + * Power off function, if any
> > + */
> > +void (*pm_power_off)(void);
> > +EXPORT_SYMBOL(pm_power_off);
> > +
> > +void machine_emergency_restart(void)
> > +{
> > + /* We really want to get pending console data out before we die. */
> > + xencons_force_flush();
> > + HYPERVISOR_shutdown(SHUTDOWN_reboot);
> > +}
> > +
> > +void machine_restart(char * __unused)
> > +{
> > + machine_emergency_restart();
> > +}
> > +
> > +void machine_halt(void)
> > +{
> > + machine_power_off();
> > +}
> > +
> > +void machine_power_off(void)
> > +{
> > + /* We really want to get pending console data out before we die. */
> > + xencons_force_flush();
> > + if (pm_power_off)
> > + pm_power_off();
> > + HYPERVISOR_shutdown(SHUTDOWN_poweroff);
> > +}
> > +
> > +int reboot_thru_bios = 0; /* for dmi_scan.c */
> > +EXPORT_SYMBOL(machine_restart);
> > +EXPORT_SYMBOL(machine_halt);
> > +EXPORT_SYMBOL(machine_power_off);
> > +
> > +#endif /* defined(__i386__) || defined(__x86_64__) */
> > +
> > +#if defined(__i386__) || defined(__x86_64__)
> > +
> > +/* Ensure we run on the idle task page tables so that we will
> > + switch page tables before running user space. This is needed
> > + on architectures with separate kernel and user page tables
> > + because the user page table pointer is not saved/restored. */
> > +static void switch_idle_mm(void)
> > +{
> > + struct mm_struct *mm = current->active_mm;
> > +
> > + if (mm == &init_mm)
> > + return;
> > +
> > + atomic_inc(&init_mm.mm_count);
> > + switch_mm(mm, &init_mm, current);
> > + current->active_mm = &init_mm;
> > + mmdrop(mm);
> > +}
> > +
> > +static void pre_suspend(void)
> > +{
> > + HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
> > + clear_fixmap(FIX_SHARED_INFO);
> > +
> > + xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
> > + xen_start_info->console.domU.mfn =
> > + mfn_to_pfn(xen_start_info->console.domU.mfn);
> > +}
> > +
> > +static void post_suspend(void)
> > +{
> > + int i, j, k, fpp;
> > + extern unsigned long max_pfn;
> > + extern unsigned long *pfn_to_mfn_frame_list_list;
> > + extern unsigned long *pfn_to_mfn_frame_list[];
> > +
> > + set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
> > +
> > + HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
> > +
> > + memset(empty_zero_page, 0, PAGE_SIZE);
> > +
> > + HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
> > + virt_to_mfn(pfn_to_mfn_frame_list_list);
> > +
> > + fpp = PAGE_SIZE/sizeof(unsigned long);
> > + for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
> > + if ((j % fpp) == 0) {
> > + k++;
> > + pfn_to_mfn_frame_list_list[k] =
> > + virt_to_mfn(pfn_to_mfn_frame_list[k]);
> > + j = 0;
> > + }
> > + pfn_to_mfn_frame_list[k][j] =
> > + virt_to_mfn(&phys_to_machine_mapping[i]);
> > + }
> > + HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
> > +}
> > +
> > +#else /* !(defined(__i386__) || defined(__x86_64__)) */
> > +
> > +#define switch_idle_mm() ((void)0)
> > +#define mm_pin_all() ((void)0)
> > +#define pre_suspend() ((void)0)
> > +#define post_suspend() ((void)0)
> > +
> > +#endif
> > +
> > +int __do_suspend(void *ignore)
> > +{
> > + int err;
> > +
> > + extern void time_resume(void);
> > +
> > + BUG_ON(smp_processor_id() != 0);
> > + BUG_ON(in_interrupt());
> > +
> > +#if defined(__i386__) || defined(__x86_64__)
> > + if (xen_feature(XENFEAT_auto_translated_physmap)) {
> > + printk(KERN_WARNING "Cannot suspend in "
> > + "auto_translated_physmap mode.\n");
> > + return -EOPNOTSUPP;
> > + }
> > +#endif
> > +
> > + err = smp_suspend();
> > + if (err)
> > + return err;
> > +
> > + xenbus_suspend();
> > +
> > + preempt_disable();
> > +
> > + mm_pin_all();
> > + local_irq_disable();
> > + preempt_enable();
> > +
> > + gnttab_suspend();
> > +
> > + pre_suspend();
> > +
> > + /*
> > + * We'll stop somewhere inside this hypercall. When it returns,
> > + * we'll start resuming after the restore.
> > + */
> > + HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
> > +
> > + shutting_down = SHUTDOWN_INVALID;
> > +
> > + post_suspend();
> > +
> > + gnttab_resume();
> > +
> > + irq_resume();
> > +
> > + time_resume();
> > +
> > + switch_idle_mm();
> > +
> > + local_irq_enable();
> > +
> > + xencons_resume();
> > +
> > + xenbus_resume();
> > +
> > + smp_resume();
> > +
> > + return err;
> > +}
> > +
> > +int kthread_create_on_cpu(int (*f)(void *arg),
> > + void *arg,
> > + const char *name,
> > + int cpu)
> > +{
> > + struct task_struct *p;
> > + p = kthread_create(f, arg, name);
> > + if (IS_ERR(p))
> > + return PTR_ERR(p);
> > + kthread_bind(p, cpu);
> > + wake_up_process(p);
> > + return 0;
> > +}
> > diff -r 38f9bd7a4ce6 linux-2.6-xen-sparse/include/xen/reboot.h
> > --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> > +++ b/linux-2.6-xen-sparse/include/xen/reboot.h Mon Oct 16 22:35:22
> > 2006 +0900
> > @@ -0,0 +1,19 @@
> > +#define SHUTDOWN_INVALID -1
> > +#define SHUTDOWN_POWEROFF 0
> > +#define SHUTDOWN_SUSPEND 2
> > +/* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
> > + * report a crash, not be instructed to crash!
> > + * HALT is the same as POWEROFF, as far as we're concerned. The tools use
> > + * the distinction when we return the reason code to them.
> > + */
> > +#define SHUTDOWN_HALT 4
> > +
> > +/******************************************************************************
> > + * Stop/pickle callback handling.
> > + */
> > +
> > +/* Ignore multiple shutdown requests. */
> > +static int shutting_down = SHUTDOWN_INVALID;
> > +
> > +int kthread_create_on_cpu(int (*f)(void *), void *, const char *, int);
> > +int __do_suspend(void *);
> >
> >
> > ------------------------------------------------------------------------
> >
> > _______________________________________________
> > Xen-devel mailing list
> > Xen-devel@xxxxxxxxxxxxxxxxxxx
> > http://lists.xensource.com/xen-devel
>
>
> diff -r 4a320d26fc24 linux-2.6-xen-sparse/drivers/xen/core/Makefile
> --- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile Thu Oct 26 16:56:16
> 2006 +0100
> +++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile Fri Oct 27 17:02:19
> 2006 +0900
> @@ -9,5 +9,5 @@ obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug
> obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
> obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
> obj-$(CONFIG_XEN_SKBUFF) += skbuff.o
> -obj-$(CONFIG_XEN_REBOOT) += reboot.o
> +obj-$(CONFIG_XEN_REBOOT) += reboot.o machine_reboot.o
> obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o
> diff -r 4a320d26fc24 linux-2.6-xen-sparse/drivers/xen/core/reboot.c
> --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Thu Oct 26 16:56:16
> 2006 +0100
> +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Fri Oct 27 17:03:46
> 2006 +0900
> @@ -1,215 +1,19 @@
> #define __KERNEL_SYSCALLS__
> #include <linux/version.h>
> #include <linux/kernel.h>
> -#include <linux/mm.h>
> #include <linux/unistd.h>
> #include <linux/module.h>
> #include <linux/reboot.h>
> #include <linux/sysrq.h>
> -#include <linux/stringify.h>
> -#include <asm/irq.h>
> -#include <asm/mmu_context.h>
> -#include <xen/evtchn.h>
> #include <asm/hypervisor.h>
> -#include <xen/interface/dom0_ops.h>
> #include <xen/xenbus.h>
> -#include <linux/cpu.h>
> #include <linux/kthread.h>
> -#include <xen/gnttab.h>
> -#include <xen/xencons.h>
> -#include <xen/cpu_hotplug.h>
> +#include <xen/reboot.h>
>
> -extern void ctrl_alt_del(void);
> +MODULE_LICENSE("Dual BSD/GPL");
>
> -#define SHUTDOWN_INVALID -1
> -#define SHUTDOWN_POWEROFF 0
> -#define SHUTDOWN_SUSPEND 2
> -/* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
> - * report a crash, not be instructed to crash!
> - * HALT is the same as POWEROFF, as far as we're concerned. The tools use
> - * the distinction when we return the reason code to them.
> - */
> -#define SHUTDOWN_HALT 4
> -
> -#if defined(__i386__) || defined(__x86_64__)
> -
> -/*
> - * Power off function, if any
> - */
> -void (*pm_power_off)(void);
> -EXPORT_SYMBOL(pm_power_off);
> -
> -void machine_emergency_restart(void)
> -{
> - /* We really want to get pending console data out before we die. */
> - xencons_force_flush();
> - HYPERVISOR_shutdown(SHUTDOWN_reboot);
> -}
> -
> -void machine_restart(char * __unused)
> -{
> - machine_emergency_restart();
> -}
> -
> -void machine_halt(void)
> -{
> - machine_power_off();
> -}
> -
> -void machine_power_off(void)
> -{
> - /* We really want to get pending console data out before we die. */
> - xencons_force_flush();
> - if (pm_power_off)
> - pm_power_off();
> - HYPERVISOR_shutdown(SHUTDOWN_poweroff);
> -}
> -
> -int reboot_thru_bios = 0; /* for dmi_scan.c */
> -EXPORT_SYMBOL(machine_restart);
> -EXPORT_SYMBOL(machine_halt);
> -EXPORT_SYMBOL(machine_power_off);
> -
> -#endif /* defined(__i386__) || defined(__x86_64__) */
> -
> -/******************************************************************************
> - * Stop/pickle callback handling.
> - */
> -
> -/* Ignore multiple shutdown requests. */
> -static int shutting_down = SHUTDOWN_INVALID;
> static void __shutdown_handler(void *unused);
> static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
> -
> -#if defined(__i386__) || defined(__x86_64__)
> -
> -/* Ensure we run on the idle task page tables so that we will
> - switch page tables before running user space. This is needed
> - on architectures with separate kernel and user page tables
> - because the user page table pointer is not saved/restored. */
> -static void switch_idle_mm(void)
> -{
> - struct mm_struct *mm = current->active_mm;
> -
> - if (mm == &init_mm)
> - return;
> -
> - atomic_inc(&init_mm.mm_count);
> - switch_mm(mm, &init_mm, current);
> - current->active_mm = &init_mm;
> - mmdrop(mm);
> -}
> -
> -static void pre_suspend(void)
> -{
> - HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
> - clear_fixmap(FIX_SHARED_INFO);
> -
> - xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
> - xen_start_info->console.domU.mfn =
> - mfn_to_pfn(xen_start_info->console.domU.mfn);
> -}
> -
> -static void post_suspend(void)
> -{
> - int i, j, k, fpp;
> - extern unsigned long max_pfn;
> - extern unsigned long *pfn_to_mfn_frame_list_list;
> - extern unsigned long *pfn_to_mfn_frame_list[];
> -
> - set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
> -
> - HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
> -
> - memset(empty_zero_page, 0, PAGE_SIZE);
> -
> - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
> - virt_to_mfn(pfn_to_mfn_frame_list_list);
> -
> - fpp = PAGE_SIZE/sizeof(unsigned long);
> - for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
> - if ((j % fpp) == 0) {
> - k++;
> - pfn_to_mfn_frame_list_list[k] =
> - virt_to_mfn(pfn_to_mfn_frame_list[k]);
> - j = 0;
> - }
> - pfn_to_mfn_frame_list[k][j] =
> - virt_to_mfn(&phys_to_machine_mapping[i]);
> - }
> - HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
> -}
> -
> -#else /* !(defined(__i386__) || defined(__x86_64__)) */
> -
> -#define switch_idle_mm() ((void)0)
> -#define mm_pin_all() ((void)0)
> -#define pre_suspend() ((void)0)
> -#define post_suspend() ((void)0)
> -
> -#endif
> -
> -static int __do_suspend(void *ignore)
> -{
> - int err;
> -
> - extern void time_resume(void);
> -
> - BUG_ON(smp_processor_id() != 0);
> - BUG_ON(in_interrupt());
> -
> -#if defined(__i386__) || defined(__x86_64__)
> - if (xen_feature(XENFEAT_auto_translated_physmap)) {
> - printk(KERN_WARNING "Cannot suspend in "
> - "auto_translated_physmap mode.\n");
> - return -EOPNOTSUPP;
> - }
> -#endif
> -
> - err = smp_suspend();
> - if (err)
> - return err;
> -
> - xenbus_suspend();
> -
> - preempt_disable();
> -
> - mm_pin_all();
> - local_irq_disable();
> - preempt_enable();
> -
> - gnttab_suspend();
> -
> - pre_suspend();
> -
> - /*
> - * We'll stop somewhere inside this hypercall. When it returns,
> - * we'll start resuming after the restore.
> - */
> - HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
> -
> - shutting_down = SHUTDOWN_INVALID;
> -
> - post_suspend();
> -
> - gnttab_resume();
> -
> - irq_resume();
> -
> - time_resume();
> -
> - switch_idle_mm();
> -
> - local_irq_enable();
> -
> - xencons_resume();
> -
> - xenbus_resume();
> -
> - smp_resume();
> -
> - return err;
> -}
>
> static int shutdown_process(void *__unused)
> {
> @@ -222,11 +26,13 @@ static int shutdown_process(void *__unus
>
> if ((shutting_down == SHUTDOWN_POWEROFF) ||
> (shutting_down == SHUTDOWN_HALT)) {
> - if (execve("/sbin/poweroff", poweroff_argv, envp) < 0) {
> + if (call_usermodehelper_keys("/sbin/poweroff", poweroff_argv,
> envp, NULL, 0) < 0) {
> +#ifdef CONFIG_XEN
> sys_reboot(LINUX_REBOOT_MAGIC1,
> LINUX_REBOOT_MAGIC2,
> LINUX_REBOOT_CMD_POWER_OFF,
> NULL);
> +#endif /* CONFIG_XEN */
> }
> }
>
> @@ -235,29 +41,21 @@ static int shutdown_process(void *__unus
> return 0;
> }
>
> -static int kthread_create_on_cpu(int (*f)(void *arg),
> - void *arg,
> - const char *name,
> - int cpu)
> -{
> - struct task_struct *p;
> - p = kthread_create(f, arg, name);
> - if (IS_ERR(p))
> - return PTR_ERR(p);
> - kthread_bind(p, cpu);
> - wake_up_process(p);
> - return 0;
> -}
>
> static void __shutdown_handler(void *unused)
> {
> int err;
>
> +#ifdef CONFIG_XEN
> if (shutting_down != SHUTDOWN_SUSPEND)
> err = kernel_thread(shutdown_process, NULL,
> CLONE_FS | CLONE_FILES);
> else
> err = kthread_create_on_cpu(__do_suspend, NULL, "suspend", 0);
> +#else /* !CONFIG_XEN */
> + err = kernel_thread(shutdown_process, NULL,
> + CLONE_FS | CLONE_FILES);
> +#endif /* !CONFIG_XEN */
>
> if (err < 0) {
> printk(KERN_WARNING "Error creating shutdown process (%d): "
> @@ -272,6 +70,8 @@ static void shutdown_handler(struct xenb
> char *str;
> struct xenbus_transaction xbt;
> int err;
> +
> + int cad_pid = 1;
>
> if (shutting_down != SHUTDOWN_INVALID)
> return;
> @@ -298,7 +98,7 @@ static void shutdown_handler(struct xenb
> if (strcmp(str, "poweroff") == 0)
> shutting_down = SHUTDOWN_POWEROFF;
> else if (strcmp(str, "reboot") == 0)
> - ctrl_alt_del();
> + kill_proc(cad_pid, SIGINT, 1);
> else if (strcmp(str, "suspend") == 0)
> shutting_down = SHUTDOWN_SUSPEND;
> else if (strcmp(str, "halt") == 0)
> @@ -378,6 +178,11 @@ static int __init setup_shutdown_event(v
> .notifier_call = setup_shutdown_watcher
> };
> register_xenstore_notifier(&xenstore_notifier);
> +
> + if (!is_initial_xendomain()) {
> + xenbus_write(XBT_NIL, "control", "reboot_module", "installed");
> + }
> +
> return 0;
> }
>
> diff -r 4a320d26fc24 tools/python/xen/xend/image.py
> --- a/tools/python/xen/xend/image.py Thu Oct 26 16:56:16 2006 +0100
> +++ b/tools/python/xen/xend/image.py Fri Oct 27 17:02:19 2006 +0900
> @@ -282,6 +282,7 @@ class HVMImageHandler(ImageHandler):
> log.debug("apic = %d", self.apic)
>
> self.register_shutdown_watch()
> + self.register_reboot_module_watch()
>
> return xc.hvm_build(dom = self.vm.getDomid(),
> image = self.kernel,
> @@ -422,6 +423,7 @@ class HVMImageHandler(ImageHandler):
>
> def destroy(self):
> self.unregister_shutdown_watch();
> + self.unregister_reboot_module_watch();
> if not self.pid:
> return
> os.kill(self.pid, signal.SIGKILL)
> @@ -463,6 +465,39 @@ class HVMImageHandler(ImageHandler):
> vm.refreshShutdown(vm.info)
>
> return 1 # Keep watching
> +
> + def register_reboot_module_watch(self):
> + """ add xen store watch on control/reboot_module """
> + self.rebootModuleWatch = xswatch(self.vm.dompath +
> "/control/reboot_module", \
> + self.hvm_reboot_module)
> + log.debug("hvm reboot module watch registered")
> +
> + def unregister_reboot_module_watch(self):
> + """Remove the watch on the control/reboot_module, if any. Nothrow
> + guarantee."""
> +
> + try:
> + if self.rebootModuleWatch:
> + self.rebootModuleWatch.unwatch()
> + except:
> + log.exception("Unwatching hvm reboot module watch failed.")
> + self.rebootModuleWatch = None
> + log.debug("hvm reboot module watch unregistered")
> +
> + def hvm_reboot_module(self, _):
> + """ watch call back on node control/reboot_module,
> + if node changed, this function will be called
> + """
> + xd = xen.xend.XendDomain.instance()
> + vm = xd.domain_lookup( self.vm.getDomid() )
> +
> + reboot_module_status = vm.readDom('control/reboot_module')
> + log.debug("hvm_reboot_module fired, module status=%s",
> reboot_module_status)
> + if reboot_module_status == 'installed':
> + self.unregister_shutdown_watch()
> +
> + return 1 # Keep watching
> +
>
> class IA64_HVM_ImageHandler(HVMImageHandler):
>
> diff -r 4a320d26fc24 unmodified_drivers/linux-2.6/Makefile
> --- a/unmodified_drivers/linux-2.6/Makefile Thu Oct 26 16:56:16 2006 +0100
> +++ b/unmodified_drivers/linux-2.6/Makefile Fri Oct 27 17:02:19 2006 +0900
> @@ -4,3 +4,4 @@ obj-m += xenbus/
> obj-m += xenbus/
> obj-m += blkfront/
> obj-m += netfront/
> +obj-m += util/
> diff -r 4a320d26fc24 unmodified_drivers/linux-2.6/mkbuildtree
> --- a/unmodified_drivers/linux-2.6/mkbuildtree Thu Oct 26 16:56:16
> 2006 +0100
> +++ b/unmodified_drivers/linux-2.6/mkbuildtree Fri Oct 27 17:02:19
> 2006 +0900
> @@ -22,6 +22,7 @@ ln -sf ${XL}/drivers/xen/core/gnttab.c p
> ln -sf ${XL}/drivers/xen/core/gnttab.c platform-pci
> ln -sf ${XL}/drivers/xen/core/features.c platform-pci
> ln -sf ${XL}/drivers/xen/core/xen_proc.c xenbus
> +ln -sf ${XL}/drivers/xen/core/reboot.c util
>
> mkdir -p include
> mkdir -p include/xen
> diff -r 4a320d26fc24 linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c Fri Oct 27
> 17:02:19 2006 +0900
> @@ -0,0 +1,206 @@
> +#define __KERNEL_SYSCALLS__
> +#include <linux/version.h>
> +#include <linux/kernel.h>
> +#include <linux/mm.h>
> +#include <linux/unistd.h>
> +#include <linux/module.h>
> +#include <linux/reboot.h>
> +#include <linux/sysrq.h>
> +#include <linux/stringify.h>
> +#include <asm/irq.h>
> +#include <asm/mmu_context.h>
> +#include <xen/evtchn.h>
> +#include <asm/hypervisor.h>
> +#include <xen/interface/dom0_ops.h>
> +#include <xen/xenbus.h>
> +#include <linux/cpu.h>
> +#include <linux/kthread.h>
> +#include <xen/gnttab.h>
> +#include <xen/xencons.h>
> +#include <xen/cpu_hotplug.h>
> +#include <xen/reboot.h>
> +
> +#if defined(__i386__) || defined(__x86_64__)
> +
> +/*
> + * Power off function, if any
> + */
> +void (*pm_power_off)(void);
> +EXPORT_SYMBOL(pm_power_off);
> +
> +void machine_emergency_restart(void)
> +{
> + /* We really want to get pending console data out before we die. */
> + xencons_force_flush();
> + HYPERVISOR_shutdown(SHUTDOWN_reboot);
> +}
> +
> +void machine_restart(char * __unused)
> +{
> + machine_emergency_restart();
> +}
> +
> +void machine_halt(void)
> +{
> + machine_power_off();
> +}
> +
> +void machine_power_off(void)
> +{
> + /* We really want to get pending console data out before we die. */
> + xencons_force_flush();
> + if (pm_power_off)
> + pm_power_off();
> + HYPERVISOR_shutdown(SHUTDOWN_poweroff);
> +}
> +
> +int reboot_thru_bios = 0; /* for dmi_scan.c */
> +EXPORT_SYMBOL(machine_restart);
> +EXPORT_SYMBOL(machine_halt);
> +EXPORT_SYMBOL(machine_power_off);
> +
> +#endif /* defined(__i386__) || defined(__x86_64__) */
> +
> +#if defined(__i386__) || defined(__x86_64__)
> +
> +/* Ensure we run on the idle task page tables so that we will
> + switch page tables before running user space. This is needed
> + on architectures with separate kernel and user page tables
> + because the user page table pointer is not saved/restored. */
> +static void switch_idle_mm(void)
> +{
> + struct mm_struct *mm = current->active_mm;
> +
> + if (mm == &init_mm)
> + return;
> +
> + atomic_inc(&init_mm.mm_count);
> + switch_mm(mm, &init_mm, current);
> + current->active_mm = &init_mm;
> + mmdrop(mm);
> +}
> +
> +static void pre_suspend(void)
> +{
> + HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
> + clear_fixmap(FIX_SHARED_INFO);
> +
> + xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
> + xen_start_info->console.domU.mfn =
> + mfn_to_pfn(xen_start_info->console.domU.mfn);
> +}
> +
> +static void post_suspend(void)
> +{
> + int i, j, k, fpp;
> + extern unsigned long max_pfn;
> + extern unsigned long *pfn_to_mfn_frame_list_list;
> + extern unsigned long *pfn_to_mfn_frame_list[];
> +
> + set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
> +
> + HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
> +
> + memset(empty_zero_page, 0, PAGE_SIZE);
> +
> + HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
> + virt_to_mfn(pfn_to_mfn_frame_list_list);
> +
> + fpp = PAGE_SIZE/sizeof(unsigned long);
> + for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
> + if ((j % fpp) == 0) {
> + k++;
> + pfn_to_mfn_frame_list_list[k] =
> + virt_to_mfn(pfn_to_mfn_frame_list[k]);
> + j = 0;
> + }
> + pfn_to_mfn_frame_list[k][j] =
> + virt_to_mfn(&phys_to_machine_mapping[i]);
> + }
> + HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
> +}
> +
> +#else /* !(defined(__i386__) || defined(__x86_64__)) */
> +
> +#define switch_idle_mm() ((void)0)
> +#define mm_pin_all() ((void)0)
> +#define pre_suspend() ((void)0)
> +#define post_suspend() ((void)0)
> +
> +#endif
> +
> +int __do_suspend(void *ignore)
> +{
> + int err;
> +
> + extern void time_resume(void);
> +
> + BUG_ON(smp_processor_id() != 0);
> + BUG_ON(in_interrupt());
> +
> +#if defined(__i386__) || defined(__x86_64__)
> + if (xen_feature(XENFEAT_auto_translated_physmap)) {
> + printk(KERN_WARNING "Cannot suspend in "
> + "auto_translated_physmap mode.\n");
> + return -EOPNOTSUPP;
> + }
> +#endif
> +
> + err = smp_suspend();
> + if (err)
> + return err;
> +
> + xenbus_suspend();
> +
> + preempt_disable();
> +
> + mm_pin_all();
> + local_irq_disable();
> + preempt_enable();
> +
> + gnttab_suspend();
> +
> + pre_suspend();
> +
> + /*
> + * We'll stop somewhere inside this hypercall. When it returns,
> + * we'll start resuming after the restore.
> + */
> + HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
> +
> + shutting_down = SHUTDOWN_INVALID;
> +
> + post_suspend();
> +
> + gnttab_resume();
> +
> + irq_resume();
> +
> + time_resume();
> +
> + switch_idle_mm();
> +
> + local_irq_enable();
> +
> + xencons_resume();
> +
> + xenbus_resume();
> +
> + smp_resume();
> +
> + return err;
> +}
> +
> +int kthread_create_on_cpu(int (*f)(void *arg),
> + void *arg,
> + const char *name,
> + int cpu)
> +{
> + struct task_struct *p;
> + p = kthread_create(f, arg, name);
> + if (IS_ERR(p))
> + return PTR_ERR(p);
> + kthread_bind(p, cpu);
> + wake_up_process(p);
> + return 0;
> +}
> diff -r 4a320d26fc24 linux-2.6-xen-sparse/include/xen/reboot.h
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/linux-2.6-xen-sparse/include/xen/reboot.h Fri Oct 27 17:02:19
> 2006 +0900
> @@ -0,0 +1,19 @@
> +#define SHUTDOWN_INVALID -1
> +#define SHUTDOWN_POWEROFF 0
> +#define SHUTDOWN_SUSPEND 2
> +/* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
> + * report a crash, not be instructed to crash!
> + * HALT is the same as POWEROFF, as far as we're concerned. The tools use
> + * the distinction when we return the reason code to them.
> + */
> +#define SHUTDOWN_HALT 4
> +
> +/******************************************************************************
> + * Stop/pickle callback handling.
> + */
> +
> +/* Ignore multiple shutdown requests. */
> +static int shutting_down = SHUTDOWN_INVALID;
> +
> +int kthread_create_on_cpu(int (*f)(void *), void *, const char *, int);
> +int __do_suspend(void *);
> diff -r 4a320d26fc24 unmodified_drivers/linux-2.6/util/Kbuild
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/unmodified_drivers/linux-2.6/util/Kbuild Fri Oct 27 17:02:19
> 2006 +0900
> @@ -0,0 +1,3 @@
> +include $(M)/overrides.mk
> +
> +obj-m := reboot.o
signature.asc
Description: Digital signature
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|