diff options
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/Makefile | 5 | ||||
-rw-r--r-- | arch/i386/boot/compressed/head.S | 8 | ||||
-rw-r--r-- | arch/i386/defconfig | 2 | ||||
-rw-r--r-- | arch/i386/kernel/acpi.c | 30 | ||||
-rw-r--r-- | arch/i386/kernel/head.S | 10 | ||||
-rw-r--r-- | arch/i386/kernel/i386_ksyms.c | 3 | ||||
-rw-r--r-- | arch/i386/kernel/pci-i386.c | 14 | ||||
-rw-r--r-- | arch/i386/kernel/pci-pc.c | 38 | ||||
-rw-r--r-- | arch/i386/kernel/setup.c | 44 | ||||
-rw-r--r-- | arch/i386/kernel/time.c | 22 |
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; |