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