i386: Support more than 8 cores on AMD systems This adds a new PHYSFLAT subarchitecture for this purpose. I unfortunately had to change all other subarchitectures to make the probing work properly. get_physical_broadcast is moved into the subarchitecture now. Index: linux/arch/i386/mach-generic/physflat.c =================================================================== --- /dev/null +++ linux/arch/i386/mach-generic/physflat.c @@ -0,0 +1,27 @@ +/* + * APIC driver for "physflat" AMD machines with more than 8 cores. + * Drives the local APIC in physical flat mode. + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static __init int probe_physflat(void) +{ + /* Check later after we know the number of CPUs */ + return 0; +} + +struct genapic apic_physflat = APIC_INIT("physflat", probe_bigsmp); Index: linux/arch/i386/mach-generic/probe.c =================================================================== --- linux.orig/arch/i386/mach-generic/probe.c +++ linux/arch/i386/mach-generic/probe.c @@ -19,11 +19,13 @@ extern struct genapic apic_summit; extern struct genapic apic_bigsmp; extern struct genapic apic_es7000; extern struct genapic apic_default; +extern struct genapic apic_physflat; struct genapic *genapic = &apic_default; struct genapic *apic_probe[] __initdata = { &apic_summit, + &apic_physflat, &apic_bigsmp, &apic_es7000, &apic_default, /* must be last */ @@ -96,6 +98,20 @@ int __init acpi_madt_oem_check(char *oem return 0; } +int __init clustered_apic_check(void) +{ + int i; + for (i = 0; apic_probe[i]; ++i) { + if (apic_probe[i]->clustered_apic_check()) { + genapic = apic_probe[i]; + printk(KERN_INFO "Switched to APIC driver `%s'.\n", + genapic->name); + return 1; + } + } + return 0; +} + int hard_smp_processor_id(void) { return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID)); Index: linux/arch/i386/mach-generic/Makefile =================================================================== --- linux.orig/arch/i386/mach-generic/Makefile +++ linux/arch/i386/mach-generic/Makefile @@ -4,4 +4,5 @@ EXTRA_CFLAGS += -I../kernel -obj-y := probe.o summit.o bigsmp.o es7000.o default.o ../mach-es7000/ +obj-y := probe.o summit.o bigsmp.o es7000.o default.o \ + ../mach-es7000/ physflat.o Index: linux/arch/i386/Kconfig =================================================================== --- linux.orig/arch/i386/Kconfig +++ linux/arch/i386/Kconfig @@ -85,12 +85,23 @@ config X86_SUMMIT If you don't have one of these computers, you should say N here. + +config X86_PHYSFLAT + bool "Support for AMD systems with more than 8 CPUs" + depends on SMP + help + Chose this option (or GENERICARCH) for a AMD system with more + than 8 CPUs where the BIOS set up an extended APIC mask. + Don't enable it on other systems. When in doubt chose GENERICARCH + instead. + config X86_BIGSMP - bool "Support for other sub-arch SMP systems with more than 8 CPUs" + bool "Support for other sub-arch Intel SMP systems with more than 8 CPUs" depends on SMP help - This option is needed for the systems that have more than 8 CPUs - and if the system is not of any sub-arch type above. + This option is needed for Intel systems that have more than 8 CPUs + and if the system is not of any sub-arch type above. Big AMD + systems should use the PHYSFLAT driver (or generic) If you don't have such a system, you should say N here. @@ -106,10 +117,11 @@ config X86_VISWS and vice versa. See for details. config X86_GENERICARCH - bool "Generic architecture (Summit, bigsmp, ES7000, default)" + bool "Generic architecture (Summit, bigsmp, ES7000, physflat, default)" depends on SMP help - This option compiles in the Summit, bigsmp, ES7000, default subarchitectures. + This option compiles in the Summit, bigsmp, ES7000, physflat, + default subarchitectures and does runtime probing. It is intended for a generic binary kernel. config X86_ES7000 Index: linux/arch/i386/kernel/mpparse.c =================================================================== --- linux.orig/arch/i386/kernel/mpparse.c +++ linux/arch/i386/kernel/mpparse.c @@ -103,21 +103,6 @@ static int __init mpf_checksum(unsigned static int mpc_record; static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata; -#ifdef CONFIG_X86_NUMAQ -static int MP_valid_apicid(int apicid, int version) -{ - return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf; -} -#else -static int MP_valid_apicid(int apicid, int version) -{ - if (version >= 0x14) - return apicid < 0xff; - else - return apicid < 0xf; -} -#endif - static void __init MP_processor_info (struct mpc_config_processor *m) { int ver, apicid; @@ -195,12 +180,16 @@ static void __init MP_processor_info (st num_processors++; ver = m->mpc_apicver; +#if 0 + /* Need to disable this check because we're in a chicken and egg + situation with physflat. */ if (!MP_valid_apicid(apicid, ver)) { printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n", m->mpc_apicid, MAX_APICS); --num_processors; return; } +#endif tmp = apicid_to_cpu_present(apicid); physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp); @@ -479,7 +468,7 @@ static int __init smp_read_mpc(struct mp } ++mpc_record; } - clustered_apic_check(); + clustered_apic_check(); if (!num_processors) printk(KERN_ERR "SMP mptable: no processors registered!\n"); return num_processors; @@ -833,7 +822,7 @@ void __init mp_register_lapic ( struct mpc_config_processor processor; int boot_cpu = 0; - if (MAX_APICS - id <= 0) { + if ((int)id >= MAX_APICS) { printk(KERN_WARNING "Processor #%d invalid (max %d)\n", id, MAX_APICS); return; Index: linux/arch/i386/kernel/smp.c =================================================================== --- linux.orig/arch/i386/kernel/smp.c +++ linux/arch/i386/kernel/smp.c @@ -113,9 +113,9 @@ DEFINE_PER_CPU(struct tlb_state, cpu_tlb * We use 'broadcast', CPU->CPU IPIs and self-IPIs too. */ -static inline int __prepare_ICR (unsigned int shortcut, int vector) +static inline int __prepare_ICR (unsigned int shortcut, int vector,int logical) { - return APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL; + return APIC_DM_FIXED | shortcut | vector | logical; } static inline int __prepare_ICR2 (unsigned int mask) @@ -123,7 +123,7 @@ static inline int __prepare_ICR2 (unsign return SET_APIC_DEST_FIELD(mask); } -void __send_IPI_shortcut(unsigned int shortcut, int vector) +void __send_IPI_shortcut(unsigned int shortcut, int vector, int logical) { /* * Subtle. In the case of the 'never do double writes' workaround @@ -142,7 +142,7 @@ void __send_IPI_shortcut(unsigned int sh /* * No need to touch the target chip field */ - cfg = __prepare_ICR(shortcut, vector); + cfg = __prepare_ICR(shortcut, vector, logical); /* * Send the IPI. The write to APIC_ICR fires this off. @@ -152,7 +152,7 @@ void __send_IPI_shortcut(unsigned int sh void fastcall send_IPI_self(int vector) { - __send_IPI_shortcut(APIC_DEST_SELF, vector); + __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL); } /* @@ -180,7 +180,7 @@ void send_IPI_mask_bitmask(cpumask_t cpu /* * program the ICR */ - cfg = __prepare_ICR(0, vector); + cfg = __prepare_ICR(0, vector, APIC_DEST_LOGICAL); /* * Send the IPI. The write to APIC_ICR fires this off. @@ -220,7 +220,7 @@ void send_IPI_mask_sequence(cpumask_t ma /* * program the ICR */ - cfg = __prepare_ICR(0, vector); + cfg = __prepare_ICR(0, vector, APIC_DEST_PHYSICAL); /* * Send the IPI. The write to APIC_ICR fires this off. Index: linux/arch/i386/kernel/apic.c =================================================================== --- linux.orig/arch/i386/kernel/apic.c +++ linux/arch/i386/kernel/apic.c @@ -49,7 +49,7 @@ int enable_local_apic __initdata = 0; /* /* * Debug level */ -int apic_verbosity; +int apic_verbosity = APIC_DEBUG; static void apic_pm_activate(void); @@ -111,17 +111,6 @@ void enable_NMI_through_LVT0 (void * dum apic_write_around(APIC_LVT0, v); } -int get_physical_broadcast(void) -{ - unsigned int lvr, version; - lvr = apic_read(APIC_LVR); - version = GET_APIC_VERSION(lvr); - if (!APIC_INTEGRATED(version) || version >= 0x14) - return 0xff; - else - return 0xf; -} - int get_maxlvt(void) { unsigned int v, ver, maxlvt; Index: linux/arch/i386/Makefile =================================================================== --- linux.orig/arch/i386/Makefile +++ linux/arch/i386/Makefile @@ -98,6 +98,10 @@ mcore-$(CONFIG_X86_BIGSMP) := mach-defau mflags-$(CONFIG_X86_SUMMIT) := -Iinclude/asm-i386/mach-summit mcore-$(CONFIG_X86_SUMMIT) := mach-default +#physflat subarch support +mflags-$(CONFIG_X86_PHYSFLAT) := -Iinclude/asm-i386/mach-physflat +mcore-$(CONFIG_X86_PHYSFLAT) := mach-default + # generic subarchitecture mflags-$(CONFIG_X86_GENERICARCH) := -Iinclude/asm-i386/mach-generic mcore-$(CONFIG_X86_GENERICARCH) := mach-default Index: linux/include/asm-i386/mach-generic/mach_apic.h =================================================================== --- linux.orig/include/asm-i386/mach-generic/mach_apic.h +++ linux/include/asm-i386/mach-generic/mach_apic.h @@ -13,7 +13,7 @@ #define apic_id_registered (genapic->apic_id_registered) #define init_apic_ldr (genapic->init_apic_ldr) #define ioapic_phys_id_map (genapic->ioapic_phys_id_map) -#define clustered_apic_check (genapic->clustered_apic_check) +extern int clustered_apic_check(void); #define multi_timer_check (genapic->multi_timer_check) #define apicid_to_node (genapic->apicid_to_node) #define cpu_to_logical_apicid (genapic->cpu_to_logical_apicid) @@ -27,5 +27,6 @@ #define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid) #define enable_apic_mode (genapic->enable_apic_mode) #define phys_pkg_id (genapic->phys_pkg_id) +#define get_physical_broadcast (genapic->get_physical_broadcast) #endif /* __ASM_MACH_APIC_H */ Index: linux/include/asm-i386/apicdef.h =================================================================== --- linux.orig/include/asm-i386/apicdef.h +++ linux/include/asm-i386/apicdef.h @@ -58,6 +58,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 Index: linux/include/asm-i386/genapic.h =================================================================== --- linux.orig/include/asm-i386/genapic.h +++ linux/include/asm-i386/genapic.h @@ -34,7 +34,7 @@ struct genapic { void (*init_apic_ldr)(void); physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map); - void (*clustered_apic_check)(void); + int (*clustered_apic_check)(void); int (*multi_timer_check)(int apic, int irq); int (*apicid_to_node)(int logical_apicid); int (*cpu_to_logical_apicid)(int cpu); @@ -63,6 +63,7 @@ struct genapic { unsigned (*get_apic_id)(unsigned long x); unsigned long apic_id_mask; unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask); + int (*get_physical_broadcast)(void); /* ipi */ void (*send_IPI_mask)(cpumask_t mask, int vector); @@ -86,7 +87,7 @@ struct genapic { APICFUNC(check_apicid_present), \ APICFUNC(init_apic_ldr), \ APICFUNC(ioapic_phys_id_map), \ - APICFUNC(clustered_apic_check), \ + APICFUNC(clustered_apic_check), \ APICFUNC(multi_timer_check), \ APICFUNC(apicid_to_node), \ APICFUNC(cpu_to_logical_apicid), \ @@ -95,6 +96,7 @@ struct genapic { APICFUNC(mpc_apic_id), \ APICFUNC(setup_portio_remap), \ APICFUNC(check_phys_apicid_present), \ + APICFUNC(get_physical_broadcast), \ APICFUNC(mpc_oem_bus_info), \ APICFUNC(mpc_oem_pci_bus), \ APICFUNC(mps_oem_check), \ Index: linux/include/asm-i386/mpspec_def.h =================================================================== --- linux.orig/include/asm-i386/mpspec_def.h +++ linux/include/asm-i386/mpspec_def.h @@ -14,7 +14,7 @@ #define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_') #define MAX_MPC_ENTRY 1024 -#define MAX_APICS 256 +#define MAX_APICS 255 struct intel_mp_floating { Index: linux/include/asm-i386/apic.h =================================================================== --- linux.orig/include/asm-i386/apic.h +++ linux/include/asm-i386/apic.h @@ -70,8 +70,6 @@ static __inline__ void apic_wait_icr_idl cpu_relax(); } -int get_physical_broadcast(void); - #ifdef CONFIG_X86_GOOD_APIC # define FORCE_READ_AROUND_WRITE 0 # define apic_read_around(x) Index: linux/include/asm-i386/mach-default/mach_apic.h =================================================================== --- linux.orig/include/asm-i386/mach-default/mach_apic.h +++ linux/include/asm-i386/mach-default/mach_apic.h @@ -54,10 +54,22 @@ static inline physid_mask_t ioapic_phys_ return phys_map; } -static inline void clustered_apic_check(void) +static inline int clustered_apic_check(void) { printk("Enabling APIC mode: %s. Using %d I/O APICs\n", "Flat", nr_ioapics); + return 1; +} + +static inline int get_physical_broadcast(void) +{ + unsigned int lvr, version; + lvr = apic_read(APIC_LVR); + version = GET_APIC_VERSION(lvr); + if (!APIC_INTEGRATED(version) || version >= 0x14) + return 0xff; + else + return 0xf; } static inline int multi_timer_check(int apic, int irq) Index: linux/include/asm-i386/mach-default/mach_ipi.h =================================================================== --- linux.orig/include/asm-i386/mach-default/mach_ipi.h +++ linux/include/asm-i386/mach-default/mach_ipi.h @@ -2,7 +2,7 @@ #define __ASM_MACH_IPI_H void send_IPI_mask_bitmask(cpumask_t mask, int vector); -void __send_IPI_shortcut(unsigned int shortcut, int vector); +void __send_IPI_shortcut(unsigned int shortcut, int vector, int logical); extern int no_broadcast; @@ -21,7 +21,7 @@ static inline void __local_send_IPI_allb send_IPI_mask(mask, vector); put_cpu(); } else - __send_IPI_shortcut(APIC_DEST_ALLBUT, vector); + __send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_LOGICAL); } static inline void __local_send_IPI_all(int vector) @@ -29,7 +29,7 @@ static inline void __local_send_IPI_all( if (no_broadcast) send_IPI_mask(cpu_online_map, vector); else - __send_IPI_shortcut(APIC_DEST_ALLINC, vector); + __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL); } static inline void send_IPI_allbutself(int vector) Index: linux/include/asm-i386/mach-bigsmp/mach_apic.h =================================================================== --- linux.orig/include/asm-i386/mach-bigsmp/mach_apic.h +++ linux/include/asm-i386/mach-bigsmp/mach_apic.h @@ -74,10 +74,27 @@ static inline void init_apic_ldr(void) apic_write_around(APIC_LDR, val); } -static inline void clustered_apic_check(void) +static inline int clustered_apic_check(void) { +#ifdef CONFIG_X86_GENERICARCH + extern struct genapic apic_bigsmp; + if (genapic != &apic_bigsmp) + return 0; +#endif printk("Enabling APIC mode: %s. Using %d I/O APICs\n", "Cluster", nr_ioapics); + return 1; +} + +static inline int get_physical_broadcast(void) +{ + unsigned int lvr, version; + lvr = apic_read(APIC_LVR); + version = GET_APIC_VERSION(lvr); + if (!APIC_INTEGRATED(version) || version >= 0x14) + return 0xff; + else + return 0xf; } static inline int multi_timer_check(int apic, int irq) Index: linux/include/asm-i386/mach-es7000/mach_apic.h =================================================================== --- linux.orig/include/asm-i386/mach-es7000/mach_apic.h +++ linux/include/asm-i386/mach-es7000/mach_apic.h @@ -81,12 +81,29 @@ static inline void enable_apic_mode(void } extern int apic_version [MAX_APICS]; -static inline void clustered_apic_check(void) +static inline int clustered_apic_check(void) { int apic = bios_cpu_apicid[smp_processor_id()]; +#ifdef CONFIG_X86_GENERICARCH + extern struct genapic apic_es7000; + if (genapic != &apic_es7000) + return 0; +#endif printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", (apic_version[apic] == 0x14) ? "Physical Cluster" : "Logical Cluster", nr_ioapics, cpus_addr(TARGET_CPUS)[0]); + return 1; +} + +static inline int get_physical_broadcast(void) +{ + unsigned int lvr, version; + lvr = apic_read(APIC_LVR); + version = GET_APIC_VERSION(lvr); + if (!APIC_INTEGRATED(version) || version >= 0x14) + return 0xff; + else + return 0xf; } static inline int multi_timer_check(int apic, int irq) Index: linux/include/asm-i386/mach-numaq/mach_apic.h =================================================================== --- linux.orig/include/asm-i386/mach-numaq/mach_apic.h +++ linux/include/asm-i386/mach-numaq/mach_apic.h @@ -34,12 +34,17 @@ static inline void init_apic_ldr(void) /* Already done in NUMA-Q firmware */ } -static inline void clustered_apic_check(void) +static inline int clustered_apic_check(void) { printk("Enabling APIC mode: %s. Using %d I/O APICs\n", "NUMA-Q", nr_ioapics); } +static inline int get_physical_broadcast(void) +{ + return 0xf; /* correct ?*/ +} + /* * Skip adding the timer int on secondary nodes, which causes * a small but painful rift in the time-space continuum. Index: linux/include/asm-i386/mach-visws/mach_apic.h =================================================================== --- linux.orig/include/asm-i386/mach-visws/mach_apic.h +++ linux/include/asm-i386/mach-visws/mach_apic.h @@ -47,10 +47,21 @@ static inline void summit_check(char *oe { } -static inline void clustered_apic_check(void) +static inline int clustered_apic_check(void) { } +static inline int get_physical_broadcast(void) +{ + unsigned int lvr, version; + lvr = apic_read(APIC_LVR); + version = GET_APIC_VERSION(lvr); + if (!APIC_INTEGRATED(version) || version >= 0x14) + return 0xff; + else + return 0xf; +} + /* Mapping from cpu number to logical apicid */ static inline int cpu_to_logical_apicid(int cpu) { Index: linux/include/asm-i386/mach-summit/mach_apic.h =================================================================== --- linux.orig/include/asm-i386/mach-summit/mach_apic.h +++ linux/include/asm-i386/mach-summit/mach_apic.h @@ -78,10 +78,27 @@ static inline int apic_id_registered(voi return 1; } -static inline void clustered_apic_check(void) +static inline int clustered_apic_check(void) { +#ifdef CONFIG_X86_GENERICARCH + extern struct genapic apic_summit; + if (genapic != &apic_summit) + return 0; +#endif printk("Enabling APIC mode: Summit. Using %d I/O APICs\n", nr_ioapics); + return 1; +} + +static inline int get_physical_broadcast(void) +{ + unsigned int lvr, version; + lvr = apic_read(APIC_LVR); + version = GET_APIC_VERSION(lvr); + if (!APIC_INTEGRATED(version) || version >= 0x14) + return 0xff; + else + return 0xf; } static inline int apicid_to_node(int logical_apicid) Index: linux/include/asm-i386/mach-physflat/mach_apicdef.h =================================================================== --- /dev/null +++ linux/include/asm-i386/mach-physflat/mach_apicdef.h @@ -0,0 +1,13 @@ +#ifndef __ASM_MACH_APICDEF_H +#define __ASM_MACH_APICDEF_H + +#define APIC_ID_MASK (0xFF<<24) + +static inline unsigned get_apic_id(unsigned long x) +{ + return (((x)>>24)&0xFF); +} + +#define GET_APIC_ID(x) get_apic_id(x) + +#endif Index: linux/include/asm-i386/mach-physflat/mach_apic.h =================================================================== --- /dev/null +++ linux/include/asm-i386/mach-physflat/mach_apic.h @@ -0,0 +1,180 @@ +#ifndef __ASM_MACH_APIC_H +#define __ASM_MACH_APIC_H + +/* Physical flat mode. + + This is mostly duplication from mach-default/mach_apic.h, but + there is no nice way to only declare the different definitions + here. + + The main difference is to use physical addressing instead of + logical addressing to address more than 8 CPUs on AMD systems. + We assume the BIOS on these systems set the right bits to + enable the extended adressing mode. + + The AMD docs state clustered mode should work too, but it doesn't + seem to so use this. */ + +#include +#include + +#define APIC_DFR_VALUE (APIC_DFR_FLAT) + +static inline cpumask_t target_cpus(void) +{ + return cpumask_of_cpu(0); +} +#define TARGET_CPUS (target_cpus()) + +#define NO_BALANCE_IRQ (1) +#define esr_disable (0) + +#define NO_IOAPIC_CHECK (0) + +#define INT_DELIVERY_MODE dest_LowestPrio +#define INT_DEST_MODE 0 + +static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) +{ + return physid_isset(apicid, bitmap); +} + +static inline unsigned long check_apicid_present(int bit) +{ + return physid_isset(bit, phys_cpu_present_map); +} + +/* + * Set up the logical destination ID. + * + * Intel recommends to set DFR, LDR and TPR before enabling + * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel + * document number 292116). So here it goes... + * + * We actually don't need this in physical mode, but then it also + * doesn't hurt. Duplicate the mask every 8 CPUs. + */ +static inline void init_apic_ldr(void) +{ + unsigned long val; + + apic_write_around(APIC_DFR, APIC_DFR_VALUE); + val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + val |= SET_APIC_LOGICAL_ID(1UL << (smp_processor_id() % 8)); + apic_write_around(APIC_LDR, val); +} + +static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) +{ + return phys_map; +} + +extern u8 bios_cpu_apicid[]; + +static inline int clustered_apic_check(void) +{ + int i; +#ifdef CONFIG_X86_PHYSFLAT + int ret = 1; /* When not in generic mode always print */ +#else + int ret = 0; +#endif + int num_cpus = 0; + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) + goto out; + for (i = 0; i < NR_CPUS; i++) { + if (bios_cpu_apicid[i] == BAD_APICID) + continue; + num_cpus++; + } + printk("phys: num_cpus %d\n", num_cpus); + ret = num_cpus > 8; + out: + if (ret) + printk("Enabling APIC mode: %s. Using %d I/O APICs\n", + "physical flat", nr_ioapics); + return ret; +} + +static inline int get_physical_broadcast(void) +{ + /* Could actually read the bit in the Northbridge to decide. + But PCI is not up yet at this stage. This might lead + to PHYSFLAT kernels to not boot on systems where + the BIOS didn't enable it, but then everybody should + be using GENERIC anyways. */ + return 0xff; +} + +static inline int multi_timer_check(int apic, int irq) +{ + return 0; +} + +static inline int apicid_to_node(int logical_apicid) +{ + return 0; +} + +/* We actually return the physical APIC-ID here because + we use physical adressing (the i386 APIC interface is all messed up). + It will result in the right thing. */ +static inline int cpu_to_logical_apicid(int cpu) +{ + return x86_cpu_to_apicid[cpu]; +} + +static inline int cpu_present_to_apicid(int mps_cpu) +{ + if (mps_cpu < get_physical_broadcast()) + return mps_cpu; + else + return BAD_APICID; +} + +static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) +{ + return physid_mask_of_physid(phys_apicid); +} + +static inline int mpc_apic_id(struct mpc_config_processor *m, + struct mpc_config_translation *translation_record) +{ + printk("Processor #%d %ld:%ld APIC version %d\n", + m->mpc_apicid, + (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8, + (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4, + m->mpc_apicver); + return (m->mpc_apicid); +} + +static inline void setup_portio_remap(void) +{ +} + +static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map); +} + +static inline int apic_id_registered(void) +{ + return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map); +} + +static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) +{ + /* Can only send to the first CPU in the mask */ + return cpu_to_logical_apicid(first_cpu(cpumask)); +} + +static inline void enable_apic_mode(void) +{ +} + +static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) +{ + return cpuid_apic >> index_msb; +} + +#endif /* __ASM_MACH_APIC_H */ Index: linux/include/asm-i386/mach-physflat/irq_vectors_limits.h =================================================================== --- /dev/null +++ linux/include/asm-i386/mach-physflat/irq_vectors_limits.h @@ -0,0 +1,7 @@ +#ifndef _ASM_IRQ_VECTORS_LIMITS_H +#define _ASM_IRQ_VECTORS_LIMITS_H + +#define NR_IRQS 224 +#define NR_IRQ_VECTORS 1024 + +#endif /* _ASM_IRQ_VECTORS_LIMITS_H */ Index: linux/include/asm-i386/mach-physflat/mach_mpspec.h =================================================================== --- /dev/null +++ linux/include/asm-i386/mach-physflat/mach_mpspec.h @@ -0,0 +1,9 @@ +#ifndef __ASM_MACH_MPSPEC_H +#define __ASM_MACH_MPSPEC_H + +/* Support a big box */ + +#define MAX_IRQ_SOURCES 256 +#define MAX_MP_BUSSES 260 + +#endif /* __ASM_MACH_MPSPEC_H */ Index: linux/include/asm-i386/mach-physflat/mach_ipi.h =================================================================== --- /dev/null +++ linux/include/asm-i386/mach-physflat/mach_ipi.h @@ -0,0 +1,30 @@ +#ifndef __ASM_MACH_IPI_H +#define __ASM_MACH_IPI_H + +void __send_IPI_shortcut(unsigned int shortcut, int vector, int logical); +void send_IPI_mask_sequence(cpumask_t mask, int vector); + +static inline void send_IPI_mask(cpumask_t mask, int vector) +{ + send_IPI_mask_sequence(mask, vector); +} + +static inline void send_IPI_allbutself(int vector) +{ + /* + * if there are no other CPUs in the system then we get an APIC send + * error if we try to broadcast, thus avoid sending IPIs in this case. + */ + if (!(num_online_cpus() > 1)) + return; + + __send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_PHYSICAL); + return; +} + +static inline void send_IPI_all(int vector) +{ + __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_PHYSICAL); +} + +#endif /* __ASM_MACH_IPI_H */