diff options
-rw-r--r-- | xen/arch/x86/crash.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/hpet.c | 31 | ||||
-rw-r--r-- | xen/arch/x86/smp.c | 2 | ||||
-rw-r--r-- | xen/include/asm-x86/hpet.h | 5 |
4 files changed, 38 insertions, 2 deletions
diff --git a/xen/arch/x86/crash.c b/xen/arch/x86/crash.c index a76f9aca20..2faeb3fd18 100644 --- a/xen/arch/x86/crash.c +++ b/xen/arch/x86/crash.c @@ -25,6 +25,7 @@ #include <public/xen.h> #include <asm/shared.h> #include <asm/hvm/support.h> +#include <asm/hpet.h> static atomic_t waiting_for_crash_ipi; static unsigned int crashing_cpu; @@ -77,6 +78,7 @@ static void nmi_shootdown_cpus(void) __stop_this_cpu(); disable_IO_APIC(); + hpet_disable(); local_irq_enable(); } diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c index ca6a0297a0..e0b8659554 100644 --- a/xen/arch/x86/hpet.c +++ b/xen/arch/x86/hpet.c @@ -722,12 +722,14 @@ int hpet_legacy_irq_tick(void) return 1; } +static u32 *hpet_boot_cfg; + u64 hpet_setup(void) { static u64 hpet_rate; static u32 system_reset_latch; u32 hpet_id, hpet_period, cfg; - int i; + unsigned int i, last; if ( system_reset_latch == system_reset_counter ) return hpet_rate; @@ -753,13 +755,20 @@ u64 hpet_setup(void) return 0; } + last = (hpet_id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT; + hpet_boot_cfg = xmalloc_array(u32, 2 + last); + cfg = hpet_read32(HPET_CFG); + if ( hpet_boot_cfg ) + *hpet_boot_cfg = cfg; cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY); hpet_write32(cfg, HPET_CFG); - for ( i = 0; i <= ((hpet_id >> 8) & 31); i++ ) + for ( i = 0; i <= last; ++i ) { cfg = hpet_read32(HPET_Tn_CFG(i)); + if ( hpet_boot_cfg ) + hpet_boot_cfg[i + 1] = cfg; cfg &= ~HPET_TN_ENABLE; hpet_write32(cfg, HPET_Tn_CFG(i)); } @@ -773,3 +782,21 @@ u64 hpet_setup(void) return hpet_rate; } + +void hpet_disable(void) +{ + unsigned int i; + u32 id; + + if ( !hpet_boot_cfg ) + return; + + hpet_write32(*hpet_boot_cfg & ~HPET_CFG_ENABLE, HPET_CFG); + + id = hpet_read32(HPET_ID); + for ( i = 0; i <= ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT); ++i ) + hpet_write32(hpet_boot_cfg[i + 1], HPET_Tn_CFG(i)); + + if ( *hpet_boot_cfg & HPET_CFG_ENABLE ) + hpet_write32(*hpet_boot_cfg, HPET_CFG); +} diff --git a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c index 61b93a8b26..393e957f8f 100644 --- a/xen/arch/x86/smp.c +++ b/xen/arch/x86/smp.c @@ -19,6 +19,7 @@ #include <asm/mc146818rtc.h> #include <asm/flushtlb.h> #include <asm/hardirq.h> +#include <asm/hpet.h> #include <asm/hvm/support.h> #include <mach_apic.h> @@ -362,6 +363,7 @@ void smp_send_stop(void) local_irq_disable(); __stop_this_cpu(); disable_IO_APIC(); + hpet_disable(); local_irq_enable(); } diff --git a/xen/include/asm-x86/hpet.h b/xen/include/asm-x86/hpet.h index da08880f6c..2f18ba0283 100644 --- a/xen/include/asm-x86/hpet.h +++ b/xen/include/asm-x86/hpet.h @@ -67,6 +67,11 @@ extern unsigned long hpet_address; u64 hpet_setup(void); /* + * Disable HPET hardware: restore it to boot time state. + */ +void hpet_disable(void); + +/* * Callback from legacy timer (PIT channel 0) IRQ handler. * Returns 1 if tick originated from HPET; else 0. */ |