arch/arm64: Supports cluster PMU

Summary:
Some processors implement cluster PMUs, such as Cortex-R82.

Signed-off-by: wangming9 <wangming9@xiaomi.com>
This commit is contained in:
wangming9
2023-06-19 15:00:56 +08:00
committed by GUIDINGLI
parent fa96350574
commit e48b81ebe9
5 changed files with 236 additions and 0 deletions
+14
View File
@@ -156,6 +156,19 @@ config ARCH_HAVE_EL3
runing at EL3 is not necessary and system register for EL3
is not accessible
config ARCH_HAVE_CLUSTER_PMU
bool
default n
---help---
Some processors implement cluster PMUs, such as Cortex-R82
config ARCH_CLUSTER_PMU
bool "Enable the cluster PMUs"
default n
depends on ARCH_HAVE_CLUSTER_PMU
---help---
If the processor supports cluster PMU, can configure cluster PMU
config ARCH_ARM64_EXCEPTION_LEVEL
int "Exception level to operate"
default 1
@@ -253,6 +266,7 @@ config ARCH_CORTEX_R82
select ARCH_ICACHE
select ARCH_HAVE_MPU
select ARCH_HAVE_FPU
select ARCH_HAVE_CLUSTER_PMU
select ARCH_HAVE_TESTSET
select ARM64_HAVE_NEON
+11
View File
@@ -96,6 +96,17 @@
#define SCTLR_SA_BIT BIT(3)
#define SCTLR_I_BIT BIT(12)
#define ACTLR_AUX_BIT BIT(9)
#define ACTLR_CLPORTS_BIT BIT(8)
#define ACTLR_CLPMU_BIT BIT(7)
#define ACTLR_TESTR1_BIT BIT(6)
#define ACTLR_CDBG_BIT BIT(5)
#define ACTLR_PATCH_BIT BIT(4)
#define ACTLR_BPRED_BIT BIT(3)
#define ACTLR_POWER_BIT BIT(2)
#define ACTLR_DIAGNOSTIC_BIT BIT(1)
#define ACTLR_REGIONS_BIT BIT(0)
/* SPSR M[3:0] define
*
* Arm® Architecture Registers Armv8, for Armv8-A architecture profile
+6
View File
@@ -129,6 +129,12 @@ void arm64_boot_el2_init(void)
SCTLR_SA_BIT); /* Enable SP alignment check */
write_sysreg(reg, sctlr_el2);
#ifdef CONFIG_ARCH_CLUSTER_PMU
reg = read_sysreg(actlr_el2);
reg |= ACTLR_CLPMU_BIT;
write_sysreg(reg, actlr_el2);
#endif
reg = read_sysreg(hcr_el2);
reg |= HCR_RW_BIT; /* EL1 Execution state is AArch64 */
write_sysreg(reg, hcr_el2);
+12
View File
@@ -42,11 +42,19 @@ void up_perf_init(void *arg)
{
g_cpu_freq = (unsigned long)(uintptr_t)arg;
#ifdef CONFIG_ARCH_CLUSTER_PMU
pmu_clucntr_control_config(CLUSTERPMCR_EL1_C | CLUSTERPMCR_EL1_P |
CLUSTERPMCR_EL1_E);
pmu_clucntr_ovsclr_config(CLUSTERPMOVSCLR_EL1_C);
pmu_clucntr_irq_disable(CLUSTERPMINTENCLR_EL1_C);
pmu_clucntr_enable(CLUSTERPMCNTENSET_EL1_C);
#else
pmu_ccntr_ccfiltr_config(PMCCFILTR_EL0_NSH);
pmu_cntr_control_config(PMCR_EL0_C | PMCR_EL0_E);
pmu_cntr_trap_control(PMUSERENR_EL0_EN);
pmu_cntr_irq_disable(PMINTENCLR_EL1_C);
pmu_cntr_enable(PMCNTENSET_EL0_C);
#endif
}
unsigned long up_perf_getfreq(void)
@@ -56,7 +64,11 @@ unsigned long up_perf_getfreq(void)
unsigned long up_perf_gettime(void)
{
#ifdef CONFIG_ARCH_CLUSTER_PMU
return pmu_get_cluccntr();
#else
return pmu_get_ccntr();
#endif
}
void up_perf_convert(unsigned long elapsed, struct timespec *ts)
+193
View File
@@ -85,6 +85,41 @@
#define PMUSERENR_EL0_SW (1ul << 1) /* Software Increment write trap control */
#define PMUSERENR_EL0_EN (1ul << 0) /* Software can access all PMU registers at EL0 */
#ifdef CONFIG_ARCH_CLUSTER_PMU
/* The CORTEX-R82 processor implements the cluster PMU */
/* CLUSTERPMCR_EL1 */
#define CLUSTERPMCR_EL1_X (1ul << 4) /* Enable export of events */
#define CLUSTERPMCR_EL1_C (1ul << 2) /* Cycle counter reset */
#define CLUSTERPMCR_EL1_P (1ul << 1) /* Event counter reset */
#define CLUSTERPMCR_EL1_E (1ul << 0) /* All counters that are accessible at Non-secure EL1 are enabled by PMCNTENSET_EL0 */
/* CLUSTERPMCNTENSET_EL1 */
#define CLUSTERPMCNTENSET_EL1_C (1ul << 31) /* Enables the cycle counter register */
/* CLUSTERPMOVSCLR_EL1 */
#define CLUSTERPMOVSCLR_EL1_C (1ul << 31) /* CLUSTERPMCCNTR_EL0 overflow bit */
/* CLUSTERPMSELR_EL1 */
#define CLUSTERPMSELR_EL1_SEL_C (0x1ful << 0) /* When CLUSTERPMSELR_EL0.SEL is 0b11111, it selects the cycle counter */
/* CLUSTERPMINTENCLR_EL1 */
#define CLUSTERPMINTENCLR_EL1_C (1ul << 31) /* CLUSTERPMCCNTR_EL0 overflow interrupt request disable bit */
#define clusterpmcr_el1 s3_0_c15_c5_0
#define clusterpmcntenset_el1 s3_0_c15_c5_1
#define clusterpmovsclr_el1 s3_0_c15_c5_4
#define clusterpmintenclr_el1 s3_0_c15_c5_7
#define clusterpmccntr_el1 s3_0_c15_c6_0
#endif
/****************************************************************************
* Inline Functions
****************************************************************************/
@@ -232,4 +267,162 @@ static inline void pmu_cntr_irq_disable(uint64_t mask)
write_sysreg(mask, pmintenclr_el1);
}
#ifdef CONFIG_ARCH_CLUSTER_PMU
/****************************************************************************
* Name: pmu_get_cluccntr
*
* Description:
* Read cluster cycle counter.
*
* Return Value:
* Cycle count.
*
****************************************************************************/
static inline uint64_t pmu_get_cluccntr(void)
{
return read_sysreg(clusterpmccntr_el1);
}
/****************************************************************************
* Name: pmu_cntr_control_config
*
* Description:
* Config counters.
*
* Parameters:
* mask - Configuration flags for counters.
*
****************************************************************************/
static inline void pmu_clucntr_control_config(uint64_t mask)
{
write_sysreg(mask, clusterpmcr_el1);
}
/****************************************************************************
* Name: pmu_clucntr_enable
*
* Description:
* Enable counters.
*
* Parameters:
* mask - Counters to enable.
*
* Note:
* Enables one or more of the following:
* event counters (0-30)
* cycle counter
*
****************************************************************************/
static inline void pmu_clucntr_enable(uint64_t mask)
{
write_sysreg(mask, clusterpmcntenset_el1);
}
/****************************************************************************
* Name: pmu_clucntr_ovsclr_config
*
* Description:
* Clear counter overflow bits.
*
* Parameters:
* mask - Corresponds to the counter overflow bit to clear.
*
****************************************************************************/
static inline void pmu_clucntr_ovsclr_config(uint64_t mask)
{
write_sysreg(mask, clusterpmovsclr_el1);
}
/****************************************************************************
* Name: pmu_clucntr_select
*
* Description:
* Selects the current event counter or the cycle counter.
*
* Parameters:
* mask - Select counter flag.
*
****************************************************************************/
static inline void pmu_clucntr_select(uint64_t mask)
{
write_sysreg(mask, clusterpmselr_el1);
}
/****************************************************************************
* Name: pmu_clucntr_irq_disable
*
* Description:
* Disable counter overflow interrupt request.
*
* Parameters:
* mask - Counter overflow interrupt request bits to clear.
*
* Note:
* Sets overflow interrupt request bits for one or more of the following:
* event counters (0-30)
* cycle counter
*
****************************************************************************/
static inline void pmu_clucntr_irq_disable(uint64_t mask)
{
write_sysreg(mask, clusterpmintenclr_el1);
}
/****************************************************************************
* Name: pmu_clucntr_get_xevtyper
*
* Description:
* Gets the selected counter type.
*
* Return Value:
* Select the value of the counter type.
*
****************************************************************************/
static inline uint64_t pmu_clucntr_get_xevtyper(void)
{
return read_sysreg(clusterpmxevtyper_el1);
}
/****************************************************************************
* Name: pmu_clucntr_set_xevtyper
*
* Description:
* Sets the selected counter type.
*
* Parameters:
* mask - The value of the type counter.
*
****************************************************************************/
static inline void pmu_clucntr_set_xevtyper(uint64_t mask)
{
write_sysreg(mask, clusterpmxevtyper_el1);
}
/****************************************************************************
* Name: pmu_clucntr_get_xevcntr
*
* Description:
* Reads the value of the selected counter.
*
* Return Value:
* Select the value of the counter.
*
****************************************************************************/
static inline uint64_t pmu_clucntr_get_xevcntr(void)
{
return read_sysreg(clusterpmxevcntr_el1);
}
#endif
#endif /* __ARCH_ARM64_SRC_COMMON_ARM64_PMU_H */