Commit 56a824d8 authored by Yicong Yang's avatar Yicong Yang Committed by Yushan Wang
Browse files

perf: Configure BRBE correctly on VHE host

driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBSI0M
CVE: NA

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

The BRBE support backported of v18 didn't configure the BRBCR_EL1
correctly which will miss some key functions like FZP during sampling.

In VHE mode with MDCR_EL2.HPMN set to PMCR_EL0.N, the counters are
controlled by BRBCR_EL1 rather than BRBCR_EL2 (which writes to
BRBCR_EL1 are redirected to). Use the same value for both register
except keep EL1 and EL0 recording disabled in guests.

The fix is backported from the v19 version [1].

[1] https://lore.kernel.org/linux-arm-kernel/


    20250202-arm-brbe-v19-v19-0-1c1300802385@kernel.org/
    T/#m887b1dcf7f6784b7293626952052f27b68784beb

Fixes: 6c6848e7 ("drivers: perf: arm_pmuv3: Enable branch stack sampling via FEAT_BRBE")
Signed-off-by: default avatarYicong Yang <yangyicong@hisilicon.com>
Signed-off-by: default avatarQizhi Zhang <zhangqizhi3@h-partners.com>
parent fa4d5d13
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -874,6 +874,16 @@ void armv8pmu_branch_enable(struct arm_pmu *arm_pmu)
	brbcr &= ~BRBCR_ELx_CONFIG_MASK;
	brbcr |= branch_type_to_brbcr(cpuc->branch_sample_type);
	write_sysreg_s(brbcr, SYS_BRBCR_EL1);

	/*
	 * In VHE mode with MDCR_EL2.HPMN set to PMCR_EL0.N, the counters are
	 * controlled by BRBCR_EL1 rather than BRBCR_EL2 (which writes to
	 * BRBCR_EL1 are redirected to). Use the same value for both register
	 * except keep EL1 and EL0 recording disabled in guests.
	 */
	if (is_kernel_in_hyp_mode())
		write_sysreg_s(brbcr & ~(BRBCR_ELx_ExBRE | BRBCR_ELx_E0BRE), SYS_BRBCR_EL12);

	isb();
}

@@ -886,6 +896,11 @@ void armv8pmu_branch_disable(void)
	brbcr &= ~(BRBCR_ELx_E0BRE | BRBCR_ELx_ExBRE);
	brbfcr |= BRBFCR_EL1_PAUSED;
	write_sysreg_s(brbcr, SYS_BRBCR_EL1);

	/* See the comment in armv8pmu_branch_enable() */
	if (is_kernel_in_hyp_mode())
		write_sysreg_s(brbcr, SYS_BRBCR_EL12);

	write_sysreg_s(brbfcr, SYS_BRBFCR_EL1);
	isb();
}