summaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-08-28 22:00:09 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-08-28 22:00:09 +0000
commit1a1d77dd589de5a567fa95e36aa6999c704ceca4 (patch)
tree141e31f89f18b9fe0831f31852e0435ceaccafc5 /arch/i386/kernel
parentfb9c690a18b3d66925a65b17441c37fa14d4370b (diff)
Merge with 2.4.0-test7.
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r--arch/i386/kernel/apic.c112
-rw-r--r--arch/i386/kernel/entry.S5
-rw-r--r--arch/i386/kernel/io_apic.c2
-rw-r--r--arch/i386/kernel/mca.c101
-rw-r--r--arch/i386/kernel/microcode.c2
-rw-r--r--arch/i386/kernel/mpparse.c4
-rw-r--r--arch/i386/kernel/setup.c69
-rw-r--r--arch/i386/kernel/smpboot.c45
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;
}
/*