return cpu_online_map;
 }
 
+static cpumask_t flat_vector_allocation_domain(int cpu)
+{
+       /* Careful. Some cpus do not strictly honor the set of cpus
+        * specified in the interrupt destination when using lowest
+        * priority interrupt delivery mode.
+        *
+        * In particular there was a hyperthreading cpu observed to
+        * deliver interrupts to the wrong hyperthread when only one
+        * hyperthread was specified in the interrupt desitination.
+        */
+       cpumask_t domain = { { [0] = APIC_ALL_CPUS, } };
+       return domain;
+}
+
 /*
  * Set up the logical destination ID.
  *
        .int_delivery_mode = dest_LowestPrio,
        .int_dest_mode = (APIC_DEST_LOGICAL != 0),
        .target_cpus = flat_target_cpus,
+       .vector_allocation_domain = flat_vector_allocation_domain,
        .apic_id_registered = flat_apic_id_registered,
        .init_apic_ldr = flat_init_apic_ldr,
        .send_IPI_all = flat_send_IPI_all,
        return cpumask_of_cpu(0);
 }
 
+static cpumask_t physflat_vector_allocation_domain(int cpu)
+{
+       cpumask_t domain = CPU_MASK_NONE;
+       cpu_set(cpu, domain);
+       return domain;
+}
+
+
 static void physflat_send_IPI_mask(cpumask_t cpumask, int vector)
 {
        send_IPI_mask_sequence(cpumask, vector);
        .int_delivery_mode = dest_Fixed,
        .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
        .target_cpus = physflat_target_cpus,
+       .vector_allocation_domain = physflat_vector_allocation_domain,
        .apic_id_registered = flat_apic_id_registered,
        .init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/
        .send_IPI_all = physflat_send_IPI_all,
 
 #include <asm/msidef.h>
 #include <asm/hypertransport.h>
 
-static int assign_irq_vector(int irq, cpumask_t mask);
+static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result);
 
 #define __apicdebuginit  __init
 
 
        cpus_and(mask, tmp, CPU_MASK_ALL);
 
-       vector = assign_irq_vector(irq, mask);
+       vector = assign_irq_vector(irq, mask, &tmp);
        if (vector < 0)
                return;
 
-       cpus_clear(tmp);
-       cpu_set(vector >> 8, tmp);
        dest = cpu_mask_to_apicid(tmp);
 
        /*
        dest = SET_APIC_LOGICAL_ID(dest);
 
        spin_lock_irqsave(&ioapic_lock, flags);
-       __target_IO_APIC_irq(irq, dest, vector & 0xff);
+       __target_IO_APIC_irq(irq, dest, vector);
        set_native_irq_info(irq, mask);
        spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 }
 
 /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-unsigned int irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_EXTERNAL_VECTOR, 0 };
+static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = {
+       [0] = FIRST_EXTERNAL_VECTOR + 0,
+       [1] = FIRST_EXTERNAL_VECTOR + 1,
+       [2] = FIRST_EXTERNAL_VECTOR + 2,
+       [3] = FIRST_EXTERNAL_VECTOR + 3,
+       [4] = FIRST_EXTERNAL_VECTOR + 4,
+       [5] = FIRST_EXTERNAL_VECTOR + 5,
+       [6] = FIRST_EXTERNAL_VECTOR + 6,
+       [7] = FIRST_EXTERNAL_VECTOR + 7,
+       [8] = FIRST_EXTERNAL_VECTOR + 8,
+       [9] = FIRST_EXTERNAL_VECTOR + 9,
+       [10] = FIRST_EXTERNAL_VECTOR + 10,
+       [11] = FIRST_EXTERNAL_VECTOR + 11,
+       [12] = FIRST_EXTERNAL_VECTOR + 12,
+       [13] = FIRST_EXTERNAL_VECTOR + 13,
+       [14] = FIRST_EXTERNAL_VECTOR + 14,
+       [15] = FIRST_EXTERNAL_VECTOR + 15,
+};
+
+static cpumask_t irq_domain[NR_IRQ_VECTORS] __read_mostly = {
+       [0] = CPU_MASK_ALL,
+       [1] = CPU_MASK_ALL,
+       [2] = CPU_MASK_ALL,
+       [3] = CPU_MASK_ALL,
+       [4] = CPU_MASK_ALL,
+       [5] = CPU_MASK_ALL,
+       [6] = CPU_MASK_ALL,
+       [7] = CPU_MASK_ALL,
+       [8] = CPU_MASK_ALL,
+       [9] = CPU_MASK_ALL,
+       [10] = CPU_MASK_ALL,
+       [11] = CPU_MASK_ALL,
+       [12] = CPU_MASK_ALL,
+       [13] = CPU_MASK_ALL,
+       [14] = CPU_MASK_ALL,
+       [15] = CPU_MASK_ALL,
+};
 
-static int __assign_irq_vector(int irq, cpumask_t mask)
+static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
 {
        /*
         * NOTE! The local APIC isn't very good at handling
 
        if (irq_vector[irq] > 0)
                old_vector = irq_vector[irq];
-       if ((old_vector > 0) && cpu_isset(old_vector >> 8, mask)) {
-               return old_vector;
+       if (old_vector > 0) {
+               cpus_and(*result, irq_domain[irq], mask);
+               if (!cpus_empty(*result))
+                       return old_vector;
        }
 
        for_each_cpu_mask(cpu, mask) {
+               cpumask_t domain;
+               int first, new_cpu;
                int vector, offset;
-               vector = pos[cpu].vector;
-               offset = pos[cpu].offset;
+
+               domain = vector_allocation_domain(cpu);
+               first = first_cpu(domain);
+
+               vector = pos[first].vector;
+               offset = pos[first].offset;
 next:
                vector += 8;
                if (vector >= FIRST_SYSTEM_VECTOR) {
                        offset = (offset + 1) % 8;
                        vector = FIRST_DEVICE_VECTOR + offset;
                }
-               if (unlikely(pos[cpu].vector == vector))
+               if (unlikely(pos[first].vector == vector))
                        continue;
                if (vector == IA32_SYSCALL_VECTOR)
                        goto next;
-               if (per_cpu(vector_irq, cpu)[vector] != -1)
-                       goto next;
+               for_each_cpu_mask(new_cpu, domain)
+                       if (per_cpu(vector_irq, cpu)[vector] != -1)
+                               goto next;
                /* Found one! */
