patch-2.3.40 linux/arch/i386/kernel/smpboot.c

Next file: linux/arch/i386/kernel/time.c
Previous file: linux/arch/i386/kernel/smp.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
@@ -1,8 +1,8 @@
 /*
- *	Intel MP v1.1/v1.4 specification compliant parsing routines.
+ *	x86 SMP booting functions
  *
  *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
- *	(c) 1998, 1999 Ingo Molnar <mingo@redhat.com>
+ *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
  *
  *	Much of the core SMP work is based on previous work by Thomas Radke, to
  *	whom a great many thanks are extended.
@@ -26,10 +26,8 @@
  *		Alan Cox	:	Dumb bug: 'B' step PPro's are fine
  *		Ingo Molnar	:	Added APIC timers, based on code
  *					from Jose Renau
- *		Alan Cox	:	Added EBDA scanning
  *		Ingo Molnar	:	various cleanups and rewrites
  *		Tigran Aivazian	:	fixed "0.00 in /proc/uptime on SMP" bug.
- *	Maciej W. Rozycki	:	Bits for genuine 82489DX timers
  */
 
 #include <linux/config.h>
@@ -51,70 +49,28 @@
 
 /* Setup configured maximum number of CPUs to activate */
 static int max_cpus = -1;
-/* 1 if "noapic" boot option passed */
-int skip_ioapic_setup = 0;
 
 /* Total count of live CPUs */
 int smp_num_cpus = 1;
-/* Internal processor count */
-static unsigned int num_processors = 1;
 
-/* Have we found an SMP box */
-int smp_found_config = 0;
-
-/* Bitmask of physically existing CPUs */
-unsigned long cpu_present_map = 0;
 /* Bitmask of currently online CPUs */
 unsigned long cpu_online_map = 0;
 
-/* which CPU maps to which logical number */
-volatile int cpu_number_map[NR_CPUS];
-/* which logical number maps to which CPU */
-volatile int __cpu_logical_map[NR_CPUS];
+/* which CPU (physical APIC ID) maps to which logical CPU number */
+volatile int x86_apicid_to_cpu[NR_CPUS];
+/* which logical CPU number maps to which CPU (physical APIC ID) */
+volatile int x86_cpu_to_apicid[NR_CPUS];
 
 static volatile unsigned long cpu_callin_map = 0;
 static volatile unsigned long cpu_callout_map = 0;
 
 /* Per CPU bogomips and other parameters */
 struct cpuinfo_x86 cpu_data[NR_CPUS];
