/*
* Intel Multiprocessor Specification 1.1 and 1.4
* compliant MP-table parsing routines.
*
* (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
* (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
*
* Fixes
* Erich Boleyn : MP v1.4 and additional changes.
* Alan Cox : Added EBDA scanning
* Ingo Molnar : various cleanups and rewrites
* Maciej W. Rozycki: Bits for default MP configurations
* Paul Diefenbaugh: Added full ACPI support
*/
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/bootmem.h>
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
#include <linux/bitops.h>
#include <asm/smp.h>
#include <asm/acpi.h>
#include <asm/mtrr.h>
#include <asm/mpspec.h>
#include <asm/io_apic.h>
#include <asm/bios_ebda.h>
#include <mach_apic.h>
#include <mach_apicdef.h>
#include <mach_mpparse.h>
/* Have we found an MP table */
int smp_found_config;
unsigned int __cpuinitdata maxcpus = NR_CPUS;
/*
* Various Linux-internal data structures created from the
* MP-table.
*/
int apic_version [MAX_APICS];
#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
int mp_bus_id_to_type [MAX_MP_BUSSES];
#endif
DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
static int mp_current_pci_id;
/* I/O APIC entries */
struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
/* # of MP IRQ source entries */
struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* MP IRQ source entries */
int mp_irq_entries;
int nr_ioapics;
int pic_mode;
unsigned long mp_lapic_addr;
unsigned int def_to_bigsmp = 0;
/* Processor that is doing the boot up */
unsigned int boot_cpu_physical_apicid = -1U;
/* Internal processor count */
unsigned int num_processors;
unsigned disabled_cpus __cpuinitdata;
/* Bitmask of physically existing CPUs */
physid_mask_t phys_cpu_present_map;
#ifndef CONFIG_SMP
DEFINE_PER_CPU(u16, x86_bios_cpu_apicid) = BAD_APICID;
#endif
/*
* Intel MP BIOS table parsing routines:
*/
/*
* Checksum an MP configuration block.
*/
static int __init mpf_checksum(unsigned char *mp, int len)
{
int sum = 0;
while (len--)
sum += *mp++;
return sum & 0xFF;
}
#ifdef CONFIG_X86_NUMAQ
/*
* Have to match translation table entries to main table entries by counter
* hence the mpc_record variable .... can't see a less disgusting way of
* doing this ....
*/
static int mpc_record;
static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __cpuinitdata;
#endif
static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
{
int ver, apicid, cpu;
cpumask_t tmp_map;
physid_mask_t phys_cpu;
if (!(m->mpc_cpuflag & CPU_ENABLED)) {
disabled_cpus++;
return;
}
#ifdef CONFIG_X86_NUMAQ
apicid = mpc_apic_id(m, translation_table[mpc_record]);
#else
Dprintk("Processor #%d %u:%u APIC version %d\n",
m->mpc_apicid,
(m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
(m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
m->mpc_apicver);
apicid = m->mpc_apicid;
#endif
if (m->mpc_featureflag&(1<<0))
Dprintk(" Floating point unit present.\n");
if (m->mpc_featureflag&(1<<7))
Dprintk(" Machine Exception supported.\n");
if (m->mpc_featureflag&(1<<8))
Dprintk(" 64 bit compare & exchange supported.\n