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
|