Commit b4043e7c authored by Sebastian Ott's avatar Sebastian Ott Committed by Oliver Upton
Browse files

KVM: arm64: Maintain per-VM copy of implementation ID regs



Get ready to allow changes to the implementation ID registers by
tracking the VM-wide values.

Signed-off-by: default avatarSebastian Ott <sebott@redhat.com>
Link: https://lore.kernel.org/r/20250225005401.679536-3-oliver.upton@linux.dev


Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parent 4cd48565
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -373,6 +373,9 @@ struct kvm_arch {
#define KVM_ARM_ID_REG_NUM	(IDREG_IDX(sys_reg(3, 0, 0, 7, 7)) + 1)
	u64 id_regs[KVM_ARM_ID_REG_NUM];

	u64 midr_el1;
	u64 revidr_el1;
	u64 aidr_el1;
	u64 ctr_el0;

	/* Masks for VNCR-backed and general EL2 sysregs */
@@ -1459,6 +1462,12 @@ static inline u64 *__vm_id_reg(struct kvm_arch *ka, u32 reg)
		return &ka->id_regs[IDREG_IDX(reg)];
	case SYS_CTR_EL0:
		return &ka->ctr_el0;
	case SYS_MIDR_EL1:
		return &ka->midr_el1;
	case SYS_REVIDR_EL1:
		return &ka->revidr_el1;
	case SYS_AIDR_EL1:
		return &ka->aidr_el1;
	default:
		WARN_ON_ONCE(1);
		return NULL;
+22 −21
Original line number Diff line number Diff line
@@ -1663,15 +1663,24 @@ static bool is_feature_id_reg(u32 encoding)
 * Return true if the register's (Op0, Op1, CRn, CRm, Op2) is
 * (3, 0, 0, crm, op2), where 1<=crm<8, 0<=op2<8, which is the range of ID
 * registers KVM maintains on a per-VM basis.
 *
 * Additionally, the implementation ID registers and CTR_EL0 are handled as
 * per-VM registers.
 */
static inline bool is_vm_ftr_id_reg(u32 id)
{
	if (id == SYS_CTR_EL0)
	switch (id) {
	case SYS_CTR_EL0:
	case SYS_MIDR_EL1:
	case SYS_REVIDR_EL1:
	case SYS_AIDR_EL1:
		return true;

	default:
		return (sys_reg_Op0(id) == 3 && sys_reg_Op1(id) == 0 &&
			sys_reg_CRn(id) == 0 && sys_reg_CRm(id) >= 1 &&
			sys_reg_CRm(id) < 8);

	}
}

static inline bool is_vcpu_ftr_id_reg(u32 id)
@@ -2540,36 +2549,27 @@ static void init_imp_id_regs(void)
	boot_cpu_aidr_val = read_sysreg(aidr_el1);
}

static int get_imp_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
			  u64 *val)
static u64 reset_imp_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
{
	switch (reg_to_encoding(r)) {
	case SYS_MIDR_EL1:
		*val = boot_cpu_midr_val;
		break;
		return boot_cpu_midr_val;
	case SYS_REVIDR_EL1:
		*val = boot_cpu_revidr_val;
		break;
		return boot_cpu_revidr_val;
	case SYS_AIDR_EL1:
		*val = boot_cpu_aidr_val;
		break;
		return boot_cpu_aidr_val;
	default:
		WARN_ON_ONCE(1);
		return -EINVAL;
	}

		KVM_BUG_ON(1, vcpu->kvm);
		return 0;
	}
}

static int set_imp_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
			  u64 val)
{
	u64 expected;
	int ret;

	ret = get_imp_id_reg(vcpu, r, &expected);
	if (ret)
		return ret;
	expected = read_id_reg(vcpu, r);

	return (expected == val) ? 0 : -EINVAL;
}
@@ -2577,8 +2577,9 @@ static int set_imp_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
#define IMPLEMENTATION_ID(reg) {			\
	SYS_DESC(SYS_##reg),				\
	.access = access_imp_id_reg,			\
	.get_user = get_imp_id_reg,			\
	.get_user = get_id_reg,				\
	.set_user = set_imp_id_reg,			\
	.reset = reset_imp_id_reg,			\
}

/*