patch-2.2.0-final linux/arch/i386/kernel/smp.c
Next file: linux/arch/i386/mm/init.c
Previous file: linux/arch/i386/kernel/setup.c
Back to the patch index
Back to the overall index
- Lines: 404
- Date:
Thu Jan 21 11:28:40 1999
- Orig file:
v2.2.0-pre9/linux/arch/i386/kernel/smp.c
- Orig date:
Wed Jan 20 23:14:04 1999
diff -u --recursive --new-file v2.2.0-pre9/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
@@ -37,19 +37,8 @@
#include <linux/delay.h>
#include <linux/mc146818rtc.h>
#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
#include <linux/init.h>
-#include <asm/pgtable.h>
-#include <asm/bitops.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_MTRR
-# include <asm/mtrr.h>
-#endif
-
-#define __KERNEL_SYSCALLS__
-#include <linux/unistd.h>
+#include <asm/mtrr.h>
#include "irq.h"
@@ -100,21 +89,6 @@
spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
/*
- * Why isn't this somewhere standard ??
- *
- * Maybe because this procedure is horribly buggy, and does
- * not deserve to live. Think about signedness issues for five
- * seconds to see why. - Linus
- */
-
-extern __inline int max(int a,int b)
-{
- if (a>b)
- return a;
- return b;
-}
-
-/*
* function prototypes:
*/
static void cache_APIC_registers (void);
@@ -168,6 +142,11 @@
#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
@@ -197,19 +176,11 @@
apic_write(APIC_EOI, 0);
}
-#ifdef CONFIG_X86_VISWS_APIC
/*
- * hacky!
+ * Intel MP BIOS table parsing routines:
*/
-int __init smp_scan_config(unsigned long base, unsigned long length)
-{
- cpu_present_map |= 2; /* or in id 1 */
- apic_version[1] |= 0x10; /* integrated APIC */
- num_processors = 2;
- return 1;
-}
-#else
+#ifndef CONFIG_X86_VISWS_APIC
/*
* Checksum an MP configuration block.
*/
@@ -429,7 +400,7 @@
* Scan the memory blocks for an SMP configuration block.
*/
-int __init smp_scan_config(unsigned long base, unsigned long length)
+static int __init smp_scan_config(unsigned long base, unsigned long length)
{
unsigned long *bp=phys_to_virt(base);
struct intel_mp_floating *mpf;
@@ -463,7 +434,7 @@
unsigned long cfg;
/* local APIC has default address */
- mp_lapic_addr = 0xFEE00000;
+ mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
/*
* We need to know what the local
* APIC id of the boot CPU is!
@@ -579,7 +550,76 @@
return 0;
}
+
+void __init init_intel_smp (void)
+{
+ /*
+ * 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)) {
+ /*
+ * 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.
+ */
+ unsigned int address;
+
+ 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.
@@ -674,6 +714,26 @@
value &= ~APIC_TPRI_MASK; /* Set Task Priority to 'accept all' */
apic_write(APIC_TASKPRI,value);
+ /*
+ * Set arbitrarion priority to 0
+ */
+ value = apic_read(APIC_ARBPRI);
+ value &= ~APIC_ARBPRI_MASK;
+ apic_write(APIC_ARBPRI, value);
+
+ /*
+ * Set the logical destination ID to 'all', just to be safe.
+ * also, put the APIC into flat delivery mode.
+ */
+ value = apic_read(APIC_LDR);
+ value &= ~APIC_LDR_MASK;
+ value |= SET_APIC_LOGICAL_ID(0xff);
+ apic_write(APIC_LDR,value);
+
+ value = apic_read(APIC_DFR);
+ value |= SET_APIC_DFR(0xf);
+ apic_write(APIC_DFR, value);
+
udelay(100); /* B safe */
ack_APIC_irq();
udelay(100);
@@ -681,14 +741,11 @@
unsigned long __init init_smp_mappings(unsigned long memory_start)
{
- unsigned long apic_phys, ioapic_phys;
+ unsigned long apic_phys;
memory_start = PAGE_ALIGN(memory_start);
if (smp_found_config) {
apic_phys = mp_lapic_addr;
-#ifdef CONFIG_X86_IO_APIC
- ioapic_phys = mp_ioapic_addr;
-#endif
} else {
/*
* set up a fake all zeroes page to simulate the
@@ -697,17 +754,27 @@
* this way if some buggy code writes to this page ...
*/
apic_phys = __pa(memory_start);
- ioapic_phys = __pa(memory_start+PAGE_SIZE);
- memset((void *)memory_start, 0, 2*PAGE_SIZE);
- memory_start += 2*PAGE_SIZE;
+ memset((void *)memory_start, 0, PAGE_SIZE);
+ memory_start += PAGE_SIZE;
}
+ set_fixmap(FIX_APIC_BASE,apic_phys);
+ printk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
#ifdef CONFIG_X86_IO_APIC
- set_fixmap(FIX_APIC_BASE,apic_phys);
- set_fixmap(FIX_IO_APIC_BASE,ioapic_phys);
+ {
+ unsigned long ioapic_phys;
- printk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
- printk("mapped IOAPIC to %08lx (%08lx)\n", fix_to_virt(FIX_IO_APIC_BASE), ioapic_phys);
+ if (smp_found_config) {
+ ioapic_phys = mp_ioapic_addr;
+ } else {
+ ioapic_phys = __pa(memory_start);
+ memset((void *)memory_start, 0, PAGE_SIZE);
+ memory_start += PAGE_SIZE;
+ }
+ set_fixmap(FIX_IO_APIC_BASE,ioapic_phys);
+ printk("mapped IOAPIC to %08lx (%08lx)\n",
+ fix_to_virt(FIX_IO_APIC_BASE), ioapic_phys);
+ }
#endif
return memory_start;
@@ -925,8 +992,7 @@
apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */
cfg=apic_read(APIC_ICR);
cfg&=~0xCDFFF; /* Clear bits */
- cfg |= (APIC_DEST_FIELD | APIC_DEST_LEVELTRIG
- | APIC_DEST_ASSERT | APIC_DEST_DM_INIT);
+ cfg |= (APIC_DEST_LEVELTRIG | APIC_DEST_ASSERT | APIC_DEST_DM_INIT);
apic_write(APIC_ICR, cfg); /* Send IPI */
udelay(200);
@@ -937,8 +1003,7 @@
apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */
cfg=apic_read(APIC_ICR);
cfg&=~0xCDFFF; /* Clear bits */
- cfg |= (APIC_DEST_FIELD | APIC_DEST_LEVELTRIG
- | APIC_DEST_DM_INIT);
+ cfg |= (APIC_DEST_LEVELTRIG | APIC_DEST_DM_INIT);
apic_write(APIC_ICR, cfg); /* Send IPI */
/*
@@ -974,9 +1039,7 @@
apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */
cfg=apic_read(APIC_ICR);
cfg&=~0xCDFFF; /* Clear bits */
- cfg |= (APIC_DEST_FIELD
- | APIC_DEST_DM_STARTUP
- | (start_eip >> 12)); /* Boot on the stack */
+ cfg |= (APIC_DEST_DM_STARTUP | (start_eip >> 12)); /* Boot on the stack */
SMP_PRINTK(("Before start apic_write.\n"));
apic_write(APIC_ICR, cfg); /* Kick the second */
@@ -1099,7 +1162,6 @@
void __init smp_boot_cpus(void)
{
int i;
- unsigned long cfg;
#ifdef CONFIG_MTRR
/* Must be done before other processors booted */
@@ -1134,20 +1196,20 @@
cpu_number_map[boot_cpu_id] = 0;
-#ifdef CONFIG_X86_IO_APIC
/*
- * If we don't conform to the Intel MPS standard, get out
- * of here now!
+ * 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;
goto smp_done;
}
-#endif
/*
* If SMP should be disabled, then really disable it!
@@ -1246,29 +1308,34 @@
* Cleanup possible dangling ends...
*/
- /*
- * Install writable page 0 entry.
- */
-
- cfg = pg0[0];
- pg0[0] = 3; /* writeable, present, addr 0 */
- local_flush_tlb();
+#ifndef CONFIG_VISWS
+ {
+ unsigned long cfg;
- /*
- * Paranoid: Set warm reset code and vector here back
- * to default values.
- */
+ /*
+ * Install writable page 0 entry.
+ */
+ cfg = pg0[0];
+ pg0[0] = 3; /* writeable, present, addr 0 */
+ local_flush_tlb();
+
+ /*
+ * Paranoid: Set warm reset code and vector here back
+ * to default values.
+ */
- CMOS_WRITE(0, 0xf);
+ CMOS_WRITE(0, 0xf);
- *((volatile long *) phys_to_virt(0x467)) = 0;
+ *((volatile long *) phys_to_virt(0x467)) = 0;
- /*
- * Restore old page 0 entry.
- */
+ /*
+ * Restore old page 0 entry.
+ */
- pg0[0] = cfg;
- local_flush_tlb();
+ pg0[0] = cfg;
+ local_flush_tlb();
+ }
+#endif
/*
* Allow the user to impress friends.
@@ -1301,15 +1368,16 @@
SMP_PRINTK(("Boot done.\n"));
cache_APIC_registers();
-#ifdef CONFIG_X86_IO_APIC
+#ifndef CONFIG_VISWS
/*
* Here we can be sure that there is an IO-APIC in the system. Let's
* go and set it up:
*/
if (!skip_ioapic_setup)
setup_IO_APIC();
-smp_done:
#endif
+
+smp_done:
}
@@ -1393,7 +1461,7 @@
unsigned int cfg;
cfg = __get_ICR();
- cfg |= APIC_DEST_FIELD|APIC_DEST_DM_FIXED|shortcut|vector;
+ cfg |= APIC_DEST_DM_FIXED|shortcut|vector;
return cfg;
}
@@ -1903,7 +1971,7 @@
((long)(t2-t1)/LOOPS)/(1000000/HZ),
((long)(t2-t1)/LOOPS)%(1000000/HZ) );
- printk("..... APIC bus clock speed is %ld.%04ld MHz.\n",
+ printk("..... system bus clock speed is %ld.%04ld MHz.\n",
calibration_result/(1000000/HZ),
calibration_result%(1000000/HZ) );
#undef LOOPS
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov