[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] Avoid race conditions in HPET initialization
Avoid turning on legacy interrupts before hpet_event has been set up. Particularly, the spinlock can be uninitialised at the point at which the interrupt first arrives. Also, fix a memory leak of a cpumask in the unlikely event that hpet_assign_irq() fails. Signed-off-by: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx> --- xen/arch/x86/hpet.c | 59 +++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c index 3a4f7e8..0dedfb7 100644 --- a/xen/arch/x86/hpet.c +++ b/xen/arch/x86/hpet.c @@ -387,6 +387,26 @@ static int __init hpet_assign_irq(struct hpet_event_channel *ch) return 0; } +static void __init hpet_init_channel(struct hpet_event_channel *ch) +{ + u64 hpet_rate = hpet_setup(); + + /* + * The period is a femto seconds value. We need to calculate the scaled + * math multiplication factor for nanosecond to hpet tick conversion. + */ + ch->mult = div_sc((unsigned long)hpet_rate, + 1000000000ul, 32); + ch->shift = 32; + ch->next_event = STIME_MAX; + spin_lock_init(&ch->lock); + ch->event_handler = handle_hpet_broadcast; + + ch->msi.irq = -1; + ch->msi.msi_attrib.maskbit = 1; + ch->msi.msi_attrib.pos = MSI_TYPE_HPET; +} + static void __init hpet_fsb_cap_lookup(void) { u32 id; @@ -423,11 +443,15 @@ static void __init hpet_fsb_cap_lookup(void) break; } + hpet_init_channel(ch); + ch->flags = 0; ch->idx = i; if ( hpet_assign_irq(ch) == 0 ) num_hpets_used++; + else + free_cpumask_var(ch->cpumask); } printk(XENLOG_INFO "HPET: %u timers usable for broadcast (%u total)\n", @@ -553,7 +577,6 @@ void __init hpet_broadcast_init(void) { u64 hpet_rate = hpet_setup(); u32 hpet_id, cfg; - unsigned int i, n; if ( hpet_rate == 0 || hpet_broadcast_is_available() ) return; @@ -565,7 +588,6 @@ void __init hpet_broadcast_init(void) { /* Stop HPET legacy interrupts */ cfg &= ~HPET_CFG_LEGACY; - n = num_hpets_used; } else { @@ -577,11 +599,10 @@ void __init hpet_broadcast_init(void) hpet_events = xzalloc(struct hpet_event_channel); if ( !hpet_events || !zalloc_cpumask_var(&hpet_events->cpumask) ) return; - hpet_events->msi.irq = -1; + hpet_init_channel(hpet_events); /* Start HPET legacy interrupts */ cfg |= HPET_CFG_LEGACY; - n = 1; if ( !force_hpet_broadcast ) pv_rtc_handler = handle_rtc_once; @@ -589,31 +610,13 @@ void __init hpet_broadcast_init(void) hpet_write32(cfg, HPET_CFG); - for ( i = 0; i < n; i++ ) + if ( cfg & HPET_CFG_LEGACY ) { - if ( i == 0 && (cfg & HPET_CFG_LEGACY) ) - { - /* set HPET T0 as oneshot */ - cfg = hpet_read32(HPET_Tn_CFG(0)); - cfg &= ~(HPET_TN_LEVEL | HPET_TN_PERIODIC); - cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; - hpet_write32(cfg, HPET_Tn_CFG(0)); - } - - /* - * The period is a femto seconds value. We need to calculate the scaled - * math multiplication factor for nanosecond to hpet tick conversion. - */ - hpet_events[i].mult = div_sc((unsigned long)hpet_rate, - 1000000000ul, 32); - hpet_events[i].shift = 32; - hpet_events[i].next_event = STIME_MAX; - spin_lock_init(&hpet_events[i].lock); - wmb(); - hpet_events[i].event_handler = handle_hpet_broadcast; - - hpet_events[i].msi.msi_attrib.maskbit = 1; - hpet_events[i].msi.msi_attrib.pos = MSI_TYPE_HPET; + /* set HPET T0 as oneshot */ + cfg = hpet_read32(HPET_Tn_CFG(0)); + cfg &= ~(HPET_TN_LEVEL | HPET_TN_PERIODIC); + cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; + hpet_write32(cfg, HPET_Tn_CFG(0)); } if ( !num_hpets_used ) -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |