summaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r--arch/i386/kernel/acpi.c98
-rw-r--r--arch/i386/kernel/apic.c5
-rw-r--r--arch/i386/kernel/pci-i386.c14
-rw-r--r--arch/i386/kernel/pci-i386.h3
-rw-r--r--arch/i386/kernel/pci-irq.c38
-rw-r--r--arch/i386/kernel/pci-pc.c18
-rw-r--r--arch/i386/kernel/ptrace.c36
-rw-r--r--arch/i386/kernel/setup.c305
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;
}