aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2020-02-26 13:22:23 +0000
committerAndrew Turner <andrew@FreeBSD.org>2020-02-26 13:22:23 +0000
commita4c354bdd5ffa611dfd7f5daddb5da7a68b79aa9 (patch)
treed906774ca478dc955bf3f35833c10d0dc713bfaa
parentd985858aa6df49248d2beb806a788dd5cdde0ca2 (diff)
downloadsrc-a4c354bdd5ffa611dfd7f5daddb5da7a68b79aa9.tar.gz
src-a4c354bdd5ffa611dfd7f5daddb5da7a68b79aa9.zip
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
Notes
Notes: svn path=/head/; revision=358330
-rw-r--r--sys/arm64/arm64/identcpu.c82
1 files changed, 75 insertions, 7 deletions
diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
index 4bfd5f06bae4..e414738a777c 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -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)
+{
+
+ 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)
{
- struct mrs_field_value *fv;
- int field, i, j, printed;
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_name, uint64_t reg,
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);
@@ -1364,6 +1429,9 @@ identify_cpu(void)
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);
__asm __volatile("sev" ::: "memory");