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;
+}