aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2012-09-25 08:36:33 +0200
committerJan Beulich <jbeulich@suse.com>2012-09-25 08:36:33 +0200
commit797b603c7e32459c782ec2738fa6a30b4fbbcb83 (patch)
treef40d33af32a9e3ab1fe89f62b2eb937d5df4f400
parent1b33d3acd1a7550b858379f38e01e085dc444d08 (diff)
downloadxen-797b603c7e32459c782ec2738fa6a30b4fbbcb83.tar.gz
xen-797b603c7e32459c782ec2738fa6a30b4fbbcb83.tar.bz2
xen-797b603c7e32459c782ec2738fa6a30b4fbbcb83.zip
x86: fix MWAIT-based idle driver for CPUs without ARAT
lapic_timer_{on,off} need to get initialized in this case. This in turn requires getting HPET broadcast setup to be carried out earlier (and hence preventing double initialization there). Signed-off-by: Jan Beulich <jbeulich@suse.com>
-rw-r--r--xen/arch/x86/acpi/cpu_idle.c42
-rw-r--r--xen/arch/x86/cpu/mwait-idle.c7
-rw-r--r--xen/arch/x86/hpet.c2
-rw-r--r--xen/include/asm-x86/cpuidle.h1
4 files changed, 33 insertions, 19 deletions
diff --git a/xen/arch/x86/acpi/cpu_idle.c b/xen/arch/x86/acpi/cpu_idle.c
index cb3aae7e9c..45eb603242 100644
--- a/xen/arch/x86/acpi/cpu_idle.c
+++ b/xen/arch/x86/acpi/cpu_idle.c
@@ -74,6 +74,29 @@ static void lapic_timer_nop(void) { }
void (*__read_mostly lapic_timer_off)(void);
void (*__read_mostly lapic_timer_on)(void);
+bool_t lapic_timer_init(void)
+{
+ if ( boot_cpu_has(X86_FEATURE_ARAT) )
+ {
+ lapic_timer_off = lapic_timer_nop;
+ lapic_timer_on = lapic_timer_nop;
+ }
+ else if ( hpet_broadcast_is_available() )
+ {
+ lapic_timer_off = hpet_broadcast_enter;
+ lapic_timer_on = hpet_broadcast_exit;
+ }
+ else if ( pit_broadcast_is_available() )
+ {
+ lapic_timer_off = pit_broadcast_enter;
+ lapic_timer_on = pit_broadcast_exit;
+ }
+ else
+ return 0;
+
+ return 1;
+}
+
static uint64_t (*__read_mostly tick_to_ns)(uint64_t) = acpi_pm_tick_to_ns;
void (*__read_mostly pm_idle_save)(void);
@@ -789,25 +812,8 @@ static int check_cx(struct acpi_processor_power *power, xen_processor_cx_t *cx)
if ( local_apic_timer_c2_ok )
break;
case ACPI_STATE_C3:
- if ( boot_cpu_has(X86_FEATURE_ARAT) )
- {
- lapic_timer_off = lapic_timer_nop;
- lapic_timer_on = lapic_timer_nop;
- }
- else if ( hpet_broadcast_is_available() )
- {
- lapic_timer_off = hpet_broadcast_enter;
- lapic_timer_on = hpet_broadcast_exit;
- }
- else if ( pit_broadcast_is_available() )
- {
- lapic_timer_off = pit_broadcast_enter;
- lapic_timer_on = pit_broadcast_exit;
- }
- else
- {
+ if ( !lapic_timer_init() )
return -EINVAL;
- }
/* All the logic here assumes flags.bm_check is same across all CPUs */
if ( bm_check_flag == -1 )
diff --git a/xen/arch/x86/cpu/mwait-idle.c b/xen/arch/x86/cpu/mwait-idle.c
index 5c10fd206d..6a9ca95d33 100644
--- a/xen/arch/x86/cpu/mwait-idle.c
+++ b/xen/arch/x86/cpu/mwait-idle.c
@@ -56,6 +56,7 @@
#include <xen/softirq.h>
#include <xen/trace.h>
#include <asm/cpuidle.h>
+#include <asm/hpet.h>
#include <asm/mwait.h>
#include <asm/msr.h>
#include <acpi/cpufreq/cpufreq.h>
@@ -501,6 +502,12 @@ int __init mwait_idle_init(struct notifier_block *nfb)
err = mwait_idle_probe();
if (!err) {
+ if (!boot_cpu_has(X86_FEATURE_ARAT))
+ hpet_broadcast_init();
+ if (!lapic_timer_init())
+ err = -EINVAL;
+ }
+ if (!err) {
nfb->notifier_call = mwait_idle_cpu_init;
mwait_idle_cpu_init(nfb, CPU_UP_PREPARE, NULL);
diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c
index 1b9fd574e5..45f7abae7d 100644
--- a/xen/arch/x86/hpet.c
+++ b/xen/arch/x86/hpet.c
@@ -495,7 +495,7 @@ void __init hpet_broadcast_init(void)
u32 hpet_id, cfg;
unsigned int i, n;
- if ( hpet_rate == 0 )
+ if ( hpet_rate == 0 || hpet_broadcast_is_available() )
return;
cfg = hpet_read32(HPET_CFG);
diff --git a/xen/include/asm-x86/cpuidle.h b/xen/include/asm-x86/cpuidle.h
index 73edf90efd..ac1dddf069 100644
--- a/xen/include/asm-x86/cpuidle.h
+++ b/xen/include/asm-x86/cpuidle.h
@@ -10,6 +10,7 @@ extern struct acpi_processor_power *processor_powers[];
extern void (*pm_idle_save)(void);
+bool_t lapic_timer_init(void);
extern void (*lapic_timer_off)(void);
extern void (*lapic_timer_on)(void);