mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
bitkeeper revision 1.1159.17.21 (411baa1dkWXzaVHGnr6yk4SeGTJAHA)
Merge 2.4/2.6 shutdown/suspend control message handling code.
This commit is contained in:
1 parent
34948bea5a
commit
fa6b5eb32b
4 files changed
+222
-174
No files matched your search
@@ -1184,173 +1184,3 @@ void __init cpu_init (void)
|
||||
current->used_math = 0;
|
||||
stts();
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Stop/pickle callback handling.
|
||||
*/
|
||||
|
||||
#include <asm/suspend.h>
|
||||
|
||||
/* Ignore multiple shutdown requests. */
|
||||
static int shutting_down = -1;
|
||||
|
||||
static void __do_suspend(void)
|
||||
{
|
||||
int i,j;
|
||||
/* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
|
||||
extern void blkdev_suspend(void);
|
||||
extern void blkdev_resume(void);
|
||||
extern void netif_suspend(void);
|
||||
extern void netif_resume(void);
|
||||
extern void time_suspend(void);
|
||||
extern void time_resume(void);
|
||||
|
||||
suspend_record_t *suspend_record = NULL;
|
||||
|
||||
if ( (suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL))
|
||||
== NULL )
|
||||
goto out;
|
||||
|
||||
suspend_record->nr_pfns = max_pfn; /* final number of pfns */
|
||||
|
||||
__cli();
|
||||
|
||||
netif_suspend();
|
||||
|
||||
blkdev_suspend();
|
||||
|
||||
time_suspend();
|
||||
|
||||
ctrl_if_suspend();
|
||||
|
||||
irq_suspend();
|
||||
|
||||
HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
|
||||
clear_fixmap(FIX_SHARED_INFO);
|
||||
|
||||
memcpy(&suspend_record->resume_info, &start_info, sizeof(start_info));
|
||||
|
||||
HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT);
|
||||
|
||||
shutting_down = -1;
|
||||
|
||||
memcpy(&start_info, &suspend_record->resume_info, sizeof(start_info));
|
||||
|
||||
set_fixmap(FIX_SHARED_INFO, start_info.shared_info);
|
||||
|
||||
HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
|
||||
|
||||
memset(empty_zero_page, 0, PAGE_SIZE);
|
||||
|
||||
for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
|
||||
{
|
||||
pfn_to_mfn_frame_list[j] =
|
||||
virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT;
|
||||
}
|
||||
HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
|
||||
virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT;
|
||||
|
||||
|
||||
irq_resume();
|
||||
|
||||
ctrl_if_resume();
|
||||
|
||||
time_resume();
|
||||
|
||||
blkdev_resume();
|
||||
|
||||
netif_resume();
|
||||
|
||||
__sti();
|
||||
|
||||
|
||||
out:
|
||||
if ( suspend_record != NULL )
|
||||
free_page((unsigned long)suspend_record);
|
||||
}
|
||||
|
||||
static int shutdown_process(void *__unused)
|
||||
{
|
||||
static char *envp[] = { "HOME=/", "TERM=linux",
|
||||
"PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
|
||||
static char *restart_argv[] = { "/sbin/shutdown", "-r", "now", NULL };
|
||||
static char *poweroff_argv[] = { "/sbin/halt", "-p", NULL };
|
||||
|
||||
extern asmlinkage long sys_reboot(int magic1, int magic2,
|
||||
unsigned int cmd, void *arg);
|
||||
|
||||
daemonize();
|
||||
|
||||
switch ( shutting_down )
|
||||
{
|
||||
case CMSG_SHUTDOWN_POWEROFF:
|
||||
if ( execve("/sbin/halt", poweroff_argv, envp) < 0 )
|
||||
{
|
||||
sys_reboot(LINUX_REBOOT_MAGIC1,
|
||||
LINUX_REBOOT_MAGIC2,
|
||||
LINUX_REBOOT_CMD_POWER_OFF,
|
||||
NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMSG_SHUTDOWN_REBOOT:
|
||||
if ( execve("/sbin/shutdown", restart_argv, envp) < 0 )
|
||||
{
|
||||
sys_reboot(LINUX_REBOOT_MAGIC1,
|
||||
LINUX_REBOOT_MAGIC2,
|
||||
LINUX_REBOOT_CMD_RESTART,
|
||||
NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __shutdown_handler(void *unused)
|
||||
{
|
||||
int err;
|
||||
|
||||
if ( shutting_down != CMSG_SHUTDOWN_SUSPEND )
|
||||
{
|
||||
err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES);
|
||||
if ( err < 0 )
|
||||
printk(KERN_ALERT "Error creating shutdown process!\n");
|
||||
else
|
||||
shutting_down = -1; /* could try again */
|
||||
}
|
||||
else
|
||||
{
|
||||
__do_suspend();
|
||||
}
|
||||
}
|
||||
|
||||
static void shutdown_handler(ctrl_msg_t *msg, unsigned long id)
|
||||
{
|
||||
static struct tq_struct shutdown_tq;
|
||||
|
||||
if ( (shutting_down == -1) &&
|
||||
((msg->subtype == CMSG_SHUTDOWN_POWEROFF) ||
|
||||
(msg->subtype == CMSG_SHUTDOWN_REBOOT) ||
|
||||
(msg->subtype == CMSG_SHUTDOWN_SUSPEND)) )
|
||||
{
|
||||
shutting_down = msg->subtype;
|
||||
shutdown_tq.routine = __shutdown_handler;
|
||||
schedule_task(&shutdown_tq);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("Ignore spurious shutdown request\n");
|
||||
}
|
||||
|
||||
ctrl_if_send_response(msg);
|
||||
}
|
||||
|
||||
static int __init setup_shutdown_event(void)
|
||||
{
|
||||
ctrl_if_register_receiver(CMSG_SHUTDOWN, shutdown_handler, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(setup_shutdown_event);
|
||||
@@ -510,7 +510,7 @@ unsigned long get_cmos_time(void)
|
||||
|
||||
static long clock_cmos_diff;
|
||||
|
||||
static int time_suspend(struct sys_device *dev, u32 state)
|
||||
static int __time_suspend(struct sys_device *dev, u32 state)
|
||||
{
|
||||
/*
|
||||
* Estimate time zone so that set_time can update the clock
|
||||
@@ -520,7 +520,7 @@ static int time_suspend(struct sys_device *dev, u32 state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int time_resume(struct sys_device *dev)
|
||||
static int __time_resume(struct sys_device *dev)
|
||||
{
|
||||
unsigned long sec = get_cmos_time() + clock_cmos_diff;
|
||||
write_seqlock_irq(&xtime_lock);
|
||||
@@ -531,8 +531,8 @@ static int time_resume(struct sys_device *dev)
|
||||
}
|
||||
|
||||
static struct sysdev_class pit_sysclass = {
|
||||
.resume = time_resume,
|
||||
.suspend = time_suspend,
|
||||
.resume = __time_resume,
|
||||
.suspend = __time_suspend,
|
||||
set_kset_name("pit"),
|
||||
};
|
||||
|
||||
@@ -647,6 +647,25 @@ int set_timeout_timer(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void time_suspend(void)
|
||||
{
|
||||
}
|
||||
|
||||
void time_resume(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
write_lock_irqsave(&xtime_lock, flags);
|
||||
/* Get timebases for new environment. */
|
||||
__get_time_values_from_xen();
|
||||
/* Reset our own concept of passage of system time. */
|
||||
processed_system_time = shadow_system_time;
|
||||
/* Accept a warp in UTC (wall-clock) time. */
|
||||
last_seen_tv.tv_sec = 0;
|
||||
/* Make sure we resync UTC time with Xen on next timer interrupt. */
|
||||
last_update_from_xen = 0;
|
||||
write_unlock_irqrestore(&xtime_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* /proc/sys/xen: This really belongs in another file. It can stay here for
|
||||
* now however.
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
|
||||
#define __KERNEL_SYSCALLS__
|
||||
static int errno;
|
||||
#include <linux/errno.h>
|
||||
#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 <asm/irq.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm-xen/ctrl_if.h>
|
||||
#include <asm-xen/hypervisor.h>
|
||||
#include <asm-xen/hypervisor-ifs/dom0_ops.h>
|
||||
#include <asm-xen/suspend.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
int reboot_thru_bios = 0; /* for dmi_scan.c */
|
||||
@@ -40,3 +51,188 @@ void machine_power_off(void)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
EXPORT_SYMBOL(machine_power_off);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Stop/pickle callback handling.
|
||||
*/
|
||||
|
||||
#include <asm/suspend.h>
|
||||
|
||||
/* Ignore multiple shutdown requests. */
|
||||
static int shutting_down = -1;
|
||||
|
||||
static void __do_suspend(void)
|
||||
{
|
||||
int i,j;
|
||||
/* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
|
||||
extern void blkdev_suspend(void);
|
||||
extern void blkdev_resume(void);
|
||||
extern void netif_suspend(void);
|
||||
extern void netif_resume(void);
|
||||
extern void time_suspend(void);
|
||||
extern void time_resume(void);
|
||||
extern unsigned long max_pfn;
|
||||
extern unsigned long *pfn_to_mfn_frame_list;
|
||||
|
||||
suspend_record_t *suspend_record = NULL;
|
||||
|
||||
if ( (suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL))
|
||||
== NULL )
|
||||
goto out;
|
||||
|
||||
suspend_record->nr_pfns = max_pfn; /* final number of pfns */
|
||||
|
||||
__cli();
|
||||
|
||||
netif_suspend();
|
||||
|
||||
blkdev_suspend();
|
||||
|
||||
time_suspend();
|
||||
|
||||
ctrl_if_suspend();
|
||||
|
||||
irq_suspend();
|
||||
|
||||
HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
|
||||
clear_fixmap(FIX_SHARED_INFO);
|
||||
|
||||
memcpy(&suspend_record->resume_info, &start_info, sizeof(start_info));
|
||||
|
||||
HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT);
|
||||
|
||||
shutting_down = -1;
|
||||
|
||||
memcpy(&start_info, &suspend_record->resume_info, sizeof(start_info));
|
||||
|
||||
set_fixmap(FIX_SHARED_INFO, start_info.shared_info);
|
||||
|
||||
HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
|
||||
|
||||
memset(empty_zero_page, 0, PAGE_SIZE);
|
||||
|
||||
for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
|
||||
{
|
||||
pfn_to_mfn_frame_list[j] =
|
||||
virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT;
|
||||
}
|
||||
HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
|
||||
virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT;
|
||||
|
||||
|
||||
irq_resume();
|
||||
|
||||
ctrl_if_resume();
|
||||
|
||||
time_resume();
|
||||
|
||||
blkdev_resume();
|
||||
|
||||
netif_resume();
|
||||
|
||||
__sti();
|
||||
|
||||
|
||||
out:
|
||||
if ( suspend_record != NULL )
|
||||
free_page((unsigned long)suspend_record);
|
||||
}
|
||||
|
||||
static int shutdown_process(void *__unused)
|
||||
{
|
||||
static char *envp[] = { "HOME=/", "TERM=linux",
|
||||
"PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
|
||||
static char *restart_argv[] = { "/sbin/shutdown", "-r", "now", NULL };
|
||||
static char *poweroff_argv[] = { "/sbin/halt", "-p", NULL };
|
||||
|
||||
extern asmlinkage long sys_reboot(int magic1, int magic2,
|
||||
unsigned int cmd, void *arg);
|
||||
|
||||
daemonize(
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
"shutdown"
|
||||
#endif
|
||||
);
|
||||
|
||||
switch ( shutting_down )
|
||||
{
|
||||
case CMSG_SHUTDOWN_POWEROFF:
|
||||
if ( execve("/sbin/halt", poweroff_argv, envp) < 0 )
|
||||
{
|
||||
sys_reboot(LINUX_REBOOT_MAGIC1,
|
||||
LINUX_REBOOT_MAGIC2,
|
||||
LINUX_REBOOT_CMD_POWER_OFF,
|
||||
NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMSG_SHUTDOWN_REBOOT:
|
||||
if ( execve("/sbin/shutdown", restart_argv, envp) < 0 )
|
||||
{
|
||||
sys_reboot(LINUX_REBOOT_MAGIC1,
|
||||
LINUX_REBOOT_MAGIC2,
|
||||
LINUX_REBOOT_CMD_RESTART,
|
||||
NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
shutting_down = -1; /* could try again */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __shutdown_handler(void *unused)
|
||||
{
|
||||
int err;
|
||||
|
||||
if ( shutting_down != CMSG_SHUTDOWN_SUSPEND )
|
||||
{
|
||||
err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES);
|
||||
if ( err < 0 )
|
||||
printk(KERN_ALERT "Error creating shutdown process!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
__do_suspend();
|
||||
}
|
||||
}
|
||||
|
||||
static void shutdown_handler(ctrl_msg_t *msg, unsigned long id)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
|
||||
#else
|
||||
static struct tq_struct shutdown_tq;
|
||||
#endif
|
||||
|
||||
if ( (shutting_down == -1) &&
|
||||
((msg->subtype == CMSG_SHUTDOWN_POWEROFF) ||
|
||||
(msg->subtype == CMSG_SHUTDOWN_REBOOT) ||
|
||||
(msg->subtype == CMSG_SHUTDOWN_SUSPEND)) )
|
||||
{
|
||||
shutting_down = msg->subtype;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
schedule_work(&shutdown_work);
|
||||
#else
|
||||
shutdown_tq.routine = __shutdown_handler;
|
||||
schedule_task(&shutdown_tq);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("Ignore spurious shutdown request\n");
|
||||
}
|
||||
|
||||
ctrl_if_send_response(msg);
|
||||
}
|
||||
|
||||
static int __init setup_shutdown_event(void)
|
||||
{
|
||||
ctrl_if_register_receiver(CMSG_SHUTDOWN, shutdown_handler, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(setup_shutdown_event);
|
||||
@@ -140,6 +140,9 @@ extern int bind_virq_to_irq(int virq);
|
||||
extern void unbind_virq_from_irq(int virq);
|
||||
extern int bind_evtchn_to_irq(int evtchn);
|
||||
extern void unbind_evtchn_from_irq(int evtchn);
|
||||
|
||||
extern void irq_suspend(void);
|
||||
extern void irq_resume(void);
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_IRQ_VECTORS_H */
|
||||