diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-08-28 22:00:09 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-08-28 22:00:09 +0000 |
commit | 1a1d77dd589de5a567fa95e36aa6999c704ceca4 (patch) | |
tree | 141e31f89f18b9fe0831f31852e0435ceaccafc5 /arch/i386/kernel | |
parent | fb9c690a18b3d66925a65b17441c37fa14d4370b (diff) |
Merge with 2.4.0-test7.
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r-- | arch/i386/kernel/apic.c | 112 | ||||
-rw-r--r-- | arch/i386/kernel/entry.S | 5 | ||||
-rw-r--r-- | arch/i386/kernel/io_apic.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/mca.c | 101 | ||||
-rw-r--r-- | arch/i386/kernel/microcode.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/mpparse.c | 4 | ||||
-rw-r--r-- | arch/i386/kernel/setup.c | 69 | ||||
-rw-r--r-- | arch/i386/kernel/smpboot.c | 45 |
8 files changed, 208 insertions, 132 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index a839790f8..aed275365 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -7,7 +7,8 @@ * Maciej W. Rozycki : Bits for genuine 82489DX APICs; * thanks to Eric Gilmore * and Rolf G. Tews - * for testing these extensively + * for testing these extensively. + * Maciej W. Rozycki : Various updates and fixes. */ #include <linux/config.h> @@ -127,6 +128,67 @@ void disable_local_APIC(void) apic_write_around(APIC_SPIV, value); } +/* + * This is to verify that we're looking at a real local APIC. + * Check these against your board if the CPUs aren't getting + * started for no apparent reason. + */ +int __init verify_local_APIC(void) +{ + unsigned int reg0, reg1; + + /* + * The version register is read-only in a real APIC. + */ + reg0 = apic_read(APIC_LVR); + Dprintk("Getting VERSION: %x\n", reg0); + apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK); + reg1 = apic_read(APIC_LVR); + Dprintk("Getting VERSION: %x\n", reg1); + + /* + * The two version reads above should print the same + * numbers. If the second one is different, then we + * poke at a non-APIC. + */ + if (reg1 != reg0) + return 0; + + /* + * Check if the version looks reasonably. + */ + reg1 = GET_APIC_VERSION(reg0); + if (reg1 == 0x00 || reg1 == 0xff) + return 0; + reg1 = get_maxlvt(); + if (reg1 < 0x02 || reg1 == 0xff) + return 0; + + /* + * The ID register is read/write in a real APIC. + */ + reg0 = apic_read(APIC_ID); + Dprintk("Getting ID: %x\n", reg0); + apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); + reg1 = apic_read(APIC_ID); + Dprintk("Getting ID: %x\n", reg1); + apic_write(APIC_ID, reg0); + if (reg1 != (reg0 ^ APIC_ID_MASK)) + return 0; + + /* + * The next two are just to see if we have sane values. + * They're only really relevant if we're in Virtual Wire + * compatibility mode, but most boxes are anymore. + */ + reg0 = apic_read(APIC_LVT0); + Dprintk("Getting LVT0: %x\n", reg0); + reg1 = apic_read(APIC_LVT1); + Dprintk("Getting LVT1: %x\n", reg1); + + return 1; +} + void __init sync_Arb_IDs(void) { /* @@ -682,46 +744,28 @@ asmlinkage void smp_spurious_interrupt(void) * This interrupt should never happen with our APIC/SMP architecture */ -static spinlock_t err_lock = SPIN_LOCK_UNLOCKED; - asmlinkage void smp_error_interrupt(void) { - unsigned long v; - - spin_lock(&err_lock); + unsigned long v, v1; + /* First tickle the hardware, only then report what went on. -- REW */ v = apic_read(APIC_ESR); - printk(KERN_INFO "APIC error interrupt on CPU#%d, should never happen.\n", - smp_processor_id()); - printk(KERN_INFO "... APIC ESR0: %08lx\n", v); - apic_write(APIC_ESR, 0); - v |= apic_read(APIC_ESR); - printk(KERN_INFO "... APIC ESR1: %08lx\n", v); - /* - * Be a bit more verbose. (multiple bits can be set) - */ - if (v & 0x01) - printk(KERN_INFO "... bit 0: APIC Send CS Error (hw problem).\n"); - if (v & 0x02) - printk(KERN_INFO "... bit 1: APIC Receive CS Error (hw problem).\n"); - if (v & 0x04) - printk(KERN_INFO "... bit 2: APIC Send Accept Error.\n"); - if (v & 0x08) - printk(KERN_INFO "... bit 3: APIC Receive Accept Error.\n"); - if (v & 0x10) - printk(KERN_INFO "... bit 4: Reserved!.\n"); - if (v & 0x20) - printk(KERN_INFO "... bit 5: Send Illegal Vector (kernel bug).\n"); - if (v & 0x40) - printk(KERN_INFO "... bit 6: Received Illegal Vector.\n"); - if (v & 0x80) - printk(KERN_INFO "... bit 7: Illegal Register Address.\n"); - + v1 = apic_read(APIC_ESR); ack_APIC_irq(); - irq_err_count++; - spin_unlock(&err_lock); + /* Here is what the APIC error bits mean: + 0: Send CS error + 1: Receive CS error + 2: Send accept error + 3: Receive accept error + 4: Reserved + 5: Send illegal vector + 6: Received illegal vector + 7: Illegal register address + */ + printk (KERN_ERR "APIC error on CPU%d: %02lx(%02lx)\n", + smp_processor_id(), v , v1); } diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 337879b63..fb9b7b2ea 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -641,7 +641,8 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_pivot_root) .long SYMBOL_NAME(sys_mincore) .long SYMBOL_NAME(sys_madvise) - + .long SYMBOL_NAME(sys_getdents64) /* 220 */ + .long SYMBOL_NAME(sys_fcntl64) /* * NOTE!! This doesn't have to be exact - we just have @@ -649,6 +650,6 @@ ENTRY(sys_call_table) * entries. Don't panic if you notice that this hasn't * been shrunk every time we add a new system call. */ - .rept NR_syscalls-219 + .rept NR_syscalls-221 .long SYMBOL_NAME(sys_ni_syscall) .endr diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 525f78624..e1b00a702 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -688,7 +688,7 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) void __init UNEXPECTED_IO_APIC(void) { printk(KERN_WARNING " WARNING: unexpected IO-APIC, please mail\n"); - printk(KERN_WARNING " to linux-smp@vger.rutgers.edu\n"); + printk(KERN_WARNING " to linux-smp@vger.kernel.org\n"); } void __init print_IO_APIC(void) diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c index 6c6053bf7..e9c8377cd 100644 --- a/arch/i386/kernel/mca.c +++ b/arch/i386/kernel/mca.c @@ -15,7 +15,7 @@ * * Chris Beauregard August 9th, 1996 * - Rewrote /proc/mca - * + * * Chris Beauregard January 7th, 1997 * - Added basic NMI-processing * - Added more information to mca_info structure @@ -30,8 +30,11 @@ * - Fixed the output of 'Driver Installed' in /proc/mca/pos * - Made the Integrated Video & SCSI show up even if they have id 0000 * - * AV November 9th, 1999 - * - switched to regular procfs methods. + * Alexander Viro November 9th, 1999 + * - Switched to regular procfs methods + * + * Alfred Arnold & David Weinehall August 23rd, 2000 + * - Added support for Planar POS-registers */ #include <linux/module.h> @@ -50,9 +53,10 @@ #include <asm/uaccess.h> #include <linux/init.h> -/* This structure holds MCA information. Each (plug-in) adapter has +/* This structure holds MCA information. Each (plug-in) adapter has * eight POS registers. Then the machine may have integrated video and * SCSI subsystems, which also have eight POS registers. + * Finally, the motherboard (planar) has got POS-registers. * Other miscellaneous information follows. */ @@ -92,7 +96,7 @@ struct MCA_info { /* The mca_info structure pointer. If MCA bus is present, the function * mca_probe() is invoked. The function puts motherboard, then all * adapters into setup mode, allocates and fills an MCA_info structure, - * and points this pointer to the structure. Otherwise the pointer + * and points this pointer to the structure. Otherwise the pointer * is set to zero. */ @@ -194,7 +198,7 @@ void __init mca_init(void) */ /* Make sure the MCA bus is present */ - + if(!MCA_bus) return; printk("Micro Channel bus detected.\n"); @@ -216,7 +220,16 @@ void __init mca_init(void) outb_p(0, MCA_ADAPTER_SETUP_REG); - /* Put motherboard into video setup mode, read integrated video + /* Read motherboard POS registers */ + + outb_p(0x7f, MCA_MOTHERBOARD_SETUP_REG); + mca_info->slot[MCA_MOTHERBOARD].name[0] = 0; + for(j=0; j<8; j++) { + mca_info->slot[MCA_MOTHERBOARD].pos[j] = inb_p(MCA_POS_REG(j)); + } + mca_configure_adapter_status(MCA_MOTHERBOARD); + + /* Put motherboard into video setup mode, read integrated video * POS registers, and turn motherboard setup off. */ @@ -242,7 +255,7 @@ void __init mca_init(void) outb_p(0xf7, MCA_MOTHERBOARD_SETUP_REG); mca_info->slot[MCA_INTEGSCSI].name[0] = 0; for(j=0; j<8; j++) { - if((mca_info->slot[MCA_INTEGSCSI].pos[j] = inb_p(MCA_POS_REG(j))) != 0xff) + if((mca_info->slot[MCA_INTEGSCSI].pos[j] = inb_p(MCA_POS_REG(j))) != 0xff) { /* 0xff all across means no device. 0x00 means * something's broken, but a device is probably there. @@ -256,17 +269,17 @@ void __init mca_init(void) mca_info->which_scsi = 0xf7; } } - if(!mca_info->which_scsi) { + if(!mca_info->which_scsi) { /* Didn't find it at 0xf7, try somewhere else... */ mca_info->which_scsi = 0xfd; outb_p(0xfd, MCA_MOTHERBOARD_SETUP_REG); - for(j=0; j<8; j++) + for(j=0; j<8; j++) mca_info->slot[MCA_INTEGSCSI].pos[j] = inb_p(MCA_POS_REG(j)); } mca_configure_adapter_status(MCA_INTEGSCSI); - + /* Turn off motherboard setup */ outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG); @@ -311,6 +324,9 @@ static void mca_handle_nmi_slot(int slot, int check_flag) } else if(slot == MCA_INTEGVIDEO) { printk("NMI: caused by MCA integrated video adapter (%s)\n", mca_info->slot[slot].name); + } else if(slot == MCA_MOTHERBOARD) { + printk("NMI: caused by motherboard (%s)\n", + mca_info->slot[slot].name); } /* More info available in POS 6 and 7? */ @@ -375,7 +391,7 @@ void mca_handle_nmi(void) * * Disabled adapters are not reported. */ - + int mca_find_adapter(int id, int start) { if(mca_info == NULL || id == 0xffff) { @@ -423,7 +439,7 @@ EXPORT_SYMBOL(mca_find_adapter); * to scan for further cards when some may already be driven. */ -int mca_find_unused_adapter(int id, int start) +int mca_find_unused_adapter(int id, int start) { if(mca_info == NULL || id == 0xffff) { return MCA_NOTFOUND; @@ -450,7 +466,7 @@ int mca_find_unused_adapter(int id, int start) } return MCA_NOTFOUND; -} /* mca_find_unused_adapter() */ +} /* mca_find_unused_adapter() */ EXPORT_SYMBOL(mca_find_unused_adapter); @@ -465,8 +481,8 @@ EXPORT_SYMBOL(mca_find_unused_adapter); * when it scanned the MCA space. The register value is returned. * Missing or invalid registers report 0. */ - -unsigned char mca_read_stored_pos(int slot, int reg) + +unsigned char mca_read_stored_pos(int slot, int reg) { if(slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == NULL) return 0; if(reg < 0 || reg >= 8) return 0; @@ -487,9 +503,8 @@ EXPORT_SYMBOL(mca_read_stored_pos); * may not be invoked from interrupt context. It handles the * deep magic required for onboard devices transparently. */ - -unsigned char mca_read_pos(int slot, int reg) +unsigned char mca_read_pos(int slot, int reg) { unsigned int byte = 0; unsigned long flags; @@ -524,6 +539,14 @@ unsigned char mca_read_pos(int slot, int reg) byte = inb_p(MCA_POS_REG(reg)); outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG); + } else if(slot == MCA_MOTHERBOARD) { + + /* Disable adapter setup, enable motherboard setup */ + outb_p(0, MCA_ADAPTER_SETUP_REG); + outb_p(0x7f, MCA_MOTHERBOARD_SETUP_REG); + + byte = inb_p(MCA_POS_REG(reg)); + outp_b(0xff, MCA_MOTHERBOARD_SETUP_REG); } else if(slot < MCA_MAX_SLOT_NR) { /* Make sure motherboard setup is off */ @@ -556,7 +579,7 @@ EXPORT_SYMBOL(mca_read_pos); * @reg: register to read from * @byte: byte to write to the POS registers * - * Store a POS value directly from the hardware. You should not + * Store a POS value directly from the hardware. You should not * normally need to use this function and should have a very good * knowledge of MCA bus before you do so. Doing this wrongly can * damage the hardware. @@ -574,7 +597,7 @@ EXPORT_SYMBOL(mca_read_pos); * screws up. */ -void mca_write_pos(int slot, int reg, unsigned char byte) +void mca_write_pos(int slot, int reg, unsigned char byte) { unsigned long flags; @@ -615,11 +638,11 @@ EXPORT_SYMBOL(mca_write_pos); * @name: text string for the namen * * This function sets the name reported via /proc for this - * adapter slot. This is for user information only. Setting a + * adapter slot. This is for user information only. Setting a * name deletes any previous name. */ - -void mca_set_adapter_name(int slot, char* name) + +void mca_set_adapter_name(int slot, char* name) { if(mca_info == NULL) return; @@ -640,7 +663,7 @@ EXPORT_SYMBOL(mca_set_adapter_name); /** * mca_set_adapter_procfn - Set the /proc callback * @slot: slot to configure - * @procfn: callback function to call for /proc + * @procfn: callback function to call for /proc * @dev: device information passed to the callback * * This sets up an information callback for /proc/mca/slot?. The @@ -648,7 +671,7 @@ EXPORT_SYMBOL(mca_set_adapter_name); * 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 - * before this is called though, so don't do it again. + * before this is called though, so don't do it again. * * This should be called with a %NULL @procfn when a module * unregisters, thus preventing kernel crashes and other such @@ -722,8 +745,8 @@ EXPORT_SYMBOL(mca_mark_as_unused); * Return the adapter description if set. If it has not been * set or the slot is out range then return NULL. */ - -char *mca_get_adapter_name(int slot) + +char *mca_get_adapter_name(int slot) { if(mca_info == NULL) return 0; @@ -789,14 +812,12 @@ int get_mca_info(char *page, char **start, off_t off, { int i, j, len = 0; - if(MCA_bus && mca_info != NULL) - { + if(MCA_bus && mca_info != NULL) { /* Format POS registers of eight MCA slots */ - for(i=0; i<MCA_MAX_SLOT_NR; i++) - { + for(i=0; i<MCA_MAX_SLOT_NR; i++) { len += sprintf(page+len, "Slot %d: ", i+1); - for(j=0; j<8; j++) + for(j=0; j<8; j++) len += sprintf(page+len, "%02x ", mca_info->slot[i].pos[j]); len += sprintf(page+len, " %s\n", mca_info->slot[i].name); } @@ -804,19 +825,26 @@ int get_mca_info(char *page, char **start, off_t off, /* Format POS registers of integrated video subsystem */ len += sprintf(page+len, "Video : "); - for(j=0; j<8; j++) + for(j=0; j<8; j++) len += sprintf(page+len, "%02x ", mca_info->slot[MCA_INTEGVIDEO].pos[j]); len += sprintf(page+len, " %s\n", mca_info->slot[MCA_INTEGVIDEO].name); /* Format POS registers of integrated SCSI subsystem */ - + len += sprintf(page+len, "SCSI : "); for(j=0; j<8; j++) len += sprintf(page+len, "%02x ", mca_info->slot[MCA_INTEGSCSI].pos[j]); len += sprintf(page+len, " %s\n", mca_info->slot[MCA_INTEGSCSI].name); + + /* Format POS registers of motherboard */ + + len += sprintf(page+len, "Planar: "); + for(j=0; j<8; j++) + len += sprintf(page+len, "%02x ", mca_info->slot[MCA_MOTHERBOARD].pos[j]); + len += sprintf(page+len, " %s\n", mca_info->slot[MCA_MOTHERBOARD].name); } else { /* Leave it empty if MCA not detected - this should *never* - * happen! + * happen! */ } @@ -843,6 +871,8 @@ static int mca_default_procfn(char* buf, struct MCA_adapter *p) len += sprintf(buf+len, "Integrated SCSI Adapter\n"); } else if(slot == MCA_INTEGVIDEO) { len += sprintf(buf+len, "Integrated Video Adapter\n"); + } else if(slot == MCA_MOTHERBOARD) { + len += sprintf(buf+len, "Motherboard\n"); } if(p->name[0]) { @@ -932,6 +962,7 @@ void __init mca_do_proc_init(void) if(i < MCA_MAX_SLOT_NR) sprintf(p->procname,"slot%d", i+1); else if(i == MCA_INTEGVIDEO) sprintf(p->procname,"video"); else if(i == MCA_INTEGSCSI) sprintf(p->procname,"scsi"); + else if(i == MCA_MOTHERBOARD) sprintf(p->procname,"planar"); if(!mca_isadapter(i)) continue; diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index 64db873a9..1d5b7b3c8 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -67,7 +67,7 @@ static int do_microcode_update(void); static void do_update_one(void *); /* read()/write()/ioctl() are serialized on this */ -DECLARE_RWSEM(microcode_rwsem); +static DECLARE_RWSEM(microcode_rwsem); static struct microcode *microcode; /* array of 2048byte microcode blocks */ static unsigned int microcode_num; /* number of chunks in microcode */ diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 9455d2e3a..746bea030 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -170,7 +170,7 @@ static void __init MP_bus_info (struct mpc_config_bus *m) 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"); + panic("cannot handle bus - mail to linux-smp@vger.kernel.org"); } } @@ -565,7 +565,7 @@ void __init find_intel_smp (void) address <<= 4; smp_scan_config(address, 0x1000); if (smp_found_config) - printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n"); + printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.kernel.org if you experience SMP problems!\n"); } #else diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 24ea5e641..e79572f90 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -16,7 +16,7 @@ * Intel Mobile Pentium II detection fix. Sean Gilley, June 1999. * * IDT Winchip tweaks, misc clean ups. - * Dave Jones <dave@powertweak.com>, August 1999 + * Dave Jones <davej@suse.de>, August 1999 * * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 * @@ -27,7 +27,7 @@ * David Parsons <orc@pell.chi.il.us>, July-August 1999 * * Cleaned up cache-detection code - * Dave Jones <dave@powertweak.com>, October 1999 + * Dave Jones <davej@suse.de>, October 1999 * * Added proper L2 cache detection for Coppermine * Dragan Stancevic <visitor@valinux.com>, October 1999 @@ -38,7 +38,7 @@ * * Detection for Celeron coppermine, identify_cpu() overhauled, * and a few other clean ups. - * Dave Jones <dave@powertweak.com>, April 2000 + * Dave Jones <davej@suse.de>, April 2000 * * Pentium III FXSR, SSE support * General FPU state handling cleanups @@ -48,6 +48,9 @@ * and 8-way type cache happy bunch from Intel:^) * Dragan Stancevic <visitor@valinux.com>, May 2000 * + * Forward port AMD Duron errata T13 from 2.2.17pre + * Dave Jones <davej@suse.de>, August 2000 + * */ /* @@ -380,8 +383,8 @@ static void __init probe_roms(void) } } -void __init add_memory_region(unsigned long start, - unsigned long size, int type) +void __init add_memory_region(unsigned long long start, + unsigned long long size, int type) { int x = e820.nr_map; @@ -398,12 +401,12 @@ void __init add_memory_region(unsigned long start, #define E820_DEBUG 1 -static void __init print_e820_map(void) +static void __init print_memory_map(char *who) { int i; for (i = 0; i < e820.nr_map; i++) { - printk(" e820: %016Lx @ %016Lx ", + printk(" %s: %016Lx @ %016Lx ", who, e820.map[i].size, e820.map[i].addr); switch (e820.map[i].type) { case E820_RAM: printk("(usable)\n"); @@ -449,7 +452,7 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) unsigned long long start = biosmap->addr; unsigned long long size = biosmap->size; unsigned long long end = start + size; - long type = biosmap->type; + unsigned long type = biosmap->type; /* Overflow in 64 bits? Ignore the memory map. */ if (start > end) @@ -460,12 +463,12 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) * Not right. Fix it up. */ if (type == E820_RAM) { - if (start < 0x100000 && end > 0xA0000) { - if (start < 0xA0000) - add_memory_region(start, 0xA0000-start, type); - if (end < 0x100000) + if (start < 0x100000ULL && end > 0xA0000ULL) { + if (start < 0xA0000ULL) + add_memory_region(start, 0xA0000ULL-start, type); + if (end < 0x100000ULL) continue; - start = 0x100000; + start = 0x100000ULL; size = end - start; } } @@ -482,6 +485,8 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) void __init setup_memory_region(void) { + char *who = "BIOS-e820"; + /* * Try to copy the BIOS-supplied E820-map. * @@ -491,14 +496,21 @@ void __init setup_memory_region(void) if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) { unsigned long mem_size; - mem_size = (ALT_MEM_K < EXT_MEM_K) ? EXT_MEM_K : ALT_MEM_K; + /* compare results from other methods and take the greater */ + if (ALT_MEM_K < EXT_MEM_K) { + mem_size = EXT_MEM_K; + who = "BIOS-88"; + } else { + mem_size = ALT_MEM_K; + who = "BIOS-e801"; + } e820.nr_map = 0; add_memory_region(0, LOWMEMSIZE(), E820_RAM); add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM); } printk("BIOS-provided physical RAM map:\n"); - print_e820_map(); + print_memory_map(who); } /* setup_memory_region */ @@ -568,7 +580,7 @@ static inline void parse_mem_cmdline (char ** cmdline_p) *cmdline_p = command_line; if (usermem) { printk("user-defined physical RAM map:\n"); - print_e820_map(); + print_memory_map("user"); } } @@ -925,7 +937,7 @@ static int __init amd_model(struct cpuinfo_x86 *c) break; } break; - case 6: /* An Athlon. We can trust the BIOS probably */ + case 6: /* An Athlon/Duron. We can trust the BIOS probably */ break; } @@ -936,10 +948,19 @@ static int __init amd_model(struct cpuinfo_x86 *c) edx>>24, ecx>>24, edx&0xFF); c->x86_cache_size=(ecx>>24)+(edx>>24); } - if (n >= 0x80000006) { - cpuid(0x80000006, &dummy, &dummy, &ecx, &edx); - printk("CPU: L2 Cache: %dK\n", ecx>>16); - c->x86_cache_size=(ecx>>16); + + /* AMD errata T13 (order #21922) */ + if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 3 && + boot_cpu_data.x86_mask == 0) + { + c->x86_cache_size = 64; + printk("CPU: L2 Cache: 64K\n"); + } else { + if (n >= 0x80000006) { + cpuid(0x80000006, &dummy, &dummy, &ecx, &edx); + printk("CPU: L2 Cache: %dK\n", ecx>>16); + c->x86_cache_size=(ecx>>16); + } } return r; @@ -1538,7 +1559,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c) if(c->x86_vendor == X86_VENDOR_NEXGEN) c->x86_cache_size = 256; /* A few had 1Mb.. */ - + for (i = 0; i < sizeof(cpu_models)/sizeof(struct cpu_model_info); i++) { if (cpu_models[i].vendor == c->x86_vendor && cpu_models[i].x86 == c->x86) { @@ -1570,8 +1591,8 @@ void __init dodgy_tsc(void) cyrix_model(&boot_cpu_data); } - - + + static char *cpu_vendor_names[] __initdata = { "Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur", "Rise", "Transmeta" }; diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 084e3b963..7629bb3d2 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -883,39 +883,18 @@ void __init smp_boot_cpus(void) phys_cpu_present_map |= (1 << hard_smp_processor_id()); } - { - int reg; - - /* - * This is to verify that we're looking at - * a real local APIC. Check these against - * your board if the CPUs aren't getting - * started for no apparent reason. - */ - - reg = apic_read(APIC_LVR); - Dprintk("Getting VERSION: %x\n", reg); - - apic_write(APIC_LVR, 0); - reg = apic_read(APIC_LVR); - Dprintk("Getting VERSION: %x\n", reg); - - /* - * The two version reads above should print the same - * NON-ZERO!!! numbers. If the second one is zero, - * there is a problem with the APIC write/read - * definitions. - * - * The next two are just to see if we have sane values. - * They're only really relevant if we're in Virtual Wire - * compatibility mode, but most boxes are anymore. - */ - - reg = apic_read(APIC_LVT0); - Dprintk("Getting LVT0: %x\n", reg); - - reg = apic_read(APIC_LVT1); - Dprintk("Getting LVT1: %x\n", reg); + /* + * If we couldn't find a local APIC, then get out of here now! + */ + if (!verify_local_APIC()) { + printk(KERN_ERR "BIOS bug, local APIC at 0x%lX not detected!...\n", mp_lapic_addr); + printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); +#ifndef CONFIG_VISWS + io_apic_irqs = 0; +#endif + cpu_online_map = phys_cpu_present_map = 1; + smp_num_cpus = 1; + goto smp_done; } /* |