#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) { }
 # 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
 
 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
        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;
        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();
 }
 
        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
        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);