Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:lafenghu
xen
25101-x86-hpet-disable.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 25101-x86-hpet-disable.patch of Package xen
References: bnc#748896 # HG changeset patch # User Jan Beulich <jbeulich@suse.com> # Date 1332854423 -7200 # Node ID f06ff3dfde08ee563970cffba502742249ff5820 # Parent ed48258053aea953afd28b746b53af7b8b30531b x86/hpet: disable before reboot or kexec Linux up to now is not smart enough to properly clear the HPET when it boots, which is particularly a problem when a kdump attempt from running under Xen is being made. Linux itself added code to work around this to its shutdown paths quite some time ago, so let's do something similar in Xen: Save the configuration register settings during boot, and restore them during shutdown. This should cover the majority of cases where the secondary kernel might not come up because timer interrupts don't work. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org> --- a/xen/arch/x86/crash.c +++ b/xen/arch/x86/crash.c @@ -94,6 +94,7 @@ static void nmi_shootdown_cpus(void) x2apic_enabled = (current_local_apic_mode() == APIC_MODE_X2APIC); disable_IO_APIC(); + hpet_disable(); } void machine_crash_shutdown(void) --- a/xen/arch/x86/hpet.c +++ b/xen/arch/x86/hpet.c @@ -721,12 +721,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; @@ -752,13 +754,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)); } @@ -772,3 +781,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); +} --- 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> @@ -373,6 +374,7 @@ void smp_send_stop(void) local_irq_disable(); __stop_this_cpu(); disable_IO_APIC(); + hpet_disable(); local_irq_enable(); } --- a/xen/include/asm-x86/hpet.h +++ b/xen/include/asm-x86/hpet.h @@ -68,6 +68,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. */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor