Tetsu Yamamoto
2006-Oct-06 07:06 UTC
[Xen-devel] [PATCH] xm reboot/shutdown/sysrq to HVM domain
Hi, 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. Usage: 1. Build modules in unmodifiled_drivers/linux-2.6 2. Start HVM domain and load modules on the guest Linux. # insmod xen-platform-pci.ko # insmod xenbus.ko # insmod reboot.ko 3. Execute xm reboot/shutdown/sysrq to HVM domain. Regards, Tetsu Yamamoto Signed-off-by: Tetsu Yamamoto <yamamoto.tetsu@jp.fujitsu.com> _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Steven Smith
2006-Oct-06 09:59 UTC
Re: [Xen-devel] [PATCH] xm reboot/shutdown/sysrq to HVM domain
> 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? -- 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? -- 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. -- Because of the way mkbuildtree works, you''re going to create symlinks from unmodified-drivers to all of the files in linux-2.6-xen-sparse/drivers/core, rather than just to reboot.c. It''s a trivial aesthetic issue, but it''d be nice not to create lots of useless symlinks. Apart from that, it looks pretty reasonable. Steven. _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Tetsu Yamamoto
2006-Oct-10 07:43 UTC
Re: [Xen-devel] [PATCH] xm reboot/shutdown/sysrq to HVM domain
Hi Steven, Thank you for your comments. 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.> -- 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.> -- 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.> -- Because of the way mkbuildtree works, you''re going to create > symlinks from unmodified-drivers to all of the files in > linux-2.6-xen-sparse/drivers/core, rather than just to reboot.c. > It''s a trivial aesthetic issue, but it''d be nice not to create lots > of useless symlinks.The modified patch is attached. Regards, Tetsu Yamamoto Signed-off-by: Tetsu Yamamoto <yamamoto.tetsu@jp.fujitsu.com>> > Apart from that, it looks pretty reasonable. > > Steven._______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Tetsu Yamamoto
2006-Oct-18 09:52 UTC
Re: [Xen-devel] [PATCH] xm reboot/shutdown/sysrq to HVM domain
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@jp.fujitsu.com> 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._______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Tetsu Yamamoto
2006-Oct-27 09:54 UTC
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@jp.fujitsu.com> 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@jp.fujitsu.com> > > 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@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Steven Smith
2006-Oct-31 20:15 UTC
Re: [Xen-devel] [PATCH] xm reboot/shutdown/sysrq to HVM domain
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@jp.fujitsu.com> > > 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@jp.fujitsu.com> > > > > 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@lists.xensource.com > > 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@lists.xensource.com http://lists.xensource.com/xen-devel