perf_event.c (e199e6136ce6b151e6638ae93dca60748424d900) | perf_event.c (51b0fe39549a04858001922919ab355dee9bdfcf) |
---|---|
1/* Performance event support for sparc64. 2 * 3 * Copyright (C) 2009, 2010 David S. Miller <davem@davemloft.net> 4 * 5 * This code is based almost entirely upon the x86 perf event 6 * code, which is: 7 * 8 * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de> --- 1085 unchanged lines hidden (view full) --- 1094 return 0; 1095} 1096 1097/* 1098 * Start group events scheduling transaction 1099 * Set the flag to make pmu::enable() not perform the 1100 * schedulability test, it will be performed at commit time 1101 */ | 1/* Performance event support for sparc64. 2 * 3 * Copyright (C) 2009, 2010 David S. Miller <davem@davemloft.net> 4 * 5 * This code is based almost entirely upon the x86 perf event 6 * code, which is: 7 * 8 * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de> --- 1085 unchanged lines hidden (view full) --- 1094 return 0; 1095} 1096 1097/* 1098 * Start group events scheduling transaction 1099 * Set the flag to make pmu::enable() not perform the 1100 * schedulability test, it will be performed at commit time 1101 */ |
1102static void sparc_pmu_start_txn(const struct pmu *pmu) | 1102static void sparc_pmu_start_txn(struct pmu *pmu) |
1103{ 1104 struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); 1105 1106 cpuhw->group_flag |= PERF_EVENT_TXN; 1107} 1108 1109/* 1110 * Stop group events scheduling transaction 1111 * Clear the flag and pmu::enable() will perform the 1112 * schedulability test. 1113 */ | 1103{ 1104 struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); 1105 1106 cpuhw->group_flag |= PERF_EVENT_TXN; 1107} 1108 1109/* 1110 * Stop group events scheduling transaction 1111 * Clear the flag and pmu::enable() will perform the 1112 * schedulability test. 1113 */ |
1114static void sparc_pmu_cancel_txn(const struct pmu *pmu) | 1114static void sparc_pmu_cancel_txn(struct pmu *pmu) |
1115{ 1116 struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); 1117 1118 cpuhw->group_flag &= ~PERF_EVENT_TXN; 1119} 1120 1121/* 1122 * Commit group events scheduling transaction 1123 * Perform the group schedulability test as a whole 1124 * Return 0 if success 1125 */ | 1115{ 1116 struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); 1117 1118 cpuhw->group_flag &= ~PERF_EVENT_TXN; 1119} 1120 1121/* 1122 * Commit group events scheduling transaction 1123 * Perform the group schedulability test as a whole 1124 * Return 0 if success 1125 */ |
1126static int sparc_pmu_commit_txn(const struct pmu *pmu) | 1126static int sparc_pmu_commit_txn(struct pmu *pmu) |
1127{ 1128 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 1129 int n; 1130 1131 if (!sparc_pmu) 1132 return -EINVAL; 1133 1134 cpuc = &__get_cpu_var(cpu_hw_events); 1135 n = cpuc->n_events; 1136 if (check_excludes(cpuc->event, 0, n)) 1137 return -EINVAL; 1138 if (sparc_check_constraints(cpuc->event, cpuc->events, n)) 1139 return -EAGAIN; 1140 1141 cpuc->group_flag &= ~PERF_EVENT_TXN; 1142 return 0; 1143} 1144 | 1127{ 1128 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 1129 int n; 1130 1131 if (!sparc_pmu) 1132 return -EINVAL; 1133 1134 cpuc = &__get_cpu_var(cpu_hw_events); 1135 n = cpuc->n_events; 1136 if (check_excludes(cpuc->event, 0, n)) 1137 return -EINVAL; 1138 if (sparc_check_constraints(cpuc->event, cpuc->events, n)) 1139 return -EAGAIN; 1140 1141 cpuc->group_flag &= ~PERF_EVENT_TXN; 1142 return 0; 1143} 1144 |
1145static const struct pmu pmu = { | 1145static struct pmu pmu = { |
1146 .enable = sparc_pmu_enable, 1147 .disable = sparc_pmu_disable, 1148 .read = sparc_pmu_read, 1149 .unthrottle = sparc_pmu_unthrottle, 1150 .start_txn = sparc_pmu_start_txn, 1151 .cancel_txn = sparc_pmu_cancel_txn, 1152 .commit_txn = sparc_pmu_commit_txn, 1153}; 1154 | 1146 .enable = sparc_pmu_enable, 1147 .disable = sparc_pmu_disable, 1148 .read = sparc_pmu_read, 1149 .unthrottle = sparc_pmu_unthrottle, 1150 .start_txn = sparc_pmu_start_txn, 1151 .cancel_txn = sparc_pmu_cancel_txn, 1152 .commit_txn = sparc_pmu_commit_txn, 1153}; 1154 |
1155const struct pmu *hw_perf_event_init(struct perf_event *event) | 1155struct pmu *hw_perf_event_init(struct perf_event *event) |
1156{ 1157 int err = __hw_perf_event_init(event); 1158 1159 if (err) 1160 return ERR_PTR(err); 1161 return &pmu; 1162} 1163 --- 114 unchanged lines hidden (view full) --- 1278 pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type); 1279 1280 /* All sparc64 PMUs currently have 2 events. */ 1281 perf_max_events = 2; 1282 1283 register_die_notifier(&perf_event_nmi_notifier); 1284} 1285 | 1156{ 1157 int err = __hw_perf_event_init(event); 1158 1159 if (err) 1160 return ERR_PTR(err); 1161 return &pmu; 1162} 1163 --- 114 unchanged lines hidden (view full) --- 1278 pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type); 1279 1280 /* All sparc64 PMUs currently have 2 events. */ 1281 perf_max_events = 2; 1282 1283 register_die_notifier(&perf_event_nmi_notifier); 1284} 1285 |
1286static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip) | 1286void perf_callchain_kernel(struct perf_callchain_entry *entry, 1287 struct pt_regs *regs) |
1287{ | 1288{ |
1288 if (entry->nr < PERF_MAX_STACK_DEPTH) 1289 entry->ip[entry->nr++] = ip; 1290} 1291 1292static void perf_callchain_kernel(struct pt_regs *regs, 1293 struct perf_callchain_entry *entry) 1294{ | |
1295 unsigned long ksp, fp; 1296#ifdef CONFIG_FUNCTION_GRAPH_TRACER 1297 int graph = 0; 1298#endif 1299 | 1289 unsigned long ksp, fp; 1290#ifdef CONFIG_FUNCTION_GRAPH_TRACER 1291 int graph = 0; 1292#endif 1293 |
1300 callchain_store(entry, PERF_CONTEXT_KERNEL); 1301 callchain_store(entry, regs->tpc); | 1294 stack_trace_flush(); |
1302 | 1295 |
1296 perf_callchain_store(entry, regs->tpc); 1297 |
|
1303 ksp = regs->u_regs[UREG_I6]; 1304 fp = ksp + STACK_BIAS; 1305 do { 1306 struct sparc_stackf *sf; 1307 struct pt_regs *regs; 1308 unsigned long pc; 1309 1310 if (!kstack_valid(current_thread_info(), fp)) --- 6 unchanged lines hidden (view full) --- 1317 if (user_mode(regs)) 1318 break; 1319 pc = regs->tpc; 1320 fp = regs->u_regs[UREG_I6] + STACK_BIAS; 1321 } else { 1322 pc = sf->callers_pc; 1323 fp = (unsigned long)sf->fp + STACK_BIAS; 1324 } | 1298 ksp = regs->u_regs[UREG_I6]; 1299 fp = ksp + STACK_BIAS; 1300 do { 1301 struct sparc_stackf *sf; 1302 struct pt_regs *regs; 1303 unsigned long pc; 1304 1305 if (!kstack_valid(current_thread_info(), fp)) --- 6 unchanged lines hidden (view full) --- 1312 if (user_mode(regs)) 1313 break; 1314 pc = regs->tpc; 1315 fp = regs->u_regs[UREG_I6] + STACK_BIAS; 1316 } else { 1317 pc = sf->callers_pc; 1318 fp = (unsigned long)sf->fp + STACK_BIAS; 1319 } |
1325 callchain_store(entry, pc); | 1320 perf_callchain_store(entry, pc); |
1326#ifdef CONFIG_FUNCTION_GRAPH_TRACER 1327 if ((pc + 8UL) == (unsigned long) &return_to_handler) { 1328 int index = current->curr_ret_stack; 1329 if (current->ret_stack && index >= graph) { 1330 pc = current->ret_stack[index - graph].ret; | 1321#ifdef CONFIG_FUNCTION_GRAPH_TRACER 1322 if ((pc + 8UL) == (unsigned long) &return_to_handler) { 1323 int index = current->curr_ret_stack; 1324 if (current->ret_stack && index >= graph) { 1325 pc = current->ret_stack[index - graph].ret; |
1331 callchain_store(entry, pc); | 1326 perf_callchain_store(entry, pc); |
1332 graph++; 1333 } 1334 } 1335#endif 1336 } while (entry->nr < PERF_MAX_STACK_DEPTH); 1337} 1338 | 1327 graph++; 1328 } 1329 } 1330#endif 1331 } while (entry->nr < PERF_MAX_STACK_DEPTH); 1332} 1333 |
1339static void perf_callchain_user_64(struct pt_regs *regs, 1340 struct perf_callchain_entry *entry) | 1334static void perf_callchain_user_64(struct perf_callchain_entry *entry, 1335 struct pt_regs *regs) |
1341{ 1342 unsigned long ufp; 1343 | 1336{ 1337 unsigned long ufp; 1338 |
1344 callchain_store(entry, PERF_CONTEXT_USER); 1345 callchain_store(entry, regs->tpc); | 1339 perf_callchain_store(entry, regs->tpc); |
1346 1347 ufp = regs->u_regs[UREG_I6] + STACK_BIAS; 1348 do { 1349 struct sparc_stackf *usf, sf; 1350 unsigned long pc; 1351 1352 usf = (struct sparc_stackf *) ufp; 1353 if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) 1354 break; 1355 1356 pc = sf.callers_pc; 1357 ufp = (unsigned long)sf.fp + STACK_BIAS; | 1340 1341 ufp = regs->u_regs[UREG_I6] + STACK_BIAS; 1342 do { 1343 struct sparc_stackf *usf, sf; 1344 unsigned long pc; 1345 1346 usf = (struct sparc_stackf *) ufp; 1347 if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) 1348 break; 1349 1350 pc = sf.callers_pc; 1351 ufp = (unsigned long)sf.fp + STACK_BIAS; |
1358 callchain_store(entry, pc); | 1352 perf_callchain_store(entry, pc); |
1359 } while (entry->nr < PERF_MAX_STACK_DEPTH); 1360} 1361 | 1353 } while (entry->nr < PERF_MAX_STACK_DEPTH); 1354} 1355 |
1362static void perf_callchain_user_32(struct pt_regs *regs, 1363 struct perf_callchain_entry *entry) | 1356static void perf_callchain_user_32(struct perf_callchain_entry *entry, 1357 struct pt_regs *regs) |
1364{ 1365 unsigned long ufp; 1366 | 1358{ 1359 unsigned long ufp; 1360 |
1367 callchain_store(entry, PERF_CONTEXT_USER); 1368 callchain_store(entry, regs->tpc); | 1361 perf_callchain_store(entry, regs->tpc); |
1369 1370 ufp = regs->u_regs[UREG_I6] & 0xffffffffUL; 1371 do { 1372 struct sparc_stackf32 *usf, sf; 1373 unsigned long pc; 1374 1375 usf = (struct sparc_stackf32 *) ufp; 1376 if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) 1377 break; 1378 1379 pc = sf.callers_pc; 1380 ufp = (unsigned long)sf.fp; | 1362 1363 ufp = regs->u_regs[UREG_I6] & 0xffffffffUL; 1364 do { 1365 struct sparc_stackf32 *usf, sf; 1366 unsigned long pc; 1367 1368 usf = (struct sparc_stackf32 *) ufp; 1369 if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) 1370 break; 1371 1372 pc = sf.callers_pc; 1373 ufp = (unsigned long)sf.fp; |
1381 callchain_store(entry, pc); | 1374 perf_callchain_store(entry, pc); |
1382 } while (entry->nr < PERF_MAX_STACK_DEPTH); 1383} 1384 | 1375 } while (entry->nr < PERF_MAX_STACK_DEPTH); 1376} 1377 |
1385/* Like powerpc we can't get PMU interrupts within the PMU handler, 1386 * so no need for separate NMI and IRQ chains as on x86. 1387 */ 1388static DEFINE_PER_CPU(struct perf_callchain_entry, callchain); 1389 1390struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | 1378void 1379perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) |
1391{ | 1380{ |
1392 struct perf_callchain_entry *entry = &__get_cpu_var(callchain); 1393 1394 entry->nr = 0; 1395 if (!user_mode(regs)) { 1396 stack_trace_flush(); 1397 perf_callchain_kernel(regs, entry); 1398 if (current->mm) 1399 regs = task_pt_regs(current); 1400 else 1401 regs = NULL; 1402 } 1403 if (regs) { 1404 flushw_user(); 1405 if (test_thread_flag(TIF_32BIT)) 1406 perf_callchain_user_32(regs, entry); 1407 else 1408 perf_callchain_user_64(regs, entry); 1409 } 1410 return entry; | 1381 flushw_user(); 1382 if (test_thread_flag(TIF_32BIT)) 1383 perf_callchain_user_32(entry, regs); 1384 else 1385 perf_callchain_user_64(entry, regs); |
1411} | 1386} |