Commit 795a0bba authored by Marc Zyngier's avatar Marc Zyngier
Browse files

KVM: arm64: Add helper for last ditch idreg adjustments



We already have to perform a set of last-chance adjustments for
NV purposes. We will soon have to do the same for the GIC, so
introduce a helper for that exact purpose.

Reviewed-by: default avatarOliver Upton <oliver.upton@linux.dev>
Link: https://lore.kernel.org/r/20240827152517.3909653-5-maz@kernel.org


Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent 8d917e0a
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@
#include <kvm/arm_pmu.h>
#include <kvm/arm_psci.h>

#include "sys_regs.h"

static enum kvm_mode kvm_mode = KVM_MODE_DEFAULT;

enum kvm_wfx_trap_policy {
@@ -821,15 +823,13 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
			return ret;
	}

	if (vcpu_has_nv(vcpu)) {
		ret = kvm_init_nv_sysregs(vcpu->kvm);
	ret = kvm_finalize_sys_regs(vcpu);
	if (ret)
		return ret;
	}

	/*
	 * This needs to happen after NV has imposed its own restrictions on
	 * the feature set
	 * This needs to happen after any restriction has been applied
	 * to the feature set.
	 */
	kvm_calculate_traps(vcpu);

+5 −10
Original line number Diff line number Diff line
@@ -954,19 +954,16 @@ static void set_sysreg_masks(struct kvm *kvm, int sr, u64 res0, u64 res1)
int kvm_init_nv_sysregs(struct kvm *kvm)
{
	u64 res0, res1;
	int ret = 0;

	mutex_lock(&kvm->arch.config_lock);
	lockdep_assert_held(&kvm->arch.config_lock);

	if (kvm->arch.sysreg_masks)
		goto out;
		return 0;

	kvm->arch.sysreg_masks = kzalloc(sizeof(*(kvm->arch.sysreg_masks)),
					 GFP_KERNEL_ACCOUNT);
	if (!kvm->arch.sysreg_masks) {
		ret = -ENOMEM;
		goto out;
	}
	if (!kvm->arch.sysreg_masks)
		return -ENOMEM;

	limit_nv_id_regs(kvm);

@@ -1195,8 +1192,6 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
	if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, V1P1))
		res0 |= ~(res0 | res1);
	set_sysreg_masks(kvm, HAFGRTR_EL2, res0, res1);
out:
	mutex_unlock(&kvm->arch.config_lock);

	return ret;
	return 0;
}
+23 −0
Original line number Diff line number Diff line
@@ -4620,6 +4620,29 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
	mutex_unlock(&kvm->arch.config_lock);
}

/*
 * Perform last adjustments to the ID registers that are implied by the
 * configuration outside of the ID regs themselves, as well as any
 * initialisation that directly depend on these ID registers (such as
 * RES0/RES1 behaviours). This is not the place to configure traps though.
 *
 * Because this can be called once per CPU, changes must be idempotent.
 */
int kvm_finalize_sys_regs(struct kvm_vcpu *vcpu)
{
	struct kvm *kvm = vcpu->kvm;

	guard(mutex)(&kvm->arch.config_lock);

	if (vcpu_has_nv(vcpu)) {
		int ret = kvm_init_nv_sysregs(kvm);
		if (ret)
			return ret;
	}

	return 0;
}

int __init kvm_sys_reg_table_init(void)
{
	bool valid = true;
+2 −0
Original line number Diff line number Diff line
@@ -235,6 +235,8 @@ int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,

bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index);

int kvm_finalize_sys_regs(struct kvm_vcpu *vcpu);

#define AA32(_x)	.aarch32_map = AA32_##_x
#define Op0(_x) 	.Op0 = _x
#define Op1(_x) 	.Op1 = _x