aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/ftrace.c239
1 files changed, 84 insertions, 155 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index e43c793093e5..d325a1e76554 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1373,6 +1373,21 @@ update:
1373 return 0; 1373 return 0;
1374} 1374}
1375 1375
1376static bool hash_contains_ip(unsigned long ip,
1377 struct ftrace_ops_hash *hash)
1378{
1379 /*
1380 * The function record is a match if it exists in the filter
1381 * hash and not in the notrace hash. Note, an emty hash is
1382 * considered a match for the filter hash, but an empty
1383 * notrace hash is considered not in the notrace hash.
1384 */
1385 return (ftrace_hash_empty(hash->filter_hash) ||
1386 ftrace_lookup_ip(hash->filter_hash, ip)) &&
1387 (ftrace_hash_empty(hash->notrace_hash) ||
1388 !ftrace_lookup_ip(hash->notrace_hash, ip));
1389}
1390
1376/* 1391/*
1377 * Test the hashes for this ops to see if we want to call 1392 * Test the hashes for this ops to see if we want to call
1378 * the ops->func or not. 1393 * the ops->func or not.
@@ -1388,8 +1403,7 @@ update:
1388static int 1403static int
1389ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs) 1404ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs)
1390{ 1405{
1391 struct ftrace_hash *filter_hash; 1406 struct ftrace_ops_hash hash;
1392 struct ftrace_hash *notrace_hash;
1393 int ret; 1407 int ret;
1394 1408
1395#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS 1409#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
@@ -1402,13 +1416,10 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs)
1402 return 0; 1416 return 0;
1403#endif 1417#endif
1404 1418
1405 filter_hash = rcu_dereference_raw_notrace(ops->func_hash->filter_hash); 1419 hash.filter_hash = rcu_dereference_raw_notrace(ops->func_hash->filter_hash);
1406 notrace_hash = rcu_dereference_raw_notrace(ops->func_hash->notrace_hash); 1420 hash.notrace_hash = rcu_dereference_raw_notrace(ops->func_hash->notrace_hash);
1407 1421
1408 if ((ftrace_hash_empty(filter_hash) || 1422 if (hash_contains_ip(ip, &hash))
1409 ftrace_lookup_ip(filter_hash, ip)) &&
1410 (ftrace_hash_empty(notrace_hash) ||
1411 !ftrace_lookup_ip(notrace_hash, ip)))
1412 ret = 1; 1423 ret = 1;
1413 else 1424 else
1414 ret = 0; 1425 ret = 0;
@@ -1520,46 +1531,6 @@ static bool test_rec_ops_needs_regs(struct dyn_ftrace *rec)
1520 return keep_regs; 1531 return keep_regs;
1521} 1532}
1522 1533
1523static void ftrace_remove_tramp(struct ftrace_ops *ops,
1524 struct dyn_ftrace *rec)
1525{
1526 /* If TRAMP is not set, no ops should have a trampoline for this */
1527 if (!(rec->flags & FTRACE_FL_TRAMP))
1528 return;
1529
1530 rec->flags &= ~FTRACE_FL_TRAMP;
1531
1532 if ((!ftrace_hash_empty(ops->func_hash->filter_hash) &&
1533 !ftrace_lookup_ip(ops->func_hash->filter_hash, rec->ip)) ||
1534 ftrace_lookup_ip(ops->func_hash->notrace_hash, rec->ip))
1535 return;
1536 /*
1537 * The tramp_hash entry will be removed at time
1538 * of update.
1539 */
1540 ops->nr_trampolines--;
1541}
1542
1543static void ftrace_clear_tramps(struct dyn_ftrace *rec, struct ftrace_ops *ops)
1544{
1545 struct ftrace_ops *op;
1546
1547 /* If TRAMP is not set, no ops should have a trampoline for this */
1548 if (!(rec->flags & FTRACE_FL_TRAMP))
1549 return;
1550
1551 do_for_each_ftrace_op(op, ftrace_ops_list) {
1552 /*
1553 * This function is called to clear other tramps
1554 * not the one that is being updated.
1555 */
1556 if (op == ops)
1557 continue;
1558 if (op->nr_trampolines)
1559 ftrace_remove_tramp(op, rec);
1560 } while_for_each_ftrace_op(op);
1561}
1562
1563static void __ftrace_hash_rec_update(struct ftrace_ops *ops, 1534static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
1564 int filter_hash, 1535 int filter_hash,
1565 bool inc) 1536 bool inc)
@@ -1648,18 +1619,16 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
1648 * function, and the ops has a trampoline registered 1619 * function, and the ops has a trampoline registered
1649 * for it, then we can call it directly. 1620 * for it, then we can call it directly.
1650 */ 1621 */
1651 if (ftrace_rec_count(rec) == 1 && ops->trampoline) { 1622 if (ftrace_rec_count(rec) == 1 && ops->trampoline)
1652 rec->flags |= FTRACE_FL_TRAMP; 1623 rec->flags |= FTRACE_FL_TRAMP;
1653 ops->nr_trampolines++; 1624 else
1654 } else {
1655 /* 1625 /*
1656 * If we are adding another function callback 1626 * If we are adding another function callback
1657 * to this function, and the previous had a 1627 * to this function, and the previous had a
1658 * custom trampoline in use, then we need to go 1628 * custom trampoline in use, then we need to go
1659 * back to the default trampoline. 1629 * back to the default trampoline.
1660 */ 1630 */
1661 ftrace_clear_tramps(rec, ops); 1631 rec->flags &= ~FTRACE_FL_TRAMP;
1662 }
1663 1632
1664 /* 1633 /*
1665 * If any ops wants regs saved for this function 1634 * If any ops wants regs saved for this function
@@ -1672,9 +1641,6 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
1672 return; 1641 return;
1673 rec->flags--; 1642 rec->flags--;
1674 1643
1675 if (ops->trampoline && !ftrace_rec_count(rec))
1676 ftrace_remove_tramp(ops, rec);
1677
1678 /* 1644 /*
1679 * If the rec had REGS enabled and the ops that is 1645 * If the rec had REGS enabled and the ops that is
1680 * being removed had REGS set, then see if there is 1646 * being removed had REGS set, then see if there is
@@ -1689,6 +1655,17 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
1689 } 1655 }
1690 1656
1691 /* 1657 /*
1658 * If the rec had TRAMP enabled, then it needs to
1659 * be cleared. As TRAMP can only be enabled iff
1660 * there is only a single ops attached to it.
1661 * In otherwords, always disable it on decrementing.
1662 * In the future, we may set it if rec count is
1663 * decremented to one, and the ops that is left
1664 * has a trampoline.
1665 */
1666 rec->flags &= ~FTRACE_FL_TRAMP;
1667
1668 /*
1692 * flags will be cleared in ftrace_check_record() 1669 * flags will be cleared in ftrace_check_record()
1693 * if rec count is zero. 1670 * if rec count is zero.
1694 */ 1671 */
@@ -1910,15 +1887,14 @@ static struct ftrace_ops *
1910ftrace_find_tramp_ops_any(struct dyn_ftrace *rec) 1887ftrace_find_tramp_ops_any(struct dyn_ftrace *rec)
1911{ 1888{
1912 struct ftrace_ops *op; 1889 struct ftrace_ops *op;
1890 unsigned long ip = rec->ip;
1913 1891
1914 do_for_each_ftrace_op(op, ftrace_ops_list) { 1892 do_for_each_ftrace_op(op, ftrace_ops_list) {
1915 1893
1916 if (!op->trampoline) 1894 if (!op->trampoline)
1917 continue; 1895 continue;
1918 1896
1919 if (ftrace_lookup_ip(op->func_hash->filter_hash, rec->ip) && 1897 if (hash_contains_ip(ip, op->func_hash))
1920 (ftrace_hash_empty(op->func_hash->notrace_hash) ||
1921 !ftrace_lookup_ip(op->func_hash->notrace_hash, rec->ip)))
1922 return op; 1898 return op;
1923 } while_for_each_ftrace_op(op); 1899 } while_for_each_ftrace_op(op);
1924 1900
@@ -1929,18 +1905,51 @@ static struct ftrace_ops *
1929ftrace_find_tramp_ops_curr(struct dyn_ftrace *rec) 1905ftrace_find_tramp_ops_curr(struct dyn_ftrace *rec)
1930{ 1906{
1931 struct ftrace_ops *op; 1907 struct ftrace_ops *op;
1908 unsigned long ip = rec->ip;
1932 1909
1933 /* Removed ops need to be tested first */ 1910 /*
1934 if (removed_ops && removed_ops->tramp_hash) { 1911 * Need to check removed ops first.
1935 if (ftrace_lookup_ip(removed_ops->tramp_hash, rec->ip)) 1912 * If they are being removed, and this rec has a tramp,
1913 * and this rec is in the ops list, then it would be the
1914 * one with the tramp.
1915 */
1916 if (removed_ops) {
1917 if (hash_contains_ip(ip, &removed_ops->old_hash))
1936 return removed_ops; 1918 return removed_ops;
1937 } 1919 }
1938 1920
1921 /*
1922 * Need to find the current trampoline for a rec.
1923 * Now, a trampoline is only attached to a rec if there
1924 * was a single 'ops' attached to it. But this can be called
1925 * when we are adding another op to the rec or removing the
1926 * current one. Thus, if the op is being added, we can
1927 * ignore it because it hasn't attached itself to the rec
1928 * yet. That means we just need to find the op that has a
1929 * trampoline and is not beeing added.
1930 */
1939 do_for_each_ftrace_op(op, ftrace_ops_list) { 1931 do_for_each_ftrace_op(op, ftrace_ops_list) {
1940 if (!op->tramp_hash) 1932
1933 if (!op->trampoline)
1934 continue;
1935
1936 /*
1937 * If the ops is being added, it hasn't gotten to
1938 * the point to be removed from this tree yet.
1939 */
1940 if (op->flags & FTRACE_OPS_FL_ADDING)
1941 continue; 1941 continue;
1942 1942
1943 if (ftrace_lookup_ip(op->tramp_hash, rec->ip)) 1943 /*
1944 * If the ops is not being added and has a trampoline,
1945 * then it must be the one that we want!
1946 */
1947 if (hash_contains_ip(ip, op->func_hash))
1948 return op;
1949
1950 /* If the ops is being modified, it may be in the old hash. */
1951 if ((op->flags & FTRACE_OPS_FL_MODIFYING) &&
1952 hash_contains_ip(ip, &op->old_hash))
1944 return op; 1953 return op;
1945 1954
1946 } while_for_each_ftrace_op(op); 1955 } while_for_each_ftrace_op(op);
@@ -1952,10 +1961,11 @@ static struct ftrace_ops *
1952ftrace_find_tramp_ops_new(struct dyn_ftrace *rec) 1961ftrace_find_tramp_ops_new(struct dyn_ftrace *rec)
1953{ 1962{
1954 struct ftrace_ops *op; 1963 struct ftrace_ops *op;
1964 unsigned long ip = rec->ip;
1955 1965
1956 do_for_each_ftrace_op(op, ftrace_ops_list) { 1966 do_for_each_ftrace_op(op, ftrace_ops_list) {
1957 /* pass rec in as regs to have non-NULL val */ 1967 /* pass rec in as regs to have non-NULL val */
1958 if (ftrace_ops_test(op, rec->ip, rec)) 1968 if (hash_contains_ip(ip, op->func_hash))
1959 return op; 1969 return op;
1960 } while_for_each_ftrace_op(op); 1970 } while_for_each_ftrace_op(op);
1961 1971
@@ -2262,92 +2272,6 @@ void __weak arch_ftrace_update_code(int command)
2262 ftrace_run_stop_machine(command); 2272 ftrace_run_stop_machine(command);
2263} 2273}
2264 2274
2265static int ftrace_save_ops_tramp_hash(struct ftrace_ops *ops)
2266{
2267 struct ftrace_page *pg;
2268 struct dyn_ftrace *rec;
2269 int size, bits;
2270 int ret;
2271
2272 size = ops->nr_trampolines;
2273 bits = 0;
2274 /*
2275 * Make the hash size about 1/2 the # found
2276 */
2277 for (size /= 2; size; size >>= 1)
2278 bits++;
2279
2280 ops->tramp_hash = alloc_ftrace_hash(bits);
2281 /*
2282 * TODO: a failed allocation is going to screw up
2283 * the accounting of what needs to be modified
2284 * and not. For now, we kill ftrace if we fail
2285 * to allocate here. But there are ways around this,
2286 * but that will take a little more work.
2287 */
2288 if (!ops->tramp_hash)
2289 return -ENOMEM;
2290
2291 do_for_each_ftrace_rec(pg, rec) {
2292 if (ftrace_rec_count(rec) == 1 &&
2293 ftrace_ops_test(ops, rec->ip, rec)) {
2294
2295 /*
2296 * If another ops adds to a rec, the rec will
2297 * lose its trampoline and never get it back
2298 * until all ops are off of it.
2299 */
2300 if (!(rec->flags & FTRACE_FL_TRAMP))
2301 continue;
2302
2303 /* This record had better have a trampoline */
2304 if (FTRACE_WARN_ON(!(rec->flags & FTRACE_FL_TRAMP_EN)))
2305 return -1;
2306
2307 ret = add_hash_entry(ops->tramp_hash, rec->ip);
2308 if (ret < 0)
2309 return ret;
2310 }
2311 } while_for_each_ftrace_rec();
2312
2313 /* The number of recs in the hash must match nr_trampolines */
2314 if (FTRACE_WARN_ON(ops->tramp_hash->count != ops->nr_trampolines))
2315 pr_warn("count=%ld trampolines=%d\n",
2316 ops->tramp_hash->count,
2317 ops->nr_trampolines);
2318
2319 return 0;
2320}
2321
2322static int ftrace_save_tramp_hashes(void)
2323{
2324 struct ftrace_ops *op;
2325 int ret;
2326
2327 /*
2328 * Now that any trampoline is being used, we need to save the
2329 * hashes for the ops that have them. This allows the mapping
2330 * back from the record to the ops that has the trampoline to
2331 * know what code is being replaced. Modifying code must always
2332 * verify what it is changing.
2333 */
2334 do_for_each_ftrace_op(op, ftrace_ops_list) {
2335
2336 /* The tramp_hash is recreated each time. */
2337 free_ftrace_hash(op->tramp_hash);
2338 op->tramp_hash = NULL;
2339
2340 if (op->nr_trampolines) {
2341 ret = ftrace_save_ops_tramp_hash(op);
2342 if (ret)
2343 return ret;
2344 }
2345
2346 } while_for_each_ftrace_op(op);
2347
2348 return 0;
2349}
2350
2351static void ftrace_run_update_code(int command) 2275static void ftrace_run_update_code(int command)
2352{ 2276{
2353 int ret; 2277 int ret;
@@ -2367,9 +2291,6 @@ static void ftrace_run_update_code(int command)
2367 2291
2368 ret = ftrace_arch_code_modify_post_process(); 2292 ret = ftrace_arch_code_modify_post_process();
2369 FTRACE_WARN_ON(ret); 2293 FTRACE_WARN_ON(ret);
2370
2371 ret = ftrace_save_tramp_hashes();
2372 FTRACE_WARN_ON(ret);
2373} 2294}
2374 2295
2375static void ftrace_run_modify_code(struct ftrace_ops *ops, int command) 2296static void ftrace_run_modify_code(struct ftrace_ops *ops, int command)
@@ -2489,8 +2410,16 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)
2489 ops->flags |= FTRACE_OPS_FL_REMOVING; 2410 ops->flags |= FTRACE_OPS_FL_REMOVING;
2490 removed_ops = ops; 2411 removed_ops = ops;
2491 2412
2413 /* The trampoline logic checks the old hashes */
2414 ops->old_hash.filter_hash = ops->func_hash->filter_hash;
2415 ops->old_hash.notrace_hash = ops->func_hash->notrace_hash;
2416
2492 ftrace_run_update_code(command); 2417 ftrace_run_update_code(command);
2493 2418
2419 ops->old_hash.filter_hash = NULL;
2420 ops->old_hash.notrace_hash = NULL;
2421
2422 removed_ops = NULL;
2494 ops->flags &= ~FTRACE_OPS_FL_REMOVING; 2423 ops->flags &= ~FTRACE_OPS_FL_REMOVING;
2495 2424
2496 /* 2425 /*
@@ -3017,7 +2946,7 @@ static int t_show(struct seq_file *m, void *v)
3017 struct ftrace_ops *ops; 2946 struct ftrace_ops *ops;
3018 2947
3019 ops = ftrace_find_tramp_ops_any(rec); 2948 ops = ftrace_find_tramp_ops_any(rec);
3020 if (ops && ops->trampoline) 2949 if (ops)
3021 seq_printf(m, "\ttramp: %pS", 2950 seq_printf(m, "\ttramp: %pS",
3022 (void *)ops->trampoline); 2951 (void *)ops->trampoline);
3023 else 2952 else