Module Name:    src
Committed By:   mrg
Date:           Tue Jan 16 08:23:18 UTC 2018

Modified Files:
        src/sys/arch/sparc/include: cpu.h
        src/sys/arch/sparc/sparc: cache.c cache.h cpu.c cpuvar.h pmap.c
        src/sys/arch/sparc64/include: cpu.h
        src/sys/arch/sparc64/sparc64: cpu.c
        src/usr.sbin/cpuctl: cpuctl.c cpuctl.h
        src/usr.sbin/cpuctl/arch: arm.c i386.c noarch.c
Added Files:
        src/sys/arch/sparc/sparc: cache_print.h
        src/usr.sbin/cpuctl/arch: sparc.c sparc64.c

Log Message:
implement cpuctl identify for sparc and sparc64.

sparc:
- move enum vactype and struct cacheinfo into cpu.h
- move the cache flags from cpuinfo.flags into CACHEINFO.c_flags
  (this allows the new cache_printf_backend() to see them.)
  remove unused CPUFLG_CACHEIOMMUTABLES and CPUFLG_CACHEDVMA.
- align xmpsg to 64 bytes
- move cache_print() into cache_print.h so it can be shared with
  cpuctl.  it only depends upon a working printf().
- if found, store the CPU node's "name" into cpu_longname.  this
  changes the default output to show the local CPU not the
  generic CPU family.  eg:
  cpu0 at mainbus0: mid 8: Ross,RT625 @ 90 MHz, on-chip FPU
  vs the generic "RT620/625" previously shown.
- for each CPU export these things:
  - name
  - fpuname
  - mid
  - cloc
  - freq
  - psr impl and version
  - mmu impl, version, and number of contexts
  - cacheinfo structure (which changed for the first time ever
    with this commit.)

sparc64:
- add a minimal "cacheinfo" structure to export the i/d/e-cache
  size and linesize.
- store %ver, cpu node "name" and cacheinfo in cpu_info.
- set cpu_info ver, name and cacheinfo in cpu_attach(), and
  export them via sysctl, as well as CPU ID and clock freq

cpuctl:
- add identifycpu_bind() that returns false on !x86 as their
  identify routines do not need to run on a particular CPU to
  obtain its information, and use it to avoid trying to set
  affinity when not needed.
- add sparc and sparc64 cpu identify support using the newly
  exported values.


To generate a diff of this commit:
cvs rdiff -u -r1.99 -r1.100 src/sys/arch/sparc/include/cpu.h
cvs rdiff -u -r1.99 -r1.100 src/sys/arch/sparc/sparc/cache.c
cvs rdiff -u -r1.35 -r1.36 src/sys/arch/sparc/sparc/cache.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/sparc/sparc/cache_print.h
cvs rdiff -u -r1.250 -r1.251 src/sys/arch/sparc/sparc/cpu.c
cvs rdiff -u -r1.94 -r1.95 src/sys/arch/sparc/sparc/cpuvar.h
cvs rdiff -u -r1.361 -r1.362 src/sys/arch/sparc/sparc/pmap.c
cvs rdiff -u -r1.123 -r1.124 src/sys/arch/sparc64/include/cpu.h
cvs rdiff -u -r1.132 -r1.133 src/sys/arch/sparc64/sparc64/cpu.c
cvs rdiff -u -r1.28 -r1.29 src/usr.sbin/cpuctl/cpuctl.c
cvs rdiff -u -r1.5 -r1.6 src/usr.sbin/cpuctl/cpuctl.h
cvs rdiff -u -r1.1 -r1.2 src/usr.sbin/cpuctl/arch/arm.c
cvs rdiff -u -r1.79 -r1.80 src/usr.sbin/cpuctl/arch/i386.c
cvs rdiff -u -r1.5 -r1.6 src/usr.sbin/cpuctl/arch/noarch.c
cvs rdiff -u -r0 -r1.1 src/usr.sbin/cpuctl/arch/sparc.c \
    src/usr.sbin/cpuctl/arch/sparc64.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/sparc/include/cpu.h
diff -u src/sys/arch/sparc/include/cpu.h:1.99 src/sys/arch/sparc/include/cpu.h:1.100
--- src/sys/arch/sparc/include/cpu.h:1.99	Sat Dec  2 00:48:04 2017
+++ src/sys/arch/sparc/include/cpu.h	Tue Jan 16 08:23:17 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.99 2017/12/02 00:48:04 macallan Exp $ */
+/*	$NetBSD: cpu.h,v 1.100 2018/01/16 08:23:17 mrg Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -56,6 +56,67 @@
  * Exported definitions unique to SPARC cpu support.
  */
 
+/*
+ * Sun-4 and Sun-4c virtual address cache.
+ *
+ * Sun-4 virtual caches come in two flavors, write-through (Sun-4c)
+ * and write-back (Sun-4).  The write-back caches are much faster
+ * but require a bit more care.
+ *
+ * This is exported via sysctl so be careful changing it.
+ */
+enum vactype { VAC_UNKNOWN, VAC_NONE, VAC_WRITETHROUGH, VAC_WRITEBACK };
+
+/*
+ * Cache control information.
+ *
+ * This is exported via sysctl so be careful changing it.
+ */
+
+struct cacheinfo {
+	int	c_totalsize;		/* total size, in bytes */
+					/* if split, MAX(icache,dcache) */
+	int	c_enabled;		/* true => cache is enabled */
+	int	c_hwflush;		/* true => have hardware flush */
+	int	c_linesize;		/* line size, in bytes */
+					/* if split, MIN(icache,dcache) */
+	int	c_l2linesize;		/* log2(linesize) */
+	int	c_nlines;		/* precomputed # of lines to flush */
+	int	c_physical;		/* true => cache has physical
+						   address tags */
+	int 	c_associativity;	/* # of "buckets" in cache line */
+	int 	c_split;		/* true => cache is split */
+
+	int 	ic_totalsize;		/* instruction cache */
+	int 	ic_enabled;
+	int 	ic_linesize;
+	int 	ic_l2linesize;
+	int 	ic_nlines;
+	int 	ic_associativity;
+
+	int 	dc_totalsize;		/* data cache */
+	int 	dc_enabled;
+	int 	dc_linesize;
+	int 	dc_l2linesize;
+	int 	dc_nlines;
+	int 	dc_associativity;
+
+	int	ec_totalsize;		/* external cache info */
+	int 	ec_enabled;
+	int	ec_linesize;
+	int	ec_l2linesize;
+	int 	ec_nlines;
+	int 	ec_associativity;
+
+	enum vactype	c_vactype;
+
+	int	c_flags;
+#define CACHE_PAGETABLES	0x1	/* caching pagetables OK on (sun4m) */
+#define CACHE_TRAPPAGEBUG	0x2	/* trap page can't be cached (sun4) */
+#define CACHE_MANDATORY		0x4	/* if cache is on, don't use
+					   uncached access */
+};
+
 /* Things needed by crash or the kernel */
 #if defined(_KERNEL) || defined(_KMEMUSER)
 
@@ -74,9 +135,6 @@
 #if defined(_KERNEL)
 #include <sparc/sparc/cpuvar.h>
 #include <sparc/sparc/intreg.h>
-#else
-#include <arch/sparc/sparc/vaddrs.h>
-#include <arch/sparc/sparc/cache.h>
 #endif
 
 struct trapframe;
@@ -123,9 +181,9 @@ struct cpu_info {
 	/*
 	 * Primary Inter-processor message area.  Keep this aligned
 	 * to a cache line boundary if possible, as the structure
-	 * itself is one (normal 32 byte) cache-line.
+	 * itself is one or less (32/64 byte) cache-line.
 	 */
-	struct xpmsg	msg __aligned(32);
+	struct xpmsg	msg __aligned(64);
 
 	/* Scheduler flags */
 	int	ci_want_ast;
@@ -149,7 +207,7 @@ struct cpu_info {
 	paddr_t		ctx_tbl_pa;	/* [4m] ctx table physical address */
 
 	/* Cache information */
-	struct cacheinfo	cacheinfo;	/* see cache.h */
+	struct cacheinfo	cacheinfo;	/* see above */
 
 	/* various flags to workaround anomalies in chips */
 	volatile int	flags;		/* see CPUFLG_xxx, below */

Index: src/sys/arch/sparc/sparc/cache.c
diff -u src/sys/arch/sparc/sparc/cache.c:1.99 src/sys/arch/sparc/sparc/cache.c:1.100
--- src/sys/arch/sparc/sparc/cache.c:1.99	Mon Jan 15 21:25:25 2018
+++ src/sys/arch/sparc/sparc/cache.c	Tue Jan 16 08:23:17 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: cache.c,v 1.99 2018/01/15 21:25:25 mrg Exp $ */
+/*	$NetBSD: cache.c,v 1.100 2018/01/16 08:23:17 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -59,7 +59,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cache.c,v 1.99 2018/01/15 21:25:25 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cache.c,v 1.100 2018/01/16 08:23:17 mrg Exp $");
 
 #include "opt_multiprocessor.h"
 #include "opt_sparc_arch.h"
@@ -166,7 +166,7 @@ ms1_cache_enable(void)
 	 * MS1 cache is write-through and not write-allocate, so we can
 	 * use cacheable access while not displacing cache lines.
 	 */
-	cpuinfo.flags |= CPUFLG_CACHE_MANDATORY;
+	CACHEINFO.c_flags |= CACHE_MANDATORY;
 }
 
 void
@@ -197,7 +197,7 @@ viking_cache_enable(void)
 		/* Set external cache enable bit in MXCC control register */
 		stda(MXCC_CTRLREG, ASI_CONTROL,
 		     ldda(MXCC_CTRLREG, ASI_CONTROL) | MXCC_CTRLREG_CE);
-		cpuinfo.flags |= CPUFLG_CACHEPAGETABLES; /* Ok to cache PTEs */
+		CACHEINFO.c_flags |= CACHE_PAGETABLES; /* Ok to cache PTEs */
 		CACHEINFO.ec_enabled = 1;
 	}
 }

Index: src/sys/arch/sparc/sparc/cache.h
diff -u src/sys/arch/sparc/sparc/cache.h:1.35 src/sys/arch/sparc/sparc/cache.h:1.36
--- src/sys/arch/sparc/sparc/cache.h:1.35	Sun Mar  4 06:00:45 2007
+++ src/sys/arch/sparc/sparc/cache.h	Tue Jan 16 08:23:17 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: cache.h,v 1.35 2007/03/04 06:00:45 christos Exp $ */
+/*	$NetBSD: cache.h,v 1.36 2018/01/16 08:23:17 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -51,16 +51,6 @@
 #endif
 
 /*
- * Sun-4 and Sun-4c virtual address cache.
- *
- * Sun-4 virtual caches come in two flavors, write-through (Sun-4c)
- * and write-back (Sun-4).  The write-back caches are much faster
- * but require a bit more care.
- *
- */
-enum vactype { VAC_UNKNOWN, VAC_NONE, VAC_WRITETHROUGH, VAC_WRITEBACK };
-
-/*
  * Cache tags can be written in control space, and must be set to 0
  * (or invalid anyway) before turning on the cache.  The tags are
  * addressed as an array of 32-bit structures of the form:
@@ -234,47 +224,6 @@ void	smp_vcache_flush_page(int va,int);	
 
 #define pcache_flush_page(pa,flag)	cpuinfo.pcache_flush_page(pa,flag)
 
-/*
- * Cache control information.
- */
-struct cacheinfo {
-	int	c_totalsize;		/* total size, in bytes */
-					/* if split, MAX(icache,dcache) */
-	int	c_enabled;		/* true => cache is enabled */
-	int	c_hwflush;		/* true => have hardware flush */
-	int	c_linesize;		/* line size, in bytes */
-					/* if split, MIN(icache,dcache) */
-	int	c_l2linesize;		/* log2(linesize) */
-	int	c_nlines;		/* precomputed # of lines to flush */
-	int	c_physical;		/* true => cache has physical
-						   address tags */
-	int 	c_associativity;	/* # of "buckets" in cache line */
-	int 	c_split;		/* true => cache is split */
-
-	int 	ic_totalsize;		/* instruction cache */
-	int 	ic_enabled;
-	int 	ic_linesize;
-	int 	ic_l2linesize;
-	int 	ic_nlines;
-	int 	ic_associativity;
-
-	int 	dc_totalsize;		/* data cache */
-	int 	dc_enabled;
-	int 	dc_linesize;
-	int 	dc_l2linesize;
-	int 	dc_nlines;
-	int 	dc_associativity;
-
-	int	ec_totalsize;		/* external cache info */
-	int 	ec_enabled;
-	int	ec_linesize;
-	int	ec_l2linesize;
-	int 	ec_nlines;
-	int 	ec_associativity;
-
-	enum vactype	c_vactype;
-};
-
 #define CACHEINFO cpuinfo.cacheinfo
 
 #endif /* SPARC_CACHE_H */

Index: src/sys/arch/sparc/sparc/cpu.c
diff -u src/sys/arch/sparc/sparc/cpu.c:1.250 src/sys/arch/sparc/sparc/cpu.c:1.251
--- src/sys/arch/sparc/sparc/cpu.c:1.250	Sat Dec  2 00:48:05 2017
+++ src/sys/arch/sparc/sparc/cpu.c	Tue Jan 16 08:23:17 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.c,v 1.250 2017/12/02 00:48:05 macallan Exp $ */
+/*	$NetBSD: cpu.c,v 1.251 2018/01/16 08:23:17 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -52,7 +52,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.250 2017/12/02 00:48:05 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.251 2018/01/16 08:23:17 mrg Exp $");
 
 #include "opt_multiprocessor.h"
 #include "opt_lockdebug.h"
@@ -68,6 +68,8 @@ __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.25
 #include <sys/xcall.h>
 #include <sys/ipi.h>
 #include <sys/cpu.h>
+#include <sys/sysctl.h>
+#include <sys/kmem.h>
 
 #include <uvm/uvm.h>
 
@@ -89,6 +91,7 @@ __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.25
 #include <sparc/sparc/asm.h>
 #include <sparc/sparc/cpuvar.h>
 #include <sparc/sparc/memreg.h>
+#include <sparc/sparc/cache_print.h>
 #if defined(SUN4D)
 #include <sparc/sparc/cpuunitvar.h>
 #endif
@@ -131,11 +134,12 @@ CFATTACH_DECL_NEW(cpu_cpuunit, sizeof(st
     cpu_cpuunit_match, cpu_cpuunit_attach, NULL, NULL);
 #endif /* SUN4D */
 
-static void cpu_init_evcnt(struct cpu_info *cpi);
+static void cpu_setup_sysctl(struct cpu_softc *);
+static void cpu_init_evcnt(struct cpu_info *);
 static void cpu_attach(struct cpu_softc *, int, int);
 
 static const char *fsrtoname(int, int, int);
-void cache_print(struct cpu_softc *);
+static void cache_print(struct cpu_softc *);
 void cpu_setup(void);
 void fpu_init(struct cpu_info *);
 
@@ -383,6 +387,58 @@ cpu_init_evcnt(struct cpu_info *cpi)
 	}
 }
 
+/* setup the hw.cpuN.* nodes for this cpu */
+static void
+cpu_setup_sysctl(struct cpu_softc *sc)
+{
+	struct cpu_info	*ci = sc->sc_cpuinfo;
+	const struct sysctlnode *cpunode = NULL;
+
+	sysctl_createv(NULL, 0, NULL, &cpunode,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, device_xname(sc->sc_dev), NULL,
+		       NULL, 0, NULL, 0,
+		       CTL_HW,
+		       CTL_CREATE, CTL_EOL);
+
+	if (cpunode == NULL)
+		return;
+
+#define SETUPS(name, member)					\
+	sysctl_createv(NULL, 0, &cpunode, NULL,			\
+		       CTLFLAG_PERMANENT,			\
+		       CTLTYPE_STRING, name, NULL,		\
+		       NULL, 0, member, 0,			\
+		       CTL_CREATE, CTL_EOL);
+
+	SETUPS("name", __UNCONST(ci->cpu_longname))
+	SETUPS("fpuname", __UNCONST(ci->fpu_name))
+#undef SETUPS
+
+#define SETUPI(name, member)					\
+	sysctl_createv(NULL, 0, &cpunode, NULL,			\
+		       CTLFLAG_PERMANENT,			\
+		       CTLTYPE_INT, name, NULL,			\
+		       NULL, 0, member, 0,			\
+		       CTL_CREATE, CTL_EOL);
+
+	SETUPI("mid", &ci->mid)
+	SETUPI("clock_frequency", &ci->hz)
+	SETUPI("psr_implementation", &ci->cpu_impl)
+	SETUPI("psr_version", &ci->cpu_vers)
+	SETUPI("mmu_implementation", &ci->mmu_impl)
+	SETUPI("mmu_version", &ci->mmu_vers)
+	SETUPI("mmu_nctx", &ci->mmu_ncontext)
+#undef SETUPI
+
+        sysctl_createv(NULL, 0, &cpunode, NULL, 
+                       CTLFLAG_PERMANENT,
+                       CTLTYPE_STRUCT, "cacheinfo", NULL,
+                       NULL, 0, &ci->cacheinfo, sizeof(ci->cacheinfo),
+		       CTL_CREATE, CTL_EOL);
+
+}
+
 /*
  * Attach the CPU.
  * Discover interesting goop about the virtual address cache
@@ -432,6 +488,7 @@ cpu_attach(struct cpu_softc *sc, int nod
 	if (cpu_attach_count > 1) {
 		cpu_attach_non_boot(sc, cpi, node);
 		cpu_init_evcnt(cpi);
+		cpu_setup_sysctl(sc);
 		return;
 	}
 #endif /* MULTIPROCESSOR */
@@ -445,6 +502,7 @@ cpu_attach(struct cpu_softc *sc, int nod
 	cpu_setmodel("%s (%s)", machine_model, buf);
 	printf(": %s\n", buf);
 	cache_print(sc);
+	cpu_setup_sysctl(sc);
 
 	cpi->master = 1;
 	cpi->eintstack = eintstack;
@@ -989,59 +1047,14 @@ fpu_init(struct cpu_info *sc)
 	}
 }
 
-void
+static void
 cache_print(struct cpu_softc *sc)
 {
 	struct cacheinfo *ci = &sc->sc_cpuinfo->cacheinfo;
 
-	if (sc->sc_cpuinfo->flags & CPUFLG_SUN4CACHEBUG)
-		printf("%s: cache chip bug; trap page uncached\n",
-		    device_xname(sc->sc_dev));
-
-	printf("%s: ", device_xname(sc->sc_dev));
-
-	if (ci->c_totalsize == 0) {
-		printf("no cache\n");
-		return;
-	}
-
-	if (ci->c_split) {
-		const char *sep = "";
-
-		printf("%s", (ci->c_physical ? "physical " : ""));
-		if (ci->ic_totalsize > 0) {
-			printf("%s%dK instruction (%d b/l)", sep,
-			    ci->ic_totalsize/1024, ci->ic_linesize);
-			sep = ", ";
-		}
-		if (ci->dc_totalsize > 0) {
-			printf("%s%dK data (%d b/l)", sep,
-			    ci->dc_totalsize/1024, ci->dc_linesize);
-		}
-	} else if (ci->c_physical) {
-		/* combined, physical */
-		printf("physical %dK combined cache (%d bytes/line)",
-		    ci->c_totalsize/1024, ci->c_linesize);
-	} else {
-		/* combined, virtual */
-		printf("%dK byte write-%s, %d bytes/line, %cw flush",
-		    ci->c_totalsize/1024,
-		    (ci->c_vactype == VAC_WRITETHROUGH) ? "through" : "back",
-		    ci->c_linesize,
-		    ci->c_hwflush ? 'h' : 's');
-	}
-
-	if (ci->ec_totalsize > 0) {
-		printf(", %dK external (%d b/l)",
-		    ci->ec_totalsize/1024, ci->ec_linesize);
-	}
-	printf(": ");
-	if (ci->c_enabled)
-		printf("cache enabled");
-	printf("\n");
+	cache_printf_backend(ci, device_xname(sc->sc_dev));
 }
 
-
 /*------------*/
 
 
@@ -1316,7 +1329,7 @@ void
 sun4_hotfix(struct cpu_info *sc)
 {
 
-	if ((sc->flags & CPUFLG_SUN4CACHEBUG) != 0)
+	if ((sc->cacheinfo.c_flags & CACHE_TRAPPAGEBUG) != 0)
 		kvm_uncache((char *)trapbase, 1);
 
 	/* Use the hardware-assisted page flush routine, if present */
@@ -1783,7 +1796,7 @@ static	int mxcc = -1;
 	/* Test if we're directly on the MBus */
 	if ((pcr & VIKING_PCR_MB) == 0) {
 		sc->mxcc = 1;
-		sc->flags |= CPUFLG_CACHE_MANDATORY;
+		sc->cacheinfo.c_flags |= CACHE_MANDATORY;
 		sc->zero_page = pmap_zero_page_viking_mxcc;
 		sc->copy_page = pmap_copy_page_viking_mxcc;
 #if !defined(MSIIEP)
@@ -1797,7 +1810,7 @@ static	int mxcc = -1;
 		if ((pcr & VIKING_PCR_TC) == 0)
 			printf("[viking: PCR_TC is off]");
 		else
-			sc->flags |= CPUFLG_CACHEPAGETABLES;
+			sc->cacheinfo.c_flags |= CACHE_PAGETABLES;
 	} else {
 #ifdef MULTIPROCESSOR
 		if (sparc_ncpus > 1 && sc->cacheinfo.ec_totalsize == 0)
@@ -1829,7 +1842,7 @@ viking_mmu_enable(void)
 			printf("[viking: turn on PCR_TC]");
 		}
 		pcr |= VIKING_PCR_TC;
-		cpuinfo.flags |= CPUFLG_CACHEPAGETABLES;
+		CACHEINFO.c_flags |= CACHE_PAGETABLES;
 	} else
 		pcr &= ~VIKING_PCR_TC;
 	sta(SRMMU_PCR, ASI_SRMMU, pcr);
@@ -2074,6 +2087,17 @@ getcpuinfo(struct cpu_info *sc, int node
 		mmu_vers = prom_getpropint(node, "version", -1);
 	}
 
+	if (node != 0) {
+		char *cpu_name;
+		char namebuf[64];
+
+		cpu_name = prom_getpropstringA(node, "name", namebuf,
+					       sizeof namebuf);
+		if (cpu_name && cpu_name[0])
+			sc->cpu_longname = kmem_strdupsize(cpu_name, NULL,
+							   KM_NOSLEEP);
+	}
+
 	for (mp = cpu_conf; ; mp++) {
 		if (mp->arch != cputyp && mp->arch != ANY)
 			continue;

Index: src/sys/arch/sparc/sparc/cpuvar.h
diff -u src/sys/arch/sparc/sparc/cpuvar.h:1.94 src/sys/arch/sparc/sparc/cpuvar.h:1.95
--- src/sys/arch/sparc/sparc/cpuvar.h:1.94	Sat Dec 10 10:41:07 2016
+++ src/sys/arch/sparc/sparc/cpuvar.h	Tue Jan 16 08:23:17 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpuvar.h,v 1.94 2016/12/10 10:41:07 mrg Exp $ */
+/*	$NetBSD: cpuvar.h,v 1.95 2018/01/16 08:23:17 mrg Exp $ */
 
 /*
  *  Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -154,12 +154,6 @@ struct module_info {
 /*
  * CPU flags
  */
-#define CPUFLG_CACHEPAGETABLES	0x1	/* caching pagetables OK on Sun4m */
-#define CPUFLG_CACHEIOMMUTABLES	0x2	/* caching IOMMU translations OK */
-#define CPUFLG_CACHEDVMA	0x4	/* DVMA goes through cache */
-#define CPUFLG_SUN4CACHEBUG	0x8	/* trap page can't be cached */
-#define CPUFLG_CACHE_MANDATORY	0x10	/* if cache is on, don't use
-					   uncached access */
 #define CPUFLG_HATCHED		0x1000	/* CPU is alive */
 #define CPUFLG_PAUSED		0x2000	/* CPU is paused */
 #define CPUFLG_GOTMSG		0x4000	/* CPU got an lev13 IPI */

Index: src/sys/arch/sparc/sparc/pmap.c
diff -u src/sys/arch/sparc/sparc/pmap.c:1.361 src/sys/arch/sparc/sparc/pmap.c:1.362
--- src/sys/arch/sparc/sparc/pmap.c:1.361	Thu Dec 22 14:47:59 2016
+++ src/sys/arch/sparc/sparc/pmap.c	Tue Jan 16 08:23:17 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.361 2016/12/22 14:47:59 cherry Exp $ */
+/*	$NetBSD: pmap.c,v 1.362 2018/01/16 08:23:17 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -56,7 +56,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.361 2016/12/22 14:47:59 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.362 2018/01/16 08:23:17 mrg Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -902,7 +902,7 @@ setpte4m(vaddr_t va, int pte)
 void *
 pgt_page_alloc(struct pool *pp, int flags)
 {
-	int cacheit = (cpuinfo.flags & CPUFLG_CACHEPAGETABLES) != 0;
+	int cacheit = (CACHEINFO.c_flags & CACHE_PAGETABLES) != 0;
 	struct vm_page *pg;
 	vaddr_t va;
 	paddr_t pa;
@@ -3844,7 +3844,7 @@ pmap_bootstrap4m(void *top)
 		pte |= PPROT_N_RX | SRMMU_TEPTE;
 
 		/* Deal with the cacheable bit for pagetable memory */
-		if ((cpuinfo.flags & CPUFLG_CACHEPAGETABLES) != 0 ||
+		if ((CACHEINFO.c_flags & CACHE_PAGETABLES) != 0 ||
 		    q < pagetables_start || q >= pagetables_end)
 			pte |= SRMMU_PG_C;
 
@@ -3856,7 +3856,7 @@ pmap_bootstrap4m(void *top)
 		pmap_kernel()->pm_stats.resident_count++;
 	}
 
-	if ((cpuinfo.flags & CPUFLG_CACHEPAGETABLES) == 0) {
+	if ((CACHEINFO.c_flags & CACHE_PAGETABLES) == 0) {
 		/*
 		 * The page tables have been setup. Since we're still
 		 * running on the PROM's memory map, the memory we
@@ -4026,7 +4026,7 @@ pmap_alloc_cpu(struct cpu_info *sc)
 	int pagesz = NBPG;
 	int i;
 
-	cachebit = (cpuinfo.flags & CPUFLG_CACHEPAGETABLES) != 0;
+	cachebit = (CACHEINFO.c_flags & CACHE_PAGETABLES) != 0;
 
 	/*
 	 * Allocate properly aligned and contiguous physically memory
@@ -7143,7 +7143,7 @@ pmap_zero_page4m(paddr_t pa)
 			pcache_flush_page(pa, 1);
 	}
 	pte = SRMMU_TEPTE | PPROT_N_RWX | (pa >> SRMMU_PPNPASHIFT);
-	if (cpuinfo.flags & CPUFLG_CACHE_MANDATORY)
+	if (CACHEINFO.c_flags & CACHE_MANDATORY)
 		pte |= SRMMU_PG_C;
 
 	va = cpuinfo.vpage[0];
@@ -7258,7 +7258,7 @@ pmap_copy_page4m(paddr_t src, paddr_t ds
 	}
 
 	dpte = SRMMU_TEPTE | PPROT_N_RWX | (dst >> SRMMU_PPNPASHIFT);
-	if (cpuinfo.flags & CPUFLG_CACHE_MANDATORY)
+	if (CACHEINFO.c_flags & CACHE_MANDATORY)
 		dpte |= SRMMU_PG_C;
 
 	sva = cpuinfo.vpage[0];

Index: src/sys/arch/sparc64/include/cpu.h
diff -u src/sys/arch/sparc64/include/cpu.h:1.123 src/sys/arch/sparc64/include/cpu.h:1.124
--- src/sys/arch/sparc64/include/cpu.h:1.123	Fri Feb 10 23:26:23 2017
+++ src/sys/arch/sparc64/include/cpu.h	Tue Jan 16 08:23:17 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.123 2017/02/10 23:26:23 palle Exp $ */
+/*	$NetBSD: cpu.h,v 1.124 2018/01/16 08:23:17 mrg Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -53,6 +53,18 @@
 #define CPU_VIS			5	/* 0 - no VIS, 1 - VIS 1.0, etc. */
 #define	CPU_MAXID		6	/* number of valid machdep ids */
 
+/*
+ * This is exported via sysctl for cpuctl(8).
+ */
+struct cacheinfo {
+	int 	c_itotalsize;
+	int 	c_ilinesize;
+	int 	c_dtotalsize;
+	int 	c_dlinesize;
+	int 	c_etotalsize;
+	int 	c_elinesize;
+};
+
 #if defined(_KERNEL) || defined(_KMEMUSER)
 /*
  * Exported definitions unique to SPARC cpu support.
@@ -128,8 +140,14 @@ struct cpu_info {
 
 	int			ci_cpuid;
 
+	uint64_t		ci_ver;
+
 	/* CPU PROM information. */
 	u_int			ci_node;
+	const char		*ci_name;
+
+	/* This is for sysctl. */
+	struct cacheinfo	ci_cacheinfo;
 
 	/* %tick and cpu frequency information */
 	u_long			ci_tick_increment;

Index: src/sys/arch/sparc64/sparc64/cpu.c
diff -u src/sys/arch/sparc64/sparc64/cpu.c:1.132 src/sys/arch/sparc64/sparc64/cpu.c:1.133
--- src/sys/arch/sparc64/sparc64/cpu.c:1.132	Mon Sep 11 19:25:07 2017
+++ src/sys/arch/sparc64/sparc64/cpu.c	Tue Jan 16 08:23:18 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.c,v 1.132 2017/09/11 19:25:07 palle Exp $ */
+/*	$NetBSD: cpu.c,v 1.133 2018/01/16 08:23:18 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -52,7 +52,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.132 2017/09/11 19:25:07 palle Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.133 2018/01/16 08:23:18 mrg Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -62,6 +62,8 @@ __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.13
 #include <sys/kernel.h>
 #include <sys/reboot.h>
 #include <sys/cpu.h>
+#include <sys/sysctl.h>
+#include <sys/kmem.h>
 
 #include <uvm/uvm.h>
 
@@ -412,6 +414,61 @@ cpu_reset_fpustate(void)
 	savefpstate(fpstate);
 }
 
+/* setup the hw.cpuN.* nodes for this cpu */
+static void
+cpu_setup_sysctl(struct cpu_info *ci, device_t dev)
+{
+	const struct sysctlnode *cpunode = NULL;
+
+	sysctl_createv(NULL, 0, NULL, &cpunode,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, device_xname(dev), NULL,
+		       NULL, 0, NULL, 0,
+		       CTL_HW,
+		       CTL_CREATE, CTL_EOL);
+
+	if (cpunode == NULL)
+		return;
+
+#define SETUPS(name, member)					\
+	sysctl_createv(NULL, 0, &cpunode, NULL,			\
+		       CTLFLAG_PERMANENT,			\
+		       CTLTYPE_STRING, name, NULL,		\
+		       NULL, 0, member, 0,			\
+		       CTL_CREATE, CTL_EOL);
+
+	SETUPS("name", __UNCONST(ci->ci_name))
+#undef SETUPS
+
+#define SETUPI(name, member)					\
+	sysctl_createv(NULL, 0, &cpunode, NULL,			\
+		       CTLFLAG_PERMANENT,			\
+		       CTLTYPE_INT, name, NULL,			\
+		       NULL, 0, member, 0,			\
+		       CTL_CREATE, CTL_EOL);
+
+	SETUPI("id", &ci->ci_cpuid);
+#undef SETUPI
+
+#define SETUPQ(name, member)					\
+	sysctl_createv(NULL, 0, &cpunode, NULL,			\
+		       CTLFLAG_PERMANENT,			\
+		       CTLTYPE_QUAD, name, NULL,			\
+		       NULL, 0, member, 0,			\
+		       CTL_CREATE, CTL_EOL);
+
+	SETUPQ("clock_frequency", &ci->ci_cpu_clockrate[0])
+	SETUPQ("ver", &ci->ci_ver)
+#undef SETUPI
+
+        sysctl_createv(NULL, 0, &cpunode, NULL, 
+                       CTLFLAG_PERMANENT,
+                       CTLTYPE_STRUCT, "cacheinfo", NULL,
+                       NULL, 0, &ci->ci_cacheinfo, sizeof(ci->ci_cacheinfo),
+		       CTL_CREATE, CTL_EOL);
+
+}
+
 /*
  * Attach the CPU.
  * Discover interesting goop about the virtual address cache
@@ -485,12 +542,14 @@ cpu_attach(device_t parent, device_t dev
 	ci->ci_system_clockrate[0] = sclk;
 	ci->ci_system_clockrate[1] = sclk / 1000000;
 
-	snprintf(buf, sizeof buf, "%s @ %s MHz",
-		prom_getpropstring(node, "name"), clockfreq(clk));
+	ci->ci_name = kmem_strdupsize(prom_getpropstring(node, "name"), NULL,
+				      KM_NOSLEEP);
+	snprintf(buf, sizeof buf, "%s @ %s MHz", ci->ci_name, clockfreq(clk));
 	cpu_setmodel("%s (%s)", machine_model, buf);
 
 	aprint_normal(": %s, CPU id %d\n", buf, ci->ci_cpuid);
 	aprint_naive("\n");
+	ci->ci_ver = getver();
 	if (CPU_ISSUN4U || CPU_ISSUN4US) {
 		aprint_normal_dev(dev, "manuf %x, impl %x, mask %x\n",
 		    (u_int)GETVER_CPU_MANUF(),
@@ -532,6 +591,8 @@ cpu_attach(device_t parent, device_t dev
 		       (long)linesize);
 		sep = ", ";
 	}
+	ci->ci_cacheinfo.c_itotalsize = totalsize;
+	ci->ci_cacheinfo.c_ilinesize = linesize;
 
 	dcachesize = cpu_dcache_size(node);
 	if (dcachesize > dcache_size)
@@ -559,6 +620,8 @@ cpu_attach(device_t parent, device_t dev
 		       (long)linesize);
 		sep = ", ";
 	}
+	ci->ci_cacheinfo.c_dtotalsize = totalsize;
+	ci->ci_cacheinfo.c_dlinesize = linesize;
 
 	linesize = l = cpu_ecache_line_size(node);
 	for (i = 0; (1 << i) < l && l; i++)
@@ -580,11 +643,15 @@ cpu_attach(device_t parent, device_t dev
 		       (long)linesize);
 	}
 	aprint_normal("\n");
+	ci->ci_cacheinfo.c_etotalsize = totalsize;
+	ci->ci_cacheinfo.c_elinesize = linesize;
 
 	if (ecache_min_line_size == 0 ||
 	    linesize < ecache_min_line_size)
 		ecache_min_line_size = linesize;
 
+	cpu_setup_sysctl(ci, dev);
+
 	/*
 	 * Now that we know the size of the largest cache on this CPU,
 	 * re-color our pages.

Index: src/usr.sbin/cpuctl/cpuctl.c
diff -u src/usr.sbin/cpuctl/cpuctl.c:1.28 src/usr.sbin/cpuctl/cpuctl.c:1.29
--- src/usr.sbin/cpuctl/cpuctl.c:1.28	Mon Nov 16 03:34:50 2015
+++ src/usr.sbin/cpuctl/cpuctl.c	Tue Jan 16 08:23:18 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpuctl.c,v 1.28 2015/11/16 03:34:50 mrg Exp $	*/
+/*	$NetBSD: cpuctl.c,v 1.29 2018/01/16 08:23:18 mrg Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008, 2009, 2012, 2015 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #ifndef lint
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: cpuctl.c,v 1.28 2015/11/16 03:34:50 mrg Exp $");
+__RCSID("$NetBSD: cpuctl.c,v 1.29 2018/01/16 08:23:18 mrg Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -254,7 +254,6 @@ cpu_ucode(char **argv)
 	}
 }
 
-
 static void
 cpu_identify(char **argv)
 {
@@ -267,7 +266,7 @@ cpu_identify(char **argv)
 		id = getcpuid(*argv);
 		snprintf(name, sizeof(name), "cpu%u", id);
 
-		if (np != 1) {
+		if (identifycpu_bind() && np != 1) {
 			cpuset = cpuset_create();
 			if (cpuset == NULL)
 				err(EXIT_FAILURE, "cpuset_create");

Index: src/usr.sbin/cpuctl/cpuctl.h
diff -u src/usr.sbin/cpuctl/cpuctl.h:1.5 src/usr.sbin/cpuctl/cpuctl.h:1.6
--- src/usr.sbin/cpuctl/cpuctl.h:1.5	Mon Dec 23 12:35:33 2013
+++ src/usr.sbin/cpuctl/cpuctl.h	Tue Jan 16 08:23:18 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpuctl.h,v 1.5 2013/12/23 12:35:33 msaitoh Exp $	*/
+/*	$NetBSD: cpuctl.h,v 1.6 2018/01/16 08:23:18 mrg Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -34,6 +34,7 @@ int	aprint_verbose_dev(const char *, con
 int	aprint_error_dev(const char *, const char *, ...) __printflike(2, 3);
 
 void	identifycpu(int, const char *);
+bool	identifycpu_bind(void);
 int	ucodeupdate_check(int, struct cpu_ucode *);
 
 extern int verbose;

Index: src/usr.sbin/cpuctl/arch/arm.c
diff -u src/usr.sbin/cpuctl/arch/arm.c:1.1 src/usr.sbin/cpuctl/arch/arm.c:1.2
--- src/usr.sbin/cpuctl/arch/arm.c:1.1	Thu Jan 31 23:40:48 2013
+++ src/usr.sbin/cpuctl/arch/arm.c	Tue Jan 16 08:23:18 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: arm.c,v 1.1 2013/01/31 23:40:48 matt Exp $	*/
+/*	$NetBSD: arm.c,v 1.2 2018/01/16 08:23:18 mrg Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
 #include <sys/cdefs.h>
 
 #ifndef lint
-__RCSID("$NetBSD: arm.c,v 1.1 2013/01/31 23:40:48 matt Exp $");
+__RCSID("$NetBSD: arm.c,v 1.2 2018/01/16 08:23:18 mrg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -210,6 +210,13 @@ print_features(const char *cpuname, cons
 	}
 }
 
+bool
+identifycpu_bind(void)
+{
+
+	return false;
+}
+
 void
 identifycpu(int fd, const char *cpuname)
 {

Index: src/usr.sbin/cpuctl/arch/i386.c
diff -u src/usr.sbin/cpuctl/arch/i386.c:1.79 src/usr.sbin/cpuctl/arch/i386.c:1.80
--- src/usr.sbin/cpuctl/arch/i386.c:1.79	Wed Jan 10 07:08:35 2018
+++ src/usr.sbin/cpuctl/arch/i386.c	Tue Jan 16 08:23:18 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: i386.c,v 1.79 2018/01/10 07:08:35 msaitoh Exp $	*/
+/*	$NetBSD: i386.c,v 1.80 2018/01/16 08:23:18 mrg Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -57,7 +57,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: i386.c,v 1.79 2018/01/10 07:08:35 msaitoh Exp $");
+__RCSID("$NetBSD: i386.c,v 1.80 2018/01/16 08:23:18 mrg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -2235,6 +2235,13 @@ powernow_probe(struct cpu_info *ci)
 	    buf);
 }
 
+bool
+identifycpu_bind(void)
+{
+
+	return true;
+}
+
 int
 ucodeupdate_check(int fd, struct cpu_ucode *uc)
 {

Index: src/usr.sbin/cpuctl/arch/noarch.c
diff -u src/usr.sbin/cpuctl/arch/noarch.c:1.5 src/usr.sbin/cpuctl/arch/noarch.c:1.6
--- src/usr.sbin/cpuctl/arch/noarch.c:1.5	Wed Oct 17 20:22:15 2012
+++ src/usr.sbin/cpuctl/arch/noarch.c	Tue Jan 16 08:23:18 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: noarch.c,v 1.5 2012/10/17 20:22:15 drochner Exp $	*/
+/*	$NetBSD: noarch.c,v 1.6 2018/01/16 08:23:18 mrg Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
 #include <sys/cdefs.h>
 
 #ifndef lint
-__RCSID("$NetBSD: noarch.c,v 1.5 2012/10/17 20:22:15 drochner Exp $");
+__RCSID("$NetBSD: noarch.c,v 1.6 2018/01/16 08:23:18 mrg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -45,6 +45,13 @@ identifycpu(int fd, const char *cpuname)
 	printf("CPU identification not implemented for this architecture.\n");
 }
 
+bool
+identifycpu_bind(void)
+{
+
+	return false;
+}
+
 int
 ucodeupdate_check(int fd, struct cpu_ucode *uc)
 {

Added files:

Index: src/sys/arch/sparc/sparc/cache_print.h
diff -u /dev/null src/sys/arch/sparc/sparc/cache_print.h:1.1
--- /dev/null	Tue Jan 16 08:23:18 2018
+++ src/sys/arch/sparc/sparc/cache_print.h	Tue Jan 16 08:23:17 2018
@@ -0,0 +1,87 @@
+/*	$NetBSD: cache_print.h,v 1.1 2018/01/16 08:23:17 mrg Exp $	*/
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This works for kernel and cpuctl(8).  It only relies upon having
+ * a working printf() in the environment.
+ */
+
+static void cache_printf_backend(struct cacheinfo *ci, const char *cpuname);
+
+static void
+cache_printf_backend(struct cacheinfo *ci, const char *cpuname)
+{
+
+	if (ci->c_flags & CACHE_TRAPPAGEBUG)
+		printf("%s: cache chip bug; trap page uncached\n", cpuname);
+
+	printf("%s: ", cpuname);
+
+	if (ci->c_totalsize == 0) {
+		printf("no cache\n");
+		return;
+	}
+
+	if (ci->c_split) {
+		const char *sep = "";
+
+		printf("%s", (ci->c_physical ? "physical " : ""));
+		if (ci->ic_totalsize > 0) {
+			printf("%s%dK instruction (%d b/l)", sep,
+			    ci->ic_totalsize/1024, ci->ic_linesize);
+			sep = ", ";
+		}
+		if (ci->dc_totalsize > 0) {
+			printf("%s%dK data (%d b/l)", sep,
+			    ci->dc_totalsize/1024, ci->dc_linesize);
+		}
+	} else if (ci->c_physical) {
+		/* combined, physical */
+		printf("physical %dK combined cache (%d bytes/line)",
+		    ci->c_totalsize/1024, ci->c_linesize);
+	} else {
+		/* combined, virtual */
+		printf("%dK byte write-%s, %d bytes/line, %cw flush",
+		    ci->c_totalsize/1024,
+		    (ci->c_vactype == VAC_WRITETHROUGH) ? "through" : "back",
+		    ci->c_linesize,
+		    ci->c_hwflush ? 'h' : 's');
+	}
+
+	if (ci->ec_totalsize > 0) {
+		printf(", %dK external (%d b/l)",
+		    ci->ec_totalsize/1024, ci->ec_linesize);
+	}
+	printf(": ");
+	if (ci->c_enabled)
+		printf("cache enabled");
+	printf("\n");
+}

Index: src/usr.sbin/cpuctl/arch/sparc.c
diff -u /dev/null src/usr.sbin/cpuctl/arch/sparc.c:1.1
--- /dev/null	Tue Jan 16 08:23:18 2018
+++ src/usr.sbin/cpuctl/arch/sparc.c	Tue Jan 16 08:23:18 2018
@@ -0,0 +1,100 @@
+/*	$NetBSD: sparc.c,v 1.1 2018/01/16 08:23:18 mrg Exp $	*/
+
+/*
+ * Copyright (c) 2018 Matthew R. Green
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+
+#ifndef lint
+__RCSID("$NetBSD: sparc.c,v 1.1 2018/01/16 08:23:18 mrg Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/cpuio.h>
+#include <sys/sysctl.h>
+
+#include <machine/cpu.h>
+
+#include <stdio.h>
+#include <err.h>
+
+#include "../cpuctl.h"
+#include "../../../sys/arch/sparc/sparc/cache_print.h"
+
+void
+identifycpu(int fd, const char *cpuname)
+{
+	char path[128];
+	char *name;
+	char *fpuname;
+	int cpu_arch, mid, hz;
+	struct cacheinfo cacheinfo;
+	size_t len;
+
+	len = sizeof(cpu_arch);
+	if (sysctlbyname("machdep.cpu_arch", &cpu_arch, &len, 0, 0) == -1)
+		err(1, "couldn't get machdep.cpu_arch");
+
+	snprintf(path, sizeof path, "hw.%s.cacheinfo", cpuname);
+	len = sizeof(cacheinfo);
+	if (sysctlbyname(path, &cacheinfo, &len, 0, 0) == -1)
+		err(1, "couldn't get %s", path);
+
+	snprintf(path, sizeof path, "hw.%s.mid", cpuname);
+	len = sizeof(mid);
+	if (sysctlbyname(path, &mid, &len, 0, 0) == -1)
+		err(1, "couldn't get %s", path);
+
+	snprintf(path, sizeof path, "hw.%s.clock_frequency", cpuname);
+	len = sizeof(hz);
+	if (sysctlbyname(path, &hz, &len, 0, 0) == -1)
+		err(1, "couldn't get %s", path);
+	snprintf(path, sizeof path, "hw.%s.name", cpuname);
+	name = asysctlbyname(path, &len);
+
+	snprintf(path, sizeof path, "hw.%s.fpuname", cpuname);
+	fpuname = asysctlbyname(path, &len);
+	
+	printf("%s: mid %d: %s @ %d MHz, %s FPU\n", cpuname, mid, name, hz / 1000000, fpuname);
+	cache_printf_backend(&cacheinfo, cpuname);
+
+	printf("%s: SPARC v%d\n", cpuname, cpu_arch);
+}
+
+bool
+identifycpu_bind(void)
+{
+
+	return false;
+}
+
+int
+ucodeupdate_check(int fd, struct cpu_ucode *uc)
+{
+
+	return 0;
+}
Index: src/usr.sbin/cpuctl/arch/sparc64.c
diff -u /dev/null src/usr.sbin/cpuctl/arch/sparc64.c:1.1
--- /dev/null	Tue Jan 16 08:23:18 2018
+++ src/usr.sbin/cpuctl/arch/sparc64.c	Tue Jan 16 08:23:18 2018
@@ -0,0 +1,129 @@
+/*	$NetBSD: sparc64.c,v 1.1 2018/01/16 08:23:18 mrg Exp $	*/
+
+/*
+ * Copyright (c) 2018 Matthew R. Green
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+
+#ifndef lint
+__RCSID("$NetBSD: sparc64.c,v 1.1 2018/01/16 08:23:18 mrg Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/cpuio.h>
+#include <sys/sysctl.h>
+
+#include <machine/cpu.h>
+#include <machine/psl.h>
+
+#include <stdio.h>
+#include <err.h>
+
+#include "../cpuctl.h"
+
+void
+identifycpu(int fd, const char *cpuname)
+{
+	char path[128];
+	char *name;
+	const char *sep;
+	uint64_t ver;
+	uint64_t hz;
+	int cpu_arch, id;
+	struct cacheinfo cacheinfo;
+	size_t len;
+
+	len = sizeof(cpu_arch);
+	if (sysctlbyname("machdep.cpu_arch", &cpu_arch, &len, 0, 0) == -1)
+		err(1, "couldn't get machdep.cpu_arch");
+
+	snprintf(path, sizeof path, "hw.%s.cacheinfo", cpuname);
+	len = sizeof(cacheinfo);
+	if (sysctlbyname(path, &cacheinfo, &len, 0, 0) == -1)
+		err(1, "couldn't get %s", path);
+
+	snprintf(path, sizeof path, "hw.%s.id", cpuname);
+	len = sizeof(id);
+	if (sysctlbyname(path, &id, &len, 0, 0) == -1)
+		err(1, "couldn't get %s", path);
+
+	snprintf(path, sizeof path, "hw.%s.ver", cpuname);
+	len = sizeof(ver);
+	if (sysctlbyname(path, &ver, &len, 0, 0) == -1)
+		err(1, "couldn't get %s", path);
+
+	snprintf(path, sizeof path, "hw.%s.clock_frequency", cpuname);
+	len = sizeof(hz);
+	if (sysctlbyname(path, &hz, &len, 0, 0) == -1)
+		err(1, "couldn't get %s", path);
+	snprintf(path, sizeof path, "hw.%s.name", cpuname);
+	name = asysctlbyname(path, &len);
+	
+	printf("%s: %s @ %ld MHz, CPU id %d\n", cpuname, name, hz / 1000000, id);
+	printf("%s: manuf %x, impl %x, mask %x\n", cpuname, 
+		(unsigned)((ver & VER_MASK) >> VER_MASK_SHIFT),
+		(unsigned)((ver & VER_IMPL) >> VER_IMPL_SHIFT),
+		(unsigned)((ver & VER_MANUF) >> VER_MANUF_SHIFT));
+	printf("%s: ", cpuname);
+
+	sep = "";
+	if (cacheinfo.c_itotalsize) {
+		printf("%s%ldK instruction (%ld b/l)", sep,
+			(long)cacheinfo.c_itotalsize/1024,
+			(long)cacheinfo.c_ilinesize);
+		sep = ", ";
+	}
+	if (cacheinfo.c_dtotalsize) {
+		printf("%s%ldK data (%ld b/l)", sep,
+			(long)cacheinfo.c_dtotalsize/1024,
+			(long)cacheinfo.c_dlinesize);
+		sep = ", ";
+	}
+
+	if (cacheinfo.c_etotalsize) {
+		printf("%s%ldK external (%ld b/l)", sep,
+			(long)cacheinfo.c_etotalsize/1024,
+			(long)cacheinfo.c_elinesize);
+	}
+	printf("\n");
+
+	printf("%s: SPARC v%d\n", cpuname, cpu_arch);
+}
+
+bool
+identifycpu_bind(void)
+{
+
+	return false;
+}
+
+int
+ucodeupdate_check(int fd, struct cpu_ucode *uc)
+{
+
+	return 0;
+}

Reply via email to