Commit b8e637bf authored by Anshuman Khandual's avatar Anshuman Khandual Committed by Junhao He
Browse files

KVM: arm64: nvhe: Disable branch generation in nVHE guests

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8EC9K
CVE: NA

Reference: https://lore.kernel.org/linux-arm-kernel/20240613061731.3109448-1-anshuman.khandual@arm.com/



--------------------------------

Cc: Marc Zyngier <maz@kernel.org>
Cc: Oliver Upton <oliver.upton@linux.dev>
Cc: James Morse <james.morse@arm.com>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: kvmarm@lists.linux.dev
Cc: linux-arm-kernel@lists.infradead.org
CC: linux-kernel@vger.kernel.org
Signed-off-by: default avatarAnshuman Khandual <anshuman.khandual@arm.com>
Signed-off-by: default avatarJunhao He <hejunhao3@huawei.com>
parent 6c6848e7
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -485,6 +485,7 @@ struct kvm_host_data {
		u64 trfcr_el1;
		/* Values of trap registers for the host before guest entry. */
		u64 mdcr_el2;
		u64 brbcr_el1;
	} host_debug_state;
};

@@ -768,6 +769,8 @@ struct kvm_vcpu_arch {
#define DEBUG_STATE_SAVE_SPE	__vcpu_single_flag(iflags, BIT(5))
/* Save TRBE context if active  */
#define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
/* Save BRBE context if active  */
#define DEBUG_STATE_SAVE_BRBE	__vcpu_single_flag(iflags, BIT(7))

/* SVE enabled for host EL0 */
#define HOST_SVE_ENABLED	__vcpu_single_flag(sflags, BIT(0))
+5 −0
Original line number Diff line number Diff line
@@ -335,10 +335,15 @@ void kvm_arch_vcpu_load_debug_state_flags(struct kvm_vcpu *vcpu)
	if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) &&
	    !(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P))
		vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRBE);

	/* Check if we have BRBE implemented and available at the host */
	if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_BRBE_SHIFT))
		vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_BRBE);
}

void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu)
{
	vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_SPE);
	vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRBE);
	vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_BRBE);
}
+31 −0
Original line number Diff line number Diff line
@@ -79,6 +79,32 @@ static void __debug_restore_trace(u64 trfcr_el1)
	write_sysreg_el1(trfcr_el1, SYS_TRFCR);
}

static void __debug_save_brbe(u64 *brbcr_el1)
{
	*brbcr_el1 = 0;

	/* Check if the BRBE is enabled */
	if (!(read_sysreg_el1(SYS_BRBCR) & (BRBCR_ELx_E0BRE | BRBCR_ELx_ExBRE)))
		return;

	/*
	 * Prohibit branch record generation while we are in guest.
	 * Since access to BRBCR_EL1 is trapped, the guest can't
	 * modify the filtering set by the host.
	 */
	*brbcr_el1 = read_sysreg_el1(SYS_BRBCR);
	write_sysreg_el1(0, SYS_BRBCR);
}

static void __debug_restore_brbe(u64 brbcr_el1)
{
	if (!brbcr_el1)
		return;

	/* Restore BRBE controls */
	write_sysreg_el1(brbcr_el1, SYS_BRBCR);
}

void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu)
{
	/* Disable and flush SPE data generation */
@@ -87,6 +113,9 @@ void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu)
	/* Disable and flush Self-Hosted Trace generation */
	if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE))
		__debug_save_trace(host_data_ptr(host_debug_state.trfcr_el1));
	/* Disable BRBE branch records */
	if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_BRBE))
		__debug_save_brbe(host_data_ptr(host_debug_state.brbcr_el1));
}

void __debug_switch_to_guest(struct kvm_vcpu *vcpu)
@@ -100,6 +129,8 @@ void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu)
		__debug_restore_spe(*host_data_ptr(host_debug_state.pmscr_el1));
	if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE))
		__debug_restore_trace(*host_data_ptr(host_debug_state.trfcr_el1));
	if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_BRBE))
		__debug_restore_brbe(*host_data_ptr(host_debug_state.brbcr_el1));
}

void __debug_switch_to_host(struct kvm_vcpu *vcpu)