-/* Processor that is doing the boot up */
-static unsigned int boot_cpu_id = 0;
 
 /* Set when the idlers are all forked */
 int smp_threads_ready = 0;
 
 /*
- * Various Linux-internal data structures created from the
- * MP-table.
- */
-int apic_version [NR_CPUS];
-int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
-extern int nr_ioapics;
-extern struct mpc_config_ioapic mp_ioapics [MAX_IO_APICS];
-extern int mp_irq_entries;
-extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
-extern int mpc_default_type;
-int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
-int mp_current_pci_id = 0;
-unsigned long mp_lapic_addr = 0;
-int pic_mode;
-
-extern void cache_APIC_registers (void);
-
-#define SMP_DEBUG 1
-
-#if SMP_DEBUG
-#define dprintk(x...) printk(##x)
-#else
-#define dprintk(x...)
-#endif
-
-/*
- * IA s/w dev Vol 3, Section 7.4
- */
-#define APIC_DEFAULT_PHYS_BASE 0xfee00000
-
-/*
  * Setup routine for controlling SMP activation
  *
  * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
@@ -142,471 +98,6 @@
 __setup("maxcpus=", maxcpus);
 
 /*
- * Intel MP BIOS table parsing routines:
- */
-
-#ifndef CONFIG_X86_VISWS_APIC
-/*
- * 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;
-}
-
-/*
- * Processor encoding in an MP configuration block
- */
-
-static char __init *mpc_family(int family,int model)
-{
-	static char n[32];
-	static char *model_defs[]=
-	{
-		"80486DX","80486DX",
-		"80486SX","80486DX/2 or 80487",
-		"80486SL","80486SX/2",
-		"Unknown","80486DX/2-WB",
-		"80486DX/4","80486DX/4-WB"
-	};
-
-	switch (family) {
-		case 0x04:
-			if (model < 10)
-				return model_defs[model];
-			break;
-
-		case 0x05:
-			return("Pentium(tm)");
-
-		case 0x06:
-			return("Pentium(tm) Pro");
-
-		case 0x0F:
-			if (model == 0x0F)
-				return("Special controller");
-	}
-	sprintf(n,"Unknown CPU [%d:%d]",family, model);
-	return n;
-}
-
-static void __init MP_processor_info (struct mpc_config_processor *m)
-{
-	int ver;
-
-	if (!(m->mpc_cpuflag & CPU_ENABLED))
-		return;
-
-	printk("Processor #%d %s APIC version %d\n",
-		m->mpc_apicid,
-		mpc_family(	(m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,
-				(m->mpc_cpufeature & CPU_MODEL_MASK)>>4),
-		m->mpc_apicver);
-
-#ifdef SMP_DEBUG
-	if (m->mpc_featureflag&(1<<0))
-		printk("    Floating point unit present.\n");
-	if (m->mpc_featureflag&(1<<7))
-		printk("    Machine Exception supported.\n");
-	if (m->mpc_featureflag&(1<<8))
-		printk("    64 bit compare & exchange supported.\n");
-	if (m->mpc_featureflag&(1<<9))
-		printk("    Internal APIC present.\n");
-#endif
-
-	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
-		dprintk("    Bootup CPU\n");
-		boot_cpu_id = m->mpc_apicid;
-	} else
-		/* Boot CPU already counted */
-		num_processors++;
-
-	if (m->mpc_apicid > NR_CPUS) {
-		printk("Processor #%d unused. (Max %d processors).\n",
-			m->mpc_apicid, NR_CPUS);
-		return;
-	}
-	ver = m->mpc_apicver;
-
-	cpu_present_map |= (1<<m->mpc_apicid);
-	/*
-	 * Validate version
-	 */
-	if (ver == 0x0) {
-		printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
-		ver = 0x10;
-	}
-	apic_version[m->mpc_apicid] = ver;
-}
-
-static void __init MP_bus_info (struct mpc_config_bus *m)
-{
-	char str[7];
-
-	memcpy(str, m->mpc_bustype, 6);
-	str[6] = 0;
-	dprintk("Bus #%d is %s\n", m->mpc_busid, str);
-
-	if (strncmp(str, "ISA", 3) == 0) {
-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
-	} else {
-	if (strncmp(str, "EISA", 4) == 0) {
-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
-	} else {
-	if (strncmp(str, "PCI", 3) == 0) {
-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
-		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
-		mp_current_pci_id++;
-	} else {
-		printk("Unknown bustype %s\n", str);
-		panic("cannot handle bus - mail to linux-smp@vger.rutgers.edu");
-	} } }
-}
-
-static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
-{
-	if (!(m->mpc_flags & MPC_APIC_USABLE))
-		return;
-
-	printk("I/O APIC #%d Version %d at 0x%lX.\n",
-		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
-	if (nr_ioapics >= MAX_IO_APICS) {
-		printk("Max # of I/O APICs (%d) exceeded (found %d).\n",
-			MAX_IO_APICS, nr_ioapics);
-		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
-	}
-	mp_ioapics[nr_ioapics] = *m;
-	nr_ioapics++;
-}
-
-static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
-{
-	mp_irqs [mp_irq_entries] = *m;
-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
-		panic("Max # of irq sources exceeded!!\n");
-}
-
-static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
-{
-	/*
-	 * Well it seems all SMP boards in existence
-	 * use ExtINT/LVT1 == LINT0 and
-	 * NMI/LVT2 == LINT1 - the following check
-	 * will show us if this assumptions is false.
-	 * Until then we do not have to add baggage.
-	 */
-	if ((m->mpc_irqtype == mp_ExtINT) &&
-		(m->mpc_destapiclint != 0))
-			BUG();
-	if ((m->mpc_irqtype == mp_NMI) &&
-		(m->mpc_destapiclint != 1))
-			BUG();
-}
-
-/*
- * Read/parse the MPC
- */
-
-static int __init smp_read_mpc(struct mp_config_table *mpc)
-{
-	char str[16];
-	int count=sizeof(*mpc);
-	unsigned char *mpt=((unsigned char *)mpc)+count;
-
-	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4))
-	{
-		panic("SMP mptable: bad signature [%c%c%c%c]!\n",
-			mpc->mpc_signature[0],
-			mpc->mpc_signature[1],
-			mpc->mpc_signature[2],
-			mpc->mpc_signature[3]);
-		return 1;
-	}
-	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length))
-	{
-		panic("SMP mptable: checksum error!\n");
-		return 1;
-	}
-	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04)
-	{
-		printk("Bad Config Table version (%d)!!\n",mpc->mpc_spec);
-		return 1;
-	}
-	memcpy(str,mpc->mpc_oem,8);
-	str[8]=0;
-	printk("OEM ID: %s ",str);
-
-	memcpy(str,mpc->mpc_productid,12);
-	str[12]=0;
-	printk("Product ID: %s ",str);
-
-	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
-
-	/* save the local APIC address, it might be non-default */
-	mp_lapic_addr = mpc->mpc_lapic;
-
-	/*
-	 *	Now process the configuration blocks.
-	 */
-	while (count < mpc->mpc_length) {
-		switch(*mpt) {
-			case MP_PROCESSOR:
-			{
-				struct mpc_config_processor *m=
-					(struct mpc_config_processor *)mpt;
-				MP_processor_info(m);
-				mpt += sizeof(*m);
-				count += sizeof(*m);
-				break;
-			}
-			case MP_BUS:
-			{
-				struct mpc_config_bus *m=
-					(struct mpc_config_bus *)mpt;
-				MP_bus_info(m);
-				mpt += sizeof(*m);
-				count += sizeof(*m);
-				break;
-			}
-			case MP_IOAPIC:
-			{
-				struct mpc_config_ioapic *m=
-					(struct mpc_config_ioapic *)mpt;
-				MP_ioapic_info(m);
-				mpt+=sizeof(*m);
-				count+=sizeof(*m);
-				break;
-			}
-			case MP_INTSRC:
-			{
-				struct mpc_config_intsrc *m=
-					(struct mpc_config_intsrc *)mpt;
-
-				MP_intsrc_info(m);
-				mpt+=sizeof(*m);
-				count+=sizeof(*m);
-				break;
-			}
-			case MP_LINTSRC:
-			{
-				struct mpc_config_lintsrc *m=
-					(struct mpc_config_lintsrc *)mpt;
-				MP_lintsrc_info(m);
-				mpt+=sizeof(*m);
-				count+=sizeof(*m);
-				break;
-			}
-		}
-	}
-	return num_processors;
-}
-
-/*
- * Scan the memory blocks for an SMP configuration block.
- */
-static int __init smp_get_mpf(struct intel_mp_floating *mpf)
-{
-	printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
-	if (mpf->mpf_feature2 & (1<<7)) {
-		printk("    IMCR and PIC compatibility mode.\n");
-		pic_mode = 1;
-	} else {
-		printk("    Virtual Wire compatibility mode.\n");
-		pic_mode = 0;
-	}
-	smp_found_config = 1;
-	/*
-	 * default CPU id - if it's different in the mptable
-	 * then we change it before first using it.
-	 */
-	boot_cpu_id = 0;
-	/*
-	 * Now see if we need to read further.
-	 */
-	if (mpf->mpf_feature1 != 0) {
-		/*
-		 * local APIC has default address
-		 */
-		mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-
-		/*
-		 * 2 CPUs, numbered 0 & 1.
-		 */
-		cpu_present_map = 3;
-		num_processors = 2;
-
-		nr_ioapics = 1;
-		mp_ioapics[0].mpc_apicaddr = 0xFEC00000;
-		/*
-		 * Save the default type number, we
-		 * need it later to set the IO-APIC
-		 * up properly:
-		 */
-		mpc_default_type = mpf->mpf_feature1;
-
-		printk("Bus #0 is ");
-	}
-
-	switch (mpf->mpf_feature1) {
-		case 1:
-		case 5:
-			printk("ISA\n");
-			break;
-		case 2:
-			printk("EISA with no IRQ0 and no IRQ13 DMA chaining\n");
-			break;
-		case 6:
-		case 3:
-			printk("EISA\n");
-			break;
-		case 4:
-		case 7:
-			printk("MCA\n");
-			break;
-		case 0:
-			if (!mpf->mpf_physptr)
-				BUG();
-			break;
-		default:
-			printk("???\nUnknown standard configuration %d\n",
-				mpf->mpf_feature1);
-			return 1;
-	}
-	if (mpf->mpf_feature1 > 4) {
-		printk("Bus #1 is PCI\n");
-
-		/*
-		 * Set local APIC version to the integrated form.
-		 * It's initialized to zero otherwise, representing
-		 * a discrete 82489DX.
-		 */
-		apic_version[0] = 0x10;
-		apic_version[1] = 0x10;
-	}
-	/*
-	 * Read the physical hardware table. Anything here will override the
-	 * defaults.
-	 */
-	if (mpf->mpf_physptr)
-		smp_read_mpc((void *)mpf->mpf_physptr);
-
-	__cpu_logical_map[0] = boot_cpu_id;
-	global_irq_holder = boot_cpu_id;
-	current->processor = boot_cpu_id;
-
-	printk("Processors: %d\n", num_processors);
-	/*
-	 * Only use the first configuration found.
-	 */
-	return 1;
-}
-
-static int __init smp_scan_config(unsigned long base, unsigned long length)
-{
-	unsigned long *bp = phys_to_virt(base);
-	struct intel_mp_floating *mpf;
-
-	dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
-	if (sizeof(*mpf) != 16)
-		printk("Error: MPF size\n");
-
-	while (length > 0) {
-		mpf = (struct intel_mp_floating *)bp;
-		if ((*bp == SMP_MAGIC_IDENT) &&
-			(mpf->mpf_length == 1) &&
-			!mpf_checksum((unsigned char *)bp, 16) &&
-			((mpf->mpf_specification == 1)
-				|| (mpf->mpf_specification == 4)) ) {
-
-			printk("found SMP MP-table at %08ld\n",
-						virt_to_phys(mpf));
-			smp_get_mpf(mpf);
-			return 1;
-		}
-		bp += 4;
-		length -= 16;
-	}
-	return 0;
-}
-
-void __init init_intel_smp (void)
-{
-	unsigned int address;
-
-	/*
-	 * FIXME: Linux assumes you have 640K of base ram..
-	 * this continues the error...
-	 *
-	 * 1) Scan the bottom 1K for a signature
-	 * 2) Scan the top 1K of base RAM
-	 * 3) Scan the 64K of bios
-	 */
-	if (smp_scan_config(0x0,0x400) ||
-		smp_scan_config(639*0x400,0x400) ||
-			smp_scan_config(0xF0000,0x10000))
-		return;
-	/*
-	 * If it is an SMP machine we should know now, unless the
-	 * configuration is in an EISA/MCA bus machine with an
-	 * extended bios data area.
-	 *
-	 * there is a real-mode segmented pointer pointing to the
-	 * 4K EBDA area at 0x40E, calculate and scan it here.
-	 *
-	 * NOTE! There are Linux loaders that will corrupt the EBDA
-	 * area, and as such this kind of SMP config may be less
-	 * trustworthy, simply because the SMP table may have been
-	 * stomped on during early boot. These loaders are buggy and
-	 * should be fixed.
-	 */
-
-	address = *(unsigned short *)phys_to_virt(0x40E);
-	address <<= 4;
-	smp_scan_config(address, 0x1000);
-	if (smp_found_config)
-		printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n");
-}
-
-#else
-
-/*
- * The Visual Workstation is Intel MP compliant in the hardware
- * sense, but it doesnt have a BIOS(-configuration table).
- * No problem for Linux.
- */
-void __init init_visws_smp(void)
-{
-	smp_found_config = 1;
-
-	cpu_present_map |= 2; /* or in id 1 */
-	apic_version[1] |= 0x10; /* integrated APIC */
-	apic_version[0] |= 0x10;
-
-	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-}
-
-#endif
-
-/*
- * - Intel MP Configuration Table
- * - or SGI Visual Workstation configuration
- */
-void __init init_smp_config (void)
-{
-#ifndef CONFIG_VISWS
-	init_intel_smp();
-#else
-	init_visws_smp();
-#endif
-}
-
-
-
-/*
  * Trampoline 80x86 program as an array.
  */
 
@@ -686,209 +177,12 @@
 	/*
 	 * Lets the callins below out of their loop.
 	 */
-	dprintk("Setting commenced=1, go go go\n");
+	Dprintk("Setting commenced=1, go go go\n");
 
 	wmb();
 	atomic_set(&smp_commenced,1);
 }
 
-extern void __error_in_io_apic_c(void);
-
-
-int get_maxlvt(void)
-{
-	unsigned int v, ver, maxlvt;
-
-	v = apic_read(APIC_LVR);
-	ver = GET_APIC_VERSION(v);
-	/* 82489DXs do not report # of LVT entries. */
-	maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(v) : 2;
-	return maxlvt;
-}
-
-void disable_local_APIC (void)
-{
-	unsigned long value;
-        int maxlvt;
-
-	/*
-	 * Disable APIC
-	 */
- 	value = apic_read(APIC_SPIV);
- 	value &= ~(1<<8);
- 	apic_write(APIC_SPIV,value);
-
-	/*
-	 * Clean APIC state for other OSs:
-	 */
- 	value = apic_read(APIC_SPIV);
- 	value &= ~(1<<8);
- 	apic_write(APIC_SPIV,value);
-	maxlvt = get_maxlvt();
-	apic_write_around(APIC_LVTT, 0x00010000);
-	apic_write_around(APIC_LVT0, 0x00010000);
-	apic_write_around(APIC_LVT1, 0x00010000);
-	if (maxlvt >= 3)
-		apic_write_around(APIC_LVTERR, 0x00010000);
-	if (maxlvt >= 4)
-		apic_write_around(APIC_LVTPC, 0x00010000);
-}
-
-void __init setup_local_APIC (void)
-{
-	unsigned long value, ver, maxlvt;
-
-	if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
-		__error_in_io_apic_c();
-
- 	value = apic_read(APIC_SPIV);
-	/*
-	 * Enable APIC
-	 */
- 	value |= (1<<8);
-
-	/*
-	 * Some unknown Intel IO/APIC (or APIC) errata is biting us with
-	 * certain networking cards. If high frequency interrupts are
-	 * happening on a particular IOAPIC pin, plus the IOAPIC routing
-	 * entry is masked/unmasked at a high rate as well then sooner or
-	 * later IOAPIC line gets 'stuck', no more interrupts are received
-	 * from the device. If focus CPU is disabled then the hang goes
-	 * away, oh well :-(
-	 *
-	 * [ This bug can be reproduced easily with a level-triggered
-	 *   PCI Ne2000 networking cards and PII/PIII processors, dual
-	 *   BX chipset. ]
-	 */
-#if 0
-	/* Enable focus processor (bit==0) */
- 	value &= ~(1<<9);
-#else
-	/* Disable focus processor (bit==1) */
-	value |= (1<<9);
-#endif
-	/*
-	 * Set spurious IRQ vector
-	 */
-	value |= SPURIOUS_APIC_VECTOR;
- 	apic_write(APIC_SPIV,value);
-
-	/*
-	 * Set up LVT0, LVT1:
-	 *
-	 * set up through-local-APIC on the BP's LINT0. This is not
-	 * strictly necessery in pure symmetric-IO mode, but sometimes
-	 * we delegate interrupts to the 8259A.
-	 */
-	if (hard_smp_processor_id() == boot_cpu_id) {
-		value = 0x00000700;
-		printk("enabled ExtINT on CPU#%d\n", hard_smp_processor_id());
-	} else {
-		value = 0x00010700;
-		printk("masked ExtINT on CPU#%d\n", hard_smp_processor_id());
-	}
- 	apic_write_around(APIC_LVT0,value);
-
-	/*
-	 * only the BP should see the LINT1 NMI signal, obviously.
-	 */
-	if (hard_smp_processor_id() == boot_cpu_id)
-		value = 0x00000400;		// unmask NMI
-	else
-		value = 0x00010400;		// mask NMI
- 	apic_write_around(APIC_LVT1,value);
-
-	value = apic_read(APIC_LVR);
-	ver = GET_APIC_VERSION(value);
-	if (APIC_INTEGRATED(ver)) {		/* !82489DX */
-		maxlvt = get_maxlvt();
-		/*
-		 * Due to the Pentium erratum 3AP.
-		 */
-		if (maxlvt > 3) {
-			apic_readaround(APIC_SPIV); // not strictly necessery
-			apic_write(APIC_ESR, 0);
-		}
-		value = apic_read(APIC_ESR);
-		printk("ESR value before enabling vector: %08lx\n", value);
-
-		value = apic_read(APIC_LVTERR);
-		value = ERROR_APIC_VECTOR;      // enables sending errors
-		apic_write(APIC_LVTERR,value);
-		/*
-		 * spec says clear errors after enabling vector.
-		 */
-		if (maxlvt != 3) {
-			apic_readaround(APIC_SPIV);
-			apic_write(APIC_ESR, 0);
-		}
-		value = apic_read(APIC_ESR);
-		printk("ESR value after enabling vector: %08lx\n", value);
-	} else
-		printk("No ESR for 82489DX.\n");
-
-	/*
-	 * Set Task Priority to 'accept all'. We never change this
-	 * later on.
-	 */
- 	value = apic_read(APIC_TASKPRI);
- 	value &= ~APIC_TPRI_MASK;
- 	apic_write(APIC_TASKPRI,value);
-
-	/*
-	 * Set up the logical destination ID and put the
-	 * APIC into flat delivery mode.
-	 */
- 	value = apic_read(APIC_LDR);
-	value &= ~APIC_LDR_MASK;
-	value |= (1<<(smp_processor_id()+24));
- 	apic_write(APIC_LDR,value);
-
- 	value = apic_read(APIC_DFR);
-	value |= SET_APIC_DFR(0xf);
- 	apic_write(APIC_DFR, value);
-}
-
-void __init init_smp_mappings(void)
-{
-	unsigned long apic_phys;
-
-	if (smp_found_config) {
-		apic_phys = mp_lapic_addr;
-	} else {
-		/*
-		 * set up a fake all zeroes page to simulate the
-		 * local APIC and another one for the IO-APIC. We
-		 * could use the real zero-page, but it's safer
-		 * this way if some buggy code writes to this page ...
-		 */
-		apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
-		apic_phys = __pa(apic_phys);
-	}
-	set_fixmap(FIX_APIC_BASE, apic_phys);
-	dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
-
-#ifdef CONFIG_X86_IO_APIC
-	{
-		unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
-		int i;
-
-		for (i = 0; i < nr_ioapics; i++) {
-			if (smp_found_config) {
-				ioapic_phys = mp_ioapics[i].mpc_apicaddr;
-			} else {
-				ioapic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
-				ioapic_phys = __pa(ioapic_phys);
-			}
-			set_fixmap(idx,ioapic_phys);
-			dprintk("mapped IOAPIC to %08lx (%08lx)\n",
-					__fix_to_virt(idx), ioapic_phys);
-			idx++;
-		}
-	}
-#endif
-}
-
 /*
  * TSC synchronization.
  *
@@ -988,20 +282,14 @@
 	}
 
 	sum = 0;
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!(cpu_online_map & (1 << i)))
-			continue;
-
+	for (i = 0; i < smp_num_cpus; i++) {
 		t0 = tsc_values[i];
 		sum += t0;
 	}
 	avg = div64(sum, smp_num_cpus);
 
 	sum = 0;
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!(cpu_online_map & (1 << i)))
-			continue;
-
+	for (i = 0; i < smp_num_cpus; i++) {
 		delta = tsc_values[i] - avg;
 		if (delta < 0)
 			delta = -delta;
@@ -1057,15 +345,20 @@
 
 void __init smp_callin(void)
 {
-	int cpuid;
+	int cpuid, phys_id;
 	unsigned long timeout;
 
 	/*
 	 * (This works even if the APIC is not enabled.)
 	 */
-	cpuid = GET_APIC_ID(apic_read(APIC_ID));
-
-	dprintk("CPU#%d waiting for CALLOUT\n", cpuid);
+	phys_id = GET_APIC_ID(apic_read(APIC_ID));
+	cpuid = current->processor;
+	if (test_and_set_bit(cpuid, &cpu_online_map)) {
+		printk("huh, phys CPU#%d, CPU#%d already present??\n",
+					phys_id, cpuid);
+		BUG();
+	}
+	Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
 
 	/*
 	 * STARTUP IPIs are fragile beasts as they might sometimes
@@ -1100,7 +393,7 @@
 	 * boards)
 	 */
 
-	dprintk("CALLIN, before setup_local_APIC().\n");
+	Dprintk("CALLIN, before setup_local_APIC().\n");
 	setup_local_APIC();
 
 	sti();
@@ -1115,7 +408,7 @@
 	 * Get our bogomips.
 	 */
 	calibrate_delay();
-	dprintk("Stack at about %p\n",&cpuid);
+	Dprintk("Stack at about %p\n",&cpuid);
 
 	/*
 	 * Save our processor parameters
@@ -1131,7 +424,7 @@
 	 *      Synchronize the TSC with the BP
 	 */
 	if (cpu_has_tsc)
-		synchronize_tsc_ap ();
+		synchronize_tsc_ap();
 }
 
 int cpucount = 0;
@@ -1196,21 +489,21 @@
 	return do_fork(CLONE_VM|CLONE_PID, 0, &regs);
 }
 
-static void __init do_boot_cpu(int i)
+static void __init do_boot_cpu (int apicid)
 {
 	unsigned long cfg;
 	struct task_struct *idle;
 	unsigned long send_status, accept_status;
-	int timeout, num_starts, j;
+	int timeout, num_starts, j, cpu;
 	unsigned long start_eip;
 
-	cpucount++;
+	cpu = ++cpucount;
 	/*
 	 * We can't use kernel_thread since we must avoid to
 	 * reschedule the child.
 	 */
 	if (fork_by_hand() < 0)
-		panic("failed fork for CPU %d", i);
+		panic("failed fork for CPU %d", cpu);
 
 	/*
 	 * We remove it from the pidhash and the runqueue
@@ -1218,23 +511,23 @@
 	 */
 	idle = init_task.prev_task;
 	if (!idle)
-		panic("No idle process for CPU %d", i);
+		panic("No idle process for CPU %d", cpu);
 
-	idle->processor = i;
-	__cpu_logical_map[cpucount] = i;
-	cpu_number_map[i] = cpucount;
+	idle->processor = cpu;
+	x86_cpu_to_apicid[cpu] = apicid;
+	x86_apicid_to_cpu[apicid] = cpu;
 	idle->has_cpu = 1; /* we schedule the first task manually */
 	idle->thread.eip = (unsigned long) start_secondary;
 
 	del_from_runqueue(idle);
 	unhash_process(idle);
-	init_tasks[cpucount] = idle;
+	init_tasks[cpu] = idle;
 
 	/* start_eip had better be page-aligned! */
 	start_eip = setup_trampoline();
 
 	/* So we see what's up   */
-	printk("Booting processor %d eip %lx\n", i, start_eip);
+	printk("Booting processor %d eip %lx\n", cpu, start_eip);
 	stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle);
 
 	/*
@@ -1242,21 +535,20 @@
 	 * the targeted processor.
 	 */
 
