diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-04-28 01:09:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-04-28 01:09:25 +0000 |
commit | b9ba7aeb165cffecdffb60aec8c3fa8d590d9ca9 (patch) | |
tree | 42d07b0c7246ae2536a702e7c5de9e2732341116 /arch/i386/kernel | |
parent | 7406b0a326f2d70ade2671c37d1beef62249db97 (diff) |
Merge with 2.3.99-pre6.
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r-- | arch/i386/kernel/acpi.c | 3 | ||||
-rw-r--r-- | arch/i386/kernel/apic.c | 271 | ||||
-rw-r--r-- | arch/i386/kernel/entry.S | 5 | ||||
-rw-r--r-- | arch/i386/kernel/head.S | 16 | ||||
-rw-r--r-- | arch/i386/kernel/i386_ksyms.c | 7 | ||||
-rw-r--r-- | arch/i386/kernel/i8259.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/io_apic.c | 242 | ||||
-rw-r--r-- | arch/i386/kernel/irq.c | 8 | ||||
-rw-r--r-- | arch/i386/kernel/mca.c | 12 | ||||
-rw-r--r-- | arch/i386/kernel/mpparse.c | 239 | ||||
-rw-r--r-- | arch/i386/kernel/mtrr.c | 34 | ||||
-rw-r--r-- | arch/i386/kernel/pci-irq.c | 7 | ||||
-rw-r--r-- | arch/i386/kernel/process.c | 1 | ||||
-rw-r--r-- | arch/i386/kernel/setup.c | 8 | ||||
-rw-r--r-- | arch/i386/kernel/signal.c | 4 | ||||
-rw-r--r-- | arch/i386/kernel/smp.c | 114 | ||||
-rw-r--r-- | arch/i386/kernel/smpboot.c | 135 | ||||
-rw-r--r-- | arch/i386/kernel/traps.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/visws_apic.c | 2 |
19 files changed, 622 insertions, 490 deletions
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, ®s); } +#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 |