static void init_cpu_ftr_reg()

in kernel/cpufeature.c [810:878]


static void init_cpu_ftr_reg(u32 sys_reg, u64 new)
{
	u64 val = 0;
	u64 strict_mask = ~0x0ULL;
	u64 user_mask = 0;
	u64 valid_mask = 0;

	const struct arm64_ftr_bits *ftrp;
	struct arm64_ftr_reg *reg = get_arm64_ftr_reg(sys_reg);

	if (!reg)
		return;

	for (ftrp = reg->ftr_bits; ftrp->width; ftrp++) {
		u64 ftr_mask = arm64_ftr_mask(ftrp);
		s64 ftr_new = arm64_ftr_value(ftrp, new);
		s64 ftr_ovr = arm64_ftr_value(ftrp, reg->override->val);

		if ((ftr_mask & reg->override->mask) == ftr_mask) {
			s64 tmp = arm64_ftr_safe_value(ftrp, ftr_ovr, ftr_new);
			char *str = NULL;

			if (ftr_ovr != tmp) {
				/* Unsafe, remove the override */
				reg->override->mask &= ~ftr_mask;
				reg->override->val &= ~ftr_mask;
				tmp = ftr_ovr;
				str = "ignoring override";
			} else if (ftr_new != tmp) {
				/* Override was valid */
				ftr_new = tmp;
				str = "forced";
			} else if (ftr_ovr == tmp) {
				/* Override was the safe value */
				str = "already set";
			}

			if (str)
				pr_warn("%s[%d:%d]: %s to %llx\n",
					reg->name,
					ftrp->shift + ftrp->width - 1,
					ftrp->shift, str, tmp);
		} else if ((ftr_mask & reg->override->val) == ftr_mask) {
			reg->override->val &= ~ftr_mask;
			pr_warn("%s[%d:%d]: impossible override, ignored\n",
				reg->name,
				ftrp->shift + ftrp->width - 1,
				ftrp->shift);
		}

		val = arm64_ftr_set_value(ftrp, val, ftr_new);

		valid_mask |= ftr_mask;
		if (!ftrp->strict)
			strict_mask &= ~ftr_mask;
		if (ftrp->visible)
			user_mask |= ftr_mask;
		else
			reg->user_val = arm64_ftr_set_value(ftrp,
							    reg->user_val,
							    ftrp->safe_val);
	}

	val &= valid_mask;

	reg->sys_val = val;
	reg->strict_mask = strict_mask;
	reg->user_mask = user_mask;
}