summaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
commitb9ba7aeb165cffecdffb60aec8c3fa8d590d9ca9 (patch)
tree42d07b0c7246ae2536a702e7c5de9e2732341116 /arch/i386
parent7406b0a326f2d70ade2671c37d1beef62249db97 (diff)
Merge with 2.3.99-pre6.
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/config.in34
-rw-r--r--arch/i386/defconfig11
-rw-r--r--arch/i386/kernel/acpi.c3
-rw-r--r--arch/i386/kernel/apic.c271
-rw-r--r--arch/i386/kernel/entry.S5
-rw-r--r--arch/i386/kernel/head.S16
-rw-r--r--arch/i386/kernel/i386_ksyms.c7
-rw-r--r--arch/i386/kernel/i8259.c2
-rw-r--r--arch/i386/kernel/io_apic.c242
-rw-r--r--arch/i386/kernel/irq.c8
-rw-r--r--arch/i386/kernel/mca.c12
-rw-r--r--arch/i386/kernel/mpparse.c239
-rw-r--r--arch/i386/kernel/mtrr.c34
-rw-r--r--arch/i386/kernel/pci-irq.c7
-rw-r--r--arch/i386/kernel/process.c1
-rw-r--r--arch/i386/kernel/setup.c8
-rw-r--r--arch/i386/kernel/signal.c4
-rw-r--r--arch/i386/kernel/smp.c114
-rw-r--r--arch/i386/kernel/smpboot.c135
-rw-r--r--arch/i386/kernel/traps.c2
-rw-r--r--arch/i386/kernel/visws_apic.c2
-rw-r--r--arch/i386/lib/delay.c3
-rw-r--r--arch/i386/mm/fault.c4
23 files changed, 654 insertions, 510 deletions
diff --git a/arch/i386/config.in b/arch/i386/config.in
index 664b77800..589c34730 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -20,48 +20,54 @@ comment 'Processor type and features'
choice 'Processor family' \
"386 CONFIG_M386 \
486/Cx486 CONFIG_M486 \
- 586/K5/5x86/6x86 CONFIG_M586 \
+ 586/K5/5x86/6x86/6x86MX CONFIG_M586 \
Pentium/TSC CONFIG_M586TSC \
- PPro/6x86MX CONFIG_M686 \
+ PPro CONFIG_M686 \
K6/II/III CONFIG_MK6 \
Athlon CONFIG_MK7" PPro
#
# Define implied options from the CPU selection here
#
-if [ "$CONFIG_M386" != "y" ]; then
+if [ "$CONFIG_M386" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 16
+else
define_bool CONFIG_X86_WP_WORKS_OK y
define_bool CONFIG_X86_INVLPG y
define_bool CONFIG_X86_CMPXCHG y
define_bool CONFIG_X86_BSWAP y
define_bool CONFIG_X86_POPAD_OK y
fi
-if [ "$CONFIG_M386" = "y" -o "$CONFIG_M486" = "y" ]; then
- define_int CONFIG_X86_L1_CACHE_BYTES 16
-else
- define_int CONFIG_X86_L1_CACHE_BYTES 32
+if [ "$CONFIG_M486" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 16
+ define_bool CONFIG_X86_USE_STRING_486 y
+ define_bool CONFIG_X86_ALIGNMENT_16 y
fi
-if [ "$CONFIG_M486" = "y" -o "$CONFIG_M586" = "y" ]; then
+if [ "$CONFIG_M586" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 32
define_bool CONFIG_X86_USE_STRING_486 y
define_bool CONFIG_X86_ALIGNMENT_16 y
fi
if [ "$CONFIG_M586TSC" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 32
define_bool CONFIG_X86_USE_STRING_486 y
define_bool CONFIG_X86_ALIGNMENT_16 y
define_bool CONFIG_X86_TSC y
fi
-if [ "$CONFIG_MK6" = "y" ]; then
- define_bool CONFIG_X86_ALIGNMENT_16 y
- define_bool CONFIG_X86_TSC y
- define_bool CONFIG_X86_USE_3DNOW y
- define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
-fi
if [ "$CONFIG_M686" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 32
define_bool CONFIG_X86_TSC y
define_bool CONFIG_X86_GOOD_APIC y
define_bool CONFIG_X86_PGE y
define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
fi
+if [ "$CONFIG_MK6" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 32
+ define_bool CONFIG_X86_ALIGNMENT_16 y
+ define_bool CONFIG_X86_TSC y
+ define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
+fi
if [ "$CONFIG_MK7" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 64
define_bool CONFIG_X86_TSC y
define_bool CONFIG_X86_GOOD_APIC y
define_bool CONFIG_X86_USE_3DNOW y
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 80f68ec31..3a8d743f7 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -107,6 +107,7 @@ CONFIG_BLK_DEV_FD=y
#
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_STRIPED is not set
@@ -189,8 +190,8 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_IDEDMA_PCI_EXPERIMENTAL is not set
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_WDC_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD7409 is not set
@@ -214,6 +215,7 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_VIA82CXXX_TUNING is not set
# CONFIG_IDE_CHIPSETS is not set
# CONFIG_IDEDMA_AUTO is not set
CONFIG_BLK_DEV_IDE_MODES=y
@@ -385,7 +387,10 @@ CONFIG_PCMCIA_PCNET=y
# CONFIG_PCMCIA_XIRC2PS is not set
# CONFIG_ARCNET_COM20020_CS is not set
# CONFIG_PCMCIA_IBMTR is not set
-# CONFIG_PCMCIA_3C575 is not set
+
+#
+# 3Com 3c575 moved to Ethernet 10/100 menu
+#
# CONFIG_PCMCIA_XIRTULIP is not set
CONFIG_NET_PCMCIA_RADIO=y
CONFIG_PCMCIA_RAYCS=y
diff --git a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c
index aa09400fc..e63a45e66 100644
--- a/arch/i386/kernel/acpi.c
+++ b/arch/i386/kernel/acpi.c
@@ -583,6 +583,8 @@ static int __init acpi_find_tables(void)
dt = acpi_map_table(facp->dsdt);
if (acpi_init_table(&acpi_dsdt, dt, 1))
acpi_unmap_table(dt);
+
+ break;
}
else {
acpi_unmap_table(dt);
@@ -1127,6 +1129,7 @@ static int acpi_enter_sx(acpi_sstate_t state)
// finished sleeping, update system time
acpi_update_clock();
acpi_enter_dx(ACPI_D0);
+ acpi_sleep_state = ACPI_S0;
return 0;
}
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index a5f72548f..d4c35fdf0 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -4,7 +4,9 @@
* (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
*
* Fixes
- * Maciej W. Rozycki : Bits for genuine 82489DX timers
+ * Maciej W. Rozycki : Bits for genuine 82489DX APICs;
+ * thanks to Eric Gilmore for
+ * testing these extensively
*/
#include <linux/config.h>
@@ -44,32 +46,96 @@ int get_maxlvt(void)
return maxlvt;
}
-void disable_local_APIC (void)
+static void clear_local_APIC(void)
{
- unsigned long value;
- int maxlvt;
+ int maxlvt;
+ unsigned long v;
+
+ maxlvt = get_maxlvt();
/*
- * Disable APIC
+ * Careful: we have to set masks only first to deassert
+ * any level-triggered sources.
*/
- value = apic_read(APIC_SPIV);
- value &= ~(1<<8);
- apic_write(APIC_SPIV,value);
+ v = apic_read(APIC_LVTT);
+ apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
+ v = apic_read(APIC_LVT0);
+ apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
+ v = apic_read(APIC_LVT1);
+ apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED);
+ if (maxlvt >= 3) {
+ v = apic_read(APIC_LVTERR);
+ apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED);
+ }
+ if (maxlvt >= 4) {
+ v = apic_read(APIC_LVTPC);
+ apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
+ }
/*
* 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);
+ apic_write_around(APIC_LVTT, APIC_LVT_MASKED);
+ apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
+ apic_write_around(APIC_LVT1, APIC_LVT_MASKED);
if (maxlvt >= 3)
- apic_write_around(APIC_LVTERR, 0x00010000);
+ apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
if (maxlvt >= 4)
- apic_write_around(APIC_LVTPC, 0x00010000);
+ apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
+}
+
+void __init connect_bsp_APIC(void)
+{
+ if (pic_mode) {
+ /*
+ * Do not trust the local APIC being empty at bootup.
+ */
+ clear_local_APIC();
+ /*
+ * PIC mode, enable symmetric IO mode in the IMCR,
+ * i.e. connect BSP's local APIC to INT and NMI lines.
+ */
+ printk("leaving PIC mode, enabling symmetric IO mode.\n");
+ outb(0x70, 0x22);
+ outb(0x01, 0x23);
+ }
+}
+
+void disconnect_bsp_APIC(void)
+{
+ if (pic_mode) {
+ /*
+ * Put the board back into PIC mode (has an effect
+ * only on certain older boards). Note that APIC
+ * interrupts, including IPIs, won't work beyond
+ * this point! The only exception are INIT IPIs.
+ */
+ printk("disabling symmetric IO mode, entering PIC mode.\n");
+ outb(0x70, 0x22);
+ outb(0x00, 0x23);
+ }
+}
+
+void disable_local_APIC(void)
+{
+ unsigned long value;
+
+ clear_local_APIC();
+
+ /*
+ * Disable APIC (implies clearing of registers
+ * for 82489DX!).
+ */
+ value = apic_read(APIC_SPIV);
+ value &= ~(1<<8);
+ apic_write_around(APIC_SPIV, value);
+}
+
+void __init sync_Arb_IDs(void)
+{
+ Dprintk("Synchronizing Arb IDs.\n");
+ apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG
+ | APIC_DM_INIT);
}
extern void __error_in_apic_c (void);
@@ -78,6 +144,9 @@ void __init setup_local_APIC (void)
{
unsigned long value, ver, maxlvt;
+ value = apic_read(APIC_LVR);
+ ver = GET_APIC_VERSION(value);
+
if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
__error_in_apic_c();
@@ -87,11 +156,12 @@ void __init setup_local_APIC (void)
if (!test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map))
BUG();
- value = apic_read(APIC_SPIV);
+ value = apic_read(APIC_SPIV);
+ value &= ~APIC_VECTOR_MASK;
/*
* Enable APIC
*/
- value |= (1<<8);
+ value |= (1<<8);
/*
* Some unknown Intel IO/APIC (or APIC) errata is biting us with
@@ -108,7 +178,7 @@ void __init setup_local_APIC (void)
*/
#if 0
/* Enable focus processor (bit==0) */
- value &= ~(1<<9);
+ value &= ~(1<<9);
#else
/* Disable focus processor (bit==1) */
value |= (1<<9);
@@ -117,7 +187,7 @@ void __init setup_local_APIC (void)
* Set spurious IRQ vector
*/
value |= SPURIOUS_APIC_VECTOR;
- apic_write(APIC_SPIV,value);
+ apic_write_around(APIC_SPIV, value);
/*
* Set up LVT0, LVT1:
@@ -126,48 +196,44 @@ void __init setup_local_APIC (void)
* strictly necessery in pure symmetric-IO mode, but sometimes
* we delegate interrupts to the 8259A.
*/
- if (!smp_processor_id()) {
- value = 0x00000700;
+ /*
+ * TODO: set up through-local-APIC from through-I/O-APIC? --macro
+ */
+ value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
+ if (!smp_processor_id() && (pic_mode || !value)) {
+ value = APIC_DM_EXTINT;
printk("enabled ExtINT on CPU#%d\n", smp_processor_id());
} else {
- value = 0x00010700;
+ value = APIC_DM_EXTINT | APIC_LVT_MASKED;
printk("masked ExtINT on CPU#%d\n", smp_processor_id());
}
- apic_write_around(APIC_LVT0,value);
+ apic_write_around(APIC_LVT0, value);
/*
* only the BP should see the LINT1 NMI signal, obviously.
*/
if (!smp_processor_id())
- value = 0x00000400; // unmask NMI
+ value = APIC_DM_NMI;
else
- value = 0x00010400; // mask NMI
- apic_write_around(APIC_LVT1,value);
+ value = APIC_DM_NMI | APIC_LVT_MASKED;
+ if (!APIC_INTEGRATED(ver)) /* 82489DX */
+ value |= APIC_LVT_LEVEL_TRIGGER;
+ 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
+ if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
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);
+ apic_write_around(APIC_LVTERR, value);
/*
* spec says clear errors after enabling vector.
*/
- if (maxlvt != 3) {
- apic_readaround(APIC_SPIV);
+ if (maxlvt > 3)
apic_write(APIC_ESR, 0);
- }
value = apic_read(APIC_ESR);
printk("ESR value after enabling vector: %08lx\n", value);
} else
@@ -177,22 +243,23 @@ void __init setup_local_APIC (void)
* 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);
+ value = apic_read(APIC_TASKPRI);
+ value &= ~APIC_TPRI_MASK;
+ apic_write_around(APIC_TASKPRI, value);
/*
* Set up the logical destination ID and put the
* APIC into flat delivery mode.
*/
- value = apic_read(APIC_LDR);
+ value = apic_read(APIC_LDR);
value &= ~APIC_LDR_MASK;
value |= (1<<(smp_processor_id()+24));
- apic_write(APIC_LDR,value);
+ apic_write_around(APIC_LDR, value);
- value = apic_read(APIC_DFR);
- value |= SET_APIC_DFR(0xf);
- apic_write(APIC_DFR, value);
+ /*
+ * Must be "all ones" explicitly for 82489DX.
+ */
+ apic_write_around(APIC_DFR, 0xffffffff);
}
void __init init_apic_mappings(void)
@@ -214,6 +281,13 @@ void __init init_apic_mappings(void)
set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
Dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
+ /*
+ * Fetch the APIC ID of the BSP in case we have a
+ * default configuration (or the MP table is broken).
+ */
+ if (boot_cpu_id == -1U)
+ boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
+
#ifdef CONFIG_X86_IO_APIC
{
unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
@@ -285,7 +359,7 @@ void __init wait_8254_wraparound(void)
* chipset timer can cause.
*/
- } while (delta<300);
+ } while (delta < 300);
}
/*
@@ -305,21 +379,19 @@ void __setup_APIC_LVTT(unsigned int clocks)
{
unsigned int lvtt1_value, tmp_value;
- tmp_value = apic_read(APIC_LVTT);
lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) |
APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
- apic_write(APIC_LVTT, lvtt1_value);
+ apic_write_around(APIC_LVTT, lvtt1_value);
/*
* Divide PICLK by 16
*/
tmp_value = apic_read(APIC_TDCR);
- apic_write(APIC_TDCR, (tmp_value
+ apic_write_around(APIC_TDCR, (tmp_value
& ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
| APIC_TDR_DIV_16);
- tmp_value = apic_read(APIC_TMICT);
- apic_write(APIC_TMICT, clocks/APIC_DIVISOR);
+ apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
}
void setup_APIC_timer(void * data)
@@ -353,6 +425,12 @@ void setup_APIC_timer(void * data)
t0 = apic_read(APIC_TMCCT)*APIC_DIVISOR;
do {
+ /*
+ * It looks like the 82489DX cannot handle
+ * consecutive reads of the TMCCT register well;
+ * this dummy read prevents it from a lockup.
+ */
+ apic_read(APIC_SPIV);
t1 = apic_read(APIC_TMCCT)*APIC_DIVISOR;
delta = (int)(t0 - t1 - slice*(smp_processor_id()+1));
} while (delta < 0);
@@ -490,6 +568,41 @@ int setup_profiling_timer(unsigned int multiplier)
#undef APIC_DIVISOR
+#ifdef CONFIG_SMP
+static inline void handle_smp_time (int user, int cpu)
+{
+ int system = !user;
+ struct task_struct * p = current;
+ /*
+ * After doing the above, we need to make like
+ * a normal interrupt - otherwise timer interrupts
+ * ignore the global interrupt lock, which is the
+ * WrongThing (tm) to do.
+ */
+
+ irq_enter(cpu, 0);
+ update_one_process(p, 1, user, system, cpu);
+ if (p->pid) {
+ p->counter -= 1;
+ if (p->counter <= 0) {
+ p->counter = 0;
+ p->need_resched = 1;
+ }
+ if (p->priority < DEF_PRIORITY) {
+ kstat.cpu_nice += user;
+ kstat.per_cpu_nice[cpu] += user;
+ } else {
+ kstat.cpu_user += user;
+ kstat.per_cpu_user[cpu] += user;
+ }
+ kstat.cpu_system += system;
+ kstat.per_cpu_system[cpu] += system;
+
+ }
+ irq_exit(cpu, 0);
+}
+#endif
+
/*
* Local timer interrupt handler. It does both profiling and
* process statistics/rescheduling.
@@ -502,7 +615,6 @@ int setup_profiling_timer(unsigned int multiplier)
inline void smp_local_timer_interrupt(struct pt_regs * regs)
{
- int user = (user_mode(regs) != 0);
int cpu = smp_processor_id();
/*
@@ -511,13 +623,8 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs)
* updated with atomic operations). This is especially
* useful with a profiling multiplier != 1
*/
- if (!user)
- x86_do_profile(regs->eip);
if (--prof_counter[cpu] <= 0) {
- int system = 1 - user;
- struct task_struct * p = current;
-
/*
* The multiplier may have changed since the last time we got
* to this point as a result of the user writing to
@@ -532,33 +639,9 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs)
prof_old_multiplier[cpu] = prof_counter[cpu];
}
- /*
- * After doing the above, we need to make like
- * a normal interrupt - otherwise timer interrupts
- * ignore the global interrupt lock, which is the
- * WrongThing (tm) to do.
- */
-
- irq_enter(cpu, 0);
- update_one_process(p, 1, user, system, cpu);
- if (p->pid) {
- p->counter -= 1;
- if (p->counter <= 0) {
- p->counter = 0;
- p->need_resched = 1;
- }
- if (p->priority < DEF_PRIORITY) {
- kstat.cpu_nice += user;
- kstat.per_cpu_nice[cpu] += user;
- } else {
- kstat.cpu_user += user;
- kstat.per_cpu_user[cpu] += user;
- }
- kstat.cpu_system += system;
- kstat.per_cpu_system[cpu] += system;
-
- }
- irq_exit(cpu, 0);
+#ifdef CONFIG_SMP
+ handle_smp_time(user_mode(regs), cpu);
+#endif
}
/*
@@ -603,7 +686,17 @@ void smp_apic_timer_interrupt(struct pt_regs * regs)
*/
asmlinkage void smp_spurious_interrupt(void)
{
- ack_APIC_irq();
+ unsigned long v;
+
+ /*
+ * Check if this really is a spurious interrupt and ACK it
+ * if it is a vectored one. Just in case...
+ * Spurious interrupts should not be ACKed.
+ */
+ v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1));
+ if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
+ ack_APIC_irq();
+
/* see sw-dev-man vol 3, chapter 7.4.13.5 */
printk("spurious APIC interrupt on CPU#%d, should never happen.\n",
smp_processor_id());
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index b488d97a8..50887c15c 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -40,6 +40,7 @@
* "current" is in register %ebx during any slow entries.
*/
+#include <linux/config.h>
#include <linux/sys.h>
#include <linux/linkage.h>
#include <asm/segment.h>
@@ -201,7 +202,7 @@ ENTRY(system_call)
call *SYMBOL_NAME(sys_call_table)(,%eax,4)
movl %eax,EAX(%esp) # save the return value
ENTRY(ret_from_sys_call)
-#ifdef __SMP__
+#ifdef CONFIG_SMP
movl processor(%ebx),%eax
shll $5,%eax
movl SYMBOL_NAME(softirq_state)(,%eax),%ecx
@@ -256,7 +257,7 @@ badsys:
ALIGN
ret_from_exception:
-#ifdef __SMP__
+#ifdef CONFIG_SMP
GET_CURRENT(%ebx)
movl processor(%ebx),%eax
shll $5,%eax
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index ee759f2bc..51ab1c8ca 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -51,7 +51,7 @@ startup_32:
movl %eax,%es
movl %eax,%fs
movl %eax,%gs
-#ifdef __SMP__
+#ifdef CONFIG_SMP
orw %bx,%bx
jz 1f
/*
@@ -105,14 +105,14 @@ startup_32:
/* Set up the stack pointer */
lss stack_start,%esp
-#ifdef __SMP__
+#ifdef CONFIG_SMP
orw %bx,%bx
jz 1f /* Initial CPU cleans BSS */
pushl $0
popfl
jmp checkCPUtype
1:
-#endif __SMP__
+#endif CONFIG_SMP
/*
* Clear BSS first so that there are no surprises...
*/
@@ -159,7 +159,7 @@ startup_32:
rep
movsl
1:
-#ifdef __SMP__
+#ifdef CONFIG_SMP
checkCPUtype:
#endif
@@ -234,7 +234,7 @@ is386: pushl %ecx # restore original EFLAGS
orl $2,%eax # set MP
2: movl %eax,%cr0
call check_x87
-#ifdef __SMP__
+#ifdef CONFIG_SMP
incb ready
#endif
lgdt gdt_descr
@@ -245,7 +245,7 @@ is386: pushl %ecx # restore original EFLAGS
movl %eax,%es
movl %eax,%fs
movl %eax,%gs
-#ifdef __SMP__
+#ifdef CONFIG_SMP
movl $(__KERNEL_DS), %eax
movl %eax,%ss # Reload the stack pointer (segment only)
#else
@@ -254,7 +254,7 @@ is386: pushl %ecx # restore original EFLAGS
xorl %eax,%eax
lldt %ax
cld # gcc2 wants the direction flag cleared at all times
-#ifdef __SMP__
+#ifdef CONFIG_SMP
movb ready, %cl
cmpb $1,%cl
je 1f # the first CPU calls start_kernel
@@ -268,7 +268,7 @@ L6:
jmp L6 # main should never return here, but
# just in case, we know what happens.
-#ifdef __SMP__
+#ifdef CONFIG_SMP
ready: .byte 0
#endif
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 5327f24a4..584caa9c1 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -27,6 +27,11 @@ extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(elf_fpregset_t *);
extern spinlock_t rtc_lock;
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+extern void machine_real_restart(unsigned char *, int);
+EXPORT_SYMBOL(machine_real_restart);
+#endif
+
#ifdef CONFIG_SMP
extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
@@ -68,7 +73,6 @@ EXPORT_SYMBOL_NOVERS(__down_write_failed);
EXPORT_SYMBOL_NOVERS(__down_read_failed);
EXPORT_SYMBOL_NOVERS(__rwsem_wake);
/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy);
EXPORT_SYMBOL(csum_partial_copy_generic);
/* Delay loops */
EXPORT_SYMBOL(__udelay);
@@ -84,7 +88,6 @@ EXPORT_SYMBOL_NOVERS(__put_user_4);
EXPORT_SYMBOL(strtok);
EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strncpy_from_user);
EXPORT_SYMBOL(__strncpy_from_user);
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index 61571ab59..334a75f88 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -415,7 +415,7 @@ void __init init_ISA_irqs (void)
for (i = 0; i < NR_IRQS; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = 0;
- irq_desc[i].depth = 0;
+ irq_desc[i].depth = 1;
if (i < 16) {
/*
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 1d4445669..dfee6e4d5 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -13,7 +13,9 @@
* and Ingo Molnar <mingo@redhat.com>
*
* Fixes
- * Maciej W. Rozycki : Bits for genuine 82489DX APICs
+ * Maciej W. Rozycki : Bits for genuine 82489DX APICs;
+ * thanks to Eric Gilmore for
+ * testing these extensively
*/
#include <linux/mm.h>
@@ -46,9 +48,6 @@ struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* MP IRQ source entries */
int mp_irq_entries = 0;
-/* non-0 if default (table-less) MP configuration */
-int mpc_default_type = 0;
-
/*
* Rough estimation of how many shared IRQs there are, can
* be changed anytime.
@@ -166,7 +165,7 @@ static void clear_IO_APIC (void)
#define MAX_PIRQS 8
int pirq_entries [MAX_PIRQS];
-int pirqs_enabled;
+int pirqs_enabled = 0;
int skip_ioapic_setup = 0;
static int __init ioapic_setup(char *str)
@@ -235,7 +234,8 @@ static int __init find_timer_pin(int type)
int lbus = mp_irqs[i].mpc_srcbus;
if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
- mp_bus_id_to_type[lbus] == MP_BUS_EISA) &&
+ mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+ mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
(mp_irqs[i].mpc_irqtype == type) &&
(mp_irqs[i].mpc_srcbusirq == 0x00))
@@ -260,13 +260,15 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin)
if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
break;
- if ((apic || IO_APIC_IRQ(mp_irqs[i].mpc_dstirq)) &&
- (mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
+ if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
!mp_irqs[i].mpc_irqtype &&
(bus == mp_bus_id_to_pci_bus[mp_irqs[i].mpc_srcbus]) &&
(slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
+ if (!(apic || IO_APIC_IRQ(irq)))
+ continue;
+
if (pci_pin == (mp_irqs[i].mpc_srcbusirq & 3))
return irq;
/*
@@ -298,15 +300,27 @@ static int __init EISA_ELCR(unsigned int irq)
* EISA conforming in the MP table, that means its trigger type must
* be read in from the ELCR */
-#define default_EISA_trigger(idx) (EISA_ELCR(mp_irqs[idx].mpc_dstirq))
+#define default_EISA_trigger(idx) (EISA_ELCR(mp_irqs[idx].mpc_srcbusirq))
#define default_EISA_polarity(idx) (0)
-/* ISA interrupts are always polarity zero edge triggered, even when
- * listed as conforming in the MP table. */
+/* ISA interrupts are always polarity zero edge triggered,
+ * when listed as conforming in the MP table. */
#define default_ISA_trigger(idx) (0)
#define default_ISA_polarity(idx) (0)
+/* PCI interrupts are always polarity one level triggered,
+ * when listed as conforming in the MP table. */
+
+#define default_PCI_trigger(idx) (1)
+#define default_PCI_polarity(idx) (1)
+
+/* MCA interrupts are always polarity zero level triggered,
+ * when listed as conforming in the MP table. */
+
+#define default_MCA_trigger(idx) (1)
+#define default_MCA_polarity(idx) (0)
+
static int __init MPBIOS_polarity(int idx)
{
int bus = mp_irqs[idx].mpc_srcbus;
@@ -326,14 +340,19 @@ static int __init MPBIOS_polarity(int idx)
polarity = default_ISA_polarity(idx);
break;
}
- case MP_BUS_EISA:
+ case MP_BUS_EISA: /* EISA pin */
{
polarity = default_EISA_polarity(idx);
break;
}
case MP_BUS_PCI: /* PCI pin */
{
- polarity = 1;
+ polarity = default_PCI_polarity(idx);
+ break;
+ }
+ case MP_BUS_MCA: /* MCA pin */
+ {
+ polarity = default_MCA_polarity(idx);
break;
}
default:
@@ -385,19 +404,24 @@ static int __init MPBIOS_trigger(int idx)
{
switch (mp_bus_id_to_type[bus])
{
- case MP_BUS_ISA:
+ case MP_BUS_ISA: /* ISA pin */
{
trigger = default_ISA_trigger(idx);
break;
}
- case MP_BUS_EISA:
+ case MP_BUS_EISA: /* EISA pin */
{
trigger = default_EISA_trigger(idx);
break;
}
- case MP_BUS_PCI: /* PCI pin, level */
+ case MP_BUS_PCI: /* PCI pin */
{
- trigger = 1;
+ trigger = default_PCI_trigger(idx);
+ break;
+ }
+ case MP_BUS_MCA: /* MCA pin */
+ {
+ trigger = default_MCA_trigger(idx);
break;
}
default:
@@ -460,6 +484,7 @@ static int __init pin_2_irq(int idx, int apic, int pin)
{
case MP_BUS_ISA: /* ISA pin */
case MP_BUS_EISA:
+ case MP_BUS_MCA:
{
irq = mp_irqs[idx].mpc_srcbusirq;
break;
@@ -624,8 +649,8 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
disable_8259A_irq(0);
- apic_readaround(APIC_LVT0);
- apic_write(APIC_LVT0, 0x00010700); // mask LVT0
+ /* mask LVT0 */
+ apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
init_8259A(1);
@@ -650,8 +675,8 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
/*
* Add it to the IO-APIC irq-routing table:
*/
- io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
+ io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
enable_8259A_irq(0);
}
@@ -725,8 +750,8 @@ void __init print_IO_APIC(void)
printk(KERN_DEBUG ".... IRQ redirection table:\n");
- printk(KERN_DEBUG " NR Log Phy ");
- printk(KERN_DEBUG "Mask Trig IRR Pol Stat Dest Deli Vect: \n");
+ printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"
+ " Stat Dest Deli Vect: \n");
for (i = 0; i <= reg_01.entries; i++) {
struct IO_APIC_route_entry entry;
@@ -831,13 +856,8 @@ void /*__init*/ print_local_APIC(void * dummy)
print_APIC_bitfield(APIC_IRR);
if (APIC_INTEGRATED(ver)) { /* !82489DX */
- /*
- * Due to the Pentium erratum 3AP.
- */
- if (maxlvt > 3) {
- apic_readaround(APIC_SPIV); // not strictly necessery
+ if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
apic_write(APIC_ESR, 0);
- }
v = apic_read(APIC_ESR);
printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
}
@@ -879,6 +899,32 @@ void print_all_local_APICs (void)
print_local_APIC(NULL);
}
+void /*__init*/ print_PIC(void)
+{
+ unsigned int v, flags;
+
+ printk(KERN_DEBUG "\nprinting PIC contents\n");
+
+ v = inb(0xa1) << 8 | inb(0x21);
+ printk(KERN_DEBUG "... PIC IMR: %04x\n", v);
+
+ v = inb(0xa0) << 8 | inb(0x20);
+ printk(KERN_DEBUG "... PIC IRR: %04x\n", v);
+
+ __save_flags(flags);
+ __cli();
+ outb(0x0b,0xa0);
+ outb(0x0b,0x20);
+ v = inb(0xa0) << 8 | inb(0x20);
+ outb(0x0a,0xa0);
+ outb(0x0a,0x20);
+ __restore_flags(flags);
+ printk(KERN_DEBUG "... PIC ISR: %04x\n", v);
+
+ v = inb(0x4d1) << 8 | inb(0x4d0);
+ printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
+}
+
static void __init enable_IO_APIC(void)
{
struct IO_APIC_reg_01 reg_01;
@@ -890,16 +936,7 @@ static void __init enable_IO_APIC(void)
}
if (!pirqs_enabled)
for (i = 0; i < MAX_PIRQS; i++)
- pirq_entries[i] =- 1;
-
- if (pic_mode) {
- /*
- * PIC mode, enable symmetric IO mode in the IMCR.
- */
- printk("leaving PIC mode, enabling symmetric IO mode.\n");
- outb(0x70, 0x22);
- outb(0x01, 0x23);
- }
+ pirq_entries[i] = -1;
/*
* The number of IO-APIC IRQ registers (== #pins):
@@ -925,15 +962,7 @@ void disable_IO_APIC(void)
*/
clear_IO_APIC();
- /*
- * Put it back into PIC mode (has an effect only on
- * certain older boards)
- */
- if (pic_mode) {
- printk("disabling symmetric IO mode, entering PIC mode.\n");
- outb_p(0x70, 0x22);
- outb_p(0x00, 0x23);
- }
+ disconnect_bsp_APIC();
}
/*
@@ -986,48 +1015,6 @@ static void __init setup_ioapic_ids_from_mpc (void)
}
}
-static void __init construct_default_ISA_mptable(void)
-{
- int i, pos = 0;
- const int bus_type = (mpc_default_type == 2 || mpc_default_type == 3 ||
- mpc_default_type == 6) ? MP_BUS_EISA : MP_BUS_ISA;
-
- for (i = 0; i < 16; i++) {
- if (!IO_APIC_IRQ(i))
- continue;
-
- mp_irqs[pos].mpc_irqtype = mp_INT;
- mp_irqs[pos].mpc_irqflag = 0; /* default */
- mp_irqs[pos].mpc_srcbus = 0;
- mp_irqs[pos].mpc_srcbusirq = i;
- mp_irqs[pos].mpc_dstapic = 0;
- mp_irqs[pos].mpc_dstirq = i;
- pos++;
- }
- mp_irq_entries = pos;
- mp_bus_id_to_type[0] = bus_type;
-
- /*
- * MP specification 1.4 defines some extra rules for default
- * configurations, fix them up here:
- */
- switch (mpc_default_type)
- {
- case 2:
- /*
- * IRQ0 is not connected:
- */
- mp_irqs[0].mpc_irqtype = mp_ExtINT;
- break;
- default:
- /*
- * pin 2 is IRQ0:
- */
- mp_irqs[0].mpc_dstirq = 2;
- }
-
-}
-
/*
* There is a nasty bug in some older SMP boards, their mptable lies
* about the timer IRQ. We do the following to work around the situation:
@@ -1041,9 +1028,17 @@ static int __init timer_irq_works(void)
unsigned int t1 = jiffies;
sti();
- mdelay(40);
+ /* Let ten ticks pass... */
+ mdelay((10 * 1000) / HZ);
- if (jiffies-t1>1)
+ /*
+ * Expect a few ticks at least, to be sure some possible
+ * glue logic does not lock up after one or two first
+ * ticks in a non-ExtINT mode. Also the local APIC
+ * might have cached one ExtINT interrupt. Finally, at
+ * least one tick may be lost due to delays.
+ */
+ if (jiffies - t1 > 4)
return 1;
return 0;
@@ -1257,8 +1252,14 @@ static struct hw_interrupt_type lapic_irq_type = {
static void enable_NMI_through_LVT0 (void * dummy)
{
- apic_readaround(APIC_LVT0);
- apic_write(APIC_LVT0, 0x00000400); // unmask and set to NMI
+ unsigned int v, ver;
+
+ ver = apic_read(APIC_LVR);
+ ver = GET_APIC_VERSION(ver);
+ v = APIC_DM_NMI; /* unmask and set to NMI */
+ if (!APIC_INTEGRATED(ver)) /* 82489DX */
+ v |= APIC_LVT_LEVEL_TRIGGER;
+ apic_write_around(APIC_LVT0, v);
}
static void setup_nmi (void)
@@ -1303,24 +1304,23 @@ static inline void check_timer(void)
printk(KERN_INFO "..TIMER: vector=%d pin1=%d pin2=%d\n", vector, pin1, pin2);
- /*
- * Ok, does IRQ0 through the IOAPIC work?
- */
- if (timer_irq_works()) {
- if (nmi_watchdog) {
- disable_8259A_irq(0);
- init_8259A(1);
- setup_nmi();
- enable_8259A_irq(0);
- if (nmi_irq_works())
- return;
- } else
- return;
- }
-
if (pin1 != -1) {
- printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
+ /*
+ * Ok, does IRQ0 through the IOAPIC work?
+ */
+ unmask_IO_APIC_irq(0);
+ if (timer_irq_works()) {
+ if (nmi_watchdog) {
+ disable_8259A_irq(0);
+ init_8259A(1);
+ setup_nmi();
+ enable_8259A_irq(0);
+ nmi_irq_works();
+ }
+ return;
+ }
clear_IO_APIC_pin(0, pin1);
+ printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
}
printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
@@ -1334,10 +1334,9 @@ static inline void check_timer(void)
printk("works.\n");
if (nmi_watchdog) {
setup_nmi();
- if (nmi_irq_works())
- return;
- } else
- return;
+ nmi_irq_works();
+ }
+ return;
}
/*
* Cleanup, just in case ...
@@ -1355,9 +1354,8 @@ static inline void check_timer(void)
disable_8259A_irq(0);
irq_desc[0].handler = &lapic_irq_type;
- init_8259A(1); // AEOI mode
- apic_readaround(APIC_LVT0);
- apic_write(APIC_LVT0, 0x00000000 | vector); // Fixed mode
+ init_8259A(1); /* AEOI mode */
+ apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */
enable_8259A_irq(0);
if (timer_irq_works()) {
@@ -1392,20 +1390,11 @@ void __init setup_IO_APIC(void)
printk("ENABLING IO-APIC IRQs\n");
/*
- * If there are no explicit MP IRQ entries, it's either one of the
- * default configuration types or we are broken. In both cases it's
- * fine to set up most of the low 16 IO-APIC pins to ISA defaults.
- */
- if (!mp_irq_entries) {
- printk("no explicit IRQ entries, using default mptable\n");
- construct_default_ISA_mptable();
- }
-
- /*
* Set up the IO-APIC IRQ routing table by parsing the MP-BIOS
* mptable:
*/
setup_ioapic_ids_from_mpc();
+ sync_Arb_IDs();
setup_IO_APIC_irqs();
init_IO_APIC_traps();
check_timer();
@@ -1421,6 +1410,7 @@ void IO_APIC_init_uniprocessor (void)
{
if (!smp_found_config)
return;
+ connect_bsp_APIC();
setup_local_APIC();
setup_IO_APIC();
setup_APIC_clocks();
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index a96540d6e..79155a326 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -462,8 +462,8 @@ int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction *
* @irq: Interrupt to disable
*
* Disable the selected interrupt line. Disables of an interrupt
- * stack. Unlike disable_irq, this function does not ensure existing
- * instances of the irq handler have completed before returning.
+ * stack. Unlike disable_irq(), this function does not ensure existing
+ * instances of the IRQ handler have completed before returning.
*
* This function may be called from IRQ context.
*/
@@ -1127,7 +1127,7 @@ static void register_irq_proc (unsigned int irq)
irq_dir[irq] = proc_mkdir(name, root_irq_dir);
/* create /proc/irq/1234/smp_affinity */
- entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]);
+ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
entry->nlink = 1;
entry->data = (void *)(long)irq;
@@ -1148,7 +1148,7 @@ void init_irq_proc (void)
root_irq_dir = proc_mkdir("irq", 0);
/* create /proc/irq/prof_cpu_mask */
- entry = create_proc_entry("prof_cpu_mask", 0700, root_irq_dir);
+ entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
entry->nlink = 1;
entry->data = (void *)&prof_cpu_mask;
diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c
index f0f0f9f37..6c6053bf7 100644
--- a/arch/i386/kernel/mca.c
+++ b/arch/i386/kernel/mca.c
@@ -366,12 +366,12 @@ void mca_handle_nmi(void)
/**
* mca_find_adapter - scan for adapters
* @id: MCA identification to search for
- * @start: Starting slot
+ * @start: starting slot
*
* Search the MCA configuration for adapters matching the 16bit
* ID given. The first time it should be called with start as zero
* and then further calls made passing the return value of the
- * previous call until MCA_NOTFOUND is returned.
+ * previous call until %MCA_NOTFOUND is returned.
*
* Disabled adapters are not reported.
*/
@@ -411,12 +411,12 @@ EXPORT_SYMBOL(mca_find_adapter);
/**
* mca_find_unused_adapter - scan for unused adapters
* @id: MCA identification to search for
- * @start: Starting slot
+ * @start: starting slot
*
* Search the MCA configuration for adapters matching the 16bit
* ID given. The first time it should be called with start as zero
* and then further calls made passing the return value of the
- * previous call until MCA_NOTFOUND is returned.
+ * previous call until %MCA_NOTFOUND is returned.
*
* Adapters that have been claimed by drivers and those that
* are disabled are not reported. This function thus allows a driver
@@ -647,10 +647,10 @@ EXPORT_SYMBOL(mca_set_adapter_name);
* function is called with the buffer, slot, and device pointer (or
* some equally informative context information, or nothing, if you
* prefer), and is expected to put useful information into the
- * buffer. The adapter name, id, and POS registers get printed
+ * buffer. The adapter name, ID, and POS registers get printed
* before this is called though, so don't do it again.
*
- * This should be called with a NULL procfn when a module
+ * This should be called with a %NULL @procfn when a module
* unregisters, thus preventing kernel crashes and other such
* nastiness.
*/
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 030b31647..5df83a10a 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -9,7 +9,7 @@
* Erich Boleyn : MP v1.4 and additional changes.
* Alan Cox : Added EBDA scanning
* Ingo Molnar : various cleanups and rewrites
- * Maciej W. Rozycki : Bits for genuine 82489DX APICs
+ * Maciej W. Rozycki : Bits for default MP configurations
*/
#include <linux/mm.h>
@@ -34,7 +34,7 @@ int smp_found_config = 0;
* Various Linux-internal data structures created from the
* MP-table.
*/
-int apic_version [NR_CPUS];
+int apic_version [MAX_APICS];
int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
int mp_current_pci_id = 0;
@@ -42,9 +42,9 @@ int pic_mode;
unsigned long mp_lapic_addr = 0;
/* Processor that is doing the boot up */
-unsigned int boot_cpu_id = 0;
+unsigned int boot_cpu_id = -1U;
/* Internal processor count */
-static unsigned int num_processors = 1;
+static unsigned int num_processors = 0;
/* Bitmask of physically existing CPUs */
unsigned long phys_cpu_present_map = 0;
@@ -132,13 +132,12 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
Dprintk(" Bootup CPU\n");
boot_cpu_id = m->mpc_apicid;
- } else
- /* Boot CPU already counted */
- num_processors++;
+ }
+ num_processors++;
- if (m->mpc_apicid > NR_CPUS) {
- printk("Processor #%d unused. (Max %d processors).\n",
- m->mpc_apicid, NR_CPUS);
+ if (m->mpc_apicid > MAX_APICS) {
+ printk("Processor #%d INVALID. (Max ID: %d).\n",
+ m->mpc_apicid, MAX_APICS);
return;
}
ver = m->mpc_apicver;
@@ -164,18 +163,18 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
if (strncmp(str, "ISA", 3) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
- } else {
- if (strncmp(str, "EISA", 4) == 0) {
+ } 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) {
+ } 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 if (strncmp(str, "MCA", 3) == 0) {
+ mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
} 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)
@@ -197,12 +196,22 @@ static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
{
mp_irqs [mp_irq_entries] = *m;
+ Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
+ " IRQ %02x, APIC ID %x, APIC INT %02x\n",
+ m->mpc_irqtype, m->mpc_irqflag & 3,
+ (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
+ m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
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)
{
+ Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
+ " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+ m->mpc_irqtype, m->mpc_irqflag & 3,
+ (m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
+ m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
/*
* Well it seems all SMP boards in existence
* use ExtINT/LVT1 == LINT0 and
@@ -316,6 +325,122 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
return num_processors;
}
+static void __init construct_default_ioirq_mptable(int mpc_default_type)
+{
+ struct mpc_config_intsrc intsrc;
+ int i;
+
+ intsrc.mpc_type = MP_INTSRC;
+ intsrc.mpc_irqflag = 0; /* conforming */
+ intsrc.mpc_srcbus = 0;
+ intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
+
+ intsrc.mpc_irqtype = mp_INT;
+ for (i = 0; i < 16; i++) {
+ switch (mpc_default_type) {
+ case 2:
+ if (i == 0 || i == 13)
+ continue; /* IRQ0 & IRQ13 not connected */
+ /* fall through */
+ default:
+ if (i == 2)
+ continue; /* IRQ2 is never connected */
+ }
+
+ intsrc.mpc_srcbusirq = i;
+ intsrc.mpc_dstirq = i ? i : 2; /* IRQ0 to INTIN2 */
+ MP_intsrc_info(&intsrc);
+ }
+
+ intsrc.mpc_irqtype = mp_ExtINT;
+ intsrc.mpc_srcbusirq = 0;
+ intsrc.mpc_dstirq = 0; /* 8259A to INTIN0 */
+ MP_intsrc_info(&intsrc);
+}
+
+static inline void __init construct_default_ISA_mptable(int mpc_default_type)
+{
+ struct mpc_config_processor processor;
+ struct mpc_config_bus bus;
+ struct mpc_config_ioapic ioapic;
+ struct mpc_config_lintsrc lintsrc;
+ int linttypes[2] = { mp_ExtINT, mp_NMI };
+ int i;
+
+ /*
+ * local APIC has default address
+ */
+ mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+
+ /*
+ * 2 CPUs, numbered 0 & 1.
+ */
+ processor.mpc_type = MP_PROCESSOR;
+ /* Either an integrated APIC or a discrete 82489DX. */
+ processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+ processor.mpc_cpuflag = CPU_ENABLED;
+ processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
+ (boot_cpu_data.x86_model << 4) |
+ boot_cpu_data.x86_mask;
+ processor.mpc_featureflag = boot_cpu_data.x86_capability;
+ processor.mpc_reserved[0] = 0;
+ processor.mpc_reserved[1] = 0;
+ for (i = 0; i < 2; i++) {
+ processor.mpc_apicid = i;
+ MP_processor_info(&processor);
+ }
+
+ bus.mpc_type = MP_BUS;
+ bus.mpc_busid = 0;
+ switch (mpc_default_type) {
+ default:
+ printk("???\nUnknown standard configuration %d\n",
+ mpc_default_type);
+ /* fall through */
+ case 1:
+ case 5:
+ memcpy(bus.mpc_bustype, "ISA ", 6);
+ break;
+ case 2:
+ case 6:
+ case 3:
+ memcpy(bus.mpc_bustype, "EISA ", 6);
+ break;
+ case 4:
+ case 7:
+ memcpy(bus.mpc_bustype, "MCA ", 6);
+ }
+ MP_bus_info(&bus);
+ if (mpc_default_type > 4) {
+ bus.mpc_busid = 1;
+ memcpy(bus.mpc_bustype, "PCI ", 6);
+ MP_bus_info(&bus);
+ }
+
+ ioapic.mpc_type = MP_IOAPIC;
+ ioapic.mpc_apicid = 2;
+ ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+ ioapic.mpc_flags = MPC_APIC_USABLE;
+ ioapic.mpc_apicaddr = 0xFEC00000;
+ MP_ioapic_info(&ioapic);
+
+ /*
+ * We set up most of the low 16 IO-APIC pins according to MPS rules.
+ */
+ construct_default_ioirq_mptable(mpc_default_type);
+
+ lintsrc.mpc_type = MP_LINTSRC;
+ lintsrc.mpc_irqflag = 0; /* conforming */
+ lintsrc.mpc_srcbusid = 0;
+ lintsrc.mpc_srcbusirq = 0;
+ lintsrc.mpc_destapic = MP_APIC_ALL;
+ for (i = 0; i < 2; i++) {
+ lintsrc.mpc_irqtype = linttypes[i];
+ lintsrc.mpc_destapiclint = i;
+ MP_lintsrc_info(&lintsrc);
+ }
+}
+
static struct intel_mp_floating *mpf_found;
/*
@@ -332,83 +457,43 @@ void __init get_smp_config (void)
printk(" Virtual Wire compatibility mode.\n");
pic_mode = 0;
}
- /*
- * 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) {
+
printk("Default MP configuration #%d\n", mpf->mpf_feature1);
+ construct_default_ISA_mptable(mpf->mpf_feature1);
- /*
- * local APIC has default address
- */
- mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+ } else if (mpf->mpf_physptr) {
/*
- * 2 CPUs, numbered 0 & 1.
+ * Read the physical hardware table. Anything here will
+ * override the defaults.
*/
- phys_cpu_present_map = 3;
- num_processors = 2;
+ smp_read_mpc((void *)mpf->mpf_physptr);
- nr_ioapics = 1;
- mp_ioapics[0].mpc_apicaddr = 0xFEC00000;
- mp_ioapics[0].mpc_apicid = 2;
/*
- * Save the default type number, we
- * need it later to set the IO-APIC
- * up properly:
+ * If there are no explicit MP IRQ entries, then we are
+ * broken. We set up most of the low 16 IO-APIC pins to
+ * ISA defaults and hope it will work.
*/
- mpc_default_type = mpf->mpf_feature1;
+ if (!mp_irq_entries) {
+ struct mpc_config_bus bus;
- printk("Bus #0 is ");
- }
+ printk("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
- 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;
- }
- if (mpf->mpf_feature1 > 4) {
- printk("Bus #1 is PCI\n");
+ bus.mpc_type = MP_BUS;
+ bus.mpc_busid = 0;
+ memcpy(bus.mpc_bustype, "ISA ", 6);
+ MP_bus_info(&bus);
- /*
- * 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);
+ construct_default_ioirq_mptable(0);
+ }
+
+ } else
+ BUG();
printk("Processors: %d\n", num_processors);
/*
diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c
index f5a035cc7..fb066f051 100644
--- a/arch/i386/kernel/mtrr.c
+++ b/arch/i386/kernel/mtrr.c
@@ -289,7 +289,7 @@
#define MTRRfix4K_F0000_MSR 0x26e
#define MTRRfix4K_F8000_MSR 0x26f
-#ifdef __SMP__
+#ifdef CONFIG_SMP
# define MTRR_CHANGE_MASK_FIXED 0x01
# define MTRR_CHANGE_MASK_VARIABLE 0x02
# define MTRR_CHANGE_MASK_DEFTYPE 0x04
@@ -302,7 +302,7 @@ typedef u8 mtrr_type;
#define LINE_SIZE 80
#define JIFFIE_TIMEOUT 100
-#ifdef __SMP__
+#ifdef CONFIG_SMP
# define set_mtrr(reg,base,size,type) set_mtrr_smp (reg, base, size, type)
#else
# define set_mtrr(reg,base,size,type) (*set_mtrr_up) (reg, base, size, type, \
@@ -767,7 +767,7 @@ static void (*set_mtrr_up) (unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type,
int do_safe) = NULL;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
struct mtrr_var_range
{
@@ -1015,7 +1015,7 @@ static void __init mtrr_state_warn(unsigned long mask)
printk ("mtrr: probably your BIOS does not setup all CPUs\n");
} /* End Function mtrr_state_warn */
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
static char *attrib_to_str (int x)
{
@@ -1110,7 +1110,7 @@ static int (*get_free_region) (unsigned long base,
*
* Memory type region registers control the caching on newer Intel and
* non Intel processors. This function allows drivers to request an
- * MTRR is added. The details and hardware specifics of each processors
+ * MTRR is added. The details and hardware specifics of each processor's
* implementation are hidden from the caller, but nevertheless the
* caller should expect to need to provide a power of two size on an
* equivalent power of two boundary.
@@ -1125,13 +1125,13 @@ static int (*get_free_region) (unsigned long base,
*
* The available types are
*
- * MTRR_TYPE_UNCACHEABLE - No caching
+ * %MTRR_TYPE_UNCACHEABLE - No caching
*
- * MTRR_TYPE_WRITEBACK - Write data back in bursts whenever
+ * %MTRR_TYPE_WRITEBACK - Write data back in bursts whenever
*
- * MTRR_TYPE_WRCOMB - Write data back soon but allow bursts
+ * %MTRR_TYPE_WRCOMB - Write data back soon but allow bursts
*
- * MTRR_TYPE_WRTHROUGH - Cache reads but not writes
+ * %MTRR_TYPE_WRTHROUGH - Cache reads but not writes
*
* BUGS: Needs a quiet flag for the cases where drivers do not mind
* failures and do not wish system log messages to be sent.
@@ -1608,7 +1608,7 @@ static void compute_ascii (void)
EXPORT_SYMBOL(mtrr_add);
EXPORT_SYMBOL(mtrr_del);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
typedef struct
{
@@ -1663,7 +1663,7 @@ static void __init cyrix_arr_init(void)
struct set_mtrr_context ctxt;
unsigned char ccr[7];
int ccrc[7] = { 0, 0, 0, 0, 0, 0, 0 };
-#ifdef __SMP__
+#ifdef CONFIG_SMP
int i;
#endif
@@ -1709,7 +1709,7 @@ static void __init cyrix_arr_init(void)
setCx86 (CX86_CCR5, ccr[5]);
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
for(i=0; i<7; i++) ccr_state[i] = ccr[i];
for(i=0; i<8; i++)
cyrix_get_arr(i,
@@ -1782,7 +1782,7 @@ static void __init mtrr_setup(void)
}
} /* End Function mtrr_setup */
-#ifdef __SMP__
+#ifdef CONFIG_SMP
static volatile unsigned long smp_changes_mask __initdata = 0;
static struct mtrr_state smp_mtrr_state __initdata = {0, 0};
@@ -1851,12 +1851,12 @@ void __init mtrr_init_secondary_cpu(void)
break;
}
} /* End Function mtrr_init_secondary_cpu */
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
int __init mtrr_init(void)
{
if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return 0;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
switch (boot_cpu_data.x86_vendor)
{
case X86_VENDOR_AMD:
@@ -1866,7 +1866,7 @@ int __init mtrr_init(void)
mtrr_state_warn (smp_changes_mask);
break;
}
-#else /* __SMP__ */
+#else /* CONFIG_SMP */
mtrr_setup ();
switch (boot_cpu_data.x86_vendor)
{
@@ -1877,7 +1877,7 @@ int __init mtrr_init(void)
centaur_mcr_init ();
break;
}
-#endif /* !__SMP__ */
+#endif /* !CONFIG_SMP */
#ifdef CONFIG_PROC_FS
proc_root_mtrr = create_proc_entry ("mtrr", S_IWUSR | S_IRUGO, &proc_root);
diff --git a/arch/i386/kernel/pci-irq.c b/arch/i386/kernel/pci-irq.c
index 8dd3f5c82..4695abdf4 100644
--- a/arch/i386/kernel/pci-irq.c
+++ b/arch/i386/kernel/pci-irq.c
@@ -29,7 +29,7 @@ static struct irq_routing_table *pirq_table;
* Avoid using: 13, 14 and 15 (FP error and IDE).
* Penalize: 3, 4, 7, 12 (known ISA uses: serial, parallel and mouse)
*/
-unsigned int pcibios_irq_mask = ~0;
+unsigned int pcibios_irq_mask = 0xfff8;
static unsigned pirq_penalty[16] = {
10000, 10000, 10000, 100, 100, 0, 0, 100,
@@ -305,10 +305,7 @@ int pcibios_lookup_irq(struct pci_dev *dev, int assign)
return 0;
}
DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
- if (pcibios_irq_mask != ~0)
- mask &= pcibios_irq_mask;
- else
- mask &= pirq_table->exclusive_irqs;
+ mask &= pcibios_irq_mask;
/* Find the best IRQ to assign */
newirq = 0;
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 3ba1d8257..96eedb519 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -589,7 +589,6 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
* More important, however, is the fact that this allows us much
* more flexibility.
*/
-extern int cpus_initialized;
void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
{
struct thread_struct *prev = &prev_p->thread,
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 71407c0ea..ac088253f 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -495,6 +495,10 @@ static inline void parse_mem_cmdline (char ** cmdline_p)
if (!memcmp(from+4, "nopentium", 9)) {
from += 9+4;
boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE;
+ } else if (!memcmp(from+4, "exactmap", 8)) {
+ from += 8+4;
+ e820.nr_map = 0;
+ usermem = 1;
} else {
/* If the user specifies memory size, we
* blow away any automatically generated
@@ -1531,8 +1535,7 @@ int get_cpuinfo(char * buffer)
return p - buffer;
}
-int cpus_initialized = 0;
-unsigned long cpu_initialized = 0;
+static unsigned long cpu_initialized __initdata = 0;
/*
* cpu_init() initializes state that is per-CPU. Some data is already
@@ -1549,7 +1552,6 @@ void __init cpu_init (void)
printk("CPU#%d already initialized!\n", nr);
for (;;) __sti();
}
- cpus_initialized++;
printk("Initializing CPU#%d\n", nr);
if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index c7c079194..4e813fac7 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -339,9 +339,9 @@ setup_sigcontext(struct sigcontext *sc, struct _fpstate *fpstate,
int tmp, err = 0;
tmp = 0;
- __asm__("movl %%gs,%w0" : "=r"(tmp): "0"(tmp));
+ __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
err |= __put_user(tmp, (unsigned int *)&sc->gs);
- __asm__("movl %%fs,%w0" : "=r"(tmp): "0"(tmp));
+ __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
err |= __put_user(tmp, (unsigned int *)&sc->fs);
err |= __put_user(regs->xes, (unsigned int *)&sc->es);
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 12f193c71..94ba5c49f 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -111,108 +111,26 @@ struct tlb_state cpu_tlbstate[NR_CPUS] = {[0 ... NR_CPUS-1] = { &init_mm, 0 }};
* We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
*/
-static unsigned int cached_APIC_ICR;
-static unsigned int cached_APIC_ICR2;
-
-/*
- * Caches reserved bits, APIC reads are (mildly) expensive
- * and force otherwise unnecessary CPU synchronization.
- *
- * (We could cache other APIC registers too, but these are the
- * main ones used in RL.)
- */
-#define slow_ICR (apic_read(APIC_ICR) & ~0xFDFFF)
-#define slow_ICR2 (apic_read(APIC_ICR2) & 0x00FFFFFF)
-
-void cache_APIC_registers (void)
-{
- cached_APIC_ICR = slow_ICR;
- cached_APIC_ICR2 = slow_ICR2;
- mb();
-}
-
-static inline unsigned int __get_ICR (void)
-{
-#if FORCE_READ_AROUND_WRITE
- /*
- * Wait for the APIC to become ready - this should never occur. It's
- * a debugging check really.
- */
- int count = 0;
- unsigned int cfg;
-
- while (count < 1000)
- {
- cfg = slow_ICR;
- if (!(cfg&(1<<12)))
- return cfg;
- printk("CPU #%d: ICR still busy [%08x]\n",
- smp_processor_id(), cfg);
- irq_err_count++;
- count++;
- udelay(10);
- }
- printk("CPU #%d: previous IPI still not cleared after 10mS\n",
- smp_processor_id());
- return cfg;
-#else
- return cached_APIC_ICR;
-#endif
-}
-
-static inline unsigned int __get_ICR2 (void)
-{
-#if FORCE_READ_AROUND_WRITE
- return slow_ICR2;
-#else
- return cached_APIC_ICR2;
-#endif
-}
-
-#define LOGICAL_DELIVERY 1
-
static inline int __prepare_ICR (unsigned int shortcut, int vector)
{
- unsigned int cfg;
-
- cfg = __get_ICR();
- cfg |= APIC_DEST_DM_FIXED|shortcut|vector
-#if LOGICAL_DELIVERY
- |APIC_DEST_LOGICAL
-#endif
- ;
-
- return cfg;
+ return APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL;
}
static inline int __prepare_ICR2 (unsigned int mask)
{
- unsigned int cfg;
-
- cfg = __get_ICR2();
-#if LOGICAL_DELIVERY
- cfg |= SET_APIC_DEST_FIELD(mask);
-#else
- cfg |= SET_APIC_DEST_FIELD(mask);
-#endif
-
- return cfg;
+ return SET_APIC_DEST_FIELD(mask);
}
static inline void __send_IPI_shortcut(unsigned int shortcut, int vector)
{
+ /*
+ * Subtle. In the case of the 'never do double writes' workaround
+ * we have to lock out interrupts to be safe. As we don't care
+ * of the value read we use an atomic rmw access to avoid costly
+ * cli/sti. Otherwise we use an even cheaper single atomic write
+ * to the APIC.
+ */
unsigned int cfg;
-/*
- * Subtle. In the case of the 'never do double writes' workaround we
- * have to lock out interrupts to be safe. Otherwise it's just one
- * single atomic write to the APIC, no need for cli/sti.
- */
-#if FORCE_READ_AROUND_WRITE
- unsigned long flags;
-
- __save_flags(flags);
- __cli();
-#endif
/*
* No need to touch the target chip field
@@ -222,10 +140,7 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector)
/*
* Send the IPI. The write to APIC_ICR fires this off.
*/
- apic_write(APIC_ICR, cfg);
-#if FORCE_READ_AROUND_WRITE
- __restore_flags(flags);
-#endif
+ apic_write_around(APIC_ICR, cfg);
}
static inline void send_IPI_allbutself(int vector)
@@ -252,19 +167,16 @@ void send_IPI_self(int vector)
static inline void send_IPI_mask(int mask, int vector)
{
unsigned long cfg;
-#if FORCE_READ_AROUND_WRITE
unsigned long flags;
__save_flags(flags);
__cli();
-#endif
/*
* prepare target chip field
*/
-
cfg = __prepare_ICR2(mask);
- apic_write(APIC_ICR2, cfg);
+ apic_write_around(APIC_ICR2, cfg);
/*
* program the ICR
@@ -274,10 +186,8 @@ static inline void send_IPI_mask(int mask, int vector)
/*
* Send the IPI. The write to APIC_ICR fires this off.
*/
- apic_write(APIC_ICR, cfg);
-#if FORCE_READ_AROUND_WRITE
+ apic_write_around(APIC_ICR, cfg);
__restore_flags(flags);
-#endif
}
/*
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 50b743a99..ae84ff2b5 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -28,6 +28,7 @@
* from Jose Renau
* Ingo Molnar : various cleanups and rewrites
* Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug.
+ * Maciej W. Rozycki : Bits for genuine 82489DX APICs
*/
#include <linux/config.h>
@@ -489,11 +490,43 @@ static int __init fork_by_hand(void)
return do_fork(CLONE_VM|CLONE_PID, 0, &regs);
}
+#if APIC_DEBUG
+static inline void inquire_remote_apic(int apicid)
+{
+ int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
+ char *names[] = { "ID", "VERSION", "SPIV" };
+ int timeout, status;
+
+ printk("Inquiring remote APIC #%d...\n", apicid);
+
+ for (i = 0; i < sizeof(regs) / sizeof(*regs); i++) {
+ printk("... APIC #%d %s: ", apicid, names[i]);
+
+ apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+ apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
+
+ timeout = 0;
+ do {
+ udelay(100);
+ status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
+ } while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
+
+ switch (status) {
+ case APIC_ICR_RR_VALID:
+ status = apic_read(APIC_RRR);
+ printk("%08x\n", status);
+ break;
+ default:
+ printk("failed\n");
+ }
+ }
+}
+#endif
+
static void __init do_boot_cpu (int apicid)
{
- unsigned long cfg;
struct task_struct *idle;
- unsigned long send_status, accept_status;
+ unsigned long send_status, accept_status, boot_status, maxlvt;
int timeout, num_starts, j, cpu;
unsigned long start_eip;
@@ -527,7 +560,7 @@ static void __init do_boot_cpu (int apicid)
start_eip = setup_trampoline();
/* So we see what's up */
- printk("Booting processor %d eip %lx\n", cpu, start_eip);
+ printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle);
/*
@@ -549,16 +582,17 @@ static void __init do_boot_cpu (int apicid)
* Be paranoid about clearing APIC errors.
*/
if (APIC_INTEGRATED(apic_version[apicid])) {
- apic_readaround(APIC_SPIV);
+ apic_read_around(APIC_SPIV);
apic_write(APIC_ESR, 0);
- accept_status = (apic_read(APIC_ESR) & 0xEF);
+ apic_read(APIC_ESR);
}
/*
* Status is now clean
*/
- send_status = 0;
+ send_status = 0;
accept_status = 0;
+ boot_status = 0;
/*
* Starting actual IPI sequence...
@@ -567,37 +601,41 @@ static void __init do_boot_cpu (int apicid)
Dprintk("Asserting INIT.\n");
/*
- * Turn INIT on
- */
- cfg = apic_read(APIC_ICR2);
- cfg &= 0x00FFFFFF;
-
- /*
- * Target chip
+ * Turn INIT on target chip
*/
- apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(apicid));
+ apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
/*
* Send IPI
*/
- cfg = apic_read(APIC_ICR);
- cfg &= ~0xCDFFF;
- cfg |= (APIC_DEST_LEVELTRIG | APIC_DEST_ASSERT | APIC_DEST_DM_INIT);
- apic_write(APIC_ICR, cfg);
+ apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
+ | APIC_DM_INIT);
+
+ Dprintk("Waiting for send to finish...\n");
+ timeout = 0;
+ do {
+ Dprintk("+");
+ udelay(100);
+ send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
+ } while (send_status && (timeout++ < 1000));
+
+ mdelay(10);
- udelay(200);
Dprintk("Deasserting INIT.\n");
/* Target chip */
- cfg = apic_read(APIC_ICR2);
- cfg &= 0x00FFFFFF;
- apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(apicid));
+ apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
/* Send IPI */
- cfg = apic_read(APIC_ICR);
- cfg &= ~0xCDFFF;
- cfg |= (APIC_DEST_LEVELTRIG | APIC_DEST_DM_INIT);
- apic_write(APIC_ICR, cfg);
+ apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+
+ Dprintk("Waiting for send to finish...\n");
+ timeout = 0;
+ do {
+ Dprintk("+");
+ udelay(100);
+ send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
+ } while (send_status && (timeout++ < 1000));
/*
* Should we send STARTUP IPIs ?
@@ -616,9 +654,11 @@ static void __init do_boot_cpu (int apicid)
*/
Dprintk("#startup loops: %d.\n", num_starts);
+ maxlvt = get_maxlvt();
+
for (j = 1; j <= num_starts; j++) {
Dprintk("Sending STARTUP #%d.\n",j);
- apic_readaround(APIC_SPIV);
+ apic_read_around(APIC_SPIV);
apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);
Dprintk("After apic_write.\n");
@@ -628,17 +668,12 @@ static void __init do_boot_cpu (int apicid)
*/
/* Target chip */
- cfg = apic_read(APIC_ICR2);
- cfg &= 0x00FFFFFF;
- apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(apicid));
+ apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
/* Boot on the stack */
- cfg = apic_read(APIC_ICR);
- cfg &= ~0xCDFFF;
- cfg |= (APIC_DEST_DM_STARTUP | (start_eip >> 12));
-
/* Kick the second */
- apic_write(APIC_ICR, cfg);
+ apic_write_around(APIC_ICR, APIC_DM_STARTUP
+ | (start_eip >> 12));
Dprintk("Startup point 1.\n");
@@ -647,13 +682,20 @@ static void __init do_boot_cpu (int apicid)
do {
Dprintk("+");
udelay(100);
- send_status = apic_read(APIC_ICR) & 0x1000;
+ send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
} while (send_status && (timeout++ < 1000));
/*
* Give the other CPU some time to accept the IPI.
*/
udelay(200);
+ /*
+ * Due to the Pentium erratum 3AP.
+ */
+ if (maxlvt > 3) {
+ apic_read_around(APIC_SPIV);
+ apic_write(APIC_ESR, 0);
+ }
accept_status = (apic_read(APIC_ESR) & 0xEF);
if (send_status || accept_status)
break;
@@ -676,7 +718,7 @@ static void __init do_boot_cpu (int apicid)
/*
* Wait 5s total for a response
*/
- for (timeout = 0; timeout < 1000000000; timeout++) {
+ for (timeout = 0; timeout < 50000; timeout++) {
if (test_bit(cpu, &cpu_callin_map))
break; /* It has booted */
udelay(100);
@@ -687,15 +729,22 @@ static void __init do_boot_cpu (int apicid)
Dprintk("OK.\n");
printk("CPU%d: ", cpu);
print_cpu_info(&cpu_data[cpu]);
+ Dprintk("CPU has booted.\n");
} else {
+ boot_status = 1;
if (*((volatile unsigned char *)phys_to_virt(8192))
- == 0xA5) /* trampoline code not run */
+ == 0xA5)
+ /* trampoline started but...? */
printk("Stuck ??\n");
else
- printk("CPU booted but not responding.\n");
+ /* trampoline code not run */
+ printk("Not responding.\n");
+#if APIC_DEBUG
+ inquire_remote_apic(apicid);
+#endif
}
- Dprintk("CPU has booted.\n");
- } else {
+ }
+ if (send_status || accept_status || boot_status) {
x86_cpu_to_apicid[cpu] = -1;
x86_apicid_to_cpu[apicid] = -1;
cpucount--;
@@ -858,6 +907,7 @@ void __init smp_boot_cpus(void)
Dprintk("Getting LVT1: %x\n", reg);
}
+ connect_bsp_APIC();
setup_local_APIC();
if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_id)
@@ -877,7 +927,7 @@ void __init smp_boot_cpus(void)
if (!(phys_cpu_present_map & (1 << apicid)))
continue;
- if ((max_cpus >= 0) && (max_cpus < cpucount+1))
+ if ((max_cpus >= 0) && (max_cpus <= cpucount+1))
continue;
do_boot_cpu(apicid);
@@ -934,7 +984,6 @@ void __init smp_boot_cpus(void)
printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
Dprintk("Boot done.\n");
- cache_APIC_registers();
#ifndef CONFIG_VISWS
/*
* Here we can be sure that there is an IO-APIC in the system. Let's
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 3a7004970..e25f50cfd 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -696,7 +696,7 @@ static void __init set_call_gate(void *a, void *addr)
((limit) & 0x0ffff); }
#define _set_tssldt_desc(n,addr,limit,type) \
-__asm__ __volatile__ ("movw %3,0(%2)\n\t" \
+__asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
"movw %%ax,2(%2)\n\t" \
"rorl $16,%%eax\n\t" \
"movb %%al,4(%2)\n\t" \
diff --git a/arch/i386/kernel/visws_apic.c b/arch/i386/kernel/visws_apic.c
index be80cd628..288f83e8f 100644
--- a/arch/i386/kernel/visws_apic.c
+++ b/arch/i386/kernel/visws_apic.c
@@ -376,7 +376,7 @@ void init_VISWS_APIC_irqs(void)
for (i = 0; i < 16; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = 0;
- irq_desc[i].depth = 0;
+ irq_desc[i].depth = 1;
/*
* Cobalt IRQs are mapped to standard ISA
diff --git a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c
index ca5eeb796..89e7940ad 100644
--- a/arch/i386/lib/delay.c
+++ b/arch/i386/lib/delay.c
@@ -10,11 +10,12 @@
* we have to worry about.
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <asm/delay.h>
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#include <asm/smp.h>
#endif
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 21c9cadff..2f030f306 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -51,7 +51,7 @@ good_area:
start &= PAGE_MASK;
for (;;) {
- if (handle_mm_fault(current, vma, start, 1) <= 0)
+ if (handle_mm_fault(current->mm, vma, start, 1) <= 0)
goto bad_area;
if (!size)
break;
@@ -193,7 +193,7 @@ good_area:
* the fault.
*/
{
- int fault = handle_mm_fault(tsk, vma, address, write);
+ int fault = handle_mm_fault(mm, vma, address, write);
if (fault < 0)
goto out_of_memory;
if (!fault)