-	dprintk("Setting warm reset code and vector.\n");
+	Dprintk("Setting warm reset code and vector.\n");
 
 	CMOS_WRITE(0xa, 0xf);
 	local_flush_tlb();
-	dprintk("1.\n");
+	Dprintk("1.\n");
 	*((volatile unsigned short *) phys_to_virt(0x469)) = start_eip >> 4;
-	dprintk("2.\n");
+	Dprintk("2.\n");
 	*((volatile unsigned short *) phys_to_virt(0x467)) = start_eip & 0xf;
-	dprintk("3.\n");
+	Dprintk("3.\n");
 
 	/*
 	 * Be paranoid about clearing APIC errors.
 	 */
-
-	if (APIC_INTEGRATED(apic_version[i])) {
+	if (APIC_INTEGRATED(apic_version[apicid])) {
 		apic_readaround(APIC_SPIV);
 		apic_write(APIC_ESR, 0);
 		accept_status = (apic_read(APIC_ESR) & 0xEF);
@@ -1272,7 +564,7 @@
 	 * Starting actual IPI sequence...
 	 */
 
-	dprintk("Asserting INIT.\n");
+	Dprintk("Asserting INIT.\n");
 
 	/*
 	 * Turn INIT on
@@ -1283,7 +575,7 @@
 	/*
 	 * Target chip
 	 */
-	apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(i));
+	apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(apicid));
 
 	/*
 	 * Send IPI
@@ -1294,12 +586,12 @@
 	apic_write(APIC_ICR, cfg);
 
 	udelay(200);
-	dprintk("Deasserting INIT.\n");
+	Dprintk("Deasserting INIT.\n");
 
 	/* Target chip */
 	cfg = apic_read(APIC_ICR2);
 	cfg &= 0x00FFFFFF;
-	apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i));
+	apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(apicid));
 
 	/* Send IPI */
 	cfg = apic_read(APIC_ICR);
@@ -1314,8 +606,7 @@
 	 * If we don't have an integrated APIC, don't
 	 * send the STARTUP IPIs.
 	 */
-
-	if (APIC_INTEGRATED(apic_version[i]))
+	if (APIC_INTEGRATED(apic_version[apicid]))
 		num_starts = 2;
 	else
 		num_starts = 0;
@@ -1323,13 +614,14 @@
 	/*
 	 * Run STARTUP IPI loop.
 	 */
+	Dprintk("#startup loops: %d.\n", num_starts);
 
 	for (j = 1; j <= num_starts; j++) {
-		dprintk("Sending STARTUP #%d.\n",j);
+		Dprintk("Sending STARTUP #%d.\n",j);
 		apic_readaround(APIC_SPIV);
 		apic_write(APIC_ESR, 0);
 		apic_read(APIC_ESR);
-		dprintk("After apic_write.\n");
+		Dprintk("After apic_write.\n");
 
 		/*
 		 * STARTUP IPI
@@ -1338,7 +630,7 @@
 		/* Target chip */
 		cfg = apic_read(APIC_ICR2);
 		cfg &= 0x00FFFFFF;
-		apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i));
+		apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(apicid));
 
 		/* Boot on the stack */
 		cfg = apic_read(APIC_ICR);
@@ -1348,12 +640,12 @@
 		/* Kick the second */
 		apic_write(APIC_ICR, cfg);
 
-		dprintk("Startup point 1.\n");
+		Dprintk("Startup point 1.\n");
 
-		dprintk("Waiting for send to finish...\n");
+		Dprintk("Waiting for send to finish...\n");
 		timeout = 0;
 		do {
-			dprintk("+");
+			Dprintk("+");
 			udelay(100);
 			send_status = apic_read(APIC_ICR) & 0x1000;
 		} while (send_status && (timeout++ < 1000));
@@ -1366,7 +658,7 @@
 		if (send_status || accept_status)
 			break;
 	}
-	dprintk("After Startup.\n");
+	Dprintk("After Startup.\n");
 
 	if (send_status)
 		printk("APIC never delivered???\n");
@@ -1377,24 +669,24 @@
 		/*
 		 * allow APs to start initializing.
 		 */
-		dprintk("Before Callout %d.\n", i);
-		set_bit(i, &cpu_callout_map);
-		dprintk("After Callout %d.\n", i);
+		Dprintk("Before Callout %d.\n", cpu);
+		set_bit(cpu, &cpu_callout_map);
+		Dprintk("After Callout %d.\n", cpu);
 
 		/*
 		 * Wait 5s total for a response
 		 */
