debuggers.hg
changeset 21226:11423ce78ee0
acpi sleep: Rearrange code for entering system sleep states.
We cannot freeze_domains in hypercall-continuation context any more,
since that is a softirq context which can interrupt an arbitrary
vcpu. Hence sleeping all vcpus in that context can easily deadlock
(against the vcpu we interrupted). So rearrange the code to
freeze_domains before calling continue_hypercall_on_cpu().
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
We cannot freeze_domains in hypercall-continuation context any more,
since that is a softirq context which can interrupt an arbitrary
vcpu. Hence sleeping all vcpus in that context can easily deadlock
(against the vcpu we interrupted). So rearrange the code to
freeze_domains before calling continue_hypercall_on_cpu().
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Thu Apr 15 11:36:20 2010 +0100 (2010-04-15) |
parents | 85ab727868ea |
children | 9d5ecf79f1b5 |
files | xen/arch/x86/acpi/power.c |
line diff
1.1 --- a/xen/arch/x86/acpi/power.c Thu Apr 15 11:33:39 2010 +0100 1.2 +++ b/xen/arch/x86/acpi/power.c Thu Apr 15 11:36:20 2010 +0100 1.3 @@ -149,15 +149,7 @@ static int enter_state(u32 state) 1.4 int error; 1.5 unsigned long cr4; 1.6 1.7 - if ( (state <= ACPI_STATE_S0) || (state > ACPI_S_STATES_MAX) ) 1.8 - return -EINVAL; 1.9 - 1.10 - if ( !spin_trylock(&pm_lock) ) 1.11 - return -EBUSY; 1.12 - 1.13 - printk(XENLOG_INFO "Preparing system for ACPI S%d state.", state); 1.14 - 1.15 - freeze_domains(); 1.16 + BUG_ON(!spin_is_locked(&pm_lock)); 1.17 1.18 disable_nonboot_cpus(); 1.19 if ( num_online_cpus() != 1 ) 1.20 @@ -246,6 +238,9 @@ static long enter_state_helper(void *dat 1.21 */ 1.22 int acpi_enter_sleep(struct xenpf_enter_acpi_sleep *sleep) 1.23 { 1.24 + int rc; 1.25 + u32 state; 1.26 + 1.27 if ( !IS_PRIV(current->domain) || !acpi_sinfo.pm1a_cnt_blk.address ) 1.28 return -EPERM; 1.29 1.30 @@ -258,14 +253,31 @@ int acpi_enter_sleep(struct xenpf_enter_ 1.31 return -EINVAL; 1.32 } 1.33 1.34 - if ( sleep->flags ) 1.35 + state = sleep->sleep_state; 1.36 + if ( sleep->flags || 1.37 + (state <= ACPI_STATE_S0) || (state > ACPI_S_STATES_MAX) ) 1.38 return -EINVAL; 1.39 1.40 + if ( !spin_trylock(&pm_lock) ) 1.41 + return -EBUSY; 1.42 + 1.43 acpi_sinfo.pm1a_cnt_val = sleep->pm1a_cnt_val; 1.44 acpi_sinfo.pm1b_cnt_val = sleep->pm1b_cnt_val; 1.45 - acpi_sinfo.sleep_state = sleep->sleep_state; 1.46 + acpi_sinfo.sleep_state = state; 1.47 + 1.48 + printk(XENLOG_INFO "Preparing system for ACPI S%d state.", state); 1.49 + 1.50 + freeze_domains(); 1.51 1.52 - return continue_hypercall_on_cpu(0, enter_state_helper, &acpi_sinfo); 1.53 + rc = continue_hypercall_on_cpu(0, enter_state_helper, &acpi_sinfo); 1.54 + if ( rc ) 1.55 + { 1.56 + /* Continuation will not execute: undo our own work so far. */ 1.57 + thaw_domains(); 1.58 + spin_unlock(&pm_lock); 1.59 + } 1.60 + 1.61 + return rc; 1.62 } 1.63 1.64 static int acpi_get_wake_status(void)