From: James Cleverdon In forthcoming IBM x445 systems, the physical APIC ID will not follow the simple rule laid out by Intel and encoded into xapic_phys_to_log_apicid. (The BIOS code that sets IDs doesn't work right above 16 CPUs if HT is turned on, so for > 16-way the BIOS will disable HT and repack the physical CPUs into APIC clusters.) Anyway, it's a good idea to make the APIC code more independent of any particular BIOS numbering scheme. This patch allocates logical IDs based on how many CPUs have already been onlined in a particular APIC cluster. 25-akpm/include/asm-i386/mach-summit/mach_apic.h | 34 ++++++++++++++--------- 1 files changed, 22 insertions(+), 12 deletions(-) diff -puN include/asm-i386/mach-summit/mach_apic.h~summit-apic-numbering-rework include/asm-i386/mach-summit/mach_apic.h --- 25/include/asm-i386/mach-summit/mach_apic.h~summit-apic-numbering-rework Fri Sep 12 15:21:29 2003 +++ 25-akpm/include/asm-i386/mach-summit/mach_apic.h Fri Sep 12 15:21:29 2003 @@ -7,14 +7,11 @@ #define esr_disable (1) #define NO_BALANCE_IRQ (0) -#define XAPIC_DEST_CPUS_MASK 0x0Fu -#define XAPIC_DEST_CLUSTER_MASK 0xF0u - -static inline unsigned long xapic_phys_to_log_apicid(int phys_apic) -{ - return ( (1ul << ((phys_apic) & 0x3)) | - ((phys_apic) & XAPIC_DEST_CLUSTER_MASK) ); -} +/* In clustered mode, the high nibble of APIC ID is a cluster number. + * The low nibble is a 4-bit bitmap. */ +#define XAPIC_DEST_CPUS_SHIFT 4 +#define XAPIC_DEST_CPUS_MASK ((1u << XAPIC_DEST_CPUS_SHIFT) - 1) +#define XAPIC_DEST_CLUSTER_MASK (XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT) #define APIC_DFR_VALUE (APIC_DFR_CLUSTER) @@ -40,15 +37,29 @@ static inline unsigned long check_apicid return 1; } -#define apicid_cluster(apicid) (apicid & 0xF0) +#define apicid_cluster(apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK) extern u8 bios_cpu_apicid[]; +extern u8 cpu_2_logical_apicid[]; static inline void init_apic_ldr(void) { unsigned long val, id; - - id = xapic_phys_to_log_apicid(hard_smp_processor_id()); + int i, count; + u8 lid; + u8 my_id = (u8)hard_smp_processor_id(); + u8 my_cluster = (u8)apicid_cluster(my_id); + + /* Create logical APIC IDs by counting CPUs already in cluster. */ + for (count = 0, i = NR_CPUS; --i >= 0; ) { + lid = cpu_2_logical_apicid[i]; + if (lid != BAD_APICID && apicid_cluster(lid) == my_cluster) + ++count; + } + /* We only have a 4 wide bitmap in cluster mode. If a deranged + * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */ + BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT); + id = my_cluster | (1UL << count); apic_write_around(APIC_DFR, APIC_DFR_VALUE); val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; val |= SET_APIC_LOGICAL_ID(id); @@ -77,7 +88,6 @@ static inline int apicid_to_node(int log } /* Mapping from cpu number to logical apicid */ -extern u8 cpu_2_logical_apicid[]; static inline int cpu_to_logical_apicid(int cpu) { if (cpu >= NR_CPUS) _