From 169f01c8545a68b5f36515c49d171b9e0555ec1b Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 4 Nov 2019 21:54:51 +0000 Subject: [PATCH] arm64: Add performance monitoring unit test command Mostly useful for identifying the interrupts used. Signed-off-by: Andre Przywara --- cmd/Makefile | 1 + cmd/arm_pmu.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 cmd/arm_pmu.c diff --git a/cmd/Makefile b/cmd/Makefile index ac843b4b16..bced333222 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -182,6 +182,7 @@ endif # !CONFIG_SPL_BUILD # core command obj-y += nvedit.o +obj-$(CONFIG_ARM64) += arm_pmu.o obj-$(CONFIG_TI_COMMON_CMD_OPTIONS) += ti/ diff --git a/cmd/arm_pmu.c b/cmd/arm_pmu.c new file mode 100644 index 0000000000..0bc072b2f5 --- /dev/null +++ b/cmd/arm_pmu.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2019 Arm Ltd. + */ + +#include +#include +#include + + +int do_pmuc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + u64 reg; + + if (argc < 2) { + /* PMU control register */ + __asm__ volatile("mrs %0, PMCR_EL0\n" : "=r"(reg)); + printf("PMCR: 0x%llx\n", reg); + /* overflow status register */ + __asm__ volatile("mrs %0, PMOVSCLR_EL0\n" : "=r"(reg)); + printf("PMOVSCLR: 0x%llx\n", reg); + /* counter register */ + __asm__ volatile("mrs %0, PMCCNTR_EL0\n" : "=r"(reg)); + printf("counter: 0x%llx\n", reg); + return CMD_RET_SUCCESS; + } + + if (!strcmp(argv[1], "start")) { + /* enable cycle counting */ + __asm__ volatile("msr PMCNTENSET_EL0, %0\n" :: "r"(BIT(31))); + /* enable overflow interrupt */ + __asm__ volatile("msr PMINTENSET_EL1, %0\n" :: "r"(BIT(31))); + /* allow counting in EL2 */ + __asm__ volatile("msr PMCCFILTR_EL0, %0\n" :: "r"(BIT(27))); + __asm__ volatile("mrs %0, PMCR_EL0\n" : "=r"(reg)); + /* enable PMU */ + reg |= 0x1; + __asm__ volatile("msr PMCR_EL0, %0\n" :: "r"(reg)); + return CMD_RET_SUCCESS; + } + if (!strcmp(argv[1], "reset")) { + /* disable all event and cycle counting */ + __asm__ volatile("msr PMCNTENCLR_EL0, %0\n" :: "r"(0xffffffff)); + /* disable all overflow interrupts */ + __asm__ volatile("msr PMINTENCLR_EL1, %0\n" :: "r"(0xffffffff)); + /* clear all overflow interrupts */ + __asm__ volatile("msr PMOVSCLR_EL0, %0\n" :: "r"(0xffffffff)); + /* clear filter (blocks EL2 counting) */ + __asm__ volatile("msr PMCCFILTR_EL0, %0\n" :: "r"(0)); + __asm__ volatile("mrs %0, PMCR_EL0\n" : "=r"(reg)); + /* disable PMU */ + reg &= ~0x1; + __asm__ volatile("msr PMCR_EL0, %0\n" :: "r"(reg)); + return CMD_RET_SUCCESS; + } + if (!strcmp(argv[1], "stop")) { + __asm__ volatile("mrs %0, PMCR_EL0\n" : "=r"(reg)); + /* disable PMU */ + reg &= ~0x1; + __asm__ volatile("msr PMCR_EL0, %0\n" :: "r"(reg)); + return CMD_RET_SUCCESS; + } + + reg = simple_strtoul(argv[1], NULL, 16); + __asm__ volatile("msr PMCCNTR_EL0, %0\n" :: "r" (reg)); + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + pmuc, 2, 1, do_pmuc, + "test the ARM performance monitoring unit", + "(no argument): print the cycle counter, PMCR and overflow status\n" + " start: enable the cycle counter and interrupts\n" + " stop: disable the cycle counter and interrupts\n" + " reset: reset the PMU\n" + " : set the cycle counter\n" +); -- 2.14.5