[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86: irq ratelimit
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1253088998 -3600 # Node ID 000e038014a524e0581e0d2d4e55b5d7aad49d93 # Parent 7655448090c870ac74ddf855e3e28eeaf56eab6e x86: irq ratelimit 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=xxx. Signed-off-by: Qing He <qing.he@xxxxxxxxx> Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/irq.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ xen/include/xen/irq.h | 6 ++++ 2 files changed, 68 insertions(+) diff -r 7655448090c8 -r 000e038014a5 xen/arch/x86/irq.c --- a/xen/arch/x86/irq.c Wed Sep 16 08:55:23 2009 +0100 +++ b/xen/arch/x86/irq.c Wed Sep 16 09:16:38 2009 +0100 @@ -55,6 +55,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,7 @@ static void init_one_irq_desc(struct irq desc->msi_desc = NULL; spin_lock_init(&desc->lock); cpus_setall(desc->affinity); + INIT_LIST_HEAD(&desc->rl_link); } static void init_one_irq_status(int irq) @@ -469,6 +478,32 @@ asmlinkage void do_IRQ(struct cpu_user_r if ( likely(desc->status & IRQ_GUEST) ) { + if ( irq_ratelimit_timer.function && /* irq rate limiting enabled? */ + unlikely(desc->rl_cnt++ >= irq_ratelimit_threshold) ) + { + s_time_t now = NOW(); + if ( now < (desc->rl_quantum_start + MILLISECS(10)) ) + { + 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; + } + desc->rl_cnt = 0; + desc->rl_quantum_start = now; + } + irq_enter(); tsc_in = tb_init_done ? get_cycles() : 0; __do_IRQ_guest(irq); @@ -511,6 +546,33 @@ 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) +{ + if ( irq_ratelimit_threshold ) + init_timer(&irq_ratelimit_timer, irq_ratelimit_timer_fn, NULL, 0); + return 0; +} +__initcall(irq_ratelimit_init); int request_irq(unsigned int irq, void (*handler)(int, void *, struct cpu_user_regs *), diff -r 7655448090c8 -r 000e038014a5 xen/include/xen/irq.h --- a/xen/include/xen/irq.h Wed Sep 16 08:55:23 2009 +0100 +++ b/xen/include/xen/irq.h Wed Sep 16 09:16:38 2009 +0100 @@ -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-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |