Commit 930a58b4 authored by Will Deacon's avatar Will Deacon
Browse files

arm64: cpuinfo: Split AArch32 registers out into a separate struct



In preparation for late initialisation of the "sanitised" AArch32 register
state, move the AArch32 registers out of 'struct cpuinfo' and into their
own struct definition.

Acked-by: default avatarMark Rutland <mark.rutland@arm.com>
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/r/20210608180313.11502-2-will@kernel.org


Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent 21047e91
Loading
Loading
Loading
Loading
+25 −21
Original line number Diff line number Diff line
@@ -12,27 +12,7 @@
/*
 * Records attributes of an individual CPU.
 */
struct cpuinfo_arm64 {
	struct cpu	cpu;
	struct kobject	kobj;
	u64		reg_ctr;
	u64		reg_cntfrq;
	u64		reg_dczid;
	u64		reg_midr;
	u64		reg_revidr;
	u64		reg_gmid;

	u64		reg_id_aa64dfr0;
	u64		reg_id_aa64dfr1;
	u64		reg_id_aa64isar0;
	u64		reg_id_aa64isar1;
	u64		reg_id_aa64mmfr0;
	u64		reg_id_aa64mmfr1;
	u64		reg_id_aa64mmfr2;
	u64		reg_id_aa64pfr0;
	u64		reg_id_aa64pfr1;
	u64		reg_id_aa64zfr0;

struct cpuinfo_32bit {
	u32		reg_id_dfr0;
	u32		reg_id_dfr1;
	u32		reg_id_isar0;
@@ -55,6 +35,30 @@ struct cpuinfo_arm64 {
	u32		reg_mvfr0;
	u32		reg_mvfr1;
	u32		reg_mvfr2;
};

struct cpuinfo_arm64 {
	struct cpu	cpu;
	struct kobject	kobj;
	u64		reg_ctr;
	u64		reg_cntfrq;
	u64		reg_dczid;
	u64		reg_midr;
	u64		reg_revidr;
	u64		reg_gmid;

	u64		reg_id_aa64dfr0;
	u64		reg_id_aa64dfr1;
	u64		reg_id_aa64isar0;
	u64		reg_id_aa64isar1;
	u64		reg_id_aa64mmfr0;
	u64		reg_id_aa64mmfr1;
	u64		reg_id_aa64mmfr2;
	u64		reg_id_aa64pfr0;
	u64		reg_id_aa64pfr1;
	u64		reg_id_aa64zfr0;

	struct cpuinfo_32bit	aarch32;

	/* pseudo-ZCR for recording maximum ZCR_EL1 LEN value: */
	u64		reg_zcr;
+39 −35
Original line number Diff line number Diff line
@@ -871,26 +871,8 @@ static void __init init_cpu_hwcaps_indirect_list(void)

static void __init setup_boot_cpu_capabilities(void);

void __init init_cpu_features(struct cpuinfo_arm64 *info)
static void __init init_32bit_cpu_features(struct cpuinfo_32bit *info)
{
	/* Before we start using the tables, make sure it is sorted */
	sort_ftr_regs();

	init_cpu_ftr_reg(SYS_CTR_EL0, info->reg_ctr);
	init_cpu_ftr_reg(SYS_DCZID_EL0, info->reg_dczid);
	init_cpu_ftr_reg(SYS_CNTFRQ_EL0, info->reg_cntfrq);
	init_cpu_ftr_reg(SYS_ID_AA64DFR0_EL1, info->reg_id_aa64dfr0);
	init_cpu_ftr_reg(SYS_ID_AA64DFR1_EL1, info->reg_id_aa64dfr1);
	init_cpu_ftr_reg(SYS_ID_AA64ISAR0_EL1, info->reg_id_aa64isar0);
	init_cpu_ftr_reg(SYS_ID_AA64ISAR1_EL1, info->reg_id_aa64isar1);
	init_cpu_ftr_reg(SYS_ID_AA64MMFR0_EL1, info->reg_id_aa64mmfr0);
	init_cpu_ftr_reg(SYS_ID_AA64MMFR1_EL1, info->reg_id_aa64mmfr1);
	init_cpu_ftr_reg(SYS_ID_AA64MMFR2_EL1, info->reg_id_aa64mmfr2);
	init_cpu_ftr_reg(SYS_ID_AA64PFR0_EL1, info->reg_id_aa64pfr0);
	init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1);
	init_cpu_ftr_reg(SYS_ID_AA64ZFR0_EL1, info->reg_id_aa64zfr0);

