1 // SPDX-License-Identifier: GPL-2.0 2 #include "debug.h" 3 #include "env.h" 4 #include "lock-contention.h" 5 #include "machine.h" 6 #include "symbol.h" 7 8 #include <limits.h> 9 #include <string.h> 10 11 #include <linux/hash.h> 12 #include <linux/zalloc.h> 13 14 #define __lockhashfn(key) hash_long((unsigned long)key, LOCKHASH_BITS) 15 #define lockhashentry(key) (lockhash_table + __lockhashfn((key))) 16 17 struct callstack_filter { 18 struct list_head list; 19 char name[]; 20 }; 21 22 static LIST_HEAD(callstack_filters); 23 struct hlist_head *lockhash_table; 24 25 int parse_call_stack(const struct option *opt __maybe_unused, const char *str, 26 int unset __maybe_unused) 27 { 28 char *s, *tmp, *tok; 29 int ret = 0; 30 31 s = strdup(str); 32 if (s == NULL) 33 return -1; 34 35 for (tok = strtok_r(s, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) { 36 struct callstack_filter *entry; 37 38 entry = malloc(sizeof(*entry) + strlen(tok) + 1); 39 if (entry == NULL) { 40 pr_err("Memory allocation failure\n"); 41 free(s); 42 return -1; 43 } 44 45 strcpy(entry->name, tok); 46 list_add_tail(&entry->list, &callstack_filters); 47 } 48 49 free(s); 50 return ret; 51 } 52 53 bool needs_callstack(void) 54 { 55 return !list_empty(&callstack_filters); 56 } 57 58 struct lock_stat *lock_stat_find(u64 addr) 59 { 60 struct hlist_head *entry = lockhashentry(addr); 61 struct lock_stat *ret; 62 63 hlist_for_each_entry(ret, entry, hash_entry) { 64 if (ret->addr == addr) 65 return ret; 66 } 67 return NULL; 68 } 69 70 struct lock_stat *lock_stat_findnew(u64 addr, const char *name, int flags) 71 { 72 struct hlist_head *entry = lockhashentry(addr); 73 struct lock_stat *ret, *new; 74 75 hlist_for_each_entry(ret, entry, hash_entry) { 76 if (ret->addr == addr) 77 return ret; 78 } 79 80 new = zalloc(sizeof(struct lock_stat)); 81 if (!new) 82 goto alloc_failed; 83 84 new->addr = addr; 85 new->name = strdup(name); 86 if (!new->name) { 87 free(new); 88 goto alloc_failed; 89 } 90 91 new->flags = flags; 92 new->wait_time_min = ULLONG_MAX; 93 94 hlist_add_head(&new->hash_entry, entry); 95 return new; 96 97 alloc_failed: 98 pr_err("memory allocation failed\n"); 99 return NULL; 100 } 101 102 bool match_callstack_filter(struct machine *machine, u64 *callstack, int max_stack_depth) 103 { 104 struct map *kmap; 105 struct symbol *sym; 106 u64 ip; 107 const char *arch = perf_env__arch(machine->env); 108 109 if (list_empty(&callstack_filters)) 110 return true; 111 112 for (int i = 0; i < max_stack_depth; i++) { 113 struct callstack_filter *filter; 114 115 /* 116 * In powerpc, the callchain saved by kernel always includes 117 * first three entries as the NIP (next instruction pointer), 118 * LR (link register), and the contents of LR save area in the 119 * second stack frame. In certain scenarios its possible to have 120 * invalid kernel instruction addresses in either LR or the second 121 * stack frame's LR. In that case, kernel will store that address as 122 * zero. 123 * 124 * The below check will continue to look into callstack, 125 * incase first or second callstack index entry has 0 126 * address for powerpc. 127 */ 128 if (!callstack || (!callstack[i] && (strcmp(arch, "powerpc") || 129 (i != 1 && i != 2)))) 130 break; 131 132 ip = callstack[i]; 133 sym = machine__find_kernel_symbol(machine, ip, &kmap); 134 if (sym == NULL) 135 continue; 136 137 list_for_each_entry(filter, &callstack_filters, list) { 138 if (strstr(sym->name, filter->name)) 139 return true; 140 } 141 } 142 return false; 143 } 144