Commit 1d6fea76 authored by Marc Zyngier's avatar Marc Zyngier Committed by Oliver Upton
Browse files

KVM: arm64: Add helper to identify a nested context



A common idiom in the KVM code is to check if we are currently
dealing with a "nested" context, defined as having NV enabled,
but being in the EL1&0 translation regime.

This is usually expressed as:

	if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu) ... )

which is a mouthful and a bit hard to read, specially when followed
by additional conditions.

Introduce a new helper that encapsulate these two terms, allowing
the above to be written as

	if (is_nested_context(vcpu) ... )

which is both shorter and easier to read, and makes more obvious
the potential for simplification on some code paths.

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Reviewed-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250708172532.1699409-4-oliver.upton@linux.dev


Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parent e3fd6662
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -224,6 +224,11 @@ static inline bool vcpu_is_host_el0(const struct kvm_vcpu *vcpu)
	return is_hyp_ctxt(vcpu) && !vcpu_is_el2(vcpu);
}

static inline bool is_nested_ctxt(struct kvm_vcpu *vcpu)
{
	return vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu);
}

/*
 * The layout of SPSR for an AArch32 state is different when observed from an
 * AArch64 SPSR_ELx or an AArch32 SPSR_*. This function generates the AArch32
+1 −1
Original line number Diff line number Diff line
@@ -830,7 +830,7 @@ static void timer_set_traps(struct kvm_vcpu *vcpu, struct timer_map *map)
	 * by the guest (either FEAT_VHE or FEAT_E2H0 is implemented, but
	 * not both). This simplifies the handling of the EL1NV* bits.
	 */
	if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
	if (is_nested_ctxt(vcpu)) {
		u64 val = __vcpu_sys_reg(vcpu, CNTHCTL_EL2);

		/* Use the VHE format for mental sanity */
+1 −1
Original line number Diff line number Diff line
@@ -521,7 +521,7 @@ static void vcpu_set_pauth_traps(struct kvm_vcpu *vcpu)
		 * Either we're running an L2 guest, and the API/APK bits come
		 * from L1's HCR_EL2, or API/APK are both set.
		 */
		if (unlikely(vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu))) {
		if (unlikely(is_nested_ctxt(vcpu))) {
			u64 val;

			val = __vcpu_sys_reg(vcpu, HCR_EL2);
+2 −7
Original line number Diff line number Diff line
@@ -2592,13 +2592,8 @@ bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index)

static bool __forward_traps(struct kvm_vcpu *vcpu, unsigned int reg, u64 control_bit)
{
	bool control_bit_set;

	if (!vcpu_has_nv(vcpu))
		return false;

	control_bit_set = __vcpu_sys_reg(vcpu, reg) & control_bit;
	if (!is_hyp_ctxt(vcpu) && control_bit_set) {
	if (is_nested_ctxt(vcpu) &&
	    (__vcpu_sys_reg(vcpu, reg) & control_bit)) {
		kvm_inject_nested_sync(vcpu, kvm_vcpu_get_esr(vcpu));
		return true;
	}
+7 −13
Original line number Diff line number Diff line
@@ -252,7 +252,7 @@ static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu)
		return 1;
	}

	if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
	if (is_nested_ctxt(vcpu)) {
		kvm_inject_nested_sync(vcpu, kvm_vcpu_get_esr(vcpu));
		return 1;
	}
@@ -311,12 +311,11 @@ static int kvm_handle_gcs(struct kvm_vcpu *vcpu)

static int handle_other(struct kvm_vcpu *vcpu)
{
	bool is_l2 = vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu);
	bool allowed, fwd = is_nested_ctxt(vcpu);
	u64 hcrx = __vcpu_sys_reg(vcpu, HCRX_EL2);
	u64 esr = kvm_vcpu_get_esr(vcpu);
	u64 iss = ESR_ELx_ISS(esr);
	struct kvm *kvm = vcpu->kvm;
	bool allowed, fwd = false;

	/*
	 * We only trap for two reasons:
@@ -335,28 +334,23 @@ static int handle_other(struct kvm_vcpu *vcpu)
	switch (iss) {
	case ESR_ELx_ISS_OTHER_ST64BV:
		allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_V);
		if (is_l2)
			fwd = !(hcrx & HCRX_EL2_EnASR);
		fwd &= !(hcrx & HCRX_EL2_EnASR);
		break;
	case ESR_ELx_ISS_OTHER_ST64BV0:
		allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA);
		if (is_l2)
			fwd = !(hcrx & HCRX_EL2_EnAS0);
		fwd &= !(hcrx & HCRX_EL2_EnAS0);
		break;
	case ESR_ELx_ISS_OTHER_LDST64B:
		allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64);
		if (is_l2)
			fwd = !(hcrx & HCRX_EL2_EnALS);
		fwd &= !(hcrx & HCRX_EL2_EnALS);
		break;
	case ESR_ELx_ISS_OTHER_TSBCSYNC:
		allowed = kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceBuffer, TRBE_V1P1);
		if (is_l2)
			fwd = (__vcpu_sys_reg(vcpu, HFGITR2_EL2) & HFGITR2_EL2_TSBCSYNC);
		fwd &= (__vcpu_sys_reg(vcpu, HFGITR2_EL2) & HFGITR2_EL2_TSBCSYNC);
		break;
	case ESR_ELx_ISS_OTHER_PSBCSYNC:
		allowed = kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMSVer, V1P5);
		if (is_l2)
			fwd = (__vcpu_sys_reg(vcpu, HFGITR_EL2) & HFGITR_EL2_PSBCSYNC);
		fwd &= (__vcpu_sys_reg(vcpu, HFGITR_EL2) & HFGITR_EL2_PSBCSYNC);
		break;
	default:
		/* Clearly, we're missing something. */
Loading