	if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
	init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
	init_cpu_ftr_reg(SYS_ID_DFR1_EL1, info->reg_id_dfr1);
	init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0);
@@ -914,6 +896,28 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
	init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
}

void __init init_cpu_features(struct cpuinfo_arm64 *info)
{
	/* Before we start using the tables, make sure it is sorted */
	sort_ftr_regs();

	init_cpu_ftr_reg(SYS_CTR_EL0, info->reg_ctr);
	init_cpu_ftr_reg(SYS_DCZID_EL0, info->reg_dczid);
	init_cpu_ftr_reg(SYS_CNTFRQ_EL0, info->reg_cntfrq);
	init_cpu_ftr_reg(SYS_ID_AA64DFR0_EL1, info->reg_id_aa64dfr0);
	init_cpu_ftr_reg(SYS_ID_AA64DFR1_EL1, info->reg_id_aa64dfr1);
	init_cpu_ftr_reg(SYS_ID_AA64ISAR0_EL1, info->reg_id_aa64isar0);
	init_cpu_ftr_reg(SYS_ID_AA64ISAR1_EL1, info->reg_id_aa64isar1);
	init_cpu_ftr_reg(SYS_ID_AA64MMFR0_EL1, info->reg_id_aa64mmfr0);
	init_cpu_ftr_reg(SYS_ID_AA64MMFR1_EL1, info->reg_id_aa64mmfr1);
	init_cpu_ftr_reg(SYS_ID_AA64MMFR2_EL1, info->reg_id_aa64mmfr2);
	init_cpu_ftr_reg(SYS_ID_AA64PFR0_EL1, info->reg_id_aa64pfr0);
	init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1);
	init_cpu_ftr_reg(SYS_ID_AA64ZFR0_EL1, info->reg_id_aa64zfr0);

	if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
		init_32bit_cpu_features(&info->aarch32);

	if (id_aa64pfr0_sve(info->reg_id_aa64pfr0)) {
		init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
		sve_init_vq_map();
@@ -986,20 +990,12 @@ static void relax_cpu_ftr_reg(u32 sys_id, int field)
	WARN_ON(!ftrp->width);
}

static int update_32bit_cpu_features(int cpu, struct cpuinfo_arm64 *info,
				     struct cpuinfo_arm64 *boot)
static int update_32bit_cpu_features(int cpu, struct cpuinfo_32bit *info,
				     struct cpuinfo_32bit *boot)
{
	int taint = 0;
	u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);

	/*
	 * If we don't have AArch32 at all then skip the checks entirely
	 * as the register values may be UNKNOWN and we're not going to be
	 * using them for anything.
	 */
	if (!id_aa64pfr0_32bit_el0(pfr0))
		return taint;

	/*
	 * If we don't have AArch32 at EL1, then relax the strictness of
	 * EL1-dependent register fields to avoid spurious sanity check fails.
@@ -1151,15 +1147,23 @@ void update_cpu_features(int cpu,
	 * value is the same on all CPUs.
	 */
	if (IS_ENABLED(CONFIG_ARM64_MTE) &&
	    id_aa64pfr1_mte(info->reg_id_aa64pfr1))
	    id_aa64pfr1_mte(info->reg_id_aa64pfr1)) {
		taint |= check_update_ftr_reg(SYS_GMID_EL1, cpu,
					      info->reg_gmid, boot->reg_gmid);
	}

	/*
	 * If we don't have AArch32 at all then skip the checks entirely
	 * as the register values may be UNKNOWN and we're not going to be
	 * using them for anything.
	 *
	 * This relies on a sanitised view of the AArch64 ID registers
	 * (e.g. SYS_ID_AA64PFR0_EL1), so we call it last.
	 */
	taint |= update_32bit_cpu_features(cpu, info, boot);
	if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
		taint |= update_32bit_cpu_features(cpu, &info->aarch32,
						   &boot->aarch32);
	}

	/*
	 * Mismatched CPU features are a recipe for disaster. Don't even
+28 −25
Original line number Diff line number Diff line
@@ -344,6 +344,32 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
	pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
}

static void __cpuinfo_store_cpu_32bit(struct cpuinfo_32bit *info)
{
	info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
	info->reg_id_dfr1 = read_cpuid(ID_DFR1_EL1);
	info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
	info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
	info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
	info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
	info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
	info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
	info->reg_id_isar6 = read_cpuid(ID_ISAR6_EL1);
	info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
	info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
	info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
	info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
	info->reg_id_mmfr4 = read_cpuid(ID_MMFR4_EL1);
	info->reg_id_mmfr5 = read_cpuid(ID_MMFR5_EL1);
	info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
	info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
	info->reg_id_pfr2 = read_cpuid(ID_PFR2_EL1);

	info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
	info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
	info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
}

static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
{
	info->reg_cntfrq = arch_timer_get_cntfrq();
@@ -374,31 +400,8 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
	if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
		info->reg_gmid = read_cpuid(GMID_EL1);

	/* Update the 32bit ID registers only if AArch32 is implemented */
	if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
		info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
		info->reg_id_dfr1 = read_cpuid(ID_DFR1_EL1);
		info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
		info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
		info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
		info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
		info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
		info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
		info->reg_id_isar6 = read_cpuid(ID_ISAR6_EL1);
		info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
		info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
		info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
		info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
		info->reg_id_mmfr4 = read_cpuid(ID_MMFR4_EL1);
		info->reg_id_mmfr5 = read_cpuid(ID_MMFR5_EL1);
		info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
		info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
		info->reg_id_pfr2 = read_cpuid(ID_PFR2_EL1);

		info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
		info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
		info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
	}
	if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
		__cpuinfo_store_cpu_32bit(&info->aarch32);

	if (IS_ENABLED(CONFIG_ARM64_SVE) &&
	    id_aa64pfr0_sve(info->reg_id_aa64pfr0))