diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index 31da2fdbd5..a2a955bdc6 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -657,9 +657,10 @@ void __init init_apic_mappings(void) * zeroes page to simulate the local APIC and another * one for the IO-APIC. */ - if (!smp_found_config && detect_init_APIC()) + if (!smp_found_config && detect_init_APIC()) { apic_phys = __pa(alloc_xenheap_page()); - else + memset(__va(apic_phys), 0, PAGE_SIZE); + } else apic_phys = mp_lapic_addr; set_fixmap_nocache(FIX_APIC_BASE, apic_phys); @@ -693,6 +694,7 @@ void __init init_apic_mappings(void) } else { fake_ioapic_page: ioapic_phys = __pa(alloc_xenheap_page()); + memset(__va(ioapic_phys), 0, PAGE_SIZE); } set_fixmap_nocache(idx, ioapic_phys); apic_printk(APIC_VERBOSE, "mapped IOAPIC to %08lx (%08lx)\n", diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c index beae3f5925..cfcae8cb85 100644 --- a/xen/arch/x86/cpu/common.c +++ b/xen/arch/x86/cpu/common.c @@ -427,6 +427,17 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c) } #ifdef CONFIG_X86_HT +/* cpuid returns the value latched in the HW at reset, not the APIC ID + * register's value. For any box whose BIOS changes APIC IDs, like + * clustered APIC systems, we must use hard_smp_processor_id. + * + * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID. + */ +static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) +{ + return hard_smp_processor_id() >> index_msb; +} + void __devinit detect_ht(struct cpuinfo_x86 *c) { u32 eax, ebx, ecx, edx; diff --git a/xen/arch/x86/genapic/Makefile b/xen/arch/x86/genapic/Makefile index 4220d8f7fe..ea51ead30a 100644 --- a/xen/arch/x86/genapic/Makefile +++ b/xen/arch/x86/genapic/Makefile @@ -2,6 +2,7 @@ include $(BASEDIR)/Rules.mk obj-y += bigsmp.o obj-y += default.o +obj-y += delivery.o obj-y += es7000.o obj-y += es7000plat.o obj-y += probe.o diff --git a/xen/arch/x86/genapic/bigsmp.c b/xen/arch/x86/genapic/bigsmp.c index 4338e5765e..ae714a8282 100644 --- a/xen/arch/x86/genapic/bigsmp.c +++ b/xen/arch/x86/genapic/bigsmp.c @@ -1,7 +1,3 @@ -/* - * APIC driver for "bigsmp" XAPIC machines with more than 8 virtual CPUs. - * Drives the local APIC in "clustered mode". - */ #include #include #include @@ -13,8 +9,6 @@ #include #include #include -#include -#include #include static int dmi_bigsmp; /* can be set by dmi scanners */ @@ -52,5 +46,5 @@ static __init int probe_bigsmp(void) struct genapic apic_bigsmp = { APIC_INIT("bigsmp", probe_bigsmp), - .send_ipi_mask = send_IPI_mask_sequence + GENAPIC_PHYS }; diff --git a/xen/arch/x86/genapic/default.c b/xen/arch/x86/genapic/default.c index a7403922bb..0e766937fc 100644 --- a/xen/arch/x86/genapic/default.c +++ b/xen/arch/x86/genapic/default.c @@ -12,8 +12,6 @@ #include #include #include -#include -#include #include /* should be called last. */ @@ -24,5 +22,5 @@ static __init int probe_default(void) struct genapic apic_default = { APIC_INIT("default", probe_default), - .send_ipi_mask = send_IPI_mask_bitmask + GENAPIC_FLAT }; diff --git a/xen/arch/x86/genapic/delivery.c b/xen/arch/x86/genapic/delivery.c new file mode 100644 index 0000000000..e343220f73 --- /dev/null +++ b/xen/arch/x86/genapic/delivery.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include + + +/* + * LOGICAL FLAT DELIVERY MODE (multicast via bitmask to <= 8 logical APIC IDs). + */ + +void init_apic_ldr_flat(void) +{ + unsigned long val; + + apic_write_around(APIC_DFR, APIC_DFR_FLAT); + val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); + apic_write_around(APIC_LDR, val); +} + +void clustered_apic_check_flat(void) +{ + printk("Enabling APIC mode: Flat. Using %d I/O APICs\n", nr_ioapics); +} + +cpumask_t target_cpus_flat(void) +{ + return cpu_online_map; +} + +unsigned int cpu_mask_to_apicid_flat(cpumask_t cpumask) +{ + return cpus_addr(cpumask)[0]; +} + + +/* + * PHYSICAL DELIVERY MODE (unicast to physical APIC IDs). + */ + +void init_apic_ldr_phys(void) +{ + unsigned long val; + apic_write_around(APIC_DFR, APIC_DFR_FLAT); + /* A dummy logical ID should be fine. We only deliver in phys mode. */ + val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + apic_write_around(APIC_LDR, val); +} + +void clustered_apic_check_phys(void) +{ + printk("Enabling APIC mode: Phys. Using %d I/O APICs\n", nr_ioapics); +} + +cpumask_t target_cpus_phys(void) +{ + /* IRQs will get bound more accurately later. */ + return cpumask_of_cpu(0); +} + +unsigned int cpu_mask_to_apicid_phys(cpumask_t cpumask) +{ + /* As we are using single CPU as destination, pick only one CPU here */ + return cpu_physical_id(first_cpu(cpumask)); +} diff --git a/xen/arch/x86/genapic/es7000.c b/xen/arch/x86/genapic/es7000.c index 37c959bf4c..09228f7dea 100644 --- a/xen/arch/x86/genapic/es7000.c +++ b/xen/arch/x86/genapic/es7000.c @@ -13,8 +13,6 @@ #include #include #include -#include -#include #include static __init int probe_es7000(void) @@ -25,5 +23,5 @@ static __init int probe_es7000(void) struct genapic apic_es7000 = { APIC_INIT("es7000", probe_es7000), - .send_ipi_mask = send_IPI_mask_sequence + GENAPIC_PHYS }; diff --git a/xen/arch/x86/genapic/summit.c b/xen/arch/x86/genapic/summit.c index acf191acfc..837a5ad85d 100644 --- a/xen/arch/x86/genapic/summit.c +++ b/xen/arch/x86/genapic/summit.c @@ -12,8 +12,6 @@ #include #include #include -#include -#include #include static __init int probe_summit(void) @@ -24,5 +22,5 @@ static __init int probe_summit(void) struct genapic apic_summit = { APIC_INIT("summit", probe_summit), - .send_ipi_mask = send_IPI_mask_sequence + GENAPIC_PHYS }; diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c index e71603c125..18d8ed961c 100644 --- a/xen/arch/x86/io_apic.c +++ b/xen/arch/x86/io_apic.c @@ -1736,8 +1736,10 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id) spin_unlock_irqrestore(&ioapic_lock, flags); /* Sanity check */ - if (reg_00.bits.ID != apic_id) - panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); + if (reg_00.bits.ID != apic_id) { + printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic); + return -1; + } } apic_printk(APIC_VERBOSE, KERN_INFO diff --git a/xen/arch/x86/mpparse.c b/xen/arch/x86/mpparse.c index 2df055f33a..3a53d91fd8 100644 --- a/xen/arch/x86/mpparse.c +++ b/xen/arch/x86/mpparse.c @@ -35,7 +35,7 @@ /* Have we found an MP table */ int smp_found_config; -unsigned int __initdata maxcpus = NR_CPUS; +unsigned int __devinitdata maxcpus = NR_CPUS; #ifdef CONFIG_HOTPLUG_CPU #define CPU_HOTPLUG_ENABLED (1) @@ -226,16 +226,11 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m) num_processors++; if (CPU_HOTPLUG_ENABLED || (num_processors > 8)) { - switch (boot_cpu_data.x86_vendor) { - case X86_VENDOR_INTEL: - if (!APIC_XAPIC(ver)) { - def_to_bigsmp = 0; - break; - } - /* If P4 and above fall through */ - case X86_VENDOR_AMD: - def_to_bigsmp = 1; - } + /* + * No need for processor or APIC checks: physical delivery + * (bigsmp) mode should always work. + */ + def_to_bigsmp = 1; } bios_cpu_apicid[num_processors - 1] = m->mpc_apicid; } @@ -916,6 +911,7 @@ void __init mp_register_ioapic ( u32 gsi_base) { int idx = 0; + int tmpid; if (nr_ioapics >= MAX_IO_APICS) { printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " @@ -936,9 +932,14 @@ void __init mp_register_ioapic ( set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 < 15)) - mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id); + tmpid = io_apic_get_unique_id(idx, id); else - mp_ioapics[idx].mpc_apicid = id; + tmpid = id; + if (tmpid == -1) { + nr_ioapics--; + return; + } + mp_ioapics[idx].mpc_apicid = tmpid; mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); /* diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c index 0ba9a9e826..fe869222dc 100644 --- a/xen/arch/x86/nmi.c +++ b/xen/arch/x86/nmi.c @@ -431,14 +431,14 @@ void nmi_watchdog_tick(struct cpu_user_regs * regs) */ static void do_nmi_trigger(unsigned char key) { - u32 id = apic_read(APIC_ID); + u32 id = GET_APIC_ID(apic_read(APIC_ID)); printk("Triggering NMI on APIC ID %x\n", id); local_irq_disable(); apic_wait_icr_idle(); apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id)); - apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_INT_ASSERT); + apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_PHYSICAL); local_irq_enable(); } diff --git a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c index f94ad00517..60d0f3d78e 100644 --- a/xen/arch/x86/smp.c +++ b/xen/arch/x86/smp.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include /* @@ -67,7 +67,7 @@ static inline int __prepare_ICR (unsigned int shortcut, int vector) { - return APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL; + return APIC_DM_FIXED | shortcut | vector; } static inline int __prepare_ICR2 (unsigned int mask) @@ -85,7 +85,7 @@ static inline void check_IPI_mask(cpumask_t cpumask) ASSERT(!cpus_empty(cpumask)); } -void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) +void send_IPI_mask_flat(cpumask_t cpumask, int vector) { unsigned long mask = cpus_addr(cpumask)[0]; unsigned long cfg; @@ -99,18 +99,18 @@ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) * Wait for idle. */ apic_wait_icr_idle(); - + /* * prepare target chip field */ cfg = __prepare_ICR2(mask); apic_write_around(APIC_ICR2, cfg); - + /* * 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. */ @@ -119,7 +119,7 @@ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) local_irq_restore(flags); } -void send_IPI_mask_sequence(cpumask_t mask, int vector) +void send_IPI_mask_phys(cpumask_t mask, int vector) { unsigned long cfg, flags; unsigned int query_cpu; @@ -140,18 +140,18 @@ void send_IPI_mask_sequence(cpumask_t mask, int vector) * Wait for idle. */ apic_wait_icr_idle(); - + /* * prepare target chip field */ - cfg = __prepare_ICR2(cpu_to_logical_apicid(query_cpu)); + cfg = __prepare_ICR2(cpu_physical_id(query_cpu)); apic_write_around(APIC_ICR2, cfg); - + /* * 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. */ diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 3a35ca339e..8cb7345bc3 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -1094,7 +1094,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) if ((apicid == boot_cpu_apicid) || (apicid == BAD_APICID)) continue; - if (!check_apicid_present(bit)) + if (!check_apicid_present(apicid)) continue; if (max_cpus <= cpucount+1) continue; diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index ff2a7991f3..b19796bbac 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -561,7 +561,7 @@ defer_nmi: testl $APIC_ICR_BUSY,%ebx jnz 1b # __send_IPI_shortcut(APIC_DEST_SELF, TRAP_deferred_nmi) - movl $(APIC_DM_FIXED | APIC_DEST_SELF | APIC_DEST_LOGICAL | \ + movl $(APIC_DM_FIXED | APIC_DEST_SELF | APIC_DEST_PHYSICAL | \ TRAP_deferred_nmi),%ss:APIC_ICR(%eax) jmp restore_all_xen #endif /* !CONFIG_X86_SUPERVISOR_MODE_KERNEL */ diff --git a/xen/include/asm-x86/apicdef.h b/xen/include/asm-x86/apicdef.h index 81bb2b84cb..272ed8c08c 100644 --- a/xen/include/asm-x86/apicdef.h +++ b/xen/include/asm-x86/apicdef.h @@ -62,6 +62,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 diff --git a/xen/include/asm-x86/genapic.h b/xen/include/asm-x86/genapic.h index 751e1dfc28..210ff6ee2d 100644 --- a/xen/include/asm-x86/genapic.h +++ b/xen/include/asm-x86/genapic.h @@ -21,27 +21,6 @@ struct genapic { char *name; int (*probe)(void); - int (*apic_id_registered)(void); - cpumask_t (*target_cpus)(void); - int int_delivery_mode; - int int_dest_mode; - int ESR_DISABLE; - int apic_destination_logical; - unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid); - unsigned long (*check_apicid_present)(int apicid); - int no_balance_irq; - void (*init_apic_ldr)(void); - physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map); - - void (*clustered_apic_check)(void); - int (*apicid_to_node)(int logical_apicid); - int (*cpu_to_logical_apicid)(int cpu); - int (*cpu_present_to_apicid)(int mps_cpu); - physid_mask_t (*apicid_to_cpu_present)(int phys_apicid); - int (*check_phys_apicid_present)(int boot_cpu_physical_apicid); - void (*enable_apic_mode)(void); - u32 (*phys_pkg_id)(u32 cpuid_apic, int index_msb); - /* When one of the next two hooks returns 1 the genapic is switched to this. Essentially they are additional probe functions. */ @@ -49,10 +28,14 @@ struct genapic { char *productid); int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); + /* Interrupt delivery parameters ('physical' vs. 'logical flat'). */ + int int_delivery_mode; + int int_dest_mode; + void (*init_apic_ldr)(void); + void (*clustered_apic_check)(void); + cpumask_t (*target_cpus)(void); unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask); - - /* ipi */ - void (*send_ipi_mask)(cpumask_t mask, int vector); + void (*send_IPI_mask)(cpumask_t mask, int vector); }; #define APICFUNC(x) .x = x @@ -60,29 +43,37 @@ struct genapic { #define APIC_INIT(aname, aprobe) \ .name = aname, \ .probe = aprobe, \ - .int_delivery_mode = INT_DELIVERY_MODE, \ - .int_dest_mode = INT_DEST_MODE, \ - .no_balance_irq = NO_BALANCE_IRQ, \ - .ESR_DISABLE = esr_disable, \ - .apic_destination_logical = APIC_DEST_LOGICAL, \ - APICFUNC(apic_id_registered), \ - APICFUNC(target_cpus), \ - APICFUNC(check_apicid_used), \ - APICFUNC(check_apicid_present), \ - APICFUNC(init_apic_ldr), \ - APICFUNC(ioapic_phys_id_map), \ - APICFUNC(clustered_apic_check), \ - APICFUNC(apicid_to_node), \ - APICFUNC(cpu_to_logical_apicid), \ - APICFUNC(cpu_present_to_apicid), \ - APICFUNC(apicid_to_cpu_present), \ - APICFUNC(check_phys_apicid_present), \ APICFUNC(mps_oem_check), \ - APICFUNC(cpu_mask_to_apicid), \ - APICFUNC(acpi_madt_oem_check), \ - APICFUNC(enable_apic_mode), \ - APICFUNC(phys_pkg_id) + APICFUNC(acpi_madt_oem_check) extern struct genapic *genapic; +void init_apic_ldr_flat(void); +void clustered_apic_check_flat(void); +cpumask_t target_cpus_flat(void); +unsigned int cpu_mask_to_apicid_flat(cpumask_t cpumask); +void send_IPI_mask_flat(cpumask_t mask, int vector); +#define GENAPIC_FLAT \ + .int_delivery_mode = dest_LowestPrio, \ + .int_dest_mode = 1 /* logical delivery */, \ + .init_apic_ldr = init_apic_ldr_flat, \ + .clustered_apic_check = clustered_apic_check_flat, \ + .target_cpus = target_cpus_flat, \ + .cpu_mask_to_apicid = cpu_mask_to_apicid_flat, \ + .send_IPI_mask = send_IPI_mask_flat + +void init_apic_ldr_phys(void); +void clustered_apic_check_phys(void); +cpumask_t target_cpus_phys(void); +unsigned int cpu_mask_to_apicid_phys(cpumask_t cpumask); +void send_IPI_mask_phys(cpumask_t mask, int vector); +#define GENAPIC_PHYS \ + .int_delivery_mode = dest_Fixed, \ + .int_dest_mode = 0 /* physical delivery */, \ + .init_apic_ldr = init_apic_ldr_phys, \ + .clustered_apic_check = clustered_apic_check_phys, \ + .target_cpus = target_cpus_phys, \ + .cpu_mask_to_apicid = cpu_mask_to_apicid_phys, \ + .send_IPI_mask = send_IPI_mask_phys + #endif diff --git a/xen/include/asm-x86/ipi.h b/xen/include/asm-x86/ipi.h new file mode 100644 index 0000000000..da8c94031f --- /dev/null +++ b/xen/include/asm-x86/ipi.h @@ -0,0 +1,8 @@ +#ifndef __ASM_IPI_H +#define __ASM_IPI_H + +#include + +#define send_IPI_mask (genapic->send_IPI_mask) + +#endif /* __ASM_IPI_H */ diff --git a/xen/include/asm-x86/mach-bigsmp/mach_apic.h b/xen/include/asm-x86/mach-bigsmp/mach_apic.h deleted file mode 100644 index 4a591053ba..0000000000 --- a/xen/include/asm-x86/mach-bigsmp/mach_apic.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H - - -extern u8 bios_cpu_apicid[]; - -#define xapic_phys_to_log_apicid(cpu) (bios_cpu_apicid[cpu]) -#define esr_disable (1) - -static inline int apic_id_registered(void) -{ - return (1); -} - -/* Round robin the irqs amoung the online cpus */ -static inline cpumask_t target_cpus(void) -{ - static unsigned long cpu = NR_CPUS; - do { - if (cpu >= NR_CPUS) - cpu = first_cpu(cpu_online_map); - else - cpu = next_cpu(cpu, cpu_online_map); - } while (cpu >= NR_CPUS); - return cpumask_of_cpu(cpu); -} - -#undef APIC_DEST_LOGICAL -#define APIC_DEST_LOGICAL 0 -#define TARGET_CPUS (target_cpus()) -#define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define INT_DELIVERY_MODE (dest_Fixed) -#define INT_DEST_MODE (0) /* phys delivery to target proc */ -#define NO_BALANCE_IRQ (0) -#define WAKE_SECONDARY_VIA_INIT - - -static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return (0); -} - -static inline unsigned long check_apicid_present(int bit) -{ - return (1); -} - -static inline unsigned long calculate_ldr(int cpu) -{ - unsigned long val, id; - val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; - id = xapic_phys_to_log_apicid(cpu); - val |= SET_APIC_LOGICAL_ID(id); - return val; -} - -/* - * 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... - */ -static inline void init_apic_ldr(void) -{ - unsigned long val; - int cpu = smp_processor_id(); - - apic_write_around(APIC_DFR, APIC_DFR_VALUE); - val = calculate_ldr(cpu); - apic_write_around(APIC_LDR, val); -} - -static inline void clustered_apic_check(void) -{ - printk("Enabling APIC mode: %s. Using %d I/O APICs\n", - "Physflat", nr_ioapics); -} - -static inline int apicid_to_node(int logical_apicid) -{ - return (0); -} - -static inline int cpu_present_to_apicid(int mps_cpu) -{ - if (mps_cpu < NR_CPUS) - return (int) bios_cpu_apicid[mps_cpu]; - - return BAD_APICID; -} - -static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) -{ - return physid_mask_of_physid(phys_apicid); -} - -extern u8 cpu_2_logical_apicid[]; -/* Mapping from cpu number to logical apicid */ -static inline int cpu_to_logical_apicid(int cpu) -{ - if (cpu >= NR_CPUS) - return BAD_APICID; - return cpu_physical_id(cpu); -} - -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) -{ - /* For clustered we don't have a good way to do this yet - hack */ - return physids_promote(0xFFL); -} - -static inline void enable_apic_mode(void) -{ -} - -static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return (1); -} - -/* As we are using single CPU as destination, pick only one CPU here */ -static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) -{ - int cpu; - int apicid; - - cpu = first_cpu(cpumask); - apicid = cpu_to_logical_apicid(cpu); - return apicid; -} - -static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) -{ - return cpuid_apic >> index_msb; -} - -#endif /* __ASM_MACH_APIC_H */ diff --git a/xen/include/asm-x86/mach-default/mach_apic.h b/xen/include/asm-x86/mach-default/mach_apic.h deleted file mode 100644 index c673ae24bb..0000000000 --- a/xen/include/asm-x86/mach-default/mach_apic.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H - -#include - -#define APIC_DFR_VALUE (APIC_DFR_FLAT) - -static inline cpumask_t target_cpus(void) -{ -#ifdef CONFIG_SMP - return cpu_online_map; -#else - return cpumask_of_cpu(0); -#endif -} -#define TARGET_CPUS (target_cpus()) - -#define NO_BALANCE_IRQ (0) -#define esr_disable (0) - -#define INT_DELIVERY_MODE dest_LowestPrio -#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ - -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... - */ -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()); - apic_write_around(APIC_LDR, val); -} - -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) -{ - return phys_map; -} - -static inline void clustered_apic_check(void) -{ - printk("Enabling APIC mode: %s. Using %d I/O APICs\n", - "Flat", nr_ioapics); -} - -static inline int apicid_to_node(int logical_apicid) -{ - return 0; -} - -/* Mapping from cpu number to logical apicid */ -static inline int cpu_to_logical_apicid(int cpu) -{ - return 1 << 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 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) -{ - return cpus_addr(cpumask)[0]; -} - -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 */ diff --git a/xen/include/asm-x86/mach-es7000/mach_apic.h b/xen/include/asm-x86/mach-es7000/mach_apic.h deleted file mode 100644 index 86264f01bd..0000000000 --- a/xen/include/asm-x86/mach-es7000/mach_apic.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H - -extern u8 bios_cpu_apicid[]; - -#define xapic_phys_to_log_apicid(cpu) (bios_cpu_apicid[cpu]) -#define esr_disable (1) - -static inline int apic_id_registered(void) -{ - return (1); -} - -static inline cpumask_t target_cpus(void) -{ -#if defined CONFIG_ES7000_CLUSTERED_APIC - return CPU_MASK_ALL; -#else - return cpumask_of_cpu(smp_processor_id()); -#endif -} -#define TARGET_CPUS (target_cpus()) - -#if defined CONFIG_ES7000_CLUSTERED_APIC -#define APIC_DFR_VALUE (APIC_DFR_CLUSTER) -#define INT_DELIVERY_MODE (dest_LowestPrio) -#define INT_DEST_MODE (1) /* logical delivery broadcast to all procs */ -#define NO_BALANCE_IRQ (1) -#undef WAKE_SECONDARY_VIA_INIT -#define WAKE_SECONDARY_VIA_MIP -#else -#define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define INT_DELIVERY_MODE (dest_Fixed) -#define INT_DEST_MODE (0) /* phys delivery to target procs */ -#define NO_BALANCE_IRQ (0) -#undef APIC_DEST_LOGICAL -#define APIC_DEST_LOGICAL 0x0 -#define WAKE_SECONDARY_VIA_INIT -#endif - -static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return 0; -} -static inline unsigned long check_apicid_present(int bit) -{ - return physid_isset(bit, phys_cpu_present_map); -} - -#define apicid_cluster(apicid) (apicid & 0xF0) - -static inline unsigned long calculate_ldr(int cpu) -{ - unsigned long id; - id = xapic_phys_to_log_apicid(cpu); - return (SET_APIC_LOGICAL_ID(id)); -} - -/* - * 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... - */ -static inline void init_apic_ldr(void) -{ - unsigned long val; - int cpu = smp_processor_id(); - - apic_write_around(APIC_DFR, APIC_DFR_VALUE); - val = calculate_ldr(cpu); - apic_write_around(APIC_LDR, val); -} - -extern void es7000_sw_apic(void); -static inline void enable_apic_mode(void) -{ - es7000_sw_apic(); - return; -} - -extern int apic_version [MAX_APICS]; -static inline void clustered_apic_check(void) -{ - int apic = bios_cpu_apicid[smp_processor_id()]; - 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]); -} - -static inline int apicid_to_node(int logical_apicid) -{ - return 0; -} - - -static inline int cpu_present_to_apicid(int mps_cpu) -{ - if (!mps_cpu) - return boot_cpu_physical_apicid; - else if (mps_cpu < NR_CPUS) - return (int) bios_cpu_apicid[mps_cpu]; - else - return BAD_APICID; -} - -static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) -{ - static int id = 0; - physid_mask_t mask; - mask = physid_mask_of_physid(id); - ++id; - return mask; -} - -extern u8 cpu_2_logical_apicid[]; -/* Mapping from cpu number to logical apicid */ -static inline int cpu_to_logical_apicid(int cpu) -{ - if (cpu >= NR_CPUS) - return BAD_APICID; - return (int)cpu_2_logical_apicid[cpu]; -} - -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) -{ - /* For clustered we don't have a good way to do this yet - hack */ - return physids_promote(0xff); -} - -extern unsigned int boot_cpu_physical_apicid; -static inline int check_phys_apicid_present(int cpu_physical_apicid) -{ - boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); - return (1); -} - -static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) -{ - int num_bits_set; - int cpus_found = 0; - int cpu; - int apicid; - - num_bits_set = cpus_weight(cpumask); - /* Return id to all */ - if (num_bits_set == NR_CPUS) -#if defined CONFIG_ES7000_CLUSTERED_APIC - return 0xFF; -#else - return cpu_to_logical_apicid(0); -#endif - /* - * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of TARGET_CPUS. - */ - cpu = first_cpu(cpumask); - apicid = cpu_to_logical_apicid(cpu); - while (cpus_found < num_bits_set) { - if (cpu_isset(cpu, cpumask)) { - int new_apicid = cpu_to_logical_apicid(cpu); - if (apicid_cluster(apicid) != - apicid_cluster(new_apicid)){ - printk ("%s: Not a valid mask!\n",__FUNCTION__); -#if defined CONFIG_ES7000_CLUSTERED_APIC - return 0xFF; -#else - return cpu_to_logical_apicid(0); -#endif - } - apicid = new_apicid; - cpus_found++; - } - cpu++; - } - return apicid; -} - -static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) -{ - return cpuid_apic >> index_msb; -} - -#endif /* __ASM_MACH_APIC_H */ diff --git a/xen/include/asm-x86/mach-generic/mach_apic.h b/xen/include/asm-x86/mach-generic/mach_apic.h index 1e0f6b9435..1d3ed4dc67 100644 --- a/xen/include/asm-x86/mach-generic/mach_apic.h +++ b/xen/include/asm-x86/mach-generic/mach_apic.h @@ -2,28 +2,40 @@ #define __ASM_MACH_APIC_H #include +#include -#define esr_disable (genapic->ESR_DISABLE) -#define NO_BALANCE_IRQ (genapic->no_balance_irq) +/* ESR was originally disabled in Linux for NUMA-Q. Do we really need to? */ +#define esr_disable (0) + +/* The following are dependent on APIC delivery mode (logical vs. physical). */ #define INT_DELIVERY_MODE (genapic->int_delivery_mode) #define INT_DEST_MODE (genapic->int_dest_mode) -#undef APIC_DEST_LOGICAL -#define APIC_DEST_LOGICAL (genapic->apic_destination_logical) #define TARGET_CPUS (genapic->target_cpus()) -#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) -#define apicid_to_node (genapic->apicid_to_node) -#define cpu_to_logical_apicid (genapic->cpu_to_logical_apicid) -#define cpu_present_to_apicid (genapic->cpu_present_to_apicid) -#define apicid_to_cpu_present (genapic->apicid_to_cpu_present) -#define check_apicid_present (genapic->check_apicid_present) -#define check_phys_apicid_present (genapic->check_phys_apicid_present) -#define check_apicid_used (genapic->check_apicid_used) #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) + +extern void es7000_sw_apic(void); +static inline void enable_apic_mode(void) +{ + es7000_sw_apic(); + return; +} + +/* No sane NUMA support right now. We should parse ACPI SRAT. */ +static inline int apicid_to_node(int logical_apicid) +{ + return 0; +} + +extern u8 bios_cpu_apicid[]; +static inline int cpu_present_to_apicid(int mps_cpu) +{ + if (mps_cpu < NR_CPUS) + return (int)bios_cpu_apicid[mps_cpu]; + else + return BAD_APICID; +} static inline int mpc_apic_id(struct mpc_config_processor *m, struct mpc_config_translation *translation_record) @@ -47,4 +59,41 @@ static inline int multi_timer_check(int apic, int irq) extern void generic_bigsmp_probe(void); +/* + * The following functions based around phys_cpu_present_map are disabled in + * some i386 Linux subarchitectures, and in x86_64 'cluster' genapic mode. I'm + * really not sure why, since all local APICs should have distinct physical + * IDs, and we need to know what they are. + */ +static inline int apic_id_registered(void) +{ + return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), + phys_cpu_present_map); +} + +static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) +{ + return phys_map; +} + +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 apicid) +{ + return physid_isset(apicid, phys_cpu_present_map); +} + +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 physid_mask_t apicid_to_cpu_present(int phys_apicid) +{ + return physid_mask_of_physid(phys_apicid); +} + #endif /* __ASM_MACH_APIC_H */ diff --git a/xen/include/asm-x86/mach-summit/mach_apic.h b/xen/include/asm-x86/mach-summit/mach_apic.h deleted file mode 100644 index 3ba02dc276..0000000000 --- a/xen/include/asm-x86/mach-summit/mach_apic.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H - -#include -#include - -#define esr_disable (1) -#define NO_BALANCE_IRQ (0) - -/* 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) - -static inline cpumask_t target_cpus(void) -{ - /* CPU_MASK_ALL (0xff) has undefined behaviour with - * dest_LowestPrio mode logical clustered apic interrupt routing - * Just start on cpu 0. IRQ balancing will spread load - */ - return cpumask_of_cpu(0); -} -#define TARGET_CPUS (target_cpus()) - -#define INT_DELIVERY_MODE (dest_LowestPrio) -#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ - -static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return 0; -} - -/* we don't use the phys_cpu_present_map to indicate apicid presence */ -static inline unsigned long check_apicid_present(int bit) -{ - return 1; -} - -#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; - 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); - apic_write_around(APIC_LDR, val); -} - -static inline int apic_id_registered(void) -{ - return 1; -} - -static inline void clustered_apic_check(void) -{ - printk("Enabling APIC mode: Summit. Using %d I/O APICs\n", - nr_ioapics); -} - -static inline int apicid_to_node(int logical_apicid) -{ - return logical_apicid >> 5; /* 2 clusterids per CEC */ -} - -/* Mapping from cpu number to logical apicid */ -static inline int cpu_to_logical_apicid(int cpu) -{ - if (cpu >= NR_CPUS) - return BAD_APICID; - return (int)cpu_2_logical_apicid[cpu]; -} - -static inline int cpu_present_to_apicid(int mps_cpu) -{ - if (mps_cpu < NR_CPUS) - return (int)bios_cpu_apicid[mps_cpu]; - else - return BAD_APICID; -} - -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_id_map) -{ - /* For clustered we don't have a good way to do this yet - hack */ - return physids_promote(0x0F); -} - -static inline physid_mask_t apicid_to_cpu_present(int apicid) -{ - return physid_mask_of_physid(0); -} - -static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return 1; -} - -static inline void enable_apic_mode(void) -{ -} - -static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) -{ - int num_bits_set; - int cpus_found = 0; - int cpu; - int apicid; - - num_bits_set = cpus_weight(cpumask); - /* Return id to all */ - if (num_bits_set == NR_CPUS) - return (int) 0xFF; - /* - * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of TARGET_CPUS. - */ - cpu = first_cpu(cpumask); - apicid = cpu_to_logical_apicid(cpu); - while (cpus_found < num_bits_set) { - if (cpu_isset(cpu, cpumask)) { - int new_apicid = cpu_to_logical_apicid(cpu); - if (apicid_cluster(apicid) != - apicid_cluster(new_apicid)){ - printk ("%s: Not a valid mask!\n",__FUNCTION__); - return 0xFF; - } - apicid = apicid | new_apicid; - cpus_found++; - } - cpu++; - } - return apicid; -} - -/* cpuid returns the value latched in the HW at reset, not the APIC ID - * register's value. For any box whose BIOS changes APIC IDs, like - * clustered APIC systems, we must use hard_smp_processor_id. - * - * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID. - */ -static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) -{ - return hard_smp_processor_id() >> index_msb; -} - -#endif /* __ASM_MACH_APIC_H */ diff --git a/xen/include/asm-x86/mach-summit/mach_mpparse.h b/xen/include/asm-x86/mach-summit/mach_mpparse.h index a951babe1d..3553af2fa3 100644 --- a/xen/include/asm-x86/mach-summit/mach_mpparse.h +++ b/xen/include/asm-x86/mach-summit/mach_mpparse.h @@ -1,8 +1,6 @@ #ifndef __ASM_MACH_MPPARSE_H #define __ASM_MACH_MPPARSE_H -#include - extern int use_cyclone; #ifdef CONFIG_X86_SUMMIT_NUMA diff --git a/xen/include/asm-x86/mach_ipi.h b/xen/include/asm-x86/mach_ipi.h deleted file mode 100644 index 20936c8df0..0000000000 --- a/xen/include/asm-x86/mach_ipi.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H - -#include - -void send_IPI_mask_bitmask(cpumask_t mask, int vector); -void send_IPI_mask_sequence(cpumask_t mask, int vector); - -#define send_IPI_mask (genapic->send_ipi_mask) - -#endif /* __ASM_MACH_IPI_H */