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}