Skip to content
cpufeature.c 69.6 KiB
Newer Older
	if (!WARN_ON(preemptible()) && n < ARM64_NCAPS) {
		const struct arm64_cpu_capabilities *cap = cpu_hwcaps_ptrs[n];

		if (cap)
			return cap->matches(cap, SCOPE_LOCAL_CPU);
	}

	return false;
void cpu_set_feature(unsigned int num)
{
	WARN_ON(num >= MAX_CPU_FEATURES);
	elf_hwcap |= BIT(num);
}
EXPORT_SYMBOL_GPL(cpu_set_feature);

bool cpu_have_feature(unsigned int num)
{
	WARN_ON(num >= MAX_CPU_FEATURES);
	return elf_hwcap & BIT(num);
}
EXPORT_SYMBOL_GPL(cpu_have_feature);

unsigned long cpu_get_elf_hwcap(void)
{
	/*
	 * We currently only populate the first 32 bits of AT_HWCAP. Please
	 * note that for userspace compatibility we guarantee that bits 62
	 * and 63 will always be returned as 0.
	 */
	return lower_32_bits(elf_hwcap);
}

unsigned long cpu_get_elf_hwcap2(void)
{
	return upper_32_bits(elf_hwcap);
}

static void __init setup_system_capabilities(void)
{
	/*
	 * We have finalised the system-wide safe feature
	 * registers, finalise the capabilities that depend
	 * on it. Also enable all the available capabilities,
	 * that are not enabled already.
	 */
	update_cpu_capabilities(SCOPE_SYSTEM);
	enable_cpu_capabilities(SCOPE_ALL & ~SCOPE_BOOT_CPU);
void __init setup_cpu_features(void)
	mark_const_caps_ready();
	setup_elf_hwcaps(arm64_elf_hwcaps);

	if (system_supports_32bit_el0())
		setup_elf_hwcaps(compat_elf_hwcaps);
	if (system_uses_ttbr0_pan())
		pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n");

	/* Advertise that we have computed the system capabilities */
	set_sys_caps_initialised();

	/*
	 * Check for sane CTR_EL0.CWG value.
	 */
	cwg = cache_type_cwg();
	if (!cwg)
		pr_warn("No Cache Writeback Granule information, assuming %d\n",
			ARCH_DMA_MINALIGN);

static bool __maybe_unused
cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused)
	return (cpus_have_const_cap(ARM64_HAS_PAN) && !cpus_have_const_cap(ARM64_HAS_UAO));
static void __maybe_unused cpu_enable_cnp(struct arm64_cpu_capabilities const *cap)
{
	cpu_replace_ttbr1(lm_alias(swapper_pg_dir));
}

/*
 * We emulate only the following system register space.
 * Op0 = 0x3, CRn = 0x0, Op1 = 0x0, CRm = [0, 4 - 7]
 * See Table C5-6 System instruction encodings for System register accesses,
 * ARMv8 ARM(ARM DDI 0487A.f) for more details.
 */
static inline bool __attribute_const__ is_emulated(u32 id)
{
	return (sys_reg_Op0(id) == 0x3 &&
		sys_reg_CRn(id) == 0x0 &&
		sys_reg_Op1(id) == 0x0 &&
		(sys_reg_CRm(id) == 0 ||
		 ((sys_reg_CRm(id) >= 4) && (sys_reg_CRm(id) <= 7))));
}

/*
 * With CRm == 0, reg should be one of :
 * MIDR_EL1, MPIDR_EL1 or REVIDR_EL1.
 */
static inline int emulate_id_reg(u32 id, u64 *valp)
{
	switch (id) {
	case SYS_MIDR_EL1:
		*valp = read_cpuid_id();
		break;
	case SYS_MPIDR_EL1:
		*valp = SYS_MPIDR_SAFE_VAL;
		break;
	case SYS_REVIDR_EL1:
		/* IMPLEMENTATION DEFINED values are emulated with 0 */
		*valp = 0;
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int emulate_sys_reg(u32 id, u64 *valp)
{
	struct arm64_ftr_reg *regp;

	if (!is_emulated(id))
		return -EINVAL;

	if (sys_reg_CRm(id) == 0)
		return emulate_id_reg(id, valp);

	regp = get_arm64_ftr_reg(id);
	if (regp)
		*valp = arm64_ftr_reg_user_value(regp);
	else
		/*
		 * The untracked registers are either IMPLEMENTATION DEFINED
		 * (e.g, ID_AFR0_EL1) or reserved RAZ.
		 */
		*valp = 0;
	return 0;
}

int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt)
{
	int rc;
	u64 val;

	rc = emulate_sys_reg(sys_reg, &val);
	if (!rc) {
		pt_regs_write_reg(regs, rt, val);
		arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
static int emulate_mrs(struct pt_regs *regs, u32 insn)
{
	u32 sys_reg, rt;

	/*
	 * sys_reg values are defined as used in mrs/msr instruction.
	 * shift the imm value to get the encoding.
	 */
	sys_reg = (u32)aarch64_insn_decode_immediate(AARCH64_INSN_IMM_16, insn) << 5;
	rt = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RT, insn);
	return do_emulate_mrs(regs, sys_reg, rt);
}

static struct undef_hook mrs_hook = {
	.instr_mask = 0xfff00000,
	.instr_val  = 0xd5300000,
	.pstate_mask = PSR_AA32_MODE_MASK,
	.pstate_val = PSR_MODE_EL0t,
	.fn = emulate_mrs,
};

static int __init enable_mrs_emulation(void)
{
	register_undef_hook(&mrs_hook);
	return 0;
}

core_initcall(enable_mrs_emulation);

ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr,
			  char *buf)
{
	if (__meltdown_safe)
		return sprintf(buf, "Not affected\n");

	if (arm64_kernel_unmapped_at_el0())
		return sprintf(buf, "Mitigation: PTI\n");

	return sprintf(buf, "Vulnerable\n");
}