[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] cpuidle: Enable hpet broadcast by default
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1239806845 -3600 # Node ID 573e6673e9e08328762bf58e7c02f8144c109ec2 # Parent 3e64dfebabd7340f5852ad112c858efcebc9cae5 cpuidle: Enable hpet broadcast by default And stop legacy hpet broadcast and limit max C-state to shallower state if RTC interrupts are enabled. Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx> Signed-off-by: Tian Kevin <kevin.tian@xxxxxxxxx> --- xen/arch/x86/acpi/cpu_idle.c | 19 ++++++++++- xen/arch/x86/hpet.c | 71 ++++++++++++++++++++++++++++++++++++++++--- xen/arch/x86/traps.c | 6 +++ xen/include/asm-x86/hpet.h | 1 4 files changed, 91 insertions(+), 6 deletions(-) diff -r 3e64dfebabd7 -r 573e6673e9e0 xen/arch/x86/acpi/cpu_idle.c --- a/xen/arch/x86/acpi/cpu_idle.c Wed Apr 15 15:38:57 2009 +0100 +++ b/xen/arch/x86/acpi/cpu_idle.c Wed Apr 15 15:47:25 2009 +0100 @@ -221,8 +221,8 @@ static void acpi_processor_idle(void) return; } - next_state = power ? cpuidle_current_governor->select(power) : -1; - if ( next_state > 0 ) + if ( max_cstate > 0 && power && + (next_state = cpuidle_current_governor->select(power)) > 0 ) { cx = &power->states[next_state]; if ( power->flags.bm_check && acpi_idle_bm_check() @@ -853,3 +853,18 @@ int pmstat_reset_cx_stat(uint32_t cpuid) return 0; } +void cpuidle_disable_deep_cstate(void) +{ + if ( max_cstate > 1 ) + { + if ( local_apic_timer_c2_ok ) + max_cstate = 2; + else + max_cstate = 1; + } + + mb(); + + hpet_disable_legacy_broadcast(); +} + diff -r 3e64dfebabd7 -r 573e6673e9e0 xen/arch/x86/hpet.c --- a/xen/arch/x86/hpet.c Wed Apr 15 15:38:57 2009 +0100 +++ b/xen/arch/x86/hpet.c Wed Apr 15 15:47:25 2009 +0100 @@ -22,8 +22,10 @@ #define MAX_HPET_NUM 32 -#define HPET_EVT_USED_BIT 2 +#define HPET_EVT_USED_BIT 0 #define HPET_EVT_USED (1 << HPET_EVT_USED_BIT) +#define HPET_EVT_DISABLE_BIT 1 +#define HPET_EVT_DISALBE (1 << HPET_EVT_DISABLE_BIT) struct hpet_event_channel { @@ -53,8 +55,11 @@ unsigned long hpet_address; void msi_compose_msg(struct pci_dev *pdev, int vector, struct msi_msg *msg); -/* force_hpet_broadcast: if true, force using hpet_broadcast to fix lapic stop - issue for deep C state with pit disabled */ +/* + * force_hpet_broadcast: by default legacy hpet broadcast will be stopped + * if RTC interrupts are enabled. Enable this option if want to always enable + * legacy hpet broadcast for deep C state + */ int force_hpet_broadcast; boolean_param("hpetbroadcast", force_hpet_broadcast); @@ -114,6 +119,9 @@ static int reprogram_hpet_evt_channel( int64_t delta; int ret; + if ( ch->flags & HPET_EVT_DISALBE ) + return 0; + if ( unlikely(expire < 0) ) { printk(KERN_DEBUG "reprogram: expire < 0\n"); @@ -482,6 +490,32 @@ static void hpet_detach_channel_share(in static void (*hpet_attach_channel)(int cpu, struct hpet_event_channel *ch); static void (*hpet_detach_channel)(int cpu); + +#include <asm/mc146818rtc.h> +void cpuidle_disable_deep_cstate(void); + +void (*pv_rtc_handler)(unsigned int port, uint8_t value); + +static void handle_rtc_once(unsigned int port, uint8_t value) +{ + static int index; + + if ( port == 0x70 ) + { + index = value; + return; + } + + if ( index != RTC_REG_B ) + return; + + /* RTC Reg B, contain PIE/AIE/UIE */ + if ( value & (RTC_PIE | RTC_AIE | RTC_UIE ) ) + { + cpuidle_disable_deep_cstate(); + pv_rtc_handler = NULL; + } +} void hpet_broadcast_init(void) { @@ -526,8 +560,11 @@ void hpet_broadcast_init(void) return; } + if ( legacy_hpet_event.flags & HPET_EVT_DISALBE ) + return; + hpet_id = hpet_read32(HPET_ID); - if ( !(hpet_id & HPET_ID_LEGSUP) || !force_hpet_broadcast ) + if ( !(hpet_id & HPET_ID_LEGSUP) ) return; /* Start HPET legacy interrupts */ @@ -555,6 +592,32 @@ void hpet_broadcast_init(void) for_each_cpu(i) per_cpu(cpu_bc_channel, i) = &legacy_hpet_event; + + if ( !force_hpet_broadcast ) + pv_rtc_handler = handle_rtc_once; +} + +void hpet_disable_legacy_broadcast(void) +{ + u32 cfg; + + spin_lock_irq(&legacy_hpet_event.lock); + + legacy_hpet_event.flags |= HPET_EVT_DISALBE; + + /* disable HPET T0 */ + cfg = hpet_read32(HPET_T0_CFG); + cfg &= ~HPET_TN_ENABLE; + hpet_write32(cfg, HPET_T0_CFG); + + /* Stop HPET legacy interrupts */ + cfg = hpet_read32(HPET_CFG); + cfg &= ~HPET_CFG_LEGACY; + hpet_write32(cfg, HPET_CFG); + + spin_unlock_irq(&legacy_hpet_event.lock); + + smp_send_event_check_mask(cpu_online_map); } void hpet_broadcast_enter(void) diff -r 3e64dfebabd7 -r 573e6673e9e0 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Wed Apr 15 15:38:57 2009 +0100 +++ b/xen/arch/x86/traps.c Wed Apr 15 15:47:25 2009 +0100 @@ -1551,6 +1551,8 @@ static uint32_t guest_io_read( return data; } +extern void (*pv_rtc_handler)(unsigned int port, uint8_t value); + static void guest_io_write( unsigned int port, unsigned int bytes, uint32_t data, struct vcpu *v, struct cpu_user_regs *regs) @@ -1565,6 +1567,8 @@ static void guest_io_write( outb((uint8_t)data, port); if ( pv_post_outb_hook ) pv_post_outb_hook(port, (uint8_t)data); + if ( ((port == 0x71) || (port == 0x70)) && pv_rtc_handler ) + pv_rtc_handler(port, (uint8_t)data); break; case 2: outw((uint16_t)data, port); @@ -1936,6 +1940,8 @@ static int emulate_privileged_op(struct io_emul(regs); if ( (op_bytes == 1) && pv_post_outb_hook ) pv_post_outb_hook(port, regs->eax); + if ( ((port == 0x71) || (port == 0x70)) && pv_rtc_handler ) + pv_rtc_handler(port, regs->eax); } else { diff -r 3e64dfebabd7 -r 573e6673e9e0 xen/include/asm-x86/hpet.h --- a/xen/include/asm-x86/hpet.h Wed Apr 15 15:38:57 2009 +0100 +++ b/xen/include/asm-x86/hpet.h Wed Apr 15 15:47:25 2009 +0100 @@ -78,5 +78,6 @@ void hpet_broadcast_enter(void); void hpet_broadcast_enter(void); void hpet_broadcast_exit(void); int hpet_broadcast_is_available(void); +void hpet_disable_legacy_broadcast(void); #endif /* __X86_HPET_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |