Update the number of vectors assigned on each CPU during vector allocation/free process. This is to prepare for the vector spreading work that, we can find out the CPU with least vectors assigned.
Cc: Thomas Gleixner <t...@linutronix.de> Cc: Ingo Molnar <mi...@redhat.com> Cc: "H. Peter Anvin" <h...@zytor.com> Cc: "Rafael J. Wysocki" <r...@rjwysocki.net> Cc: Len Brown <l...@kernel.org> Cc: Dan Williams <dan.j.willi...@intel.com> Signed-off-by: Chen Yu <yu.c.c...@intel.com> --- arch/x86/include/asm/hw_irq.h | 8 ++++++++ arch/x86/kernel/apic/vector.c | 45 ++++++++++++++++++++++++++++++++++++++++++- arch/x86/kernel/irq.c | 5 ++++- arch/x86/kernel/irqinit.c | 1 + arch/x86/lguest/boot.c | 1 + 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index b2243fe..d1b3c61 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h @@ -151,6 +151,10 @@ extern struct irq_cfg *irqd_cfg(struct irq_data *irq_data); extern void lock_vector_lock(void); extern void unlock_vector_lock(void); extern void setup_vector_irq(int cpu); +extern void inc_vector_alloc(const struct cpumask *mask, + int count); +extern void dec_vector_alloc(const struct cpumask *mask, + int count); #ifdef CONFIG_SMP extern void send_cleanup_vector(struct irq_cfg *); extern void irq_complete_move(struct irq_cfg *cfg); @@ -163,6 +167,10 @@ extern void apic_ack_edge(struct irq_data *data); #else /* CONFIG_X86_LOCAL_APIC */ static inline void lock_vector_lock(void) {} static inline void unlock_vector_lock(void) {} +static inline void inc_vector_alloc(const struct cpumask *mask, + int count) {} +static inline void dec_vector_alloc(const struct cpumask *mask, + int count) {} #endif /* CONFIG_X86_LOCAL_APIC */ /* Statistics */ diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 2ce1021..4ff84c0 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -50,6 +50,36 @@ void unlock_vector_lock(void) raw_spin_unlock(&vector_lock); } +static void update_vectors_alloc(const struct cpumask *mask, + int count, bool add) +{ + int cpu; + + for_each_cpu(cpu, mask) { + int cur_alloc = per_cpu(vector_irq, cpu).alloc; + + /* Update the number of vectors assigned on this CPU. */ + if (add && (cur_alloc + count <= NR_VECTORS)) + per_cpu(vector_irq, cpu).alloc += count; + else if (!add && cur_alloc >= count) + per_cpu(vector_irq, cpu).alloc -= count; + else + continue; + } +} + +void inc_vector_alloc(const struct cpumask *mask, + int count) +{ + update_vectors_alloc(mask, count, true); +} + +void dec_vector_alloc(const struct cpumask *mask, + int count) +{ + update_vectors_alloc(mask, count, false); +} + static struct apic_chip_data *apic_chip_data(struct irq_data *irq_data) { if (!irq_data) @@ -191,6 +221,7 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d, for_each_cpu(new_cpu, vector_searchmask) per_cpu(vector_irq, new_cpu).desc[vector] = irq_to_desc(irq); + inc_vector_alloc(vector_searchmask, 1); goto update; next_cpu: @@ -263,6 +294,7 @@ static void clear_irq_vector(int irq, struct apic_chip_data *data) { struct irq_desc *desc; int cpu, vector; + struct cpumask mask; if (!data->cfg.vector) return; @@ -271,6 +303,9 @@ static void clear_irq_vector(int irq, struct apic_chip_data *data) for_each_cpu_and(cpu, data->domain, cpu_online_mask) per_cpu(vector_irq, cpu).desc[vector] = VECTOR_UNUSED; + cpumask_and(&mask, data->domain, cpu_online_mask); + dec_vector_alloc(&mask, 1); + data->cfg.vector = 0; cpumask_clear(data->domain); @@ -289,6 +324,7 @@ static void clear_irq_vector(int irq, struct apic_chip_data *data) if (per_cpu(vector_irq, cpu).desc[vector] != desc) continue; per_cpu(vector_irq, cpu).desc[vector] = VECTOR_UNUSED; + dec_vector_alloc(cpumask_of(cpu), 1); break; } } @@ -483,6 +519,7 @@ static void __setup_vector_irq(int cpu) continue; vector = data->cfg.vector; per_cpu(vector_irq, cpu).desc[vector] = desc; + inc_vector_alloc(cpumask_of(cpu), 1); } /* Mark the free vectors */ for (vector = 0; vector < NR_VECTORS; ++vector) { @@ -491,8 +528,10 @@ static void __setup_vector_irq(int cpu) continue; data = apic_chip_data(irq_desc_get_irq_data(desc)); - if (!cpumask_test_cpu(cpu, data->domain)) + if (!cpumask_test_cpu(cpu, data->domain)) { per_cpu(vector_irq, cpu).desc[vector] = VECTOR_UNUSED; + dec_vector_alloc(cpumask_of(cpu), 1); + } } } @@ -514,6 +553,7 @@ void setup_vector_irq(int cpu) for (irq = 0; irq < nr_legacy_irqs(); irq++) per_cpu(vector_irq, cpu).desc[ISA_IRQ_VECTOR(irq)] = irq_to_desc(irq); + inc_vector_alloc(cpumask_of(cpu), irq); __setup_vector_irq(cpu); } @@ -649,6 +689,7 @@ asmlinkage __visible void __irq_entry smp_irq_move_cleanup_interrupt(void) goto unlock; } __this_cpu_write(vector_irq.desc[vector], VECTOR_UNUSED); + dec_vector_alloc(cpumask_of(me), 1); cpumask_clear_cpu(me, data->old_domain); unlock: raw_spin_unlock(&desc->lock); @@ -784,6 +825,8 @@ void irq_force_complete_move(struct irq_desc *desc) for_each_cpu(cpu, data->old_domain) per_cpu(vector_irq, cpu).desc[cfg->old_vector] = VECTOR_UNUSED; + dec_vector_alloc(data->old_domain, 1); + /* Cleanup the left overs of the (half finished) move */ cpumask_clear(data->old_domain); data->move_in_progress = 0; diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index ae11e86..67c01b8 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -250,6 +250,7 @@ __visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs) vector); } else { __this_cpu_write(vector_irq.desc[vector], VECTOR_UNUSED); + inc_vector_alloc(cpumask_of(smp_processor_id()), 1); } } @@ -491,8 +492,10 @@ void fixup_irqs(void) } raw_spin_unlock(&desc->lock); } - if (__this_cpu_read(vector_irq.desc[vector]) != VECTOR_RETRIGGERED) + if (__this_cpu_read(vector_irq.desc[vector]) != VECTOR_RETRIGGERED) { __this_cpu_write(vector_irq.desc[vector], VECTOR_UNUSED); + dec_vector_alloc(cpumask_of(smp_processor_id()), 1); + } } } #endif diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 734b54f..dd618c1 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c @@ -97,6 +97,7 @@ void __init init_IRQ(void) for (i = 0; i < nr_legacy_irqs(); i++) per_cpu(vector_irq, 0).desc[ISA_IRQ_VECTOR(i)] = irq_to_desc(i); + inc_vector_alloc(cpumask_of(1), i); x86_init.irqs.intr_init(); } diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index e80758a..0696354 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -847,6 +847,7 @@ static int lguest_setup_irq(unsigned int irq) /* Some systems map "vectors" to interrupts weirdly. Not us! */ desc = irq_to_desc(irq); __this_cpu_write(vector_irq.desc[FIRST_EXTERNAL_VECTOR + irq], desc); + inc_vector_alloc(cpumask_of(smp_processor_id()), 1); return 0; } -- 2.7.4