[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] xm reboot/shutdown/sysrq to HVM domain



Hi,

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
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.