All of lore.kernel.org
 help / color / mirror / Atom feed
From: Qing He <qing.he@intel.com>
To: Keir Fraser <keir.fraser@eu.citrix.com>
Cc: "xen-devel@lists.xensource.com" <xen-devel@lists.xensource.com>
Subject: [PATCH] irq ratelimit
Date: Tue, 15 Sep 2009 21:10:18 +0800	[thread overview]
Message-ID: <20090915131018.GA6283@ub-qhe2> (raw)
In-Reply-To: <C6CD33EC.14482%keir.fraser@eu.citrix.com>

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@intel.com>

---
 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__)

  parent reply	other threads:[~2009-09-15 13:10 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-09-09  8:48 [RFC] irq rate limit Qing He
2009-09-09  8:48 ` Keir Fraser
2009-09-09  9:07   ` Qing He
2009-09-09  9:29     ` Keir Fraser
2009-09-10  9:05       ` Qing He
2009-09-15 13:10       ` Qing He [this message]
2009-09-16  8:17         ` [PATCH] irq ratelimit Keir Fraser
2009-09-09 14:12 ` [RFC] irq rate limit Konrad Rzeszutek Wilk
2009-09-10  9:17   ` Qing He

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090915131018.GA6283@ub-qhe2 \
    --to=qing.he@intel.com \
    --cc=keir.fraser@eu.citrix.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.