[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] Re: [PATCH] irq ratelimit



Applied as c/s 20214, with some changes. Please take a look.

 -- Keir

On 15/09/2009 14:10, "Qing He" <qing.he@xxxxxxxxx> wrote:

> This patch adds the feature of irq ratelimit. It temporarily masks
> the interrupt (guest) if too many irqs are observed in a short
> period (irq storm), to ensure responsiveness of Xen and other guests.
> 
> As for now, the threshold can be adjusted at boot time using command-
> line option irq_ratelimit=.
> 
> Signed-off-by: Qing He <qing.he@xxxxxxxxx>
> 
> ---
>  arch/x86/irq.c    |   64
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/xen/irq.h |    6 +++++
>  2 files changed, 70 insertions(+)
> 
> diff -r 8f81bdd57afe xen/arch/x86/irq.c
> --- a/xen/arch/x86/irq.c Thu Sep 03 09:51:37 2009 +0100
> +++ b/xen/arch/x86/irq.c Tue Sep 15 18:16:38 2009 +0800
> @@ -54,6 +54,14 @@ DEFINE_PER_CPU(vector_irq_t, vector_irq)
>  };
>  
>  DEFINE_PER_CPU(struct cpu_user_regs *, __irq_regs);
> +
> +static LIST_HEAD(irq_ratelimit_list);
> +static DEFINE_SPINLOCK(irq_ratelimit_lock);
> +static struct timer irq_ratelimit_timer;
> +
> +/* irq_ratelimit: the max irq rate allowed in every 10ms, set 0 to disable */
> +unsigned int __read_mostly irq_ratelimit_threshold = 10000;
> +integer_param("irq_ratelimit", irq_ratelimit_threshold);
>  
>  /* Must be called when irq disabled */
>  void lock_vector_lock(void)
> @@ -241,6 +249,10 @@ static void init_one_irq_desc(struct irq
>      desc->msi_desc = NULL;
>      spin_lock_init(&desc->lock);
>      cpus_setall(desc->affinity);
> +
> +    desc->rl_quantum_start = NOW();
> +    desc->rl_cnt = 0;
> +    INIT_LIST_HEAD(&desc->rl_link);
>  }
>  
>  static void init_one_irq_status(int irq)
> @@ -469,6 +481,29 @@ asmlinkage void do_IRQ(struct cpu_user_r
>  
>      if ( likely(desc->status & IRQ_GUEST) )
>      {
> +        s_time_t now = NOW();
> +        if ( now > (desc->rl_quantum_start + MILLISECS(10)) ) {
> +            desc->rl_cnt = 0;
> +            desc->rl_quantum_start = now;
> +        }
> +        if ( unlikely(desc->rl_cnt++ >= irq_ratelimit_threshold) ) {
> +            desc->handler->disable(irq);
> +            /*
> +             * If handler->disable doesn't actually mask the interrupt,
> +             * a disabled irq still can fire. This check also avoids
> +             * possible deadlocks if ratelimit_timer_fn runs at the
> +             * same time.
> +             */
> +            if ( likely(list_empty(&desc->rl_link)) ) {
> +                spin_lock(&irq_ratelimit_lock);
> +                if ( list_empty(&irq_ratelimit_list) )
> +                    set_timer(&irq_ratelimit_timer, now + MILLISECS(10));
> +                list_add(&desc->rl_link, &irq_ratelimit_list);
> +                spin_unlock(&irq_ratelimit_lock);
> +            }
> +            goto out;
> +        }
> +
>          irq_enter();
>          tsc_in = tb_init_done ? get_cycles() : 0;
>          __do_IRQ_guest(irq);
> @@ -511,6 +546,35 @@ asmlinkage void do_IRQ(struct cpu_user_r
>      spin_unlock(&desc->lock);
>      set_irq_regs(old_regs);
>  }
> +
> +static void irq_ratelimit_timer_fn(void *data)
> +{
> +    struct irq_desc *desc, *tmp;
> +    unsigned long flags;
> +
> +    spin_lock_irqsave(&irq_ratelimit_lock, flags);
> +
> +    list_for_each_entry_safe(desc, tmp, &irq_ratelimit_list, rl_link) {
> +        spin_lock(&desc->lock);
> +        desc->handler->enable(desc->irq);
> +        list_del(&desc->rl_link);
> +        INIT_LIST_HEAD(&desc->rl_link);
> +        spin_unlock(&desc->lock);
> +    }
> +
> +    spin_unlock_irqrestore(&irq_ratelimit_lock, flags);
> +}
> +
> +static int __init irq_ratelimit_init(void)
> +{
> +    init_timer(&irq_ratelimit_timer, irq_ratelimit_timer_fn, NULL, 0);
> +
> +    if (irq_ratelimit_threshold == 0)
> +        irq_ratelimit_threshold = ~0U;
> +
> +    return 0;
> +}
> +__initcall(irq_ratelimit_init);
>  
>  int request_irq(unsigned int irq,
>          void (*handler)(int, void *, struct cpu_user_regs *),
> diff -r 8f81bdd57afe xen/include/xen/irq.h
> --- a/xen/include/xen/irq.h Thu Sep 03 09:51:37 2009 +0100
> +++ b/xen/include/xen/irq.h Tue Sep 15 18:16:38 2009 +0800
> @@ -4,6 +4,7 @@
>  #include <xen/config.h>
>  #include <xen/cpumask.h>
>  #include <xen/spinlock.h>
> +#include <xen/time.h>
>  #include <asm/regs.h>
>  #include <asm/hardirq.h>
>  
> @@ -74,6 +75,11 @@ typedef struct irq_desc {
>      int irq;
>      spinlock_t lock;
>      cpumask_t affinity;
> +
> +    /* irq ratelimit */
> +    s_time_t rl_quantum_start;
> +    unsigned int rl_cnt;
> +    struct list_head rl_link;
>  } __cacheline_aligned irq_desc_t;
>  
>  #if defined(__ia64__)



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.