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

KVM: arm64: unify code to prepare traps



There are 2 functions to calculate traps via HCR_EL2:
* kvm_init_sysreg() called via KVM_RUN (before the 1st run or when
  the pid changes)
* vcpu_reset_hcr() called via KVM_ARM_VCPU_INIT

To unify these 2 and to support traps that are dependent on the
ID register configuration, move the code from vcpu_reset_hcr()
to sys_regs.c and call it via kvm_init_sysreg().

We still have to keep the non-FWB handling stuff in vcpu_reset_hcr().
Also the initialization with HCR_GUEST_FLAGS is kept there but guarded
by !vcpu_has_run_once() to ensure that previous calculated values
don't get overwritten.

While at it rename kvm_init_sysreg() to kvm_calculate_traps() to
better reflect what it's doing.

Signed-off-by: default avatarSebastian Ott <sebott@redhat.com>
Reviewed-by: default avatarEric Auger <eric.auger@redhat.com>
Link: https://lore.kernel.org/r/20240619174036.483943-7-oliver.upton@linux.dev


Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parent 44241f34
Loading
Loading
Loading
Loading
+9 −31
Original line number Diff line number Diff line
@@ -69,41 +69,19 @@ static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)

static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
{
	if (!vcpu_has_run_once(vcpu))
		vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS;
	if (has_vhe() || has_hvhe())
		vcpu->arch.hcr_el2 |= HCR_E2H;
	if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN)) {
		/* route synchronous external abort exceptions to EL2 */
		vcpu->arch.hcr_el2 |= HCR_TEA;
		/* trap error record accesses */
		vcpu->arch.hcr_el2 |= HCR_TERR;
	}

	if (cpus_have_final_cap(ARM64_HAS_STAGE2_FWB)) {
		vcpu->arch.hcr_el2 |= HCR_FWB;
	} else {
	/*
	 * For non-FWB CPUs, we trap VM ops (HCR_EL2.TVM) until M+C
	 * get set in SCTLR_EL1 such that we can detect when the guest
	 * MMU gets turned on and do the necessary cache maintenance
	 * then.
	 */
	if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
		vcpu->arch.hcr_el2 |= HCR_TVM;
}

	if (cpus_have_final_cap(ARM64_HAS_EVT) &&
	    !cpus_have_final_cap(ARM64_MISMATCHED_CACHE_TYPE))
		vcpu->arch.hcr_el2 |= HCR_TID4;
	else
		vcpu->arch.hcr_el2 |= HCR_TID2;

	if (vcpu_el1_is_32bit(vcpu))
		vcpu->arch.hcr_el2 &= ~HCR_RW;

	if (kvm_has_mte(vcpu->kvm))
		vcpu->arch.hcr_el2 |= HCR_ATA;
}

static inline unsigned long *vcpu_hcr(struct kvm_vcpu *vcpu)
{
	return (unsigned long *)&vcpu->arch.hcr_el2;
+1 −1
Original line number Diff line number Diff line
@@ -1120,7 +1120,7 @@ int __init populate_nv_trap_config(void);
bool lock_all_vcpus(struct kvm *kvm);
void unlock_all_vcpus(struct kvm *kvm);

void kvm_init_sysreg(struct kvm_vcpu *);
void kvm_calculate_traps(struct kvm_vcpu *vcpu);

/* MMIO helpers */
void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+1 −1
Original line number Diff line number Diff line
@@ -797,7 +797,7 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
	 * This needs to happen after NV has imposed its own restrictions on
	 * the feature set
	 */
	kvm_init_sysreg(vcpu);
	kvm_calculate_traps(vcpu);

	ret = kvm_timer_enable(vcpu);
	if (ret)
+32 −2
Original line number Diff line number Diff line
@@ -4069,11 +4069,33 @@ int kvm_vm_ioctl_get_reg_writable_masks(struct kvm *kvm, struct reg_mask_range *
	return 0;
}

void kvm_init_sysreg(struct kvm_vcpu *vcpu)
static void vcpu_set_hcr(struct kvm_vcpu *vcpu)
{
	struct kvm *kvm = vcpu->kvm;

	mutex_lock(&kvm->arch.config_lock);
	if (has_vhe() || has_hvhe())
		vcpu->arch.hcr_el2 |= HCR_E2H;
	if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN)) {
		/* route synchronous external abort exceptions to EL2 */
		vcpu->arch.hcr_el2 |= HCR_TEA;
		/* trap error record accesses */
		vcpu->arch.hcr_el2 |= HCR_TERR;
	}

	if (cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
		vcpu->arch.hcr_el2 |= HCR_FWB;

	if (cpus_have_final_cap(ARM64_HAS_EVT) &&
	    !cpus_have_final_cap(ARM64_MISMATCHED_CACHE_TYPE))
		vcpu->arch.hcr_el2 |= HCR_TID4;
	else
		vcpu->arch.hcr_el2 |= HCR_TID2;

	if (vcpu_el1_is_32bit(vcpu))
		vcpu->arch.hcr_el2 &= ~HCR_RW;

	if (kvm_has_mte(vcpu->kvm))
		vcpu->arch.hcr_el2 |= HCR_ATA;

	/*
	 * In the absence of FGT, we cannot independently trap TLBI
@@ -4082,6 +4104,14 @@ void kvm_init_sysreg(struct kvm_vcpu *vcpu)
	 */
	if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, OS))
		vcpu->arch.hcr_el2 |= HCR_TTLBOS;
}

void kvm_calculate_traps(struct kvm_vcpu *vcpu)
{
	struct kvm *kvm = vcpu->kvm;

	mutex_lock(&kvm->arch.config_lock);
	vcpu_set_hcr(vcpu);

	if (cpus_have_final_cap(ARM64_HAS_HCX)) {
		vcpu->arch.hcrx_el2 = HCRX_GUEST_FLAGS;