x86-64 clustered APIC support
PATCH 1/1 x86-64 clustered APIC support
Rerolled for mm4.
Forthcoming IBM boxes will be using Nocona and/or Opteron chips in clustered mode to get beyond 8 CPUs. In fact, there are plans to try for 128 CPUs when the Tulsa chip comes out. Thus, there are a fair number of signed vs. unsigned changes in the patch.
Thanks to the HPET timer and some HW changes, I've been able to remove the MPS/ACPI string comparisons from the detection code. Instead, it scans bios_cpu_apicid and uses simple heuristics to select the correct IRQ delivery mode. No need for a config option. Hurrah!
Likewise, I've been able to avoid the preprocessor tricks that the i386 sub-arch needed to build with one or more sub-arches.
Signature · 3 lines
James Cleverdon
IBM LTC (xSeries Linux Solutions)
{jamesclv(Unix, preferred), cleverdj(Notes)} at us dot ibm dot commarch/i386/kernel/acpi/boot.c +1 -1
@@ -40,7 +40,7 @@#ifdef CONFIG_X86_64 static inline void acpi_madt_oem_check (char *oem_id,char *oem_table_id) { } -static inline void clustered_apic_check (void ) { } +extern void __init clustered_apic_check (void );static inline int ioapic_setup_disabled (void ) {return 0 ; }#include <asm/proto.h>
arch/x86_64/kernel/apic.c +3 -19
@@ -32,6 +32,7 @@#include <asm/mtrr.h> #include <asm/mpspec.h> #include <asm/pgalloc.h> +#include <asm/mach_apic.h> int apic_verbosity;
@@ -330,8 +331,7 @@ void __init setup_local_APIC (void)* Double-check whether this APIC is really registered. * This is meaningless in clustered apic mode, so we skip it. */ -if (!clustered_apic_mode && - !physid_isset (GET_APIC_ID (apic_read (APIC_ID )), phys_cpu_present_map)) +if (!apic_id_registered ())BUG ();/*
@@ -339,23 +339,7 @@ void __init setup_local_APIC (void)* an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel * document number 292116). So here it goes... */ - -if (!clustered_apic_mode) { -/* -* In clustered apic mode, the firmware does this for us -* Put the APIC into flat delivery mode. -* Must be "all ones" explicitly for 82489DX. -*/ -apic_write_around (APIC_DFR ,0xffffffff ); - -/* -* Set up the logical destination ID. -*/ - value =apic_read (APIC_LDR ); - value &= ~APIC_LDR_MASK ; - value |= (1 <<(smp_processor_id ()+24 )); -apic_write_around (APIC_LDR , value); - } +init_apic_ldr ();/* * Set Task Priority to 'accept all'. We never change this
arch/x86_64/kernel/genapic.c +80 -0
80 lines not on this page · raw message
arch/x86_64/kernel/genapic_cluster.c +146 -0
146 lines not on this page · raw message
arch/x86_64/kernel/genapic_flat.c +119 -0
119 lines not on this page · raw message
arch/x86_64/kernel/io_apic.c +11 -49
114 lines not on this page · raw message
arch/x86_64/kernel/Makefile +2 -1
@@ -17,7 +17,8 @@ obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o -obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o +obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \ + genapic.o genapic_cluster.o genapic_flat.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_PM) += suspend.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o
arch/x86_64/kernel/smpboot.c +4 -5
@@ -56,15 +56,12 @@/* Number of siblings per CPU package */ int smp_num_siblings =1 ; -char phys_proc_id[NR_CPUS ];/* Package ID of each logical CPU */ +/* Package ID of each logical CPU */ +u8 phys_proc_id[NR_CPUS ] = { [0 ...NR_CPUS -1 ] =BAD_APICID };/* Bitmask of currently online CPUs */ cpumask_t cpu_online_map; -/* which logical CPU number maps to which CPU (physical APIC ID) */ -volatile char x86_cpu_to_apicid[NR_CPUS ]; -EXPORT_SYMBOL (x86_cpu_to_apicid); -static cpumask_t cpu_callin_map;cpumask_t cpu_callout_map;static cpumask_t smp_commenced_mask;
@@ -658,6 +655,8 @@ static void __init do_boot_cpu (int apiccpu_clear (cpu, cpu_callout_map);/* was set here (do_boot_cpu()) */ clear_bit (cpu, &cpu_initialized);/* was set by cpu_init() */ cpucount--; + x86_cpu_to_apicid[cpu] =BAD_APICID ; + x86_cpu_to_log_apicid[cpu] =BAD_APICID ; } }
arch/x86_64/kernel/smp.c +1 -99
106 lines not on this page · raw message
include/asm-x86_64/apicdef.h +23 -10
@@ -11,26 +11,26 @@#define APIC_DEFAULT_PHYS_BASE 0xfee00000#define APIC_ID 0x20 -#define APIC_ID_MASK (0x0F<<24) -#define GET_APIC_ID (x) (((x)>>24)&0x0F) +#define APIC_ID_MASK (0xFFu<<24) +#define GET_APIC_ID (x) (((x)>>24)&0xFFu)#define APIC_LVR 0x30#define APIC_LVR_MASK 0xFF00FF -#define GET_APIC_VERSION (x) ((x)&0xFF) -#define GET_APIC_MAXLVT (x) (((x)>>16)&0xFF) -#define APIC_INTEGRATED (x) ((x)&0xF0) +#define GET_APIC_VERSION (x) ((x)&0xFFu) +#define GET_APIC_MAXLVT (x) (((x)>>16)&0xFFu) +#define APIC_INTEGRATED (x) ((x)&0xF0u)#define APIC_TASKPRI 0x80 -#define APIC_TPRI_MASK 0xFF +#define APIC_TPRI_MASK 0xFFu#define APIC_ARBPRI 0x90 -#define APIC_ARBPRI_MASK 0xFF +#define APIC_ARBPRI_MASK 0xFFu#define APIC_PROCPRI 0xA0#define APIC_EOI 0xB0#define APIC_EIO_ACK 0x0/* Write this to the EOI register */ #define APIC_RRR 0xC0#define APIC_LDR 0xD0 -#define APIC_LDR_MASK (0xFF<<24) -#define GET_APIC_LOGICAL_ID (x) (((x)>>24)&0xFF) +#define APIC_LDR_MASK (0xFFu<<24) +#define GET_APIC_LOGICAL_ID (x) (((x)>>24)&0xFFu)#define SET_APIC_LOGICAL_ID (x) (((x)<<24)) -#define APIC_ALL_CPUS 0xFF +#define APIC_ALL_CPUS 0xFFu#define APIC_DFR 0xE0#define APIC_DFR_CLUSTER 0x0FFFFFFFul#define APIC_DFR_FLAT 0xFFFFFFFFul
@@ -60,6 +60,7 @@#define APIC_INT_ASSERT 0x04000#define APIC_ICR_BUSY 0x01000#define APIC_DEST_LOGICAL 0x00800 +#define APIC_DEST_PHYSICAL 0x00000#define APIC_DM_FIXED 0x00000#define APIC_DM_LOWEST 0x00100#define APIC_DM_SMI 0x00200
@@ -114,6 +115,18 @@#define MAX_IO_APICS 32/* +* All x86-64 systems are xAPIC compatible. +* In the following, "apicid" is a physical APIC ID. +*/ +#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_CLUSTER (apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK) +#define APIC_CLUSTERID (apicid) (APIC_CLUSTER(apicid) >> XAPIC_DEST_CPUS_SHIFT) +#define APIC_CPUID (apicid) ((apicid) & XAPIC_DEST_CPUS_MASK) +#define NUM_APIC_CLUSTERS ((BAD_APICID + 1) >> XAPIC_DEST_CPUS_SHIFT) + +/* * the local APIC register structure, memory mapped. Not terribly well * tested, but we might eventually use this one in the future - the * problem why we cannot use it right now is the P5 APIC, it has an
include/asm-x86_64/apic.h +0 -1
@@ -111,7 +111,6 @@ extern unsigned int nmi_watchdog;#endif /* CONFIG_X86_LOCAL_APIC */ -#define clustered_apic_mode 0#define esr_disable 0extern unsigned boot_cpu_id;
include/asm-x86_64/genapic.h +34 -0
@@ -0,0 +1,34 @@ +#ifndef _ASM_GENAPIC_H +#define _ASM_GENAPIC_H 1 + +/* +* Copyright 2004 James Cleverdon, IBM. +* Subject to the GNU Public License, v.2 +* +* Generic APIC sub-arch data struct. +* +* Hacked for x86-64 by James Cleverdon from i386 architecture code by +* Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and +* James Cleverdon. +*/ + +struct genapic { +char *name; +u32 int_delivery_mode; +u32 int_dest_mode; +u32 int_delivery_dest;/* for quick IPIs */ +int (*apic_id_registered)(void ); +u8 (*target_cpus)(void ); +void (*init_apic_ldr)(void ); +/* ipi */ +void (*send_IPI_mask)(cpumask_t mask,int vector); +void (*send_IPI_allbutself)(int vector); +void (*send_IPI_all)(int vector); +/* */ +unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask); +}; + + +extern struct genapic *genapic; + +#endif
include/asm-x86_64/ipi.h +113 -0
113 lines not on this page · raw message
include/asm-x86_64/irq.h +1 -1
@@ -36,7 +36,7 @@#define NR_IRQ_VECTORS NR_IRQS#else #define NR_IRQS 224 -#define NR_IRQ_VECTORS NR_IRQS +#define NR_IRQ_VECTORS 1024#endif static __inline__int irq_canonicalize (int irq)
include/asm-x86_64/mach_apic.h +28 -0
@@ -0,0 +1,28 @@ +#ifndef __ASM_MACH_APIC_H +#define __ASM_MACH_APIC_H + +/* +* Copyright 2004 James Cleverdon, IBM. +* Subject to the GNU Public License, v.2 +* +* Generic APIC sub-arch defines. +* +* Hacked for x86-64 by James Cleverdon from i386 architecture code by +* Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and +* James Cleverdon. +*/ + +#include <asm/genapic.h> + +#define INT_DELIVERY_MODE (genapic->int_delivery_mode) +#define INT_DEST_MODE (genapic->int_dest_mode) +#define INT_DELIVERY_DEST (genapic->int_delivery_dest) +#define TARGET_CPUS (genapic->target_cpus()) +#define apic_id_registered (genapic->apic_id_registered) +#define init_apic_ldr (genapic->init_apic_ldr) +#define send_IPI_mask (genapic->send_IPI_mask) +#define send_IPI_allbutself (genapic->send_IPI_allbutself) +#define send_IPI_all (genapic->send_IPI_all) +#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid) + +#endif /* __ASM_MACH_APIC_H */
include/asm-x86_64/mpspec.h +2 -2
@@ -14,9 +14,9 @@#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_')/* -* a maximum of 16 APICs with the current APIC ID architecture. +* A maximum of 255 APICs with the current APIC ID architecture. */ -#define MAX_APICS 16 +#define MAX_APICS 128struct intel_mp_floating {
include/asm-x86_64/msi.h +1 -0
@@ -7,6 +7,7 @@#define ASM_MSI_H #include <asm/desc.h> +#include <asm/mach_apic.h> #define LAST_DEVICE_VECTOR 232#define MSI_DEST_MODE MSI_LOGICAL_MODE
include/asm-x86_64/smp.h +19 -22
70 lines not on this page · raw message