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 
check_export_pmu(void)25 static 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 
check_export_arch_timer(void)44 static 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_PTMR_USER
51     v |= CNTKCTL_PL0PTEN;
52 #endif /* CONFIG_EXPORT_PTMR_USER */
53 #ifdef CONFIG_EXPORT_VCNT_USER
54     v |= CNTKCTL_PL0VCTEN;
55 #endif
56 #ifdef CONFIG_EXPORT_VTMR_USER
57     v |= CNTKCTL_PL0VTEN;
58 #endif /* CONFIG_EXPORT_VTMR_USER */
59     MCR(CNTKCTL, v);
60 }
61 
62 
armv_init_user_access(void)63 void armv_init_user_access(void)
64 {
65     uint32_t v;
66     /* Performance Monitoring Unit */
67     MRC(ID_DFR0, v);
68     if ((v & ID_DFR0_PMU_MASK) != ID_DFR0_PMU_NONE) {
69         check_export_pmu();
70     }
71     /* Arch timers */
72     MRC(ID_PFR1, v);
73     if (v & ID_PFR1_GENERIC_TIMER) {
74         check_export_arch_timer();
75     }
76 }
77 
78