]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'linus' into x86/cpu
authorIngo Molnar <mingo@elte.hu>
Mon, 28 Jul 2008 14:26:31 +0000 (16:26 +0200)
committerIngo Molnar <mingo@elte.hu>
Mon, 28 Jul 2008 14:26:31 +0000 (16:26 +0200)
Conflicts:

arch/x86/kernel/cpu/intel_cacheinfo.c

Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/kernel/cpu/cyrix.c
arch/x86/kernel/cpu/intel_cacheinfo.c
include/asm-x86/processor-cyrix.h

index 3fd7a67bb06aa7db7f9350e2a34203cb94c3240a..db5868cd24431d592bd0ac1b3922947c98841511 100644 (file)
@@ -116,7 +116,7 @@ static void __cpuinit set_cx86_reorder(void)
        setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
 
        /* Load/Store Serialize to mem access disable (=reorder it) */
-       setCx86(CX86_PCR0, getCx86(CX86_PCR0) & ~0x80);
+       setCx86_old(CX86_PCR0, getCx86_old(CX86_PCR0) & ~0x80);
        /* set load/store serialize from 1GB to 4GB */
        ccr3 |= 0xe0;
        setCx86(CX86_CCR3, ccr3);
@@ -127,11 +127,11 @@ static void __cpuinit set_cx86_memwb(void)
        printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n");
 
        /* CCR2 bit 2: unlock NW bit */
-       setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04);
+       setCx86_old(CX86_CCR2, getCx86_old(CX86_CCR2) & ~0x04);
        /* set 'Not Write-through' */
        write_cr0(read_cr0() | X86_CR0_NW);
        /* CCR2 bit 2: lock NW bit and set WT1 */
-       setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14);
+       setCx86_old(CX86_CCR2, getCx86_old(CX86_CCR2) | 0x14);
 }
 
 static void __cpuinit set_cx86_inc(void)
@@ -144,10 +144,10 @@ static void __cpuinit set_cx86_inc(void)
        setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
        /* PCR1 -- Performance Control */
        /* Incrementor on, whatever that is */
-       setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02);
+       setCx86_old(CX86_PCR1, getCx86_old(CX86_PCR1) | 0x02);
        /* PCR0 -- Performance Control */
        /* Incrementor Margin 10 */
-       setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04);
+       setCx86_old(CX86_PCR0, getCx86_old(CX86_PCR0) | 0x04);
        setCx86(CX86_CCR3, ccr3);       /* disable MAPEN */
 }
 
@@ -162,14 +162,14 @@ static void __cpuinit geode_configure(void)
        local_irq_save(flags);
 
        /* Suspend on halt power saving and enable #SUSP pin */
-       setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88);
+       setCx86_old(CX86_CCR2, getCx86_old(CX86_CCR2) | 0x88);
 
        ccr3 = getCx86(CX86_CCR3);
        setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);       /* enable MAPEN */
 
 
        /* FPU fast, DTE cache, Mem bypass */
-       setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x38);
+       setCx86_old(CX86_CCR4, getCx86_old(CX86_CCR4) | 0x38);
        setCx86(CX86_CCR3, ccr3);                       /* disable MAPEN */
 
        set_cx86_memwb();
@@ -286,7 +286,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
                /* GXm supports extended cpuid levels 'ala' AMD */
                if (c->cpuid_level == 2) {
                        /* Enable cxMMX extensions (GX1 Datasheet 54) */
-                       setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1);
+                       setCx86_old(CX86_CCR7, getCx86_old(CX86_CCR7) | 1);
 
                        /*
                         * GXm : 0x30 ... 0x5f GXm  datasheet 51
@@ -309,7 +309,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
                if (dir1 > 7) {
                        dir0_msn++;  /* M II */
                        /* Enable MMX extensions (App note 108) */
-                       setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
+                       setCx86_old(CX86_CCR7, getCx86_old(CX86_CCR7)|1);
                } else {
                        c->coma_bug = 1;      /* 6x86MX, it has the bug. */
                }
@@ -424,7 +424,7 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c)
                        local_irq_save(flags);
                        ccr3 = getCx86(CX86_CCR3);
                        setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);       /* enable MAPEN  */
-                       setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x80);  /* enable cpuid  */
+                       setCx86_old(CX86_CCR4, getCx86_old(CX86_CCR4) | 0x80);  /* enable cpuid  */
                        setCx86(CX86_CCR3, ccr3);                       /* disable MAPEN */
                        local_irq_restore(flags);
                }
index 650d40f7912bea81023dc7f9698b8b10ced4d6fa..d763d24187c2dd573103734723708c2b65292775 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *      Routines to indentify caches on Intel CPU.
+ *     Routines to indentify caches on Intel CPU.
  *
