x86/irq/vector: Initialize matrix allocator
authorThomas Gleixner <tglx@linutronix.de>
Wed, 13 Sep 2017 21:29:38 +0000 (23:29 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Mon, 25 Sep 2017 18:51:56 +0000 (20:51 +0200)
Initialize the matrix allocator and add the proper accounting points to the
code.

No functional change, just preparation.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Juergen Gross <jgross@suse.com>
Tested-by: Yu Chen <yu.c.chen@intel.com>
Acked-by: Juergen Gross <jgross@suse.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Alok Kataria <akataria@vmware.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Rui Zhang <rui.zhang@intel.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Len Brown <lenb@kernel.org>
Link: https://lkml.kernel.org/r/20170913213155.108410660@linutronix.de
arch/x86/Kconfig
arch/x86/include/asm/apic.h
arch/x86/include/asm/hw_irq.h
arch/x86/kernel/apic/vector.c
arch/x86/kernel/i8259.c
arch/x86/kernel/irqinit.c
arch/x86/kernel/smpboot.c

index 971feac135060d371e130680b54034f9dd39556a..64e99d3c5169c8345f4f74da31539257ecc72ca1 100644 (file)
@@ -92,6 +92,7 @@ config X86
        select GENERIC_FIND_FIRST_BIT
        select GENERIC_IOMAP
        select GENERIC_IRQ_EFFECTIVE_AFF_MASK   if SMP
+       select GENERIC_IRQ_MATRIX_ALLOCATOR     if X86_LOCAL_APIC
        select GENERIC_IRQ_MIGRATION            if SMP
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
index 01bcaa8b62b3f5947db3c50a265f44751cc906ca..7a8651921ed538780619abc622f40f8d86a2911c 100644 (file)
@@ -169,6 +169,10 @@ static inline int apic_is_clustered_box(void)
 #endif
 
 extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask);
+extern void lapic_assign_system_vectors(void);
+extern void lapic_assign_legacy_vector(unsigned int isairq, bool replace);
+extern void lapic_online(void);
+extern void lapic_offline(void);
 
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }
@@ -179,6 +183,8 @@ static inline void disable_local_APIC(void) { }
 # define setup_secondary_APIC_clock x86_init_noop
 static inline void lapic_update_tsc_freq(void) { }
 static inline void apic_intr_mode_init(void) { }
+static inline void lapic_assign_system_vectors(void) { }
+static inline void lapic_assign_legacy_vector(unsigned int i, bool r) { }
 #endif /* !CONFIG_X86_LOCAL_APIC */
 
 #ifdef CONFIG_X86_X2APIC
index 6dfe366a8804576719196970e8e6c92f84fb1408..386368890376c2cdda99f8c5585d198d2888363e 100644 (file)
@@ -15,6 +15,8 @@
 
 #include <asm/irq_vectors.h>
 
+#define IRQ_MATRIX_BITS                NR_VECTORS
+
 #ifndef __ASSEMBLY__
 
 #include <linux/percpu.h>
@@ -130,7 +132,6 @@ extern struct irq_cfg *irq_cfg(unsigned int irq);
 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);
 #ifdef CONFIG_SMP
 extern void send_cleanup_vector(struct irq_cfg *);
 extern void irq_complete_move(struct irq_cfg *cfg);
index 5d5c2c064a3e365a32c2023e30668c4e1d185614..078fbd08499c31eb5d893dbb8f8c135b87b0b301 100644 (file)
@@ -36,6 +36,7 @@ EXPORT_SYMBOL_GPL(x86_vector_domain);
 static DEFINE_RAW_SPINLOCK(vector_lock);
 static cpumask_var_t vector_cpumask, vector_searchmask, searched_cpumask;
 static struct irq_chip lapic_controller;
+static struct irq_matrix *vector_matrix;
 #ifdef CONFIG_SMP
 static DEFINE_PER_CPU(struct hlist_head, cleanup_list);
 #endif
@@ -404,6 +405,36 @@ int __init arch_probe_nr_irqs(void)
        return legacy_pic->probe();
 }
 
