Add code to print the characteristics of the caches that can be discovered
authorkettenis <kettenis@openbsd.org>
Sat, 25 Aug 2018 20:45:28 +0000 (20:45 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 25 Aug 2018 20:45:28 +0000 (20:45 +0000)
through the CLIDR_EL1 register.

ok patrick@

sys/arch/arm64/arm64/cpu.c
sys/arch/arm64/include/armreg.h

index d833d7c..539259d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.c,v 1.23 2018/08/18 11:34:08 kettenis Exp $       */
+/*     $OpenBSD: cpu.c,v 1.24 2018/08/25 20:45:28 kettenis Exp $       */
 
 /*
  * Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com>
@@ -130,8 +130,12 @@ void
 cpu_identify(struct cpu_info *ci)
 {
        uint64_t midr, impl, part;
-       char *impl_name = NULL;
-       char *part_name = NULL;
+       uint64_t clidr;
+       uint32_t ctr, ccsidr, sets, ways, line;
+       const char *impl_name = NULL;
+       const char *part_name = NULL;
+       const char *il1p_name = NULL;
+       const char *sep;
        struct cpu_cores *coreselecter = cpu_cores_none;
        int i;
 
@@ -169,6 +173,62 @@ cpu_identify(struct cpu_info *ci)
                        snprintf(cpu_model, sizeof(cpu_model), "Unknown");
        }
 
+       /* Print cache information. */
+
+       ctr = READ_SPECIALREG(ctr_el0);
+       switch (ctr & CTR_IL1P_MASK) {
+       case CTR_IL1P_AIVIVT:
+               il1p_name = "AIVIVT ";
+               break;
+       case CTR_IL1P_VIPT:
+               il1p_name = "VIPT ";
+               break;
+       case CTR_IL1P_PIPT:
+               il1p_name = "PIPT ";
+               break;
+       }
+
+       clidr = READ_SPECIALREG(clidr_el1);
+       for (i = 0; i < 7; i++) {
+               if ((clidr & CLIDR_CTYPE_MASK) == 0)
+                       break;
+               printf("\n%s:", ci->ci_dev->dv_xname);
+               sep = "";
+               if (clidr & CLIDR_CTYPE_INSN) {
+                       WRITE_SPECIALREG(csselr_el1,
+                           i << CSSELR_LEVEL_SHIFT | CSSELR_IND);
+                       ccsidr = READ_SPECIALREG(ccsidr_el1);
+                       sets = CCSIDR_SETS(ccsidr);
+                       ways = CCSIDR_WAYS(ccsidr);
+                       line = CCSIDR_LINE_SIZE(ccsidr);
+                       printf("%s %dKB %db/line %d-way L%d %sI-cache", sep,
+                           (sets * ways * line) / 1024, line, ways, (i + 1),
+                           il1p_name);
+                       il1p_name = "";
+                       sep = ",";
+               }
+               if (clidr & CLIDR_CTYPE_DATA) {
+                       WRITE_SPECIALREG(csselr_el1, i << CSSELR_LEVEL_SHIFT);
+                       ccsidr = READ_SPECIALREG(ccsidr_el1);
+                       sets = CCSIDR_SETS(ccsidr);
+                       ways = CCSIDR_WAYS(ccsidr);
+                       line = CCSIDR_LINE_SIZE(ccsidr);
+                       printf("%s %dKB %db/line %d-way L%d D-cache", sep,
+                           (sets * ways * line) / 1024, line, ways, (i + 1));
+                       sep = ",";
+               }
+               if (clidr & CLIDR_CTYPE_UNIFIED) {
+                       WRITE_SPECIALREG(csselr_el1, i << CSSELR_LEVEL_SHIFT);
+                       ccsidr = READ_SPECIALREG(ccsidr_el1);
+                       sets = CCSIDR_SETS(ccsidr);
+                       ways = CCSIDR_WAYS(ccsidr);
+                       line = CCSIDR_LINE_SIZE(ccsidr);
+                       printf("%s %dKB %db/line %d-way L%d cache", sep,
+                           (sets * ways * line) / 1024, line, ways, (i + 1));
+               }
+               clidr >>= 3;
+       }
+
        /*
         * Some ARM processors are vulnerable to branch target
         * injection attacks (CVE-2017-5715).
index 3700c3c..a2365e6 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: armreg.h,v 1.6 2018/08/03 18:36:01 kettenis Exp $ */
+/* $OpenBSD: armreg.h,v 1.7 2018/08/25 20:45:28 kettenis Exp $ */
 /*-
  * Copyright (c) 2013, 2014 Andrew Turner
  * Copyright (c) 2015 The FreeBSD Foundation
 #define        WRITE_SPECIALREG(reg, val)                                      \
        __asm __volatile("msr   " __STRING(reg) ", %0" : : "r"((uint64_t)val))
 
-/* CNTHCTL_EL2 - Counter-timer Hypervisor Control register */
+/* CCSIDR_EL1 - Current Cache Size ID Register */
+#define        CCSIDR_SETS_MASK        0x0fffe000
+#define        CCSIDR_SETS_SHIFT       13
+#define        CCSIDR_SETS(reg)        \
+    ((((reg) & CCSIDR_SETS_MASK) >> CCSIDR_SETS_SHIFT) + 1)
+#define        CCSIDR_WAYS_MASK        0x00001ff8
+#define        CCSIDR_WAYS_SHIFT       3
+#define        CCSIDR_WAYS(reg)        \
+    ((((reg) & CCSIDR_WAYS_MASK) >> CCSIDR_WAYS_SHIFT) + 1)
+#define        CCSIDR_LINE_MASK        0x00000007
+#define        CCSIDR_LINE_SIZE(reg)   (1 << (((reg) & CCSIDR_LINE_MASK) + 4))
+
+/* CLIDR_EL1 - Cache Level ID Register */
+#define        CLIDR_CTYPE_MASK        0x7
+#define        CLIDR_CTYPE_INSN        0x1
+#define        CLIDR_CTYPE_DATA        0x2
+#define        CLIDR_CTYPE_UNIFIED     0x4
+
+/* CNTHCTL_EL2 - Counter-timer Hypervisor Control Register */
 #define        CNTHCTL_EVNTI_MASK      (0xf << 4) /* Bit to trigger event stream */
 #define        CNTHCTL_EVNTDIR         (1 << 3) /* Control transition trigger bit */
 #define        CNTHCTL_EVNTEN          (1 << 2) /* Enable event stream */
 #define         CPACR_FPEN_TRAP_NONE   (0x3 << 20) /* No traps */
 #define        CPACR_TTA               (0x1 << 28)
 
+/* CSSELR_EL1 - Cache Size Selection Register */
+#define        CSSELR_IND              (1 << 0)
+#define        CSSELR_LEVEL_SHIFT      1
+
 /* CTR_EL0 - Cache Type Register */
 #define        CTR_DLINE_SHIFT         16
 #define        CTR_DLINE_MASK          (0xf << CTR_DLINE_SHIFT)
 #define        CTR_DLINE_SIZE(reg)     (((reg) & CTR_DLINE_MASK) >> CTR_DLINE_SHIFT)
+#define        CTR_IL1P_SHIFT          14
+#define        CTR_IL1P_MASK           (0x3 << CTR_IL1P_SHIFT)
+#define        CTR_IL1P_AIVIVT         (0x1 << CTR_IL1P_SHIFT)
+#define        CTR_IL1P_VIPT           (0x2 << CTR_IL1P_SHIFT)
+#define        CTR_IL1P_PIPT           (0x3 << CTR_IL1P_SHIFT)
 #define        CTR_ILINE_SHIFT         0
 #define        CTR_ILINE_MASK          (0xf << CTR_ILINE_SHIFT)
 #define        CTR_ILINE_SIZE(reg)     (((reg) & CTR_ILINE_MASK) >> CTR_ILINE_SHIFT)