Index: sys/arm64/arm64/identcpu.c =================================================================== --- sys/arm64/arm64/identcpu.c +++ sys/arm64/arm64/identcpu.c @@ -49,6 +49,7 @@ static void print_cpu_midr(struct sbuf *sb, u_int cpu); static void print_cpu_features(u_int cpu); +static void print_cpu_caches(); #ifdef COMPAT_FREEBSD32 static u_long parse_cpu_features_hwcap32(void); #endif @@ -1805,6 +1806,8 @@ /* Fill in cpu_model for the hw.model sysctl */ sbuf_new(&sb, cpu_model, sizeof(cpu_model), SBUF_FIXEDLEN); print_cpu_midr(&sb, 0); + print_cpu_caches(); + sbuf_finish(&sb); sbuf_delete(&sb); } @@ -1978,6 +1981,60 @@ cpu_part_name, CPU_VAR(midr), CPU_REV(midr)); } +static void +print_cpu_cache(struct sbuf *sb, int level, uint64_t ccs, bool icache, bool unified) +{ + size_t cache_size; + + /* + * Calculate cache size (sets * ways * line size). There are different + * formats depending on the FEAT_CCIDX bit in ID_AA64MMFR2 feature + * register. + */ + if ((READ_SPECIALREG(id_aa64mmfr2_el1) & ID_AA64MMFR2_CCIDX_64)) + cache_size = (CCSIDR_NSETS_64(ccs) + 1) * + (CCSIDR_ASSOC_64(ccs) + 1); + else + cache_size = (CCSIDR_NSETS(ccs) + 1) * (CCSIDR_ASSOC(ccs) + 1); + + if (icache) + cache_size *= icache_line_size; + else + cache_size *= dcache_line_size; + sbuf_printf(sb, " L%d cache: %zuKB (%s)\n", level, cache_size / 1024, + icache ? "instruction" : unified ? "unified" : "data"); +} + +static void +print_cpu_caches() +{ + struct sbuf *sb; + + /* Print out each cache combination */ + int cache_levels; + int i = 1; + cache_levels = READ_SPECIALREG(clidr_el1); + + sb = sbuf_new_auto(); + sbuf_printf("Per-core CPU caches:\n"); + for (i = 0; (cache_levels & 0x7) != 0; i++, cache_levels >>= 3) { + if ((cache_levels & 0x1)) { + WRITE_SPECIALREG(csselr_el1, (i << 1) | 1); + + print_cpu_cache(sb, i + 1, READ_SPECIALREG(ccsidr_el1), + true, false); + } + if ((cache_levels & 0x6) == 0) + continue; + WRITE_SPECIALREG(csselr_el1, i << 1); + print_cpu_cache(sb, i + 1, READ_SPECIALREG(ccsidr_el1), + false, (cache_levels & 0x4)); + + } + sbuf_finish(sb); + printf("%s\n", sbuf_data(sb)); +} + static void print_cpu_features(u_int cpu) { Index: sys/arm64/include/armreg.h =================================================================== --- sys/arm64/include/armreg.h +++ sys/arm64/include/armreg.h @@ -69,6 +69,24 @@ #define UL(x) UINT64_C(x) +/* CCSIDR_EL1 - Cache Size ID Register */ +#define CCSIDR_EL1_NumSets_M 0x0FFFE000 +#define CCSIDR_EL1_NumSets64_M 0x00FFFFFFFE000 +#define CCSIDR_EL1_NumSets_S 13 +#define CCSIDR_EL1_NumSets64_S 32 +#define CCSIDR_EL1_Assoc_M 0x00001FF8 +#define CCSIDR_EL1_Assoc64_M 0x0000000000FFFFF8 +#define CCSIDR_EL1_Assoc_S 3 +#define CCSIDR_EL1_Assoc64_S 3 +#define CCSIDR_NSETS(idr) \ + (((idr) & CCSIDR_EL1_NumSets_M) >> CCSIDR_EL1_NumSets_S) +#define CCSIDR_ASSOC(idr) \ + (((idr) & CCSIDR_EL1_Assoc_M) >> CCSIDR_EL1_Assoc_S) +#define CCSIDR_NSETS_64(idr) \ + (((idr) & CCSIDR_EL1_NumSets64_M) >> CCSIDR_EL1_NumSets64_S) +#define CCSIDR_ASSOC_64(idr) \ + (((idr) & CCSIDR_EL1_Assoc64_M) >> CCSIDR_EL1_Assoc64_S) + /* 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 */