+void lapic_assign_legacy_vector(unsigned int irq, bool replace)
+{
+       /*
+        * Use assign system here so it wont get accounted as allocated
+        * and moveable in the cpu hotplug check and it prevents managed
+        * irq reservation from touching it.
+        */
+       irq_matrix_assign_system(vector_matrix, ISA_IRQ_VECTOR(irq), replace);
+}
+
+void __init lapic_assign_system_vectors(void)
+{
+       unsigned int i, vector = 0;
+
+       for_each_set_bit_from(vector, system_vectors, NR_VECTORS)
+               irq_matrix_assign_system(vector_matrix, vector, false);
+
+       if (nr_legacy_irqs() > 1)
+               lapic_assign_legacy_vector(PIC_CASCADE_IR, false);
+
+       /* System vectors are reserved, online it */
+       irq_matrix_online(vector_matrix);
+
+       /* Mark the preallocated legacy interrupts */
+       for (i = 0; i < nr_legacy_irqs(); i++) {
+               if (i != PIC_CASCADE_IR)
+                       irq_matrix_assign(vector_matrix, ISA_IRQ_VECTOR(i));
+       }
+}
+
 int __init arch_early_irq_init(void)
 {
        struct fwnode_handle *fn;
@@ -423,6 +454,14 @@ int __init arch_early_irq_init(void)
        BUG_ON(!alloc_cpumask_var(&vector_searchmask, GFP_KERNEL));
        BUG_ON(!alloc_cpumask_var(&searched_cpumask, GFP_KERNEL));
 
+       /*
+        * Allocate the vector matrix allocator data structure and limit the
+        * search area.
+        */
+       vector_matrix = irq_alloc_matrix(NR_VECTORS, FIRST_EXTERNAL_VECTOR,
+                                        FIRST_SYSTEM_VECTOR);
+       BUG_ON(!vector_matrix);
+
        return arch_early_ioapic_init();
 }
 
@@ -454,14 +493,16 @@ static struct irq_desc *__setup_vector_irq(int vector)
        return irq_to_desc(isairq);
 }
 
-/*
- * Setup the vector to irq mappings. Must be called with vector_lock held.
- */
-void setup_vector_irq(int cpu)
+/* Online the local APIC infrastructure and initialize the vectors */
+void lapic_online(void)
 {
        unsigned int vector;
 
        lockdep_assert_held(&vector_lock);
+
+       /* Online the vector matrix array for this CPU */
+       irq_matrix_online(vector_matrix);
+
        /*
         * The interrupt affinity logic never targets interrupts to offline
         * CPUs. The exception are the legacy PIC interrupts. In general
@@ -482,6 +523,13 @@ void setup_vector_irq(int cpu)
        vector_update_shutdown_irqs();
 }
 
+void lapic_offline(void)
+{
+       lock_vector_lock();
+       irq_matrix_offline(vector_matrix);
+       unlock_vector_lock();
+}
+
 static int apic_retrigger_irq(struct irq_data *irqd)
 {
        struct apic_chip_data *apicd = apic_chip_data(irqd);
index 4e3b8a587c882ee8a0e2c39678fde12738c7752c..317c5b38a3185ccb1ecf7152d151bf291af34a47 100644 (file)
@@ -113,6 +113,7 @@ static void make_8259A_irq(unsigned int irq)
        io_apic_irqs &= ~(1<<irq);
        irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
        enable_irq(irq);
+       lapic_assign_legacy_vector(irq, true);
 }
 
 /*
index beafcf584e444f5184086a7d8a213213fa4c79cc..c7fb57505f2de9816cbbba525a22ac53ae6d5645 100644 (file)
@@ -90,6 +90,7 @@ void __init native_init_IRQ(void)
        x86_init.irqs.pre_vector_init();
 
        idt_setup_apic_and_irq_gates();
+       lapic_assign_system_vectors();
 
        if (!acpi_ioapic && !of_ioapic && nr_legacy_irqs())
                setup_irq(2, &irq2);
index d8cef32228872e6cdd143a969ad5c0a0cd57a3b0..91c0d1cd651e7301a27fd229332c7851b375a5ac 100644 (file)
@@ -260,7 +260,7 @@ static void notrace start_secondary(void *unused)
         * from seeing a half valid vector space.
         */
        lock_vector_lock();
-       setup_vector_irq(smp_processor_id());
+       lapic_online();
        set_cpu_online(smp_processor_id(), true);
        unlock_vector_lock();
        cpu_set_state_online(smp_processor_id());
@@ -1518,6 +1518,7 @@ void cpu_disable_common(void)
        remove_cpu_from_maps(cpu);
        unlock_vector_lock();
        fixup_irqs();
+       lapic_offline();
 }
 
 int native_cpu_disable(void)