diff options
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r-- | arch/i386/kernel/acpi.c | 98 | ||||
-rw-r--r-- | arch/i386/kernel/apic.c | 5 | ||||
-rw-r--r-- | arch/i386/kernel/pci-i386.c | 14 | ||||
-rw-r--r-- | arch/i386/kernel/pci-i386.h | 3 | ||||
-rw-r--r-- | arch/i386/kernel/pci-irq.c | 38 | ||||
-rw-r--r-- | arch/i386/kernel/pci-pc.c | 18 | ||||
-rw-r--r-- | arch/i386/kernel/ptrace.c | 36 | ||||
-rw-r--r-- | arch/i386/kernel/setup.c | 305 |
8 files changed, 325 insertions, 192 deletions
diff --git a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c index e63a45e66..d9dabac2f 100644 --- a/arch/i386/kernel/acpi.c +++ b/arch/i386/kernel/acpi.c @@ -144,14 +144,21 @@ static unsigned long acpi_opts = ACPI_ENABLED; struct acpi_errata_info { - const char *oem; - const char *oem_table; - u32 oem_rev; - unsigned long options; + const char *signature; // table signature (eg. "RSDT") + const char *oem; // OEM name + const char *oem_table; // OEM table identifier (optional) + u32 oem_rev; // OEM table revision (optional) + unsigned long options; // errata options }; +/* + * We must identify systems that need ACPI_TRUST_TABLES solely from the + * RSDP ("RSD PTR "). All other options should be flagged from the + * RSDT ("RSDT") which can be better identified. + */ struct acpi_errata_info acpi_errata[] = { + {"RSD PTR ", "AMI ", NULL, 0, ACPI_TRUST_TABLES | ACPI_COPY_TABLES}, {NULL, NULL, 0, 0}, }; @@ -521,6 +528,51 @@ static void acpi_destroy_table(struct acpi_table_info *info) } /* + * Match ACPI table and set options based on platform errata, if any + */ +static int __init acpi_find_errata(struct acpi_table *table) +{ + struct acpi_errata_info *info; + int size; + + for (info = acpi_errata; info->signature && info->oem; info++) { + size = strlen(info->signature); + if (memcmp(&table->signature, info->signature, size)) + continue; + if (strcmp(info->signature, "RSD PTR ")) { + // ordinary ACPI table + size = strlen(info->oem); + if (memcmp(table->oem, info->oem, size)) + continue; + if (info->oem_table) { + size = strlen(info->oem_table); + if (memcmp(table->oem_table, + info->oem_table, + size)) + continue; + } + if (info->oem_rev && table->oem_rev != info->oem_rev) + continue; + } + else { + // special handling for RSDP + size = strlen(info->oem); + if (memcmp(((struct acpi_rsdp*) table)->oem, + info->oem, + size)) + continue; + } + + printk(KERN_INFO + "ACPI: found platform errata 0x%08lx\n", + info->options); + acpi_opts |= info->options; + return 0; + } + return -1; +} + +/* * Locate and map ACPI tables */ static int __init acpi_find_tables(void) @@ -556,6 +608,14 @@ static int __init acpi_find_tables(void) if (i >= ACPI_BIOS_ROM_END) return -ENODEV; + // find any errata based on the RSDP + if (!acpi_find_errata((struct acpi_table*) rsdp)) { + if (acpi_opts & ACPI_DISABLED) + return -EINVAL; + else if (acpi_opts & ACPI_CHIPSET_ONLY) + return -ENODEV; + } + // fetch RSDT from RSDP rsdt = acpi_map_table(rsdp->rsdt); if (!rsdt) { @@ -569,6 +629,15 @@ static int __init acpi_find_tables(void) acpi_unmap_table(rsdt); return -EINVAL; } + + // find any errata based on the RSDT + if (!acpi_find_errata(rsdt)) { + if (acpi_opts & ACPI_DISABLED) + return -EINVAL; + else if (acpi_opts & ACPI_CHIPSET_ONLY) + return -ENODEV; + } + // search RSDT for FACP acpi_facp.table = NULL; rsdt_entry = (u32 *) (rsdt + 1); @@ -631,11 +700,7 @@ static int __init acpi_init_piix4(struct pci_dev *dev) if (!(pmregmisc & ACPI_PIIX4_PMIOSE)) return -ENODEV; - pci_read_config_dword(dev, 0x40, &base); - if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) - return -ENODEV; - - base &= PCI_BASE_ADDRESS_IO_MASK; + base = dev->resource[PCI_BRIDGE_RESOURCES].start & PCI_BASE_ADDRESS_IO_MASK; if (!base) return -ENODEV; @@ -688,16 +753,13 @@ static int __init acpi_init_via(struct pci_dev *dev) if (!(tmp & 0x80)) return -ENODEV; - pci_read_config_byte(dev, PCI_CLASS_REVISION, &tmp); - tmp = (tmp & 0x10 ? 0x48 : 0x20); - - pci_read_config_dword(dev, tmp, &base); - if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) - return -ENODEV; - + base = pci_resource_start(dev, PCI_BRIDGE_RESOURCES); + if (!base) { + base = pci_resource_start(dev, PCI_BASE_ADDRESS_4); + if (!base) + return -ENODEV; + } base &= PCI_BASE_ADDRESS_IO_MASK; - if (!base) - return -ENODEV; pci_read_config_byte(dev, 0x42, &irq); diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index d4c35fdf0..bf3d3c0af 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -615,6 +615,7 @@ static inline void handle_smp_time (int user, int cpu) inline void smp_local_timer_interrupt(struct pt_regs * regs) { + int user = user_mode(regs); int cpu = smp_processor_id(); /* @@ -623,6 +624,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) { /* @@ -640,7 +643,7 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs) } #ifdef CONFIG_SMP - handle_smp_time(user_mode(regs), cpu); + handle_smp_time(user, cpu); #endif } diff --git a/arch/i386/kernel/pci-i386.c b/arch/i386/kernel/pci-i386.c index cc3f8e1da..afb90ab12 100644 --- a/arch/i386/kernel/pci-i386.c +++ b/arch/i386/kernel/pci-i386.c @@ -330,12 +330,18 @@ int pcibios_enable_resources(struct pci_dev *dev) * 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. */ +unsigned int pcibios_max_latency = 255; + 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); - } + if (lat < 16) + lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; + else if (lat > pcibios_max_latency) + lat = pcibios_max_latency; + else + return; + printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); } diff --git a/arch/i386/kernel/pci-i386.h b/arch/i386/kernel/pci-i386.h index 5af43f661..f4f808e4c 100644 --- a/arch/i386/kernel/pci-i386.h +++ b/arch/i386/kernel/pci-i386.h @@ -25,6 +25,8 @@ extern unsigned int pci_probe; /* pci-i386.c */ +extern unsigned int pcibios_max_latency; + void pcibios_resource_survey(void); int pcibios_enable_resources(struct pci_dev *); @@ -64,5 +66,6 @@ struct irq_routing_table { extern unsigned int pcibios_irq_mask; +void pcibios_irq_init(void); void pcibios_fixup_irqs(void); int pcibios_lookup_irq(struct pci_dev *dev, int assign); diff --git a/arch/i386/kernel/pci-irq.c b/arch/i386/kernel/pci-irq.c index 4695abdf4..d678801b6 100644 --- a/arch/i386/kernel/pci-irq.c +++ b/arch/i386/kernel/pci-irq.c @@ -125,11 +125,22 @@ static void eisa_set_level_irq(unsigned int irq) } } +static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq) +{ + static unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; + pirq--; + if (pirq < 8) { + u8 x; + unsigned reg = 0x48 + (pirq >> 1); + pci_read_config_byte(router, reg, &x); + return irqmap[(pirq & 1) ? (x >> 4) : (x & 0x0f)]; + } + return 0; +} + static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - static unsigned char irqmap[16] = { - 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 - }; + static unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 }; unsigned int val = irqmap[irq]; pirq--; if (val && pirq < 8) { @@ -211,7 +222,7 @@ static struct irq_router pirq_routers[] = { { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, pirq_piix_get, pirq_piix_set }, { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, pirq_piix_get, pirq_piix_set }, { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set }, - { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL, pirq_ali_set }, + { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set }, { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set }, { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set }, { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, pirq_via_get, pirq_via_set }, @@ -236,7 +247,9 @@ static void __init pirq_find_router(void) } #endif if (!(pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn))) { - DBG("PCI: Interrupt router not found\n"); + DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn); + /* fall back to default router */ + pirq_router = pirq_routers + sizeof(pirq_routers) / sizeof(pirq_routers[0]) - 1; return; } if (rt->rtr_vendor) { @@ -354,12 +367,9 @@ int pcibios_lookup_irq(struct pci_dev *dev, int assign) return 1; } -void __init pcibios_fixup_irqs(void) +void __init pcibios_irq_init(void) { - struct pci_dev *dev; - u8 pin; - - DBG("PCI: IRQ fixup\n"); + DBG("PCI: IRQ init\n"); pirq_table = pirq_find_routing_table(); #ifdef CONFIG_PCI_BIOS if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN)) @@ -369,7 +379,14 @@ void __init pcibios_fixup_irqs(void) pirq_peer_trick(); pirq_find_router(); } +} + +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev; + u8 pin; + DBG("PCI: IRQ fixup\n"); pci_for_each_dev(dev) { /* * If the BIOS has set an out of range IRQ number, just ignore it. @@ -416,7 +433,6 @@ void __init pcibios_fixup_irqs(void) dev->irq = irq; } } - pirq_table = NULL; /* Avoid automatic IRQ assignment */ } #endif /* diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c index 6dbac9abd..d1f41ff0d 100644 --- a/arch/i386/kernel/pci-pc.c +++ b/arch/i386/kernel/pci-pc.c @@ -10,6 +10,7 @@ #include <linux/sched.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/ioport.h> #include <asm/segment.h> #include <asm/io.h> @@ -208,6 +209,7 @@ static struct pci_ops * __init pci_check_direct(void) outl (tmp, 0xCF8); __restore_flags(flags); printk("PCI: Using configuration type 1\n"); + request_region(0xCF8, 8, "PCI conf1"); return &pci_direct_conf1; } outl (tmp, 0xCF8); @@ -224,6 +226,7 @@ static struct pci_ops * __init pci_check_direct(void) pci_sanity_check(&pci_direct_conf2)) { __restore_flags(flags); printk("PCI: Using configuration type 2\n"); + request_region(0xCF8, 4, "PCI conf2"); return &pci_direct_conf2; } } @@ -912,6 +915,16 @@ static void __init pci_fixup_ide_trash(struct pci_dev *d) d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0; } +static void __init pci_fixup_latency(struct pci_dev *d) +{ + /* + * SiS 5597 and 5598 chipsets require latency timer set to + * at most 32 to avoid lockups. + */ + DBG("PCI: Setting max latency to 32\n"); + pcibios_max_latency = 32; +} + struct pci_fixup pcibios_fixups[] = { { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx }, @@ -921,6 +934,8 @@ struct pci_fixup pcibios_fixups[] = { { PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash }, { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency }, { 0 } }; @@ -969,8 +984,9 @@ void __init pcibios_init(void) printk("PCI: Probing PCI hardware\n"); pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL); - pcibios_fixup_irqs(); + pcibios_irq_init(); pcibios_fixup_peer_bridges(); + pcibios_fixup_irqs(); pcibios_resource_survey(); #ifdef CONFIG_PCI_BIOS diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index ed64f15a2..de9656150 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -134,7 +134,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; struct user * dummy = NULL; - unsigned long flags; int i, ret; lock_kernel(); @@ -151,15 +150,19 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = -ESRCH; read_lock(&tasklist_lock); child = find_task_by_pid(pid); - read_unlock(&tasklist_lock); /* FIXME!!! */ + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); if (!child) goto out; + ret = -EPERM; if (pid == 1) /* you may not mess with init */ - goto out; + goto out_tsk; + if (request == PTRACE_ATTACH) { if (child == current) - goto out; + goto out_tsk; if ((!child->dumpable || (current->uid != child->euid) || (current->uid != child->suid) || @@ -168,34 +171,33 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) (current->gid != child->sgid) || (!cap_issubset(child->cap_permitted, current->cap_permitted)) || (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out; + goto out_tsk; /* the same process cannot be attached many times */ if (child->flags & PF_PTRACED) - goto out; + goto out_tsk; child->flags |= PF_PTRACED; - write_lock_irqsave(&tasklist_lock, flags); + write_lock_irq(&tasklist_lock); if (child->p_pptr != current) { REMOVE_LINKS(child); child->p_pptr = current; SET_LINKS(child); } - write_unlock_irqrestore(&tasklist_lock, flags); + write_unlock_irq(&tasklist_lock); send_sig(SIGSTOP, child, 1); ret = 0; - goto out; + goto out_tsk; } ret = -ESRCH; if (!(child->flags & PF_PTRACED)) - goto out; + goto out_tsk; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) - goto out; + goto out_tsk; } if (child->p_pptr != current) - goto out; - + goto out_tsk; switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -270,7 +272,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) data &= ~DR_CONTROL_RESERVED; for(i=0; i<4; i++) if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1) - goto out; + goto out_tsk; } addr -= (long) &dummy->u_debugreg; @@ -347,11 +349,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) break; child->flags &= ~(PF_PTRACED|PF_TRACESYS); child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); + write_lock_irq(&tasklist_lock); REMOVE_LINKS(child); child->p_pptr = child->p_opptr; SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); + write_unlock_irq(&tasklist_lock); /* make sure the single step bit is not set. */ tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; put_stack_long(child, EFL_OFFSET, tmp); @@ -435,6 +437,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } +out_tsk: + free_task_struct(child); out: unlock_kernel(); return ret; diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index ac088253f..e3e043b23 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -32,9 +32,13 @@ * Added proper L2 cache detection for Coppermine * Dragan Stancevic <visitor@valinux.com>, October 1999 * - * Added the origninal array for capability flags but forgot to credit + * Added the original array for capability flags but forgot to credit * myself :) (~1998) Fixed/cleaned up some cpu_model_info and other stuff * Jauder Ho <jauderho@carumba.com>, January 2000 + * + * Detection for Celeron coppermine, identify_cpu() overhauled, + * and a few other clean ups. + * Dave Jones <dave@powertweak.com>, April 2000 * */ @@ -794,7 +798,7 @@ void __init setup_arch(char **cmdline_p) static int __init get_model_name(struct cpuinfo_x86 *c) { - unsigned int n, dummy, *v, ecx, edx; + unsigned int n, dummy, *v; /* Actually we must have cpuid or we could never have * figured out that this was AMD/Cyrix from the vendor info :-). @@ -809,29 +813,6 @@ static int __init get_model_name(struct cpuinfo_x86 *c) cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]); cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]); c->x86_model_id[48] = 0; - /* Set MTRR capability flag if appropriate */ - - 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; } @@ -839,14 +820,24 @@ static int __init amd_model(struct cpuinfo_x86 *c) { u32 l, h; unsigned long flags; + unsigned int n, dummy, ecx, edx; int mbytes = max_mapnr >> (20-PAGE_SHIFT); - + int r=get_model_name(c); - + /* - * Now do the cache operations. + * 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; + } + + /* + * Now do the cache operations. */ - switch(c->x86) { case 5: @@ -903,6 +894,20 @@ static int __init amd_model(struct cpuinfo_x86 *c) case 6: /* An Athlon. We can trust the BIOS probably */ break; } + + cpuid(0x80000000, &n, &dummy, &dummy, &dummy); + 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 r; } @@ -1029,13 +1034,13 @@ static void __init cyrix_model(struct cpuinfo_x86 *c) /* It isnt really a PCI quirk directly, but the cure is the same. The MediaGX has deep magic SMM stuff that handles the SB emulation. It thows away the fifo on disable_dma() which - is wrong and ruins the audio. + is wrong and ruins the audio. - Bug2: VSA1 has a wrap bug so that using maximum sized DMA - causes bad things. According to NatSemi VSA2 has another - bug to do with 'hlt'. I've not seen any boards using VSA2 - and X doesn't seem to support it either so who cares 8). - VSA1 we work around however. + Bug2: VSA1 has a wrap bug so that using maximum sized DMA + causes bad things. According to NatSemi VSA2 has another + bug to do with 'hlt'. I've not seen any boards using VSA2 + and X doesn't seem to support it either so who cares 8). + VSA1 we work around however. */ @@ -1043,7 +1048,7 @@ static void __init cyrix_model(struct cpuinfo_x86 *c) 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 */ @@ -1256,7 +1261,7 @@ static struct cpu_model_info cpu_models[] __initdata = { void __init identify_cpu(struct cpuinfo_x86 *c) { - int i; + int i=0; char *p = NULL; c->loops_per_sec = loops_per_sec; @@ -1264,100 +1269,118 @@ void __init identify_cpu(struct cpuinfo_x86 *c) get_cpu_vendor(c); - if (c->x86_vendor == X86_VENDOR_UNKNOWN && - c->cpuid_level < 0) - return; + switch (c->x86_vendor) { - if (c->x86_vendor == X86_VENDOR_CYRIX) { - cyrix_model(c); - return; - } + case X86_VENDOR_UNKNOWN: + if (c->cpuid_level < 0) + return; + break; - if (c->x86_vendor == X86_VENDOR_AMD && amd_model(c)) - return; + case X86_VENDOR_CYRIX: + cyrix_model(c); + return; - if (c->x86_vendor == X86_VENDOR_CENTAUR) { - centaur_model(c); - return; - } - - if (c->cpuid_level > 0 && c->x86_vendor == X86_VENDOR_INTEL) - { - if(c->x86_capability&(1<<18)) - { - /* Disable processor serial number on Intel Pentium III - from code by Phil Karn */ - unsigned long lo,hi; - rdmsr(0x119,lo,hi); - lo |= 0x200000; - wrmsr(0x119,lo,hi); - printk(KERN_INFO "Pentium-III serial number disabled.\n"); - } - } + case X86_VENDOR_AMD: + if (amd_model(c)) + return; + break; - if (c->cpuid_level > 1) { - /* supports eax=2 call */ - int edx, dummy; + case X86_VENDOR_CENTAUR: + centaur_model(c); + return; - cpuid(2, &dummy, &dummy, &dummy, &edx); + case X86_VENDOR_INTEL: + if(c->x86_capability&(1<<18)) { + /* Disable processor serial number on Intel Pentium III + from code by Phil Karn */ + unsigned long lo,hi; + rdmsr(0x119,lo,hi); + lo |= 0x200000; + wrmsr(0x119,lo,hi); + printk(KERN_INFO "Pentium-III serial number disabled.\n"); + } - /* We need only the LSB */ - edx &= 0xff; + if (c->cpuid_level > 1) { + /* supports eax=2 call */ + int edx, dummy; - switch (edx) { - case 0x40: - c->x86_cache_size = 0; - break; + cpuid(2, &dummy, &dummy, &dummy, &edx); - case 0x41: - c->x86_cache_size = 128; - break; + /* We need only the LSB */ + edx &= 0xff; - case 0x42: - case 0x82: /*Detect 256-Kbyte cache on Coppermine*/ - c->x86_cache_size = 256; - break; + switch (edx) { + case 0x40: + c->x86_cache_size = 0; + break; - case 0x43: - c->x86_cache_size = 512; - break; + case 0x41: + c->x86_cache_size = 128; + break; - case 0x44: - c->x86_cache_size = 1024; - break; + case 0x42: + case 0x82: /*Detect 256-Kbyte cache on Coppermine*/ + c->x86_cache_size = 256; + break; - case 0x45: - c->x86_cache_size = 2048; - break; + case 0x43: + c->x86_cache_size = 512; + break; - default: - c->x86_cache_size = 0; - break; - } - } + case 0x44: + c->x86_cache_size = 1024; + break; + + case 0x45: + c->x86_cache_size = 2048; + break; + default: + c->x86_cache_size = 0; + break; + } + } + + /* Names for the Pentium II/Celeron processors + detectable only by also checking the cache size. + Dixon is NOT a Celeron. */ + if (c->x86 == 6) { + switch (c->x86_model) { + case 5: + if (c->x86_cache_size == 0) + p = "Celeron (Covington)"; + if (c->x86_cache_size == 256) + p = "Mobile Pentium II (Dixon)"; + break; + + case 6: + if (c->x86_cache_size == 128) + p = "Celeron (Mendocino)"; + break; + + case 8: + if (c->x86_cache_size == 128) + p = "Celeron (Coppermine)"; + break; + } + } + if (p!=NULL) + goto name_decoded; + + break; + } + + 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) { if (c->x86_model <= 16) p = cpu_models[i].model_names[c->x86_model]; - - /* Names for the Pentium II/Celeron processors - detectable only by also checking the cache size. - Dixon is NOT a Celeron. */ - if ((cpu_models[i].vendor == X86_VENDOR_INTEL) - && (cpu_models[i].x86 == 6)) - { - if(c->x86_model == 5 && c->x86_cache_size == 0) - p = "Celeron (Covington)"; - else if(c->x86_model == 6 && c->x86_cache_size == 128) - p = "Celeron (Mendocino)"; - else if(c->x86_model == 5 && c->x86_cache_size == 256) - p = "Mobile Pentium II (Dixon)"; - } } } +name_decoded: + if (p) { strcpy(c->x86_model_id, p); return; @@ -1373,11 +1396,10 @@ void __init identify_cpu(struct cpuinfo_x86 *c) void __init dodgy_tsc(void) { get_cpu_vendor(&boot_cpu_data); - + if(boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX) - { return; - } + cyrix_model(&boot_cpu_data); } @@ -1442,15 +1464,15 @@ int get_cpuinfo(char * buffer) continue; #endif p += sprintf(p,"processor\t: %d\n" - "vendor_id\t: %s\n" - "cpu family\t: %c\n" - "model\t\t: %d\n" - "model name\t: %s\n", - n, - c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown", - c->x86 + '0', - c->x86_model, - c->x86_model_id[0] ? c->x86_model_id : "unknown"); + "vendor_id\t: %s\n" + "cpu family\t: %c\n" + "model\t\t: %d\n" + "model name\t: %s\n", + n, + c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown", + c->x86 + '0', + c->x86_model, + c->x86_model_id[0] ? c->x86_model_id : "unknown"); if (c->x86_mask || c->cpuid_level >= 0) p += sprintf(p, "stepping\t: %d\n", c->x86_mask); @@ -1470,32 +1492,32 @@ int get_cpuinfo(char * buffer) switch (c->x86_vendor) { case X86_VENDOR_CYRIX: - x86_cap_flags[24] = "cxmmx"; - break; + x86_cap_flags[24] = "cxmmx"; + break; case X86_VENDOR_AMD: - if (c->x86 == 5 && c->x86_model == 6) - x86_cap_flags[10] = "sep"; - if (c->x86 < 6) - x86_cap_flags[16] = "fcmov"; - x86_cap_flags[22] = "mmxext"; - x86_cap_flags[30] = "3dnowext"; - x86_cap_flags[31] = "3dnow"; - break; + if (c->x86 == 5 && c->x86_model == 6) + x86_cap_flags[10] = "sep"; + if (c->x86 < 6) + x86_cap_flags[16] = "fcmov"; + x86_cap_flags[22] = "mmxext"; + x86_cap_flags[30] = "3dnowext"; + x86_cap_flags[31] = "3dnow"; + break; case X86_VENDOR_INTEL: - x86_cap_flags[16] = "pat"; - x86_cap_flags[24] = "fxsr"; - break; + x86_cap_flags[16] = "pat"; + x86_cap_flags[24] = "fxsr"; + break; case X86_VENDOR_CENTAUR: - if (c->x86_model >=8) /* Only Winchip2 and above */ - x86_cap_flags[31] = "3dnow"; - break; + if (c->x86_model >=8) /* Only Winchip2 and above */ + x86_cap_flags[31] = "3dnow"; + break; default: - /* Unknown CPU manufacturer. Transmeta ? :-) */ - break; + /* Unknown CPU manufacturer. Transmeta ? :-) */ + break; } sep_bug = c->x86_vendor == X86_VENDOR_INTEL && @@ -1528,9 +1550,10 @@ int get_cpuinfo(char * buffer) for ( i = 0 ; i < 32 ; i++ ) if ( c->x86_capability & (1 << i) ) p += sprintf(p, " %s", x86_cap_flags[i]); + p += sprintf(p, "\nbogomips\t: %lu.%02lu\n\n", - (c->loops_per_sec+2500)/500000, - ((c->loops_per_sec+2500)/5000) % 100); + (c->loops_per_sec+2500)/500000, + ((c->loops_per_sec+2500)/5000) % 100); } return p - buffer; } |