-               pos[cpu].vector = vector;
-               pos[cpu].offset = offset;
+               for_each_cpu_mask(new_cpu, domain) {
+                       pos[cpu].vector = vector;
+                       pos[cpu].offset = offset;
+               }
                if (old_vector >= 0) {
-                       int old_cpu = old_vector >> 8;
-                       old_vector &= 0xff;
-                       per_cpu(vector_irq, old_cpu)[old_vector] = -1;
+                       int old_cpu;
+                       for_each_cpu_mask(old_cpu, domain)
+                               per_cpu(vector_irq, old_cpu)[old_vector] = -1;
                }
-               per_cpu(vector_irq, cpu)[vector] = irq;
-               vector |= cpu << 8;
+               for_each_cpu_mask(new_cpu, domain)
+                       per_cpu(vector_irq, new_cpu)[vector] = irq;
                irq_vector[irq] = vector;
+               irq_domain[irq] = domain;
+               cpus_and(*result, domain, mask);
                return vector;
        }
        return -ENOSPC;
 }
 
-static int assign_irq_vector(int irq, cpumask_t mask)
+static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
 {
        int vector;
        unsigned long flags;
 
        spin_lock_irqsave(&vector_lock, flags);
-       vector = __assign_irq_vector(irq, mask);
+       vector = __assign_irq_vector(irq, mask, result);
        spin_unlock_irqrestore(&vector_lock, flags);
        return vector;
 }
 
                if (IO_APIC_IRQ(irq)) {
                        cpumask_t mask;
-                       vector = assign_irq_vector(irq, TARGET_CPUS);
+                       vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
                        if (vector < 0)
                                continue;
 
-                       cpus_clear(mask);
-                       cpu_set(vector >> 8, mask);
                        entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
-                       entry.vector = vector & 0xff;
+                       entry.vector = vector;
 
                        ioapic_register_intr(irq, vector, IOAPIC_AUTO);
                        if (!apic && (irq < 16))
 {
        int apic1, pin1, apic2, pin2;
        int vector;
+       cpumask_t mask;
 
        /*
         * get/set the timer IRQ vector:
         */
        disable_8259A_irq(0);
-       vector = assign_irq_vector(0, TARGET_CPUS);
+       vector = assign_irq_vector(0, TARGET_CPUS, &mask);
 
        /*
         * Subtle, code in do_timer_interrupt() expects an AEOI
        int new;
        int vector = 0;
        unsigned long flags;
+       cpumask_t mask;
 
        irq = -ENOSPC;
        spin_lock_irqsave(&vector_lock, flags);
                        continue;
                if (irq_vector[new] != 0)
                        continue;
-               vector = __assign_irq_vector(new, TARGET_CPUS);
+               vector = __assign_irq_vector(new, TARGET_CPUS, &mask);
                if (likely(vector > 0))
                        irq = new;
                break;
 {
        int vector;
        unsigned dest;
+       cpumask_t tmp;
 
-       vector = assign_irq_vector(irq, TARGET_CPUS);
+       vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
        if (vector >= 0) {
-               cpumask_t tmp;
-
-               cpus_clear(tmp);
-               cpu_set(vector >> 8, tmp);
                dest = cpu_mask_to_apicid(tmp);
 
                msg->address_hi = MSI_ADDR_BASE_HI;
 
        cpus_and(mask, tmp, CPU_MASK_ALL);
 
-       vector = assign_irq_vector(irq, mask);
+       vector = assign_irq_vector(irq, mask, &tmp);
        if (vector < 0)
                return;
 
-       cpus_clear(tmp);
-       cpu_set(vector >> 8, tmp);
        dest = cpu_mask_to_apicid(tmp);
 
        read_msi_msg(irq, &msg);
 
        cpus_and(mask, tmp, CPU_MASK_ALL);
 
-       vector = assign_irq_vector(irq, mask);
+       vector = assign_irq_vector(irq, mask, &tmp);
        if (vector < 0)
                return;
 
-       cpus_clear(tmp);
-       cpu_set(vector >> 8, tmp);
        dest = cpu_mask_to_apicid(tmp);
 
        target_ht_irq(irq, dest, vector & 0xff);
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 {
        int vector;
+       cpumask_t tmp;
 
-       vector = assign_irq_vector(irq, TARGET_CPUS);
+       vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
        if (vector >= 0) {
                u32 low, high;
                unsigned dest;
-               cpumask_t tmp;
 
-               cpus_clear(tmp);
-               cpu_set(vector >> 8, tmp);
                dest = cpu_mask_to_apicid(tmp);
 
                high =  HT_IRQ_HIGH_DEST_ID(dest);
                add_pin_to_irq(irq, ioapic, pin);
 
 
-       vector = assign_irq_vector(irq, TARGET_CPUS);
+       vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
        if (vector < 0)
                return vector;
 
-       cpus_clear(mask);
-       cpu_set(vector >> 8, mask);
-
        /*
         * Generate a PCI IRQ routing entry and program the IOAPIC accordingly.
         * Note that we mask (disable) IRQs now -- these get enabled when the