summaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/Makefile5
-rw-r--r--arch/i386/boot/compressed/head.S8
-rw-r--r--arch/i386/defconfig2
-rw-r--r--arch/i386/kernel/acpi.c30
-rw-r--r--arch/i386/kernel/head.S10
-rw-r--r--arch/i386/kernel/i386_ksyms.c3
-rw-r--r--arch/i386/kernel/pci-i386.c14
-rw-r--r--arch/i386/kernel/pci-pc.c38
-rw-r--r--arch/i386/kernel/setup.c44
-rw-r--r--arch/i386/kernel/time.c22
10 files changed, 137 insertions, 39 deletions
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 2a84bf05f..0e16a45b6 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -30,7 +30,8 @@ CFLAGS += $(shell if ! $(CC) -march=i486 -S -o /dev/null -xc /dev/null >/dev/nul
CFLAGS += $(shell if $(CC) -mpreferred-stack-boundary=2 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mpreferred-stack-boundary=2"; fi)
ifdef CONFIG_M386
-CFLAGS := $(CFLAGS) -m386 -DCPU=386
+CFLAGS := $(CFLAGS) -DCPU=386
+CFLAGS += $(shell if $(CC) -march=i386 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i386"; else echo "-m386"; fi)
AFLAGS := $(AFLAGS) -DCPU=386
endif
@@ -65,7 +66,7 @@ AFLAGS := $(AFLAGS) -DCPU=586
endif
ifdef CONFIG_MK7
-CFLAGS := $(CFLAGS) -DCPU=686 -march=pentiumpro -mpentiumpro -malign-functions=4 -fschedule-insns2 -mwide-multiply -fexpensive-optimizations
+CFLAGS := $(CFLAGS) -malign-functions=4 -fschedule-insns2 -mwide-multiply -fexpensive-optimizations -DCPU=686
CFLAGS += $(shell if $(CC) -march=i686 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i686"; fi)
AFLAGS := $(AFLAGS) -DCPU=686
endif
diff --git a/arch/i386/boot/compressed/head.S b/arch/i386/boot/compressed/head.S
index 51e0fc893..102850b74 100644
--- a/arch/i386/boot/compressed/head.S
+++ b/arch/i386/boot/compressed/head.S
@@ -33,10 +33,10 @@ startup_32:
cld
cli
movl $(__KERNEL_DS),%eax
- movl %ax,%ds
- movl %ax,%es
- movl %ax,%fs
- movl %ax,%gs
+ movl %eax,%ds
+ movl %eax,%es
+ movl %eax,%fs
+ movl %eax,%gs
lss SYMBOL_NAME(stack_start),%esp
xorl %eax,%eax
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 0f3f5cb8a..33f2d3cb1 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -179,7 +179,6 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_IDEDMA_PCI_AUTO is not set
# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
# CONFIG_IDEDMA_PCI_EXPERIMENTAL is not set
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
@@ -208,6 +207,7 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
CONFIG_BLK_DEV_IDE_MODES=y
#
diff --git a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c
index 8efa2832a..f9410f3fd 100644
--- a/arch/i386/kernel/acpi.c
+++ b/arch/i386/kernel/acpi.c
@@ -488,13 +488,13 @@ static int __init acpi_find_tables(void)
if (!rsdt) {
printk(KERN_ERR "ACPI: missing RSDT at 0x%p\n",
(void*) rsdp->rsdt);
- return -ENODEV;
+ return -EINVAL;
}
else if (rsdt->signature != ACPI_RSDT_SIG) {
printk(KERN_ERR "ACPI: bad RSDT at 0x%p (%08x)\n",
(void*) rsdp->rsdt, (unsigned) rsdt->signature);
acpi_unmap_table(rsdt);
- return -ENODEV;
+ return -EINVAL;
}
// search RSDT for FACP
acpi_facp.table = NULL;
@@ -532,7 +532,7 @@ static int __init acpi_find_tables(void)
if (!acpi_facp.table) {
printk(KERN_ERR "ACPI: missing FACP\n");
- return -ENODEV;
+ return -EINVAL;
}
return 0;
}
@@ -1461,8 +1461,19 @@ static int __init acpi_init(void)
switch (acpi_enabled) {
case ACPI_ENABLED:
- if (acpi_find_tables() && acpi_find_chipset())
+ switch (acpi_find_tables()) {
+ case 0:
+ // found valid ACPI tables
+ break;
+ case -ENODEV:
+ // found no ACPI tables, try chipset-specific
+ if (acpi_find_chipset())
+ return -ENODEV;
+ break;
+ default:
+ // found broken ACPI tables
return -ENODEV;
+ }
break;
case ACPI_TABLES_ONLY:
if (acpi_find_tables())
@@ -1478,6 +1489,12 @@ static int __init acpi_init(void)
facp = (struct acpi_facp*) acpi_facp.table;
+ if (PM_IS_ACTIVE()) {
+ printk(KERN_NOTICE "acpi: APM is already active.\n");
+ goto err_out;
+ }
+ pm_active = 1;
+
/*
* Internally we always keep latencies in timer
* ticks, which is simpler and more consistent (what is
@@ -1516,8 +1533,6 @@ static int __init acpi_init(void)
pm_power_off = acpi_power_off;
- pm_active = 1;
-
/*
* Set up the ACPI idle function. Note that we can't really
* do this with multiple CPU's, we'd need a per-CPU ACPI
@@ -1549,7 +1564,6 @@ static void __exit acpi_exit(void)
struct acpi_facp *facp = (struct acpi_facp*) acpi_facp.table;
pm_idle = NULL;
- pm_active = 0;
pm_power_off = NULL;
unregister_sysctl_table(acpi_sysctl);
@@ -1563,6 +1577,8 @@ static void __exit acpi_exit(void)
if (pci_driver_registered)
pci_unregister_driver(&acpi_driver);
+
+ pm_active = 0;
}
/*
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index 3340946be..7a8a17b63 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -58,10 +58,19 @@ startup_32:
* New page tables may be in 4Mbyte page mode and may
* be using the global pages.
*
+ * NOTE! If we are on a 486 we may have no cr4 at all!
+ * So we do not try to touch it unless we really have
+ * some bits in it to set. This won't work if the BSP
+ * implements cr4 but this AP does not -- very unlikely
+ * but be warned! The same applies to the pse feature
+ * if not equally supported. --macro
+ *
* NOTE! We have to correct for the fact that we're
* not yet offset PAGE_OFFSET..
*/
#define cr4_bits mmu_cr4_features-__PAGE_OFFSET
+ cmpl $0,cr4_bits
+ je 1f
movl %cr4,%eax # Turn on 4Mb pages
orl cr4_bits,%eax
movl %eax,%cr4
@@ -219,7 +228,6 @@ is386: pushl %ecx # restore original EFLAGS
orl $2,%eax # set MP
2: movl %eax,%cr0
call check_x87
-4:
#ifdef __SMP__
incb ready
#endif
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index e21c33b6f..5327f24a4 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -25,6 +25,7 @@
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(elf_fpregset_t *);
+extern spinlock_t rtc_lock;
#ifdef CONFIG_SMP
extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
@@ -131,3 +132,5 @@ EXPORT_SYMBOL(screen_info);
EXPORT_SYMBOL(get_wchan);
EXPORT_SYMBOL(irq_stat);
+
+EXPORT_SYMBOL(rtc_lock);
diff --git a/arch/i386/kernel/pci-i386.c b/arch/i386/kernel/pci-i386.c
index 6dd0a4306..942de9c79 100644
--- a/arch/i386/kernel/pci-i386.c
+++ b/arch/i386/kernel/pci-i386.c
@@ -323,3 +323,17 @@ int pcibios_enable_resources(struct pci_dev *dev)
}
return 0;
}
+
+/*
+ * If we set up a device for bus mastering, we need to check the latency
+ * timer as certain crappy BIOSes forget to set it properly.
+ */
+void pcibios_set_master(struct pci_dev *dev)
+{
+ u8 lat;
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+ if (lat < 16) {
+ printk("PCI: Increasing latency timer of device %s to 64\n", dev->slot_name);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+ }
+}
diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
index e51e96e43..b588642cc 100644
--- a/arch/i386/kernel/pci-pc.c
+++ b/arch/i386/kernel/pci-pc.c
@@ -1103,9 +1103,9 @@ static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *r
{
struct irq_info *q;
struct pci_dev *router;
- int i, pirq, newirq;
+ int i, pirq, newirq, reg;
u32 rtrid, mask;
- u8 x;
+ u8 x, y;
char *msg = NULL;
pin--;
@@ -1169,14 +1169,44 @@ static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *r
DBG(" -> [PIIX] set to %02x\n", newirq);
pci_write_config_byte(router, pirq, newirq);
msg = "PIIX-NEW";
- } else
- DBG(" -> [PIIX] sink\n");
+ } else DBG(" -> [PIIX] sink\n");
break;
case ID(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533):
newirq = ali_set_irq(router, pirq-1, newirq);
if (newirq)
msg = "ALI";
break;
+ case ID(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596):
+ case ID(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686):
+ reg = 0x55 + (pirq >> 1);
+ pci_read_config_byte(router, reg, &x);
+ y = (pirq & 1) ? (x >> 4) : (x & 0x0f);
+ if (y) {
+ DBG(" -> [VIA] %02x\n", y);
+ newirq = y;
+ msg = "VIA";
+ } else if (newirq) {
+ DBG(" -> [VIA] set to %02x\n", newirq);
+ x = (pirq & 1) ? ((x & 0x0f) | (newirq << 4)) : ((x & 0xf0) | newirq);
+ pci_write_config_byte(router, reg, y);
+ msg = "VIA-NEW";
+ } else DBG(" -> [VIA] sink\n");
+ break;
+ case ID(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C700):
+ reg = 0xb8 + (pirq >> 5);
+ pci_read_config_byte(router, reg, &x);
+ y = (pirq & 0x10) ? (x >> 4) : (x & 0x0f);
+ if (y) {
+ DBG(" -> [OPTI] %02x\n", y);
+ newirq = y;
+ msg = "OPTI";
+ } else if (newirq) {
+ DBG(" -> [OPTI] set to %02x\n", newirq);
+ x = (pirq & 0x10) ? ((x & 0x0f) | (newirq << 4)) : ((x & 0xf0) | newirq);
+ pci_write_config_byte(router, reg, y);
+ msg = "OPTI-NEW";
+ } else DBG(" -> [OPTI] sink\n");
+ break;
default:
DBG(" -> unknown router %04x/%04x\n", rt->rtr_vendor, rt->rtr_device);
if (newirq && mask == (1 << newirq)) {
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index a12b6b73d..46292496d 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -793,7 +793,7 @@ static int __init get_model_name(struct cpuinfo_x86 *c)
unsigned int n, dummy, *v, ecx, edx;
/* Actually we must have cpuid or we could never have
- * figured out that this was AMD from the vendor info :-).
+ * figured out that this was AMD/Cyrix from the vendor info :-).
*/
cpuid(0x80000000, &n, &dummy, &dummy, &dummy);
@@ -806,23 +806,27 @@ static int __init get_model_name(struct cpuinfo_x86 *c)
cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
c->x86_model_id[48] = 0;
/* Set MTRR capability flag if appropriate */
- if(boot_cpu_data.x86 == 5) {
- if((boot_cpu_data.x86_model == 9) ||
- ((boot_cpu_data.x86_model == 8) &&
- (boot_cpu_data.x86_mask >= 8)))
- c->x86_capability |= X86_FEATURE_MTRR;
- }
-
- if (n >= 0x80000005){
- cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
- printk("CPU: L1 I Cache: %dK L1 D Cache: %dK\n",
- ecx>>24, edx>>24);
- 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);
+
+ if(c->x86_vendor==X86_VENDOR_AMD)
+ {
+ if(boot_cpu_data.x86 == 5) {
+ if((boot_cpu_data.x86_model == 9) ||
+ ((boot_cpu_data.x86_model == 8) &&
+ (boot_cpu_data.x86_mask >= 8)))
+ c->x86_capability |= X86_FEATURE_MTRR;
+ }
+
+ if (n >= 0x80000005){
+ cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
+ printk("CPU: L1 I Cache: %dK L1 D Cache: %dK\n",
+ ecx>>24, edx>>24);
+ 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);
+ }
}
return 1;
}
@@ -1034,6 +1038,8 @@ static void __init cyrix_model(struct cpuinfo_x86 *c)
printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");
isa_dma_bridge_buggy = 2;
#endif
+ c->x86_cache_size=16; /* Yep 16K integrated cache thats it */
+
/* GXm supports extended cpuid levels 'ala' AMD */
if (c->cpuid_level == 2) {
get_model_name(c); /* get CPU marketing name */
@@ -1546,7 +1552,7 @@ void __init cpu_init (void)
cpus_initialized++;
printk("Initializing CPU#%d\n", nr);
- if (cpu_has_pse)
+ if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
__asm__ __volatile__("lgdt %0": "=m" (gdt_descr));
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index b4a7753b8..bcec04401 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -79,6 +79,9 @@ static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
unsigned long fast_gettimeoffset_quotient=0;
extern rwlock_t xtime_lock;
+extern volatile unsigned long lost_ticks;
+
+spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
static inline unsigned long do_fast_gettimeoffset(void)
{
@@ -113,6 +116,8 @@ static inline unsigned long do_fast_gettimeoffset(void)
#ifndef CONFIG_X86_TSC
+spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED;
+
/* This function must be called with interrupts disabled
* It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs
*
@@ -157,6 +162,8 @@ static unsigned long do_slow_gettimeoffset(void)
*/
unsigned long jiffies_t;
+ /* gets recalled with irq locally disabled */
+ spin_lock(&i8253_lock);
/* timer count may underflow right here */
outb_p(0x00, 0x43); /* latch the count ASAP */
@@ -215,6 +222,7 @@ static unsigned long do_slow_gettimeoffset(void)
}
} else
jiffies_p = jiffies_t;
+ spin_unlock(&i8253_lock);
count_p = count;
@@ -238,7 +246,6 @@ static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
*/
void do_gettimeofday(struct timeval *tv)
{
- extern volatile unsigned long lost_ticks;
unsigned long flags;
unsigned long usec, sec;
@@ -272,6 +279,7 @@ void do_settimeofday(struct timeval *tv)
* would have done, and then undo it!
*/
tv->tv_usec -= do_gettimeoffset();
+ tv->tv_usec -= lost_ticks * (1000000 / HZ);
while (tv->tv_usec < 0) {
tv->tv_usec += 1000000;
@@ -302,6 +310,8 @@ static int set_rtc_mmss(unsigned long nowtime)
int real_seconds, real_minutes, cmos_minutes;
unsigned char save_control, save_freq_select;
+ /* gets recalled with irq locally disabled */
+ spin_lock(&rtc_lock);
save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
@@ -347,6 +357,7 @@ static int set_rtc_mmss(unsigned long nowtime)
*/
CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+ spin_unlock(&rtc_lock);
return retval;
}
@@ -448,10 +459,19 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
rdtscl(last_tsc_low);
+#if 0 /*
+ * SUBTLE: this is not necessary from here because it's implicit in the
+ * write xtime_lock.
+ */
+ spin_lock(&i8253_lock);
+#endif
outb_p(0x00, 0x43); /* latch the count ASAP */
count = inb_p(0x40); /* read the latched count */
count |= inb(0x40) << 8;
+#if 0
+ spin_unlock(&i8253_lock);
+#endif
count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;