svn commit: r358330 - head/sys/arm64/arm64
Andrew Turner
andrew at FreeBSD.org
Wed Feb 26 13:22:25 UTC 2020
Author: andrew
Date: Wed Feb 26 13:22:23 2020
New Revision: 358330
URL: https://svnweb.freebsd.org/changeset/base/358330
Log:
Teach the arm64 ident CPU code to print non-ID registers
Add support for non-ID registers when printing CPU information. This is
used with the cache type register to print details of the cache on boot.
Sponsored by: Innovate UK
Modified:
head/sys/arm64/arm64/identcpu.c
Modified: head/sys/arm64/arm64/identcpu.c
==============================================================================
--- head/sys/arm64/arm64/identcpu.c Wed Feb 26 12:38:21 2020 (r358329)
+++ head/sys/arm64/arm64/identcpu.c Wed Feb 26 13:22:23 2020 (r358330)
@@ -112,6 +112,7 @@ struct cpu_desc {
uint64_t id_aa64mmfr2;
uint64_t id_aa64pfr0;
uint64_t id_aa64pfr1;
+ uint64_t ctr;
};
static struct cpu_desc cpu_desc[MAXCPU];
@@ -128,6 +129,7 @@ static u_int cpu_print_regs;
#define PRINT_ID_AA64_MMFR2 0x00004000
#define PRINT_ID_AA64_PFR0 0x00010000
#define PRINT_ID_AA64_PFR1 0x00020000
+#define PRINT_CTR_EL0 0x10000000
struct cpu_parts {
u_int part_id;
@@ -1089,14 +1091,66 @@ parse_cpu_features_hwcap(u_int cpu)
}
static void
-print_id_register(struct sbuf *sb, const char *reg_name, uint64_t reg,
- struct mrs_field *fields)
+print_ctr_fields(struct sbuf *sb, uint64_t reg, void *arg)
{
- struct mrs_field_value *fv;
- int field, i, j, printed;
+ sbuf_printf(sb, "%u byte D-cacheline,", CTR_DLINE_SIZE(reg));
+ sbuf_printf(sb, "%u byte I-cacheline,", CTR_ILINE_SIZE(reg));
+ reg &= ~(CTR_DLINE_MASK | CTR_ILINE_MASK);
+
+ switch(CTR_L1IP_VAL(reg)) {
+ case CTR_L1IP_VPIPT:
+ sbuf_printf(sb, "VPIPT");
+ break;
+ case CTR_L1IP_AIVIVT:
+ sbuf_printf(sb, "AIVIVT");
+ break;
+ case CTR_L1IP_VIVT:
+ sbuf_printf(sb, "VIVT");
+ break;
+ case CTR_L1IP_PIPT:
+ sbuf_printf(sb, "PIPT");
+ break;
+ }
+ sbuf_printf(sb, " ICache,");
+ reg &= ~CTR_L1IP_MASK;
+
+ sbuf_printf(sb, "%d byte ERG,", CTR_ERG_SIZE(reg));
+ sbuf_printf(sb, "%d byte CWG", CTR_CWG_SIZE(reg));
+ reg &= ~(CTR_ERG_MASK | CTR_CWG_MASK);
+
+ if (CTR_IDC_VAL(reg) == 0)
+ sbuf_printf(sb, ",IDC");
+ if (CTR_DIC_VAL(reg) == 0)
+ sbuf_printf(sb, ",DIC");
+ reg &= ~(CTR_IDC_MASK | CTR_DIC_MASK);
+ reg &= ~CTR_RES1;
+
+ if (reg != 0)
+ sbuf_printf(sb, ",%lx", reg);
+}
+
+static void
+print_register(struct sbuf *sb, const char *reg_name, uint64_t reg,
+ void (*print_fields)(struct sbuf *, uint64_t, void *), void *arg)
+{
+
sbuf_printf(sb, "%29s = <", reg_name);
+ print_fields(sb, reg, arg);
+
+ sbuf_finish(sb);
+ printf("%s>\n", sbuf_data(sb));
+ sbuf_clear(sb);
+}
+
+static void
+print_id_fields(struct sbuf *sb, uint64_t reg, void *arg)
+{
+ struct mrs_field *fields = arg;
+ struct mrs_field_value *fv;
+ int field, i, j, printed;
+
#define SEP_STR ((printed++) == 0) ? "" : ","
printed = 0;
for (i = 0; fields[i].type != 0; i++) {
@@ -1125,10 +1179,14 @@ print_id_register(struct sbuf *sb, const char *reg_nam
if (reg != 0)
sbuf_printf(sb, "%s%#lx", SEP_STR, reg);
#undef SEP_STR
+}
- sbuf_finish(sb);
- printf("%s>\n", sbuf_data(sb));
- sbuf_clear(sb);
+static void
+print_id_register(struct sbuf *sb, const char *reg_name, uint64_t reg,
+ struct mrs_field *fields)
+{
+
+ print_register(sb, reg_name, reg, print_id_fields, fields);
}
static void
@@ -1184,6 +1242,12 @@ print_cpu_features(u_int cpu)
"hardware bugs that may cause the incorrect operation of "
"atomic operations.\n");
+ /* Cache Type Register */
+ if (cpu == 0 || (cpu_print_regs & PRINT_CTR_EL0) != 0) {
+ print_register(sb, "Cache Type",
+ cpu_desc[cpu].ctr, print_ctr_fields, NULL);
+ }
+
/* AArch64 Instruction Set Attribute Register 0 */
if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR0) != 0)
print_id_register(sb, "Instruction Set Attributes 0",
@@ -1295,6 +1359,7 @@ identify_cpu(void)
cpu_desc[cpu].mpidr = get_mpidr();
CPU_AFFINITY(cpu) = cpu_desc[cpu].mpidr & CPU_AFF_MASK;
+ cpu_desc[cpu].ctr = READ_SPECIALREG(ctr_el0);
cpu_desc[cpu].id_aa64dfr0 = READ_SPECIALREG(id_aa64dfr0_el1);
cpu_desc[cpu].id_aa64dfr1 = READ_SPECIALREG(id_aa64dfr1_el1);
cpu_desc[cpu].id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1);
@@ -1363,6 +1428,9 @@ identify_cpu(void)
cpu_print_regs |= PRINT_ID_AA64_PFR0;
if (cpu_desc[cpu].id_aa64pfr1 != cpu_desc[0].id_aa64pfr1)
cpu_print_regs |= PRINT_ID_AA64_PFR1;
+
+ if (cpu_desc[cpu].ctr != cpu_desc[0].ctr)
+ cpu_print_regs |= PRINT_CTR_EL0;
/* Wake up the other CPUs */
atomic_store_rel_int(&ident_lock, 0);
More information about the svn-src-all
mailing list