1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <plat/machine/hardware.h> 8#include <arch/user_access.h> 9#include <mode/machine/debug.h> 10 11#define PMUSERENR_ENABLE BIT(0) 12 13#define CNTKCTL_PL0PCTEN BIT(0) 14#define CNTKCTL_PL0VCTEN BIT(1) 15#define CNTKCTL_PL0VTEN BIT(8) 16#define CNTKCTL_PL0PTEN BIT(9) 17 18#define ID_DFR0_PMU_MASK (0xful << 28) 19#define ID_DFR0_PMU_NONE (0xful << 28) 20 21#define ID_PFR1_GENERIC_TIMER BIT(16) 22 23 24 25static void check_export_pmu(void) 26{ 27#if defined CONFIG_EXPORT_PMU_USER || defined CONFIG_ENABLE_BENCHMARKS 28 /* Export performance counters */ 29 uint32_t v; 30 MRC(PMUSERENR, v); 31 v |= PMUSERENR_ENABLE; 32 MCR(PMUSERENR, v); 33 34 /* enable user-level pmu event counter if we're in secure mode */ 35 if (!(readDscrCp() & DBGDSCR_SECURE_MODE_DISABLED)) { 36 MRC(DBGSDER, v); 37 v |= DBGSDER_ENABLE_SECURE_USER_NON_INVASIVE_DEBUG; 38 MCR(DBGSDER, v); 39 } 40#endif 41} 42 43 44static void check_export_arch_timer(void) 45{ 46 uint32_t v = 0; 47#ifdef CONFIG_EXPORT_PCNT_USER 48 v |= CNTKCTL_PL0PCTEN; 49#endif 50#ifdef CONFIG_EXPORT_VCNT_USER 51 v |= CNTKCTL_PL0VCTEN; 52#endif 53 MCR(CNTKCTL, v); 54} 55 56 57void armv_init_user_access(void) 58{ 59 uint32_t v; 60 /* Performance Monitoring Unit */ 61 MRC(ID_DFR0, v); 62 if ((v & ID_DFR0_PMU_MASK) != ID_DFR0_PMU_NONE) { 63 check_export_pmu(); 64 } 65 /* Arch timers */ 66 MRC(ID_PFR1, v); 67 if (v & ID_PFR1_GENERIC_TIMER) { 68 check_export_arch_timer(); 69 } 70} 71 72