public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Deepak Saxena <dsaxena@plexity.net>
To: linux-kernel@vger.kernel.org
Cc: Andrew Morton <akpm@osdl.org>, greg@kroah.com, rmk@arm.linux.org.uk
Subject: [PATCH 3/3] [ARM] Transition /proc/cpuinfo -> sysfs
Date: Wed, 11 Aug 2004 15:47:12 -0700	[thread overview]
Message-ID: <20040811224712.GC7095@plexity.net> (raw)
In-Reply-To: <20040811224117.GA6450@plexity.net>


Russell, 

Please comment. I've moved some bits to being detected at boot time
and stuffed into a structure b/c it makes the sysfs code cleaner.
We can just have a macro handling most cases now since the values
stored as int or char* in the cpuinfo structure.

~Deepak

diff -Nru a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
--- a/arch/arm/kernel/setup.c	Wed Aug 11 14:46:15 2004
+++ b/arch/arm/kernel/setup.c	Wed Aug 11 14:46:15 2004
@@ -27,6 +27,7 @@
 #include <asm/elf.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
+#include <asm/cpuinfo.h>
 #include <asm/procinfo.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -53,6 +54,13 @@
 __setup("fpe=", fpe_setup);
 #endif
 
+static struct arm_cpuinfo cpuinfo;
+static struct cpu cpu[1] = {
+	{
+		.arch_cpuinfo = &cpuinfo
+	}
+};
+
 extern unsigned int mem_fclk_21285;
 extern void paging_init(struct meminfo *, struct machine_desc *desc);
 extern void convert_to_tag_list(struct tag *tags);
@@ -219,6 +227,18 @@
 #define CACHE_M(y)	((y) & (1 << 2))
 #define CACHE_LINE(y)	((y) & 3)
 
+static const char *hwcap_str[] = {
+	"swp",
+	"half",
+	"thumb",
+	"26bit",
+	"fastmult",
+	"fpa",
+	"vfp",
+	"edsp",
+	NULL
+};
+
 static inline void dump_cache(const char *prefix, unsigned int cache)
 {
 	unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
@@ -264,10 +284,23 @@
 	return cpu_arch;
 }
 
+#define get_cache_info(_size, _assoc, _line_size, _sets, cache)		\
+do {									\
+	unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);		\
+									\
+	cpuinfo._size = mult << (8 + CACHE_SIZE(cache));		\
+	cpuinfo._assoc = (mult << CACHE_ASSOC(cache)) >> 1;		\
+	cpuinfo._line_size =  8 << CACHE_LINE(cache);			\
+	cpuinfo._sets =  						\
+		1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -	\
+			    CACHE_LINE(cache));				\
+} while(0);
+
 static void __init setup_processor(void)
 {
 	extern struct proc_info_list __proc_info_begin, __proc_info_end;
 	struct proc_info_list *list;
+	int cache_info;
 
 	/*
 	 * locate processor in the list of supported processor
@@ -314,6 +347,48 @@
 	elf_hwcap = list->elf_hwcap;
 
 	cpu_proc_init();
+
+	cpuinfo.model = cpu_name;
+	cpuinfo.revision = (int)processor_id & 15;
+	cpuinfo.elf_platform = elf_platform;
+	cpuinfo.vendor = processor_id >> 24;
+	cpuinfo.architecture = proc_arch[cpu_architecture()];
+
+	if ((processor_id & 0x0000f000) == 0x00000000) {
+		cpuinfo.part = processor_id >> 4;
+		cpuinfo.variant = 0xfffffff;
+	} else {
+		if ((processor_id & 0x0000f000) == 0x00007000) {
+			/* ARM7 */
+			cpuinfo.variant = (processor_id >> 16) & 127;
+		} else {
+			/* post-ARM7 */
+			cpuinfo.variant = (processor_id >> 20) & 15;
+		}
+		cpuinfo.part = (processor_id >> 4) & 0xfff;
+	}
+
+	cache_info = read_cpuid(CPUID_CACHETYPE);
+	if (cache_info != processor_id) {
+		cpuinfo.cache_type = cache_types[CACHE_TYPE(cache_info)];
+		cpuinfo.cache_clean = cache_clean[CACHE_TYPE(cache_info)],
+		cpuinfo.cache_lockdown = cache_lockdown[CACHE_TYPE(cache_info)];
+		cpuinfo.cache_format = 
+			CACHE_S(cache_info) ? "Harvard" : "Unified";
+
+		if (CACHE_S(cache_info)) {
+			get_cache_info(icache_size, icache_assoc, 
+					icache_line_size, icache_sets, 
+					CACHE_ISIZE(cache_info));
+			get_cache_info(dcache_size, dcache_assoc, 
+					dcache_line_size, dcache_sets, 
+					CACHE_DSIZE(cache_info));
+		} else {
+			get_cache_info(cache_size, cache_assoc, 
+					cache_line_size, cache_sets, 
+					CACHE_ISIZE(cache_info));
+		}
+	}
 }
 
 static struct machine_desc * __init setup_machine(unsigned int nr)
@@ -740,49 +815,189 @@
 #endif
 }
 
-static struct cpu cpu[1];
 
-static int __init topology_init(void)
+/*
+ * We currently can only have 1 CPU on ARM, so we theoretically
+ * don't need to touch the incoming dev and can just dereference
+ * the global cpuinfo; however, doing it right in the first place
+ * will make life easier down the road.
+ */
+#define ARM_CPU_ATTR(_field, _format)					\
+static ssize_t show_##_field(struct sys_device*dev, char *buf)		\
+{									\
+	struct cpu *cpu = 						\
+		(struct cpu*)container_of(dev, struct cpu, sysdev);	\
+	struct arm_cpuinfo *cpuinfo = 					\
+				(struct arm_cpuinfo*)cpu->arch_cpuinfo; \
+									\
+	return sprintf(buf, _format, cpuinfo->_field);			\
+}									\
+SYSDEV_ATTR(_field, 0644, show_##_field, NULL);
+
+
+ARM_CPU_ATTR(model, "%s\n");
+ARM_CPU_ATTR(part, "%07x\n");
+ARM_CPU_ATTR(variant, "%x\n");
+ARM_CPU_ATTR(revision, "%d\n");
+ARM_CPU_ATTR(elf_platform, "%s\n");
+ARM_CPU_ATTR(vendor, "%#02x\n");
+ARM_CPU_ATTR(architecture, "ARMv%s\n");
+
+ARM_CPU_ATTR(cache_type, "%s\n");
+ARM_CPU_ATTR(cache_clean, "%s\n");
+ARM_CPU_ATTR(cache_lockdown, "%s\n");
+ARM_CPU_ATTR(cache_format, "%s\n");
+
+/*
+ * Unified cache attributes
+ */
+ARM_CPU_ATTR(cache_size, "%d\n");
+ARM_CPU_ATTR(cache_assoc, "%d\n");
+ARM_CPU_ATTR(cache_line_size, "%d\n");
+ARM_CPU_ATTR(cache_sets, "%d\n");
+
+/*
+ * Harvard cache attributes
+ */
+ARM_CPU_ATTR(icache_size, "%d\n");
+ARM_CPU_ATTR(icache_assoc, "%d\n");
+ARM_CPU_ATTR(icache_line_size, "%d\n");
+ARM_CPU_ATTR(icache_sets, "%d\n");
+ARM_CPU_ATTR(dcache_size, "%d\n");
+ARM_CPU_ATTR(dcache_assoc, "%d\n");
+ARM_CPU_ATTR(dcache_line_size, "%d\n");
+ARM_CPU_ATTR(dcache_sets, "%d\n");
+
+static ssize_t show_bogomips(struct sys_device *dev, char *buf)
 {
-	return register_cpu(cpu, 0, NULL);
+	return sprintf(buf, "%lu.%02lu\n",
+		   loops_per_jiffy / (500000/HZ),
+		   (loops_per_jiffy / (5000/HZ)) % 100);
 }
+static SYSDEV_ATTR(bogomips, 0644, show_bogomips, NULL);
 
-subsys_initcall(topology_init);
+/*
+ * TODO: Should we have one file per feature with just a 1 or 0 to
+ * let userspace know specific feature exists?
+ */
+static ssize_t show_features(struct sys_device *dev, char *buf)
+{
+	ssize_t ret;
+	int i;
 
-static const char *hwcap_str[] = {
-	"swp",
-	"half",
-	"thumb",
-	"26bit",
-	"fastmult",
-	"fpa",
-	"vfp",
-	"edsp",
-	NULL
+	ret = 0;
+	for (i = 0; hwcap_str[i]; i++)
+		if (elf_hwcap & (1 << i))
+			ret += sprintf(buf + ret, "%s ", hwcap_str[i]);
+
+	ret += sprintf(buf + ret, "\n");
+
+	return ret;
+}
+static SYSDEV_ATTR(features, 0644, show_features, NULL);
+
+static ssize_t show_hardware(struct sys_device *dev, char *buf)
+{
+	return sprintf(buf, "%s\n", machine_name);
+}
+static SYSDEV_ATTR(hardware, 0644, show_hardware, NULL);
+
+static ssize_t show_hardware_rev(struct sys_device *dev, char *buf)
+{
+	return sprintf(buf, "%04x\n", system_rev);
+}
+static SYSDEV_ATTR(hardware_rev, 0644, show_hardware_rev, NULL);
+
+static ssize_t show_hardware_serial(struct sys_device *dev, char *buf)
+{
+	return sprintf(buf, "%08x%08x\n", system_serial_high, system_serial_low);
+}
+static SYSDEV_ATTR(hardware_serial, 0644, show_hardware_serial, NULL);
+
+static struct attribute *standard_attrs[] = {
+	&attr_bogomips.attr,
+	&attr_features.attr,
+	&attr_model.attr,
+	&attr_part.attr,
+	&attr_variant.attr,
+	&attr_elf_platform.attr,
+	&attr_vendor.attr,
+	&attr_revision.attr,
+	&attr_architecture.attr,
+	&attr_cache_type.attr,
+	&attr_cache_clean.attr,
+	&attr_cache_lockdown.attr,
+	&attr_cache_format.attr,
+	&attr_hardware.attr,
+	&attr_hardware_rev.attr,
+	&attr_hardware_serial.attr
+};
+
+static struct attribute_group standard_group = {
+	.attrs = standard_attrs
 };
 
-static void
-c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
+static struct attribute *unified_cache_attrs[] = {
+	&attr_cache_size.attr,
+	&attr_cache_assoc.attr,
+	&attr_cache_line_size.attr,
+	&attr_cache_sets.attr
+};
+
+static struct attribute_group unified_cache_group = {
+	.attrs = unified_cache_attrs
+};
+
+static struct attribute *harvard_cache_attrs[] = {
+	&attr_icache_size.attr,
+	&attr_icache_assoc.attr,
+	&attr_icache_line_size.attr,
+	&attr_icache_sets.attr,
+	&attr_dcache_size.attr,
+	&attr_dcache_assoc.attr,
+	&attr_dcache_line_size.attr,
+	&attr_dcache_sets.attr
+};
+
+static struct attribute_group harvard_cache_group = {
+	.attrs = harvard_cache_attrs
+};
+
+/*
+ * Register cpu with sysfs and fill in CPU attributes
+ */
+static int __init topology_init(void)
 {
-	unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
+	int ret;
+	struct sys_device *dev = &cpu->sysdev;
+	int cache_info;
+
+	ret = register_cpu(cpu, 0, NULL);
+	if (ret) return ret;
+
+	sysfs_create_group(&dev->kobj, &standard_group);
+
+	cache_info = read_cpuid(CPUID_CACHETYPE);
+	if (cache_info != processor_id) {
+		if (CACHE_S(cache_info)) {
+			sysfs_create_group(&dev->kobj, &harvard_cache_group);
+		} else {
+			sysfs_create_group(&dev->kobj, &unified_cache_group);
+		}
+	}	
 
-	seq_printf(m, "%s size\t\t: %d\n"
-		      "%s assoc\t\t: %d\n"
-		      "%s line length\t: %d\n"
-		      "%s sets\t\t: %d\n",
-		type, mult << (8 + CACHE_SIZE(cache)),
-		type, (mult << CACHE_ASSOC(cache)) >> 1,
-		type, 8 << CACHE_LINE(cache),
-		type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
-			    CACHE_LINE(cache)));
+	return 0;
 }
 
+subsys_initcall(topology_init);
+
 static int c_show(struct seq_file *m, void *v)
 {
 	int i;
+	int cache_info;
 
 	seq_printf(m, "Processor\t: %s rev %d (%s)\n",
-		   cpu_name, (int)processor_id & 15, elf_platform);
+			cpuinfo.model, cpuinfo.revision, cpuinfo.elf_platform);
 
 	seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
 		   loops_per_jiffy / (500000/HZ),
@@ -795,45 +1010,47 @@
 		if (elf_hwcap & (1 << i))
 			seq_printf(m, "%s ", hwcap_str[i]);
 
-	seq_printf(m, "\nCPU implementer\t: 0x%02x\n", processor_id >> 24);
-	seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
+	seq_printf(m, "\nCPU implementer\t: 0x%02x\n", cpuinfo.vendor);
+	seq_printf(m, "CPU architecture: %s\n", cpuinfo.architecture);
 
-	if ((processor_id & 0x0000f000) == 0x00000000) {
-		/* pre-ARM7 */
-		seq_printf(m, "CPU part\t\t: %07x\n", processor_id >> 4);
-	} else {
-		if ((processor_id & 0x0000f000) == 0x00007000) {
-			/* ARM7 */
-			seq_printf(m, "CPU variant\t: 0x%02x\n",
-				   (processor_id >> 16) & 127);
-		} else {
-			/* post-ARM7 */
-			seq_printf(m, "CPU variant\t: 0x%x\n",
-				   (processor_id >> 20) & 15);
-		}
-		seq_printf(m, "CPU part\t: 0x%03x\n",
-			   (processor_id >> 4) & 0xfff);
+	seq_printf(m, "CPU part\t\t: %07x\n", cpuinfo.part);
+	if ((processor_id & 0x0000f000) != 0x00000000) {
+		seq_printf(m, "CPU variant\t: 0x%x\n", cpuinfo.variant);
 	}
 	seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);
 
-	{
-		unsigned int cache_info = read_cpuid(CPUID_CACHETYPE);
-		if (cache_info != processor_id) {
-			seq_printf(m, "Cache type\t: %s\n"
-				      "Cache clean\t: %s\n"
-				      "Cache lockdown\t: %s\n"
-				      "Cache format\t: %s\n",
-				   cache_types[CACHE_TYPE(cache_info)],
-				   cache_clean[CACHE_TYPE(cache_info)],
-				   cache_lockdown[CACHE_TYPE(cache_info)],
-				   CACHE_S(cache_info) ? "Harvard" : "Unified");
-
-			if (CACHE_S(cache_info)) {
-				c_show_cache(m, "I", CACHE_ISIZE(cache_info));
-				c_show_cache(m, "D", CACHE_DSIZE(cache_info));
-			} else {
-				c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
-			}
+	cache_info = read_cpuid(CPUID_CACHETYPE);
+	if (cache_info != processor_id) {
+		seq_printf(m, "Cache type\t: %s\n"
+			      "Cache clean\t: %s\n"
+			      "Cache lockdown\t: %s\n"
+			      "Cache format\t: %s\n",
+			   cpuinfo.cache_type, cpuinfo.cache_clean,
+			   cpuinfo.cache_lockdown, cpuinfo.cache_format);
+
+		if (CACHE_S(cache_info)) {
+			seq_printf(m, "I size\t\t: %d\n", cpuinfo.icache_size);
+			seq_printf(m, "I assoc\t\t: %d\n", 
+					cpuinfo.icache_assoc);
+			seq_printf(m, "I line length\t: %d\n", 
+					cpuinfo.icache_line_size);
+			seq_printf(m, "I sets\t\t: %d\n", cpuinfo.icache_sets);
+
+			seq_printf(m, "D size\t\t: %d\n", cpuinfo.dcache_size);
+			seq_printf(m, "D assoc\t\t: %d\n", 
+					cpuinfo.dcache_assoc);
+			seq_printf(m, "D line length\t: %d\n", 
+					cpuinfo.dcache_line_size);
+			seq_printf(m, "D sets\t\t: %d\n", cpuinfo.dcache_sets);
+		} else {
+			seq_printf(m, "Cache size\t\t: %d\n", 
+					cpuinfo.icache_size);
+			seq_printf(m, "Cache assoc\t\t: %d\n", 
+					cpuinfo.icache_assoc);
+			seq_printf(m, "Cache line length\t: %d\n", 
+					cpuinfo.icache_line_size);
+			seq_printf(m, "Cache sets\t\t: %d", 
+					cpuinfo.icache_sets);
 		}
 	}
 
@@ -868,3 +1085,4 @@
 	.stop	= c_stop,
 	.show	= c_show
 };
+
diff -Nru a/include/asm-arm/cpuinfo.h b/include/asm-arm/cpuinfo.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/cpuinfo.h	Wed Aug 11 14:46:15 2004
@@ -0,0 +1,51 @@
+/*
+ * include/asm-arm/cpuinfo.h
+ *
+ * per-cpu information used for sysfs
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (c) MontaVista Software, Inc. 
+ * 
+ * This file is licensed under  the terms of the GNU General Public 
+ * License version 2. This program is licensed "as is" without any 
+ * warranty of any kind, whether express or implied.
+ */
+
+
+#ifndef __ASM_CPUINFO_H__
+#define __ASM_CPUINFO_H__
+
+
+struct arm_cpuinfo {
+	const char *model;
+	unsigned long part;
+	unsigned long variant;
+	const char *elf_platform;
+	unsigned char vendor;
+	unsigned short revision;
+	const char *architecture;
+
+	const char *cache_type;
+	const char *cache_clean;
+	const char *cache_lockdown;
+	const char *cache_format;
+
+	unsigned int cache_size;
+	unsigned int cache_assoc;
+	unsigned int cache_line_size;
+	unsigned int cache_sets;	
+
+	unsigned int icache_size;
+	unsigned int icache_assoc;
+	unsigned int icache_line_size;
+	unsigned int icache_sets;	
+
+	unsigned int dcache_size;
+	unsigned int dcache_assoc;
+	unsigned int dcache_line_size;
+	unsigned int dcache_sets;	
+};
+
+#endif	/* __ASM_CPUINFO_H__ */
+

-- 
Deepak Saxena - dsaxena at plexity dot net - http://www.plexity.net/

"Unlike me, many of you have accepted the situation of your imprisonment and
 will die here like rotten cabbages." - Number 6

  parent reply	other threads:[~2004-08-11 23:32 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-08-11 22:41 [PATCH 0/3] Transition /proc/cpuinfo -> sysfs Deepak Saxena
2004-08-11 22:42 ` [PATCH 1/3] [Generic] " Deepak Saxena
2004-08-11 22:44 ` [PATCH 2/3] [i386] " Deepak Saxena
2004-08-11 22:47 ` Deepak Saxena [this message]
2004-08-11 22:47 ` [PATCH 0/3] " Deepak Saxena
2004-08-11 23:13 ` Dave Jones
2004-08-11 23:42   ` Deepak Saxena
2004-08-11 23:59     ` Dave Jones
2004-08-12  2:45       ` Deepak Saxena
2004-08-12 11:07         ` Dave Jones
2004-08-15  6:11       ` Andrew Morton
2004-08-15  6:33         ` Greg KH
2004-08-12  5:03 ` Lamont R. Peterson
2004-08-12 10:56   ` Dave Jones

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040811224712.GC7095@plexity.net \
    --to=dsaxena@plexity.net \
    --cc=akpm@osdl.org \
    --cc=greg@kroah.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rmk@arm.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox