public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/01] x86: L3 cache index disable for 2.6.26
@ 2008-07-18 21:03 Mark Langsdorf
  2008-07-21 11:37 ` Ingo Molnar
  2008-08-08 22:00 ` Pavel Machek
  0 siblings, 2 replies; 31+ messages in thread
From: Mark Langsdorf @ 2008-07-18 21:03 UTC (permalink / raw)
  To: tglx, mingo, hpa, linux-kernel

New versions of AMD processors have support to disable parts
of their L3 caches if too many MCEs are generated by the
L3 cache.  

This patch provides a /sysfs interface under the cache
hierarchy to display which caches indices are disabled
(if any) and to monitoring applications to disable a
cache index.

This patch does not set an automatic policy to disable
the L3 cache.  Policy decisions would need to be made
by a RAS handler.  This patch merely makes it easier to
see what indices are currently disabled.

Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com>

---

-Mark Langsdorf
Operating System Research Center
AMD


diff -r 3836aaac6e15 arch/x86/kernel/cpu/intel_cacheinfo.c
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c	Tue Jul 15 14:55:36 2008 -0500
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c	Thu Jul 17 16:18:40 2008 -0500
@@ -16,6 +16,7 @@
 
 #include <asm/processor.h>
 #include <asm/smp.h>
+#include <asm/k8.h>
 
 #define LVL_1_INST	1
 #define LVL_1_DATA	2
@@ -129,6 +130,7 @@ 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 */
 };
 
@@ -250,6 +252,13 @@ static void __cpuinit amd_cpuid4(int lea
 		(ebx->split.ways_of_associativity + 1) - 1;
 }
 
+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;
@@ -257,9 +266,12 @@ static int __cpuinit cpuid4_cache_lookup
 	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
+		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 ? */
@@ -636,6 +648,61 @@ static ssize_t show_type(struct _cpuid4_
 	}
 }
 
+#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_cache_disable(struct _cpuid4_info *this_leaf, char *buf)
+{
+	struct pci_dev *dev;
+	if (this_leaf->can_disable) {
+		int i;
+		ssize_t ret = 0;
+		int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map));
+		dev = k8_northbridges[node];
+
+		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;
+	}
+	return sprintf(buf, "Feature not enabled\n");
+}
+
+static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, size_t count)
+{
+	struct pci_dev *dev;
+	if (this_leaf->can_disable) {
+		/* write the MSR value */
+		unsigned int ret;
+		unsigned int index, val;
+		int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map));
+		dev = k8_northbridges[node];
+
+		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;
+		pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000);
+		wbinvd();
+		pci_write_config_dword(dev, 0x1BC + index * 4, val);
+		return 1;
+	}
+	return 0;
+}
+
 struct _cache_attr {
 	struct attribute attr;
 	ssize_t (*show)(struct _cpuid4_info *, char *);
@@ -655,6 +722,8 @@ define_one_ro(size);
 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,
@@ -666,11 +735,9 @@ 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)
 {
@@ -688,7 +755,15 @@ static ssize_t store(struct kobject * ko
 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 = {

-------------------------------------------------------


^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2008-08-15 20:02 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-18 21:03 [PATCH 01/01] x86: L3 cache index disable for 2.6.26 Mark Langsdorf
2008-07-21 11:37 ` Ingo Molnar
2008-07-21 12:48   ` Ingo Molnar
2008-07-22 18:06     ` Mark Langsdorf
2008-07-28 14:22       ` Ingo Molnar
2008-07-28 14:49         ` Ingo Molnar
2008-07-28 14:54           ` Langsdorf, Mark
2008-08-08 22:00 ` Pavel Machek
2008-08-12 16:04   ` [PATCH 01/01][retry 1] " Mark Langsdorf
2008-08-12 21:56     ` Pavel Machek
2008-08-12 22:01       ` Langsdorf, Mark
2008-08-12 22:07         ` Pavel Machek
2008-08-12 22:53         ` Greg KH
2008-08-12 22:12       ` Greg KH
2008-08-13 20:02         ` [PATCH 01/01][retry 2] " Mark Langsdorf
2008-08-13 20:38           ` Pavel Machek
2008-08-13 23:45           ` Greg KH
2008-08-14 13:43             ` [PATCH 01/01][retry 3] " Mark Langsdorf
2008-08-14 13:44               ` Pavel Machek
2008-08-14 14:02                 ` Langsdorf, Mark
2008-08-14 15:46                   ` Pavel Machek
2008-08-14 16:41                     ` Langsdorf, Mark
2008-08-14 14:04               ` Greg KH
2008-08-14 14:23           ` [PATCH 01/01][retry 4] " Mark Langsdorf
2008-08-14 16:48             ` [PATCH 01/01][retry 5] " Mark Langsdorf
2008-08-14 17:10               ` Greg KH
2008-08-14 18:32                 ` Mark Langsdorf
2008-08-15 16:42                   ` Ingo Molnar
2008-08-15 19:21                     ` Langsdorf, Mark
2008-08-15 19:57                       ` Ingo Molnar
2008-08-15 20:02                         ` Langsdorf, Mark

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox