|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] Avoid race conditions in HPET initialization
On 03/01/14 13:15, Frediano Ziglio wrote:
> 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>
Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
For reference, this was the underlying issue behind my patch "[Patch]
xen/spinlock: Improvements to check_lock()", Message ID
"1387816747-21470-1-git-send-email-andrew.cooper3@xxxxxxxxxx"
The hpet code was receiving a legacy interrupt between enabling
interrupts and initialising the spinlock, and check_lock() was mistaking
the 0 in lock->debug.irq_safe for "not IRQ-safe".
~Andrew
> ---
> 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 )
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |