From d1486c828a88fa44873debae38712f631570e6d1 Mon Sep 17 00:00:00 2001 From: kettenis Date: Mon, 18 Mar 2024 18:35:21 +0000 Subject: [PATCH] Add support for the new layout of the CCSIDR_EL1 register that was introduced in Armv8.3 when the CCIDX feature is advertised. This makes us properly detect the cache size on newer CPU cores like Neoverse N2, at least when emulated by QEMU. ok jsg@ --- sys/arch/arm64/arm64/cpu.c | 54 +++++++++++++++++++++++++-------- sys/arch/arm64/include/armreg.h | 21 ++++++++++++- 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/sys/arch/arm64/arm64/cpu.c b/sys/arch/arm64/arm64/cpu.c index 354b05299af..06c48cd3d1c 100644 --- a/sys/arch/arm64/arm64/cpu.c +++ b/sys/arch/arm64/arm64/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.111 2024/03/17 13:05:40 kettenis Exp $ */ +/* $OpenBSD: cpu.c,v 1.112 2024/03/18 18:35:21 kettenis Exp $ */ /* * Copyright (c) 2016 Dale Rahn @@ -289,13 +289,14 @@ cpu_identify(struct cpu_info *ci) static uint64_t prev_id_aa64pfr0; static uint64_t prev_id_aa64pfr1; uint64_t midr, impl, part; - uint64_t clidr, id; - uint32_t ctr, ccsidr, sets, ways, line; + uint64_t clidr, ccsidr, id; + uint32_t ctr, 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 ccidx; int i; midr = READ_SPECIALREG(midr_el1); @@ -348,7 +349,18 @@ cpu_identify(struct cpu_info *ci) break; } + id = READ_SPECIALREG(id_aa64mmfr2_el1); clidr = READ_SPECIALREG(clidr_el1); + if (ID_AA64MMFR2_CCIDX(id) > ID_AA64MMFR2_CCIDX_IMPL) { + /* Reserved value. Don't print cache information. */ + clidr = 0; + } else if (ID_AA64MMFR2_CCIDX(id) == ID_AA64MMFR2_CCIDX_IMPL) { + /* CCSIDR_EL1 uses the new 64-bit format. */ + ccidx = 1; + } else { + /* CCSIDR_EL1 uses the old 32-bit format. */ + ccidx = 0; + } for (i = 0; i < 7; i++) { if ((clidr & CLIDR_CTYPE_MASK) == 0) break; @@ -359,9 +371,15 @@ cpu_identify(struct cpu_info *ci) i << CSSELR_LEVEL_SHIFT | CSSELR_IND); __asm volatile("isb"); ccsidr = READ_SPECIALREG(ccsidr_el1); - sets = CCSIDR_SETS(ccsidr); - ways = CCSIDR_WAYS(ccsidr); - line = CCSIDR_LINE_SIZE(ccsidr); + if (ccidx) { + sets = CCSIDR_CCIDX_SETS(ccsidr); + ways = CCSIDR_CCIDX_WAYS(ccsidr); + line = CCSIDR_CCIDX_LINE_SIZE(ccsidr); + } else { + 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); @@ -372,9 +390,15 @@ cpu_identify(struct cpu_info *ci) WRITE_SPECIALREG(csselr_el1, i << CSSELR_LEVEL_SHIFT); __asm volatile("isb"); ccsidr = READ_SPECIALREG(ccsidr_el1); - sets = CCSIDR_SETS(ccsidr); - ways = CCSIDR_WAYS(ccsidr); - line = CCSIDR_LINE_SIZE(ccsidr); + if (ccidx) { + sets = CCSIDR_CCIDX_SETS(ccsidr); + ways = CCSIDR_CCIDX_WAYS(ccsidr); + line = CCSIDR_CCIDX_LINE_SIZE(ccsidr); + } else { + 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 = ","; @@ -383,9 +407,15 @@ cpu_identify(struct cpu_info *ci) WRITE_SPECIALREG(csselr_el1, i << CSSELR_LEVEL_SHIFT); __asm volatile("isb"); ccsidr = READ_SPECIALREG(ccsidr_el1); - sets = CCSIDR_SETS(ccsidr); - ways = CCSIDR_WAYS(ccsidr); - line = CCSIDR_LINE_SIZE(ccsidr); + if (ccidx) { + sets = CCSIDR_CCIDX_SETS(ccsidr); + ways = CCSIDR_CCIDX_WAYS(ccsidr); + line = CCSIDR_CCIDX_LINE_SIZE(ccsidr); + } else { + 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)); } diff --git a/sys/arch/arm64/include/armreg.h b/sys/arch/arm64/include/armreg.h index 2612142d3f5..02ded6a4ed8 100644 --- a/sys/arch/arm64/include/armreg.h +++ b/sys/arch/arm64/include/armreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: armreg.h,v 1.32 2024/03/17 13:05:40 kettenis Exp $ */ +/* $OpenBSD: armreg.h,v 1.33 2024/03/18 18:35:21 kettenis Exp $ */ /*- * Copyright (c) 2013, 2014 Andrew Turner * Copyright (c) 2015 The FreeBSD Foundation @@ -56,6 +56,18 @@ #define CCSIDR_LINE_MASK 0x00000007 #define CCSIDR_LINE_SIZE(reg) (1 << (((reg) & CCSIDR_LINE_MASK) + 4)) +#define CCSIDR_CCIDX_SETS_MASK 0x00ffffff00000000ULL +#define CCSIDR_CCIDX_SETS_SHIFT 32 +#define CCSIDR_CCIDX_SETS(reg) \ + ((((reg) & CCSIDR_CCIDX_SETS_MASK) >> CCSIDR_CCIDX_SETS_SHIFT) + 1) +#define CCSIDR_CCIDX_WAYS_MASK 0x0000000000fffff8ULL +#define CCSIDR_CCIDX_WAYS_SHIFT 3 +#define CCSIDR_CCIDX_WAYS(reg) \ + ((((reg) & CCSIDR_CCIDX_WAYS_MASK) >> CCSIDR_CCIDX_WAYS_SHIFT) + 1) +#define CCSIDR_CCIDX_LINE_MASK 0x0000000000000007ULL +#define CCSIDR_CCIDX_LINE_SIZE(reg) \ + (1 << (((reg) & CCSIDR_CCIDX_LINE_MASK) + 4)) + /* CLIDR_EL1 - Cache Level ID Register */ #define CLIDR_CTYPE_MASK 0x7 #define CLIDR_CTYPE_INSN 0x1 @@ -491,6 +503,13 @@ #define ID_AA64MMFR1_ECBHB_NONE (0x0ULL << ID_AA64MMFR1_ECBHB_SHIFT) #define ID_AA64MMFR1_ECBHB_IMPL (0x1ULL << ID_AA64MMFR1_ECBHB_SHIFT) +/* ID_AA64MMFR2_EL1 */ +#define ID_AA64MMFR2_MASK 0xffff0fffffffffffULL +#define ID_AA64MMFR2_CCIDX_SHIFT 20 +#define ID_AA64MMFR2_CCIDX_MASK (0xfULL << ID_AA64MMFR2_CCIDX_SHIFT) +#define ID_AA64MMFR2_CCIDX(x) ((x) & ID_AA64MMFR2_CCIDX_MASK) +#define ID_AA64MMFR2_CCIDX_IMPL (0x1ULL << ID_AA64MMFR2_CCIDX_SHIFT) + /* ID_AA64PFR0_EL1 */ #define ID_AA64PFR0_MASK 0xff0fffffffffffffULL #define ID_AA64PFR0_EL0_SHIFT 0 -- 2.20.1