- supported.conf: Added sparse_keymap (eeepc_laptop depends on it)
[linux-flexiantxendom0-3.2.10.git] / arch / ia64 / perfmon / perfmon_itanium.c
1 /*
2  * This file contains the Itanium PMU register description tables
3  * and pmc checker used by perfmon.c.
4  *
5  * Copyright (c) 2002-2006 Hewlett-Packard Development Company, L.P.
6  * Contributed by Stephane Eranian <eranian@hpl.hp.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of version 2 of the GNU General Public
10  * License as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21   */
22 #include <linux/module.h>
23 #include <linux/perfmon_kern.h>
24
25 MODULE_AUTHOR("Stephane Eranian <eranian@hpl.hp.com>");
26 MODULE_DESCRIPTION("Itanium (Merced) PMU description tables");
27 MODULE_LICENSE("GPL");
28
29 #define RDEP(x) (1ULL << (x))
30
31 #define PFM_ITA_MASK_PMCS (RDEP(4)|RDEP(5)|RDEP(6)|RDEP(7)|RDEP(10)|RDEP(11)|\
32                            RDEP(12))
33
34 #define PFM_ITA_NO64    (1ULL<<5)
35
36 static struct pfm_arch_pmu_info pfm_ita_pmu_info = {
37         .mask_pmcs = {PFM_ITA_MASK_PMCS,},
38 };
39 /* reserved bits are 1 in the mask */
40 #define PFM_ITA_RSVD 0xfffffffffc8000a0UL
41 /*
42  * For debug registers, writing xBR(y) means we use also xBR(y+1). Hence using
43  * PMC256+y means we use PMC256+y+1.  Yet, we do not have dependency information
44  * but this is fine because they are handled separately in the IA-64 specific
45  * code.
46  */
47 static struct pfm_regmap_desc pfm_ita_pmc_desc[] = {
48 /* pmc0  */ PMX_NA,
49 /* pmc1  */ PMX_NA,
50 /* pmc2  */ PMX_NA,
51 /* pmc3  */ PMX_NA,
52 /* pmc4  */ PMC_D(PFM_REG_W64, "PMC4" , 0x20, PFM_ITA_RSVD, PFM_ITA_NO64, 4),
53 /* pmc5  */ PMC_D(PFM_REG_W64, "PMC5" , 0x20, PFM_ITA_RSVD, PFM_ITA_NO64, 5),
54 /* pmc6  */ PMC_D(PFM_REG_W64, "PMC6" , 0x20, PFM_ITA_RSVD, PFM_ITA_NO64, 6),
55 /* pmc7  */ PMC_D(PFM_REG_W64, "PMC7" , 0x20, PFM_ITA_RSVD, PFM_ITA_NO64, 7),
56 /* pmc8  */ PMC_D(PFM_REG_W  , "PMC8" , 0xfffffffe3ffffff8UL, 0xfff00000001c0000UL, 0, 8),
57 /* pmc9  */ PMC_D(PFM_REG_W  , "PMC9" , 0xfffffffe3ffffff8UL, 0xfff00000001c0000UL, 0, 9),
58 /* pmc10 */ PMC_D(PFM_REG_W  , "PMC10", 0x0, 0xfffffffff3f0ff30UL, 0, 10),
59 /* pmc11 */ PMC_D(PFM_REG_W  , "PMC11", 0x10000000UL, 0xffffffffecf0ff30UL, 0, 11),
60 /* pmc12 */ PMC_D(PFM_REG_W  , "PMC12", 0x0, 0xffffffffffff0030UL, 0, 12),
61 /* pmc13 */ PMC_D(PFM_REG_W  , "PMC13", 0x3ffff00000001UL, 0xfffffffffffffffeUL, 0, 13),
62 /* pmc14 */ PMX_NA,
63 /* pmc15 */ PMX_NA,
64 /* pmc16 */  PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
65 /* pmc24 */  PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
66 /* pmc32 */  PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
67 /* pmc40 */  PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
68 /* pmc48 */  PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
69 /* pmc56 */  PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
70 /* pmc64 */  PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
71 /* pmc72 */  PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
72 /* pmc80 */  PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
73 /* pmc88 */  PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
74 /* pmc96 */  PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
75 /* pmc104 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
76 /* pmc112 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
77 /* pmc120 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
78 /* pmc128 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
79 /* pmc136 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
80 /* pmc144 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
81 /* pmc152 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
82 /* pmc160 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
83 /* pmc168 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
84 /* pmc176 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
85 /* pmc184 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
86 /* pmc192 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
87 /* pmc200 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
88 /* pmc208 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
89 /* pmc216 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
90 /* pmc224 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
91 /* pmc232 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
92 /* pmc240 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
93 /* pmc248 */ PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA, PMX_NA,
94 /* pmc256 */ PMC_D(PFM_REG_W  , "IBR0", 0x0, 0, 0, 0),
95 /* pmc257 */ PMC_D(PFM_REG_W  , "IBR1", 0x0, 0x8000000000000000UL, 0, 1),
96 /* pmc258 */ PMC_D(PFM_REG_W  , "IBR2", 0x0, 0, 0, 2),
97 /* pmc259 */ PMC_D(PFM_REG_W  , "IBR3", 0x0, 0x8000000000000000UL, 0, 3),
98 /* pmc260 */ PMC_D(PFM_REG_W  , "IBR4", 0x0, 0, 0, 4),
99 /* pmc261 */ PMC_D(PFM_REG_W  , "IBR5", 0x0, 0x8000000000000000UL, 0, 5),
100 /* pmc262 */ PMC_D(PFM_REG_W  , "IBR6", 0x0, 0, 0, 6),
101 /* pmc263 */ PMC_D(PFM_REG_W  , "IBR7", 0x0, 0x8000000000000000UL, 0, 7),
102 /* pmc264 */ PMC_D(PFM_REG_W  , "DBR0", 0x0, 0, 0, 0),
103 /* pmc265 */ PMC_D(PFM_REG_W  , "DBR1", 0x0, 0xc000000000000000UL, 0, 1),
104 /* pmc266 */ PMC_D(PFM_REG_W  , "DBR2", 0x0, 0, 0, 2),
105 /* pmc267 */ PMC_D(PFM_REG_W  , "DBR3", 0x0, 0xc000000000000000UL, 0, 3),
106 /* pmc268 */ PMC_D(PFM_REG_W  , "DBR4", 0x0, 0, 0, 4),
107 /* pmc269 */ PMC_D(PFM_REG_W  , "DBR5", 0x0, 0xc000000000000000UL, 0, 5),
108 /* pmc270 */ PMC_D(PFM_REG_W  , "DBR6", 0x0, 0, 0, 6),
109 /* pmc271 */ PMC_D(PFM_REG_W  , "DBR7", 0x0, 0xc000000000000000UL, 0, 7)
110 };
111 #define PFM_ITA_NUM_PMCS ARRAY_SIZE(pfm_ita_pmc_desc)
112
113 static struct pfm_regmap_desc pfm_ita_pmd_desc[] = {
114 /* pmd0  */ PMD_DP(PFM_REG_I , "PMD0", 0, 1ull << 10),
115 /* pmd1  */ PMD_DP(PFM_REG_I , "PMD1", 1, 1ull << 10),
116 /* pmd2  */ PMD_DP(PFM_REG_I , "PMD2", 2, 1ull << 11),
117 /* pmd3  */ PMD_DP(PFM_REG_I , "PMD3", 3, 1ull << 11),
118 /* pmd4  */ PMD_DP(PFM_REG_C , "PMD4", 4, 1ull << 4),
119 /* pmd5  */ PMD_DP(PFM_REG_C , "PMD5", 5, 1ull << 5),
120 /* pmd6  */ PMD_DP(PFM_REG_C , "PMD6", 6, 1ull << 6),
121 /* pmd7  */ PMD_DP(PFM_REG_C , "PMD7", 7, 1ull << 7),
122 /* pmd8  */ PMD_DP(PFM_REG_I , "PMD8", 8, 1ull << 12),
123 /* pmd9  */ PMD_DP(PFM_REG_I , "PMD9", 9, 1ull << 12),
124 /* pmd10 */ PMD_DP(PFM_REG_I , "PMD10", 10, 1ull << 12),
125 /* pmd11 */ PMD_DP(PFM_REG_I , "PMD11", 11, 1ull << 12),
126 /* pmd12 */ PMD_DP(PFM_REG_I , "PMD12", 12, 1ull << 12),
127 /* pmd13 */ PMD_DP(PFM_REG_I , "PMD13", 13, 1ull << 12),
128 /* pmd14 */ PMD_DP(PFM_REG_I , "PMD14", 14, 1ull << 12),
129 /* pmd15 */ PMD_DP(PFM_REG_I , "PMD15", 15, 1ull << 12),
130 /* pmd16 */ PMD_DP(PFM_REG_I , "PMD16", 16, 1ull << 12),
131 /* pmd17 */ PMD_DP(PFM_REG_I , "PMD17", 17, 1ull << 11)
132 };
133 #define PFM_ITA_NUM_PMDS ARRAY_SIZE(pfm_ita_pmd_desc)
134
135 static int pfm_ita_pmc_check(struct pfm_context *ctx,
136                              struct pfm_event_set *set,
137                              struct pfarg_pmc *req)
138 {
139 #define PFM_ITA_PMC_PM_POS6     (1UL<<6)
140         struct pfm_arch_context *ctx_arch;
141         u64 tmpval;
142         u16 cnum;
143         int ret = 0, is_system;
144
145         tmpval = req->reg_value;
146         cnum   = req->reg_num;
147         ctx_arch = pfm_ctx_arch(ctx);
148         is_system = ctx->flags.system;
149
150         switch (cnum) {
151         case  4:
152         case  5:
153         case  6:
154         case  7:
155         case 10:
156         case 11:
157         case 12:
158                 if (is_system)
159                         tmpval |= PFM_ITA_PMC_PM_POS6;
160                 else
161                         tmpval &= ~PFM_ITA_PMC_PM_POS6;
162                 break;
163         }
164
165         /*
166          * we must clear the (instruction) debug registers if pmc13.ta bit is
167          * cleared before they are written (fl_using_dbreg==0) to avoid
168          * picking up stale information.
169          */
170         if (cnum == 13 && ((tmpval & 0x1) == 0)
171                 && ctx_arch->flags.use_dbr == 0) {
172                 PFM_DBG("pmc13 has pmc13.ta cleared, clearing ibr");
173                 ret = pfm_ia64_mark_dbregs_used(ctx, set);
174                 if (ret)
175                         return ret;
176         }
177
178         /*
179          * we must clear the (data) debug registers if pmc11.pt bit is cleared
180          * before they are written (fl_using_dbreg==0) to avoid picking up
181          * stale information.
182          */
183         if (cnum == 11 && ((tmpval >> 28) & 0x1) == 0
184                 && ctx_arch->flags.use_dbr == 0) {
185                 PFM_DBG("pmc11 has pmc11.pt cleared, clearing dbr");
186                 ret = pfm_ia64_mark_dbregs_used(ctx, set);
187                 if (ret)
188                         return ret;
189         }
190
191         req->reg_value = tmpval;
192
193         return 0;
194 }
195
196 static int pfm_ita_probe_pmu(void)
197 {
198         return local_cpu_data->family == 0x7 && !ia64_platform_is("hpsim")
199                 ? 0 : -1;
200 }
201
202 /*
203  * impl_pmcs, impl_pmds are computed at runtime to minimize errors!
204  */
205 static struct pfm_pmu_config pfm_ita_pmu_conf = {
206         .pmu_name = "Itanium",
207         .counter_width = 32,
208         .pmd_desc = pfm_ita_pmd_desc,
209         .pmc_desc = pfm_ita_pmc_desc,
210         .pmc_write_check = pfm_ita_pmc_check,
211         .num_pmc_entries = PFM_ITA_NUM_PMCS,
212         .num_pmd_entries = PFM_ITA_NUM_PMDS,
213         .probe_pmu = pfm_ita_probe_pmu,
214         .version = "1.0",
215         .flags = PFM_PMU_BUILTIN_FLAG,
216         .owner = THIS_MODULE,
217         .pmu_info = &pfm_ita_pmu_info
218 };
219
220 static int __init pfm_ita_pmu_init_module(void)
221 {
222         return pfm_pmu_register(&pfm_ita_pmu_conf);
223 }
224
225 static void __exit pfm_ita_pmu_cleanup_module(void)
226 {
227         pfm_pmu_unregister(&pfm_ita_pmu_conf);
228 }
229
230 module_init(pfm_ita_pmu_init_module);
231 module_exit(pfm_ita_pmu_cleanup_module);
232