- *      Changes:
- *      Venkatesh Pallipadi    : Adding cache identification through cpuid(4)
+ *     Changes:
+ *     Venkatesh Pallipadi     : Adding cache identification through cpuid(4)
  *             Ashok Raj <ashok.raj@intel.com>: Work with CPU hotplug infrastructure.
  *     Andi Kleen / Andreas Herrmann   : CPUID4 emulation on AMD.
  */
@@ -13,6 +13,7 @@
 #include <linux/compiler.h>
 #include <linux/cpu.h>
 #include <linux/sched.h>
+#include <linux/pci.h>
 
 #include <asm/processor.h>
 #include <asm/smp.h>
@@ -130,9 +131,16 @@ struct _cpuid4_info {
        union _cpuid4_leaf_ebx ebx;
        union _cpuid4_leaf_ecx ecx;
        unsigned long size;
+       unsigned long can_disable;
        cpumask_t shared_cpu_map;       /* future?: only cpus/node is needed */
 };
 
+static struct pci_device_id k8_nb_id[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) },
+       {}
+};
+
 unsigned short                 num_cache_leaves;
 
 /* AMD doesn't have CPUID4. Emulate it here to report the same
@@ -182,9 +190,10 @@ static unsigned short assocs[] __cpuinitdata = {
 static unsigned char levels[] __cpuinitdata = { 1, 1, 2, 3 };
 static unsigned char types[] __cpuinitdata = { 1, 2, 3, 3 };
 
-static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
-                      union _cpuid4_leaf_ebx *ebx,
-                      union _cpuid4_leaf_ecx *ecx)
+static void __cpuinit
+amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
+                    union _cpuid4_leaf_ebx *ebx,
+                    union _cpuid4_leaf_ecx *ecx)
 {
        unsigned dummy;
        unsigned line_size, lines_per_tag, assoc, size_in_kb;
@@ -251,27 +260,40 @@ static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
                (ebx->split.ways_of_associativity + 1) - 1;
 }
 
-static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
+static void __cpuinit
+amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf)
+{
+       if (index < 3)
+               return;
+       this_leaf->can_disable = 1;
+}
+
+static int
+__cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
 {
        union _cpuid4_leaf_eax  eax;
        union _cpuid4_leaf_ebx  ebx;
        union _cpuid4_leaf_ecx  ecx;
        unsigned                edx;
 
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
                amd_cpuid4(index, &eax, &ebx, &ecx);
-       else
-               cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full,  &edx);
+               if (boot_cpu_data.x86 >= 0x10)
+                       amd_check_l3_disable(index, this_leaf);
+       } else {
+               cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
+       }
+
        if (eax.split.type == CACHE_TYPE_NULL)
                return -EIO; /* better error ? */
 
        this_leaf->eax = eax;
        this_leaf->ebx = ebx;
        this_leaf->ecx = ecx;
-       this_leaf->size = (ecx.split.number_of_sets + 1) *
-               (ebx.split.coherency_line_size + 1) *
-               (ebx.split.physical_line_partition + 1) *
-               (ebx.split.ways_of_associativity + 1);
+       this_leaf->size = (ecx.split.number_of_sets          + 1) *
+                         (ebx.split.coherency_line_size     + 1) *
+                         (ebx.split.physical_line_partition + 1) *
+                         (ebx.split.ways_of_associativity   + 1);
        return 0;
 }
 
@@ -453,7 +475,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
 
 /* pointer to _cpuid4_info array (for each cache leaf) */
 static DEFINE_PER_CPU(struct _cpuid4_info *, cpuid4_info);
-#define CPUID4_INFO_IDX(x, y)    (&((per_cpu(cpuid4_info, x))[y]))
+#define CPUID4_INFO_IDX(x, y)  (&((per_cpu(cpuid4_info, x))[y]))
 
 #ifdef CONFIG_SMP
 static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
@@ -490,7 +512,7 @@ static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index)
 
        this_leaf = CPUID4_INFO_IDX(cpu, index);
        for_each_cpu_mask_nr(sibling, this_leaf->shared_cpu_map) {
-               sibling_leaf = CPUID4_INFO_IDX(sibling, index); 
+               sibling_leaf = CPUID4_INFO_IDX(sibling, index);
                cpu_clear(cpu, sibling_leaf->shared_cpu_map);
        }
 }
@@ -573,7 +595,7 @@ struct _index_kobject {
 
 /* pointer to array of kobjects for cpuX/cache/indexY */
 static DEFINE_PER_CPU(struct _index_kobject *, index_kobject);
-#define INDEX_KOBJECT_PTR(x, y)    (&((per_cpu(index_kobject, x))[y]))
+#define INDEX_KOBJECT_PTR(x, y)                (&((per_cpu(index_kobject, x))[y]))
 
 #define show_one_plus(file_name, object, val)                          \
 static ssize_t show_##file_name                                                \
@@ -638,6 +660,92 @@ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) {
        }
 }
 