-		for (timeout = 0; timeout < 50000; timeout++) {
-			if (test_bit(i, &cpu_callin_map))
+		for (timeout = 0; timeout < 1000000000; timeout++) {
+			if (test_bit(cpu, &cpu_callin_map))
 				break;	/* It has booted */
 			udelay(100);
 		}
 
-		if (test_bit(i, &cpu_callin_map)) {
+		if (test_bit(cpu, &cpu_callin_map)) {
 			/* number CPUs logically, starting from 1 (BSP is 0) */
-			printk("OK.\n");
-			printk("CPU%d: ", i);
-			print_cpu_info(&cpu_data[i]);
+			Dprintk("OK.\n");
+			printk("CPU%d: ", cpu);
+			print_cpu_info(&cpu_data[cpu]);
 		} else {
 			if (*((volatile unsigned char *)phys_to_virt(8192))
 					== 0xA5) /* trampoline code not run */
@@ -1402,10 +694,10 @@
 			else
 				printk("CPU booted but not responding.\n");
 		}
-		dprintk("CPU has booted.\n");
+		Dprintk("CPU has booted.\n");
 	} else {
-		__cpu_logical_map[cpucount] = -1;
-		cpu_number_map[i] = -1;
+		x86_cpu_to_apicid[cpu] = -1;
+		x86_apicid_to_cpu[apicid] = -1;
 		cpucount--;
 	}
 
@@ -1460,7 +752,7 @@
 
 void __init smp_boot_cpus(void)
 {
-	int i;
+	int apicid, cpu;
 
 #ifdef CONFIG_MTRR
 	/*  Must be done before other processors booted  */
@@ -1471,58 +763,63 @@
 	 * and the per-CPU profiling counter/multiplier
 	 */
 
-	for (i = 0; i < NR_CPUS; i++) {
-		cpu_number_map[i] = -1;
-		prof_counter[i] = 1;
-		prof_old_multiplier[i] = 1;
-		prof_multiplier[i] = 1;
+	for (apicid = 0; apicid < NR_CPUS; apicid++) {
+		x86_apicid_to_cpu[apicid] = -1;
+		prof_counter[apicid] = 1;
+		prof_old_multiplier[apicid] = 1;
+		prof_multiplier[apicid] = 1;
 	}
 
 	/*
 	 * Setup boot CPU information
 	 */
-
-	smp_store_cpu_info(boot_cpu_id); /* Final full version of the data */
-	smp_tune_scheduling();
-	printk("CPU%d: ", boot_cpu_id);
-	print_cpu_info(&cpu_data[boot_cpu_id]);
+	smp_store_cpu_info(0); /* Final full version of the data */
+	printk("CPU%d: ", 0);
+	print_cpu_info(&cpu_data[0]);
 
 	/*
-	 * not necessary because the MP table should list the boot
-	 * CPU too, but we do it for the sake of robustness anyway.
-	 * (and for the case when a non-SMP board boots an SMP kernel)
-	 */
-	cpu_present_map |= (1 << hard_smp_processor_id());
-
-	cpu_number_map[boot_cpu_id] = 0;
-
+	 * We have the boot CPU online for sure.
+	 */
+	set_bit(0, &cpu_online_map);
+	x86_apicid_to_cpu[boot_cpu_id] = 0;
+	x86_cpu_to_apicid[0] = boot_cpu_id;
+	global_irq_holder = 0;
+	current->processor = 0;
 	init_idle();
+	smp_tune_scheduling();
 
 	/*
 	 * If we couldnt find an SMP configuration at boot time,
 	 * get out of here now!
 	 */
-
 	if (!smp_found_config) {
 		printk(KERN_NOTICE "SMP motherboard not detected. Using dummy APIC emulation.\n");
 #ifndef CONFIG_VISWS
 		io_apic_irqs = 0;
 #endif
-		cpu_online_map = cpu_present_map;
+		cpu_online_map = phys_cpu_present_map = 1;
 		smp_num_cpus = 1;
 		goto smp_done;
 	}
 
 	/*
-	 * If SMP should be disabled, then really disable it!
+	 * Should not be necessary because the MP table should list the boot
+	 * CPU too, but we do it for the sake of robustness anyway.
 	 */
+	if (!test_bit(boot_cpu_id, &phys_cpu_present_map)) {
+		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
+								 boot_cpu_id);
+		phys_cpu_present_map |= (1 << hard_smp_processor_id());
+	}
 
+	/*
+	 * If SMP should be disabled, then really disable it!
+	 */
 	if (!max_cpus) {
 		smp_found_config = 0;
 		printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
 	}
 
-#ifdef SMP_DEBUG
 	{
 		int reg;
 
@@ -1534,11 +831,11 @@
 		 */
 
 		reg = apic_read(APIC_LVR);
-		dprintk("Getting VERSION: %x\n", reg);
+		Dprintk("Getting VERSION: %x\n", reg);
 
 		apic_write(APIC_LVR, 0);
 		reg = apic_read(APIC_LVR);
-		dprintk("Getting VERSION: %x\n", reg);
+		Dprintk("Getting VERSION: %x\n", reg);
 
 		/*
 		 * The two version reads above should print the same
@@ -1551,14 +848,12 @@
 		 * compatibility mode, but most boxes are anymore.
 		 */
 
-
 		reg = apic_read(APIC_LVT0);
-		dprintk("Getting LVT0: %x\n", reg);
+		Dprintk("Getting LVT0: %x\n", reg);
 
 		reg = apic_read(APIC_LVT1);
-		dprintk("Getting LVT1: %x\n", reg);
+		Dprintk("Getting LVT1: %x\n", reg);
 	}
-#endif
 
 	setup_local_APIC();
 
@@ -1568,42 +863,33 @@
 	/*
 	 * Now scan the CPU present map and fire up the other CPUs.
 	 */
+	Dprintk("CPU present map: %lx\n", phys_cpu_present_map);
 
-	/*
-	 * Add all detected CPUs. (later on we can down individual
-	 * CPUs which will change cpu_online_map but not necessarily
-	 * cpu_present_map. We are pretty much ready for hot-swap CPUs.)
-	 */
-	cpu_online_map = cpu_present_map;
-	mb();
-
-	dprintk("CPU map: %lx\n", cpu_present_map);
-
-	for (i = 0; i < NR_CPUS; i++) {
+	for (apicid = 0; apicid < NR_CPUS; apicid++) {
 		/*
 		 * Don't even attempt to start the boot CPU!
 		 */
-		if (i == boot_cpu_id)
+		if (apicid == boot_cpu_id)
 			continue;
 
-		if ((cpu_online_map & (1 << i))
-		    && (max_cpus < 0 || max_cpus > cpucount+1)) {
-			do_boot_cpu(i);
-		}
+		if (!(phys_cpu_present_map & (1 << apicid)))
+			continue;
+		if ((max_cpus >= 0) && (max_cpus < cpucount+1))
+			continue;
+
+		do_boot_cpu(apicid);
 
 		/*
 		 * Make sure we unmap all failed CPUs
 		 */
-		if (cpu_number_map[i] == -1 && (cpu_online_map & (1 << i))) {
-			printk("CPU #%d not responding - cannot use it.\n",i);
-			cpu_online_map &= ~(1 << i);
-		}
+		if ((x86_apicid_to_cpu[apicid] == -1) &&
+				(phys_cpu_present_map & (1 << apicid)))
+			printk("phys CPU #%d not responding - cannot use it.\n",apicid);
 	}
 
 	/*
 	 * Cleanup possible dangling ends...
 	 */
-
 #ifndef CONFIG_VISWS
 	{
 		/*
@@ -1625,26 +911,25 @@
 	 * Allow the user to impress friends.
 	 */
 
-	dprintk("Before bogomips.\n");
+	Dprintk("Before bogomips.\n");
 	if (!cpucount) {
 		printk(KERN_ERR "Error: only one processor found.\n");
-		cpu_online_map = (1<<hard_smp_processor_id());
 	} else {
 		unsigned long bogosum = 0;
-		for(i = 0; i < 32; i++)
-			if (cpu_online_map&(1<<i))
-				bogosum+=cpu_data[i].loops_per_sec;
+		for (cpu = 0; cpu < NR_CPUS; cpu++)
+			if (cpu_online_map & (1<<cpu))
+				bogosum += cpu_data[cpu].loops_per_sec;
 		printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
 			cpucount+1,
 			(bogosum+2500)/500000,
 			((bogosum+2500)/5000)%100);
-		dprintk("Before bogocount - setting activated=1.\n");
+		Dprintk("Before bogocount - setting activated=1.\n");
 	}
 	smp_num_cpus = cpucount + 1;
 
 	if (smp_b_stepping)
 		printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
-	dprintk("Boot done.\n");
+	Dprintk("Boot done.\n");
 
 	cache_APIC_registers();
 #ifndef CONFIG_VISWS
@@ -1657,12 +942,6 @@
 #endif
 
 smp_done:
-	/*
-	 * now we know the other CPUs have fired off and we know our
-	 * APIC ID, so we can go init the TSS and stuff:
-	 */
-	cpu_init();
-
 	/*
 	 * Set up all local APIC timers in the system:
 	 */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)