arch/arm64/kernel/cpuinfo.c

Source file repositories/reference/linux-study-clean/arch/arm64/kernel/cpuinfo.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/kernel/cpuinfo.c
Extension
.c
Size
17153 bytes
Lines
545
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

device_initcall(cpuinfo_regs_init);

static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
{
	unsigned int cpu = smp_processor_id();
	u32 l1ip = CTR_L1IP(info->reg_ctr);

	switch (l1ip) {
	case CTR_EL0_L1Ip_PIPT:
		break;
	case CTR_EL0_L1Ip_VIPT:
	default:
		/* Assume aliasing */
		set_bit(ICACHEF_ALIASING, &__icache_flags);
		break;
	}

	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();
	/*
	 * Use the effective value of the CTR_EL0 than the raw value
	 * exposed by the CPU. CTR_EL0.IDC field value must be interpreted
	 * with the CLIDR_EL1 fields to avoid triggering false warnings
	 * when there is a mismatch across the CPUs. Keep track of the
	 * effective value of the CTR_EL0 in our internal records for
	 * accurate sanity check and feature enablement.
	 */
	info->reg_ctr = read_cpuid_effective_cachetype();
	info->reg_dczid = read_cpuid(DCZID_EL0);
	info->reg_midr = read_cpuid_id();
	info->reg_revidr = read_cpuid(REVIDR_EL1);
	info->reg_aidr = read_cpuid(AIDR_EL1);

	info->reg_id_aa64dfr0 = read_cpuid(ID_AA64DFR0_EL1);
	info->reg_id_aa64dfr1 = read_cpuid(ID_AA64DFR1_EL1);
	info->reg_id_aa64isar0 = read_cpuid(ID_AA64ISAR0_EL1);
	info->reg_id_aa64isar1 = read_cpuid(ID_AA64ISAR1_EL1);
	info->reg_id_aa64isar2 = read_cpuid(ID_AA64ISAR2_EL1);
	info->reg_id_aa64isar3 = read_cpuid(ID_AA64ISAR3_EL1);
	info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1);
	info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1);
	info->reg_id_aa64mmfr2 = read_cpuid(ID_AA64MMFR2_EL1);
	info->reg_id_aa64mmfr3 = read_cpuid(ID_AA64MMFR3_EL1);
	info->reg_id_aa64mmfr4 = read_cpuid(ID_AA64MMFR4_EL1);
	info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1);
	info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1);
	info->reg_id_aa64pfr2 = read_cpuid(ID_AA64PFR2_EL1);
	info->reg_id_aa64zfr0 = read_cpuid(ID_AA64ZFR0_EL1);
	info->reg_id_aa64smfr0 = read_cpuid(ID_AA64SMFR0_EL1);
	info->reg_id_aa64fpfr0 = read_cpuid(ID_AA64FPFR0_EL1);

	if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
		info->reg_gmid = read_cpuid(GMID_EL1);

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

	/*
	 * info->reg_mpamidr deferred to {init,update}_cpu_features because we
	 * don't want to read it (and trigger a trap on buggy firmware) if

Annotation

Implementation Notes