+#define to_object(k)   container_of(k, struct _index_kobject, kobj)
+#define to_attr(a)     container_of(a, struct _cache_attr, attr)
+
+static struct pci_dev *get_k8_northbridge(int node)
+{
+       struct pci_dev *dev = NULL;
+       int i;
+
+       for (i = 0; i <= node; i++) {
+               do {
+                       dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+                       if (!dev)
+                               break;
+               } while (!pci_match_id(&k8_nb_id[0], dev));
+               if (!dev)
+                       break;
+       }
+       return dev;
+}
+
+static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf)
+{
+       int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map));
+       struct pci_dev *dev = NULL;
+       ssize_t ret = 0;
+       int i;
+
+       if (!this_leaf->can_disable)
+               return sprintf(buf, "Feature not enabled\n");
+
+       dev = get_k8_northbridge(node);
+       if (!dev) {
+               printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < 2; i++) {
+               unsigned int reg;
+
+               pci_read_config_dword(dev, 0x1BC + i * 4, &reg);
+
+               ret += sprintf(buf, "%sEntry: %d\n", buf, i);
+               ret += sprintf(buf, "%sReads:  %s\tNew Entries: %s\n",  
+                       buf,
+                       reg & 0x80000000 ? "Disabled" : "Allowed",
+                       reg & 0x40000000 ? "Disabled" : "Allowed");
+               ret += sprintf(buf, "%sSubCache: %x\tIndex: %x\n",
+                       buf, (reg & 0x30000) >> 16, reg & 0xfff);
+       }
+       return ret;
+}
+
+static ssize_t
+store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf,
+                   size_t count)
+{
+       int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map));
+       struct pci_dev *dev = NULL;
+       unsigned int ret, index, val;
+
+       if (!this_leaf->can_disable)
+               return 0;
+
+       if (strlen(buf) > 15)
+               return -EINVAL;
+
+       ret = sscanf(buf, "%x %x", &index, &val);
+       if (ret != 2)
+               return -EINVAL;
+       if (index > 1)
+               return -EINVAL;
+
+       val |= 0xc0000000;
+       dev = get_k8_northbridge(node);
+       if (!dev) {
+               printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n");
+               return -EINVAL;
+       }
+
+       pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000);
+       wbinvd();
+       pci_write_config_dword(dev, 0x1BC + index * 4, val);
+
+       return 1;
+}
+
 struct _cache_attr {
        struct attribute attr;
        ssize_t (*show)(struct _cpuid4_info *, char *);
@@ -658,6 +766,8 @@ define_one_ro(size);
 define_one_ro(shared_cpu_map);
 define_one_ro(shared_cpu_list);
 
+static struct _cache_attr cache_disable = __ATTR(cache_disable, 0644, show_cache_disable, store_cache_disable);
+
 static struct attribute * default_attrs[] = {
        &type.attr,
        &level.attr,
@@ -668,12 +778,10 @@ static struct attribute * default_attrs[] = {
        &size.attr,
        &shared_cpu_map.attr,
        &shared_cpu_list.attr,
+       &cache_disable.attr,
        NULL
 };
 
-#define to_object(k) container_of(k, struct _index_kobject, kobj)
-#define to_attr(a) container_of(a, struct _cache_attr, attr)
-
 static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf)
 {
        struct _cache_attr *fattr = to_attr(attr);
@@ -683,14 +791,22 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf)
        ret = fattr->show ?
                fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
                        buf) :
-               0;
+               0;
        return ret;
 }
 
 static ssize_t store(struct kobject * kobj, struct attribute * attr,
                     const char * buf, size_t count)
 {
-       return 0;
+       struct _cache_attr *fattr = to_attr(attr);
+       struct _index_kobject *this_leaf = to_object(kobj);
+       ssize_t ret;
+
+       ret = fattr->store ?
+               fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
+                       buf, count) :
+               0;
+       return ret;
 }
 
 static struct sysfs_ops sysfs_ops = {
index 97568ada1f974f69409f4f4ffab93173327d4779..1198f2a0e42c77e5635d00934e1b4e453e836e0e 100644 (file)
@@ -28,3 +28,11 @@ static inline void setCx86(u8 reg, u8 data)
        outb(reg, 0x22);
        outb(data, 0x23);
 }
+
+#define getCx86_old(reg) ({ outb((reg), 0x22); inb(0x23); })
+
+#define setCx86_old(reg, data) do { \
+       outb((reg), 0x22); \
+       outb((data), 0x23); \
+} while (0)
+