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
This commit is contained in:
parent
d985858aa6
commit
a4c354bdd5
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user