Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'perf-tools-for-v5.14-2021-07-10' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull more perf tool updates from Arnaldo Carvalho de Melo:
"New features:

- Enable use of BPF counters with 'perf stat --for-each-cgroup',
using per-CPU 'cgroup-switch' events with an attached BPF program
that does aggregation per-cgroup in the kernel instead of using
per-cgroup perf events.

- Add Topdown metrics L2 events as default events in 'perf stat' for
systems having those events.

Hardware tracing:

- Add a config for max loops without consuming a packet in the Intel
PT packet decoder, set via 'perf config intel-pt.max-loops=N'

Hardware enablement:

- Disable misleading NMI watchdog message in 'perf stat' on hybrid
systems such as Intel Alder Lake.

- Add a dummy event on hybrid systems to collect metadata records.

- Add 24x7 nest metric events for the Power10 platform.

Fixes:

- Fix event parsing for PMUs starting with the same prefix.

- Fix the 'perf trace' 'trace' alias installation dir.

- Fix buffer size to report iregs in perf script python scripts,
supporting the extended registers in PowerPC.

- Fix overflow in elf_sec__is_text().

- Fix 's' on source line when disasm is empty in the annotation TUI,
accessible via 'perf annotate', 'perf report' and 'perf top'.

- Plug leaks in scandir() returned dirent entries in 'perf test' when
sorting the shell tests.

- Fix --task and --stat with pipe input in 'perf report'.

- Fix 'perf probe' use of debuginfo files by build id.

- If a DSO has both dynsym and symtab ELF sections, read from both
when loading the symbol table, fixing a problem processing Fedora
32 glibc DSOs.

Libraries:

- Add grouping of events to libperf, from code in tools/perf,
allowing libperf users to use that mode.

Misc:

- Filter plt stubs from the 'perf probe --functions' output.

- Update UAPI header copies for asound, DRM, mman-common.h and the
ones affected by the quotactl_fd syscall"

* tag 'perf-tools-for-v5.14-2021-07-10' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux: (29 commits)
perf test: Add free() calls for scandir() returned dirent entries
libperf: Add tests for perf_evlist__set_leader()
libperf: Remove BUG_ON() from library code in get_group_fd()
libperf: Add group support to perf_evsel__open()
perf tools: Fix pattern matching for same substring in different PMU type
perf record: Add a dummy event on hybrid systems to collect metadata records
perf stat: Add Topdown metrics L2 events as default events
libperf: Adopt evlist__set_leader() from tools/perf as perf_evlist__set_leader()
libperf: Move 'nr_groups' from tools/perf to evlist::nr_groups
libperf: Move 'leader' from tools/perf to perf_evsel::leader
libperf: Move 'idx' from tools/perf to perf_evsel::idx
libperf: Change tests to single static and shared binaries
perf intel-pt: Add a config for max loops without consuming a packet
perf stat: Disable the NMI watchdog message on hybrid
perf vendor events power10: Adds 24x7 nest metric events for power10 platform
perf script python: Fix buffer size to report iregs in perf script
perf trace: Fix the perf trace link location
perf top: Fix overflow in elf_sec__is_text()
perf annotate: Fix 's' on source line when disasm is empty
perf probe: Do not show @plt function by default
...

+1872 -331
+3
tools/include/uapi/asm-generic/mman-common.h
··· 72 72 #define MADV_COLD 20 /* deactivate these pages */ 73 73 #define MADV_PAGEOUT 21 /* reclaim these pages */ 74 74 75 + #define MADV_POPULATE_READ 22 /* populate (prefault) page tables readable */ 76 + #define MADV_POPULATE_WRITE 23 /* populate (prefault) page tables writable */ 77 + 75 78 /* compatibility flags */ 76 79 #define MAP_FILE 0 77 80
+2 -1
tools/include/uapi/asm-generic/unistd.h
··· 863 863 __SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2) 864 864 #define __NR_mount_setattr 442 865 865 __SYSCALL(__NR_mount_setattr, sys_mount_setattr) 866 - /* 443 is reserved for quotactl_path */ 866 + #define __NR_quotactl_fd 443 867 + __SYSCALL(__NR_quotactl_fd, sys_quotactl_fd) 867 868 868 869 #define __NR_landlock_create_ruleset 444 869 870 __SYSCALL(__NR_landlock_create_ruleset, sys_landlock_create_ruleset)
+24 -4
tools/include/uapi/drm/drm.h
··· 777 777 /** 778 778 * DRM_CLIENT_CAP_STEREO_3D 779 779 * 780 - * if set to 1, the DRM core will expose the stereo 3D capabilities of the 780 + * If set to 1, the DRM core will expose the stereo 3D capabilities of the 781 781 * monitor by advertising the supported 3D layouts in the flags of struct 782 - * drm_mode_modeinfo. 782 + * drm_mode_modeinfo. See ``DRM_MODE_FLAG_3D_*``. 783 + * 784 + * This capability is always supported for all drivers starting from kernel 785 + * version 3.13. 783 786 */ 784 787 #define DRM_CLIENT_CAP_STEREO_3D 1 785 788 ··· 791 788 * 792 789 * If set to 1, the DRM core will expose all planes (overlay, primary, and 793 790 * cursor) to userspace. 791 + * 792 + * This capability has been introduced in kernel version 3.15. Starting from 793 + * kernel version 3.17, this capability is always supported for all drivers. 794 794 */ 795 795 #define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 796 796 ··· 803 797 * If set to 1, the DRM core will expose atomic properties to userspace. This 804 798 * implicitly enables &DRM_CLIENT_CAP_UNIVERSAL_PLANES and 805 799 * &DRM_CLIENT_CAP_ASPECT_RATIO. 800 + * 801 + * If the driver doesn't support atomic mode-setting, enabling this capability 802 + * will fail with -EOPNOTSUPP. 803 + * 804 + * This capability has been introduced in kernel version 4.0. Starting from 805 + * kernel version 4.2, this capability is always supported for atomic-capable 806 + * drivers. 806 807 */ 807 808 #define DRM_CLIENT_CAP_ATOMIC 3 808 809 ··· 817 804 * DRM_CLIENT_CAP_ASPECT_RATIO 818 805 * 819 806 * If set to 1, the DRM core will provide aspect ratio information in modes. 807 + * See ``DRM_MODE_FLAG_PIC_AR_*``. 808 + * 809 + * This capability is always supported for all drivers starting from kernel 810 + * version 4.18. 820 811 */ 821 812 #define DRM_CLIENT_CAP_ASPECT_RATIO 4 822 813 ··· 828 811 * DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 829 812 * 830 813 * If set to 1, the DRM core will expose special connectors to be used for 831 - * writing back to memory the scene setup in the commit. Depends on client 832 - * also supporting DRM_CLIENT_CAP_ATOMIC 814 + * writing back to memory the scene setup in the commit. The client must enable 815 + * &DRM_CLIENT_CAP_ATOMIC first. 816 + * 817 + * This capability is always supported for atomic-capable drivers starting from 818 + * kernel version 4.19. 833 819 */ 834 820 #define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5 835 821
+359 -34
tools/include/uapi/drm/i915_drm.h
··· 62 62 #define I915_ERROR_UEVENT "ERROR" 63 63 #define I915_RESET_UEVENT "RESET" 64 64 65 - /* 66 - * i915_user_extension: Base class for defining a chain of extensions 65 + /** 66 + * struct i915_user_extension - Base class for defining a chain of extensions 67 67 * 68 68 * Many interfaces need to grow over time. In most cases we can simply 69 69 * extend the struct and have userspace pass in more data. Another option, ··· 76 76 * increasing complexity, and for large parts of that interface to be 77 77 * entirely optional. The downside is more pointer chasing; chasing across 78 78 * the __user boundary with pointers encapsulated inside u64. 79 + * 80 + * Example chaining: 81 + * 82 + * .. code-block:: C 83 + * 84 + * struct i915_user_extension ext3 { 85 + * .next_extension = 0, // end 86 + * .name = ..., 87 + * }; 88 + * struct i915_user_extension ext2 { 89 + * .next_extension = (uintptr_t)&ext3, 90 + * .name = ..., 91 + * }; 92 + * struct i915_user_extension ext1 { 93 + * .next_extension = (uintptr_t)&ext2, 94 + * .name = ..., 95 + * }; 96 + * 97 + * Typically the struct i915_user_extension would be embedded in some uAPI 98 + * struct, and in this case we would feed it the head of the chain(i.e ext1), 99 + * which would then apply all of the above extensions. 100 + * 79 101 */ 80 102 struct i915_user_extension { 103 + /** 104 + * @next_extension: 105 + * 106 + * Pointer to the next struct i915_user_extension, or zero if the end. 107 + */ 81 108 __u64 next_extension; 109 + /** 110 + * @name: Name of the extension. 111 + * 112 + * Note that the name here is just some integer. 113 + * 114 + * Also note that the name space for this is not global for the whole 115 + * driver, but rather its scope/meaning is limited to the specific piece 116 + * of uAPI which has embedded the struct i915_user_extension. 117 + */ 82 118 __u32 name; 83 - __u32 flags; /* All undefined bits must be zero. */ 84 - __u32 rsvd[4]; /* Reserved for future use; must be zero. */ 119 + /** 120 + * @flags: MBZ 121 + * 122 + * All undefined bits must be zero. 123 + */ 124 + __u32 flags; 125 + /** 126 + * @rsvd: MBZ 127 + * 128 + * Reserved for future use; must be zero. 129 + */ 130 + __u32 rsvd[4]; 85 131 }; 86 132 87 133 /* ··· 406 360 #define DRM_I915_QUERY 0x39 407 361 #define DRM_I915_GEM_VM_CREATE 0x3a 408 362 #define DRM_I915_GEM_VM_DESTROY 0x3b 363 + #define DRM_I915_GEM_CREATE_EXT 0x3c 409 364 /* Must be kept compact -- no holes */ 410 365 411 366 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) ··· 439 392 #define DRM_IOCTL_I915_GEM_ENTERVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT) 440 393 #define DRM_IOCTL_I915_GEM_LEAVEVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT) 441 394 #define DRM_IOCTL_I915_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create) 395 + #define DRM_IOCTL_I915_GEM_CREATE_EXT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE_EXT, struct drm_i915_gem_create_ext) 442 396 #define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread) 443 397 #define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) 444 398 #define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) ··· 1102 1054 __u32 flags; 1103 1055 }; 1104 1056 1105 - /** 1057 + /* 1106 1058 * See drm_i915_gem_execbuffer_ext_timeline_fences. 1107 1059 */ 1108 1060 #define DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES 0 1109 1061 1110 - /** 1062 + /* 1111 1063 * This structure describes an array of drm_syncobj and associated points for 1112 1064 * timeline variants of drm_syncobj. It is invalid to append this structure to 1113 1065 * the execbuf if I915_EXEC_FENCE_ARRAY is set. ··· 1748 1700 __u64 value; 1749 1701 }; 1750 1702 1751 - /** 1703 + /* 1752 1704 * Context SSEU programming 1753 1705 * 1754 1706 * It may be necessary for either functional or performance reason to configure ··· 2115 2067 __u64 properties_ptr; 2116 2068 }; 2117 2069 2118 - /** 2070 + /* 2119 2071 * Enable data capture for a stream that was either opened in a disabled state 2120 2072 * via I915_PERF_FLAG_DISABLED or was later disabled via 2121 2073 * I915_PERF_IOCTL_DISABLE. ··· 2129 2081 */ 2130 2082 #define I915_PERF_IOCTL_ENABLE _IO('i', 0x0) 2131 2083 2132 - /** 2084 + /* 2133 2085 * Disable data capture for a stream. 2134 2086 * 2135 2087 * It is an error to try and read a stream that is disabled. ··· 2138 2090 */ 2139 2091 #define I915_PERF_IOCTL_DISABLE _IO('i', 0x1) 2140 2092 2141 - /** 2093 + /* 2142 2094 * Change metrics_set captured by a stream. 2143 2095 * 2144 2096 * If the stream is bound to a specific context, the configuration change ··· 2151 2103 */ 2152 2104 #define I915_PERF_IOCTL_CONFIG _IO('i', 0x2) 2153 2105 2154 - /** 2106 + /* 2155 2107 * Common to all i915 perf records 2156 2108 */ 2157 2109 struct drm_i915_perf_record_header { ··· 2199 2151 DRM_I915_PERF_RECORD_MAX /* non-ABI */ 2200 2152 }; 2201 2153 2202 - /** 2154 + /* 2203 2155 * Structure to upload perf dynamic configuration into the kernel. 2204 2156 */ 2205 2157 struct drm_i915_perf_oa_config { ··· 2220 2172 __u64 flex_regs_ptr; 2221 2173 }; 2222 2174 2175 + /** 2176 + * struct drm_i915_query_item - An individual query for the kernel to process. 2177 + * 2178 + * The behaviour is determined by the @query_id. Note that exactly what 2179 + * @data_ptr is also depends on the specific @query_id. 2180 + */ 2223 2181 struct drm_i915_query_item { 2182 + /** @query_id: The id for this query */ 2224 2183 __u64 query_id; 2225 2184 #define DRM_I915_QUERY_TOPOLOGY_INFO 1 2226 2185 #define DRM_I915_QUERY_ENGINE_INFO 2 2227 2186 #define DRM_I915_QUERY_PERF_CONFIG 3 2187 + #define DRM_I915_QUERY_MEMORY_REGIONS 4 2228 2188 /* Must be kept compact -- no holes and well documented */ 2229 2189 2230 - /* 2190 + /** 2191 + * @length: 2192 + * 2231 2193 * When set to zero by userspace, this is filled with the size of the 2232 - * data to be written at the data_ptr pointer. The kernel sets this 2194 + * data to be written at the @data_ptr pointer. The kernel sets this 2233 2195 * value to a negative value to signal an error on a particular query 2234 2196 * item. 2235 2197 */ 2236 2198 __s32 length; 2237 2199 2238 - /* 2200 + /** 2201 + * @flags: 2202 + * 2239 2203 * When query_id == DRM_I915_QUERY_TOPOLOGY_INFO, must be 0. 2240 2204 * 2241 2205 * When query_id == DRM_I915_QUERY_PERF_CONFIG, must be one of the 2242 - * following : 2243 - * - DRM_I915_QUERY_PERF_CONFIG_LIST 2244 - * - DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID 2245 - * - DRM_I915_QUERY_PERF_CONFIG_FOR_UUID 2206 + * following: 2207 + * 2208 + * - DRM_I915_QUERY_PERF_CONFIG_LIST 2209 + * - DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID 2210 + * - DRM_I915_QUERY_PERF_CONFIG_FOR_UUID 2246 2211 */ 2247 2212 __u32 flags; 2248 2213 #define DRM_I915_QUERY_PERF_CONFIG_LIST 1 2249 2214 #define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID 2 2250 2215 #define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID 3 2251 2216 2252 - /* 2253 - * Data will be written at the location pointed by data_ptr when the 2254 - * value of length matches the length of the data to be written by the 2217 + /** 2218 + * @data_ptr: 2219 + * 2220 + * Data will be written at the location pointed by @data_ptr when the 2221 + * value of @length matches the length of the data to be written by the 2255 2222 * kernel. 2256 2223 */ 2257 2224 __u64 data_ptr; 2258 2225 }; 2259 2226 2227 + /** 2228 + * struct drm_i915_query - Supply an array of struct drm_i915_query_item for the 2229 + * kernel to fill out. 2230 + * 2231 + * Note that this is generally a two step process for each struct 2232 + * drm_i915_query_item in the array: 2233 + * 2234 + * 1. Call the DRM_IOCTL_I915_QUERY, giving it our array of struct 2235 + * drm_i915_query_item, with &drm_i915_query_item.length set to zero. The 2236 + * kernel will then fill in the size, in bytes, which tells userspace how 2237 + * memory it needs to allocate for the blob(say for an array of properties). 2238 + * 2239 + * 2. Next we call DRM_IOCTL_I915_QUERY again, this time with the 2240 + * &drm_i915_query_item.data_ptr equal to our newly allocated blob. Note that 2241 + * the &drm_i915_query_item.length should still be the same as what the 2242 + * kernel previously set. At this point the kernel can fill in the blob. 2243 + * 2244 + * Note that for some query items it can make sense for userspace to just pass 2245 + * in a buffer/blob equal to or larger than the required size. In this case only 2246 + * a single ioctl call is needed. For some smaller query items this can work 2247 + * quite well. 2248 + * 2249 + */ 2260 2250 struct drm_i915_query { 2251 + /** @num_items: The number of elements in the @items_ptr array */ 2261 2252 __u32 num_items; 2262 2253 2263 - /* 2264 - * Unused for now. Must be cleared to zero. 2254 + /** 2255 + * @flags: Unused for now. Must be cleared to zero. 2265 2256 */ 2266 2257 __u32 flags; 2267 2258 2268 - /* 2269 - * This points to an array of num_items drm_i915_query_item structures. 2259 + /** 2260 + * @items_ptr: 2261 + * 2262 + * Pointer to an array of struct drm_i915_query_item. The number of 2263 + * array elements is @num_items. 2270 2264 */ 2271 2265 __u64 items_ptr; 2272 2266 }; ··· 2382 2292 * Describes one engine and it's capabilities as known to the driver. 2383 2293 */ 2384 2294 struct drm_i915_engine_info { 2385 - /** Engine class and instance. */ 2295 + /** @engine: Engine class and instance. */ 2386 2296 struct i915_engine_class_instance engine; 2387 2297 2388 - /** Reserved field. */ 2298 + /** @rsvd0: Reserved field. */ 2389 2299 __u32 rsvd0; 2390 2300 2391 - /** Engine flags. */ 2301 + /** @flags: Engine flags. */ 2392 2302 __u64 flags; 2393 2303 2394 - /** Capabilities of this engine. */ 2304 + /** @capabilities: Capabilities of this engine. */ 2395 2305 __u64 capabilities; 2396 2306 #define I915_VIDEO_CLASS_CAPABILITY_HEVC (1 << 0) 2397 2307 #define I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC (1 << 1) 2398 2308 2399 - /** Reserved fields. */ 2309 + /** @rsvd1: Reserved fields. */ 2400 2310 __u64 rsvd1[4]; 2401 2311 }; 2402 2312 ··· 2407 2317 * an array of struct drm_i915_engine_info structures. 2408 2318 */ 2409 2319 struct drm_i915_query_engine_info { 2410 - /** Number of struct drm_i915_engine_info structs following. */ 2320 + /** @num_engines: Number of struct drm_i915_engine_info structs following. */ 2411 2321 __u32 num_engines; 2412 2322 2413 - /** MBZ */ 2323 + /** @rsvd: MBZ */ 2414 2324 __u32 rsvd[3]; 2415 2325 2416 - /** Marker for drm_i915_engine_info structures. */ 2326 + /** @engines: Marker for drm_i915_engine_info structures. */ 2417 2327 struct drm_i915_engine_info engines[]; 2418 2328 }; 2419 2329 ··· 2465 2375 * - n_flex_regs 2466 2376 */ 2467 2377 __u8 data[]; 2378 + }; 2379 + 2380 + /** 2381 + * enum drm_i915_gem_memory_class - Supported memory classes 2382 + */ 2383 + enum drm_i915_gem_memory_class { 2384 + /** @I915_MEMORY_CLASS_SYSTEM: System memory */ 2385 + I915_MEMORY_CLASS_SYSTEM = 0, 2386 + /** @I915_MEMORY_CLASS_DEVICE: Device local-memory */ 2387 + I915_MEMORY_CLASS_DEVICE, 2388 + }; 2389 + 2390 + /** 2391 + * struct drm_i915_gem_memory_class_instance - Identify particular memory region 2392 + */ 2393 + struct drm_i915_gem_memory_class_instance { 2394 + /** @memory_class: See enum drm_i915_gem_memory_class */ 2395 + __u16 memory_class; 2396 + 2397 + /** @memory_instance: Which instance */ 2398 + __u16 memory_instance; 2399 + }; 2400 + 2401 + /** 2402 + * struct drm_i915_memory_region_info - Describes one region as known to the 2403 + * driver. 2404 + * 2405 + * Note that we reserve some stuff here for potential future work. As an example 2406 + * we might want expose the capabilities for a given region, which could include 2407 + * things like if the region is CPU mappable/accessible, what are the supported 2408 + * mapping types etc. 2409 + * 2410 + * Note that to extend struct drm_i915_memory_region_info and struct 2411 + * drm_i915_query_memory_regions in the future the plan is to do the following: 2412 + * 2413 + * .. code-block:: C 2414 + * 2415 + * struct drm_i915_memory_region_info { 2416 + * struct drm_i915_gem_memory_class_instance region; 2417 + * union { 2418 + * __u32 rsvd0; 2419 + * __u32 new_thing1; 2420 + * }; 2421 + * ... 2422 + * union { 2423 + * __u64 rsvd1[8]; 2424 + * struct { 2425 + * __u64 new_thing2; 2426 + * __u64 new_thing3; 2427 + * ... 2428 + * }; 2429 + * }; 2430 + * }; 2431 + * 2432 + * With this things should remain source compatible between versions for 2433 + * userspace, even as we add new fields. 2434 + * 2435 + * Note this is using both struct drm_i915_query_item and struct drm_i915_query. 2436 + * For this new query we are adding the new query id DRM_I915_QUERY_MEMORY_REGIONS 2437 + * at &drm_i915_query_item.query_id. 2438 + */ 2439 + struct drm_i915_memory_region_info { 2440 + /** @region: The class:instance pair encoding */ 2441 + struct drm_i915_gem_memory_class_instance region; 2442 + 2443 + /** @rsvd0: MBZ */ 2444 + __u32 rsvd0; 2445 + 2446 + /** @probed_size: Memory probed by the driver (-1 = unknown) */ 2447 + __u64 probed_size; 2448 + 2449 + /** @unallocated_size: Estimate of memory remaining (-1 = unknown) */ 2450 + __u64 unallocated_size; 2451 + 2452 + /** @rsvd1: MBZ */ 2453 + __u64 rsvd1[8]; 2454 + }; 2455 + 2456 + /** 2457 + * struct drm_i915_query_memory_regions 2458 + * 2459 + * The region info query enumerates all regions known to the driver by filling 2460 + * in an array of struct drm_i915_memory_region_info structures. 2461 + * 2462 + * Example for getting the list of supported regions: 2463 + * 2464 + * .. code-block:: C 2465 + * 2466 + * struct drm_i915_query_memory_regions *info; 2467 + * struct drm_i915_query_item item = { 2468 + * .query_id = DRM_I915_QUERY_MEMORY_REGIONS; 2469 + * }; 2470 + * struct drm_i915_query query = { 2471 + * .num_items = 1, 2472 + * .items_ptr = (uintptr_t)&item, 2473 + * }; 2474 + * int err, i; 2475 + * 2476 + * // First query the size of the blob we need, this needs to be large 2477 + * // enough to hold our array of regions. The kernel will fill out the 2478 + * // item.length for us, which is the number of bytes we need. 2479 + * err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query); 2480 + * if (err) ... 2481 + * 2482 + * info = calloc(1, item.length); 2483 + * // Now that we allocated the required number of bytes, we call the ioctl 2484 + * // again, this time with the data_ptr pointing to our newly allocated 2485 + * // blob, which the kernel can then populate with the all the region info. 2486 + * item.data_ptr = (uintptr_t)&info, 2487 + * 2488 + * err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query); 2489 + * if (err) ... 2490 + * 2491 + * // We can now access each region in the array 2492 + * for (i = 0; i < info->num_regions; i++) { 2493 + * struct drm_i915_memory_region_info mr = info->regions[i]; 2494 + * u16 class = mr.region.class; 2495 + * u16 instance = mr.region.instance; 2496 + * 2497 + * .... 2498 + * } 2499 + * 2500 + * free(info); 2501 + */ 2502 + struct drm_i915_query_memory_regions { 2503 + /** @num_regions: Number of supported regions */ 2504 + __u32 num_regions; 2505 + 2506 + /** @rsvd: MBZ */ 2507 + __u32 rsvd[3]; 2508 + 2509 + /** @regions: Info about each supported region */ 2510 + struct drm_i915_memory_region_info regions[]; 2511 + }; 2512 + 2513 + /** 2514 + * struct drm_i915_gem_create_ext - Existing gem_create behaviour, with added 2515 + * extension support using struct i915_user_extension. 2516 + * 2517 + * Note that in the future we want to have our buffer flags here, at least for 2518 + * the stuff that is immutable. Previously we would have two ioctls, one to 2519 + * create the object with gem_create, and another to apply various parameters, 2520 + * however this creates some ambiguity for the params which are considered 2521 + * immutable. Also in general we're phasing out the various SET/GET ioctls. 2522 + */ 2523 + struct drm_i915_gem_create_ext { 2524 + /** 2525 + * @size: Requested size for the object. 2526 + * 2527 + * The (page-aligned) allocated size for the object will be returned. 2528 + * 2529 + * Note that for some devices we have might have further minimum 2530 + * page-size restrictions(larger than 4K), like for device local-memory. 2531 + * However in general the final size here should always reflect any 2532 + * rounding up, if for example using the I915_GEM_CREATE_EXT_MEMORY_REGIONS 2533 + * extension to place the object in device local-memory. 2534 + */ 2535 + __u64 size; 2536 + /** 2537 + * @handle: Returned handle for the object. 2538 + * 2539 + * Object handles are nonzero. 2540 + */ 2541 + __u32 handle; 2542 + /** @flags: MBZ */ 2543 + __u32 flags; 2544 + /** 2545 + * @extensions: The chain of extensions to apply to this object. 2546 + * 2547 + * This will be useful in the future when we need to support several 2548 + * different extensions, and we need to apply more than one when 2549 + * creating the object. See struct i915_user_extension. 2550 + * 2551 + * If we don't supply any extensions then we get the same old gem_create 2552 + * behaviour. 2553 + * 2554 + * For I915_GEM_CREATE_EXT_MEMORY_REGIONS usage see 2555 + * struct drm_i915_gem_create_ext_memory_regions. 2556 + */ 2557 + #define I915_GEM_CREATE_EXT_MEMORY_REGIONS 0 2558 + __u64 extensions; 2559 + }; 2560 + 2561 + /** 2562 + * struct drm_i915_gem_create_ext_memory_regions - The 2563 + * I915_GEM_CREATE_EXT_MEMORY_REGIONS extension. 2564 + * 2565 + * Set the object with the desired set of placements/regions in priority 2566 + * order. Each entry must be unique and supported by the device. 2567 + * 2568 + * This is provided as an array of struct drm_i915_gem_memory_class_instance, or 2569 + * an equivalent layout of class:instance pair encodings. See struct 2570 + * drm_i915_query_memory_regions and DRM_I915_QUERY_MEMORY_REGIONS for how to 2571 + * query the supported regions for a device. 2572 + * 2573 + * As an example, on discrete devices, if we wish to set the placement as 2574 + * device local-memory we can do something like: 2575 + * 2576 + * .. code-block:: C 2577 + * 2578 + * struct drm_i915_gem_memory_class_instance region_lmem = { 2579 + * .memory_class = I915_MEMORY_CLASS_DEVICE, 2580 + * .memory_instance = 0, 2581 + * }; 2582 + * struct drm_i915_gem_create_ext_memory_regions regions = { 2583 + * .base = { .name = I915_GEM_CREATE_EXT_MEMORY_REGIONS }, 2584 + * .regions = (uintptr_t)&region_lmem, 2585 + * .num_regions = 1, 2586 + * }; 2587 + * struct drm_i915_gem_create_ext create_ext = { 2588 + * .size = 16 * PAGE_SIZE, 2589 + * .extensions = (uintptr_t)&regions, 2590 + * }; 2591 + * 2592 + * int err = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext); 2593 + * if (err) ... 2594 + * 2595 + * At which point we get the object handle in &drm_i915_gem_create_ext.handle, 2596 + * along with the final object size in &drm_i915_gem_create_ext.size, which 2597 + * should account for any rounding up, if required. 2598 + */ 2599 + struct drm_i915_gem_create_ext_memory_regions { 2600 + /** @base: Extension link. See struct i915_user_extension. */ 2601 + struct i915_user_extension base; 2602 + 2603 + /** @pad: MBZ */ 2604 + __u32 pad; 2605 + /** @num_regions: Number of elements in the @regions array. */ 2606 + __u32 num_regions; 2607 + /** 2608 + * @regions: The regions/placements array. 2609 + * 2610 + * An array of struct drm_i915_gem_memory_class_instance. 2611 + */ 2612 + __u64 regions; 2468 2613 }; 2469 2614 2470 2615 #if defined(__cplusplus)
+28 -2
tools/include/uapi/sound/asound.h
··· 710 710 * Raw MIDI section - /dev/snd/midi?? 711 711 */ 712 712 713 - #define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 1) 713 + #define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 2) 714 714 715 715 enum { 716 716 SNDRV_RAWMIDI_STREAM_OUTPUT = 0, ··· 736 736 unsigned char reserved[64]; /* reserved for future use */ 737 737 }; 738 738 739 + #define SNDRV_RAWMIDI_MODE_FRAMING_MASK (7<<0) 740 + #define SNDRV_RAWMIDI_MODE_FRAMING_SHIFT 0 741 + #define SNDRV_RAWMIDI_MODE_FRAMING_NONE (0<<0) 742 + #define SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP (1<<0) 743 + #define SNDRV_RAWMIDI_MODE_CLOCK_MASK (7<<3) 744 + #define SNDRV_RAWMIDI_MODE_CLOCK_SHIFT 3 745 + #define SNDRV_RAWMIDI_MODE_CLOCK_NONE (0<<3) 746 + #define SNDRV_RAWMIDI_MODE_CLOCK_REALTIME (1<<3) 747 + #define SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC (2<<3) 748 + #define SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC_RAW (3<<3) 749 + 750 + #define SNDRV_RAWMIDI_FRAMING_DATA_LENGTH 16 751 + 752 + struct snd_rawmidi_framing_tstamp { 753 + /* For now, frame_type is always 0. Midi 2.0 is expected to add new 754 + * types here. Applications are expected to skip unknown frame types. 755 + */ 756 + __u8 frame_type; 757 + __u8 length; /* number of valid bytes in data field */ 758 + __u8 reserved[2]; 759 + __u32 tv_nsec; /* nanoseconds */ 760 + __u64 tv_sec; /* seconds */ 761 + __u8 data[SNDRV_RAWMIDI_FRAMING_DATA_LENGTH]; 762 + } __packed; 763 + 739 764 struct snd_rawmidi_params { 740 765 int stream; 741 766 size_t buffer_size; /* queue size in bytes */ 742 767 size_t avail_min; /* minimum avail bytes for wakeup */ 743 768 unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */ 744 - unsigned char reserved[16]; /* reserved for future use */ 769 + unsigned int mode; /* For input data only, frame incoming data */ 770 + unsigned char reserved[12]; /* reserved for future use */ 745 771 }; 746 772 747 773 #ifndef __KERNEL__
+2
tools/lib/perf/Build
··· 11 11 $(OUTPUT)zalloc.o: ../../lib/zalloc.c FORCE 12 12 $(call rule_mkdir) 13 13 $(call if_changed_dep,cc_o_c) 14 + 15 + tests-y += tests/
+25 -5
tools/lib/perf/Makefile
··· 52 52 Q = @ 53 53 endif 54 54 55 + TEST_ARGS := $(if $(V),-v) 56 + 55 57 # Set compile option CFLAGS 56 58 ifdef EXTRA_CFLAGS 57 59 CFLAGS := $(EXTRA_CFLAGS) ··· 138 136 139 137 clean: $(LIBAPI)-clean 140 138 $(call QUIET_CLEAN, libperf) $(RM) $(LIBPERF_A) \ 141 - *.o *~ *.a *.so *.so.$(VERSION) *.so.$(LIBPERF_VERSION) .*.d .*.cmd LIBPERF-CFLAGS $(LIBPERF_PC) 142 - $(Q)$(MAKE) -C tests clean 139 + *.o *~ *.a *.so *.so.$(VERSION) *.so.$(LIBPERF_VERSION) .*.d .*.cmd tests/*.o LIBPERF-CFLAGS $(LIBPERF_PC) \ 140 + $(TESTS_STATIC) $(TESTS_SHARED) 143 141 144 - tests: libs 145 - $(Q)$(MAKE) -C tests 146 - $(Q)$(MAKE) -C tests run 142 + TESTS_IN = tests-in.o 143 + 144 + TESTS_STATIC = $(OUTPUT)tests-static 145 + TESTS_SHARED = $(OUTPUT)tests-shared 146 + 147 + $(TESTS_IN): FORCE 148 + $(Q)$(MAKE) $(build)=tests 149 + 150 + $(TESTS_STATIC): $(TESTS_IN) $(LIBPERF_A) $(LIBAPI) 151 + $(QUIET_LINK)$(CC) -o $@ $^ 152 + 153 + $(TESTS_SHARED): $(TESTS_IN) $(LIBAPI) 154 + $(QUIET_LINK)$(CC) -o $@ -L$(if $(OUTPUT),$(OUTPUT),.) $^ -lperf 155 + 156 + make-tests: libs $(TESTS_SHARED) $(TESTS_STATIC) 157 + 158 + tests: make-tests 159 + @echo "running static:" 160 + @./$(TESTS_STATIC) $(TEST_ARGS) 161 + @echo "running dynamic:" 162 + @LD_LIBRARY_PATH=. ./$(TESTS_SHARED) $(TEST_ARGS) 147 163 148 164 $(LIBPERF_PC): 149 165 $(QUIET_GEN)sed -e "s|@PREFIX@|$(prefix)|" \
+22
tools/lib/perf/evlist.c
··· 66 66 void perf_evlist__add(struct perf_evlist *evlist, 67 67 struct perf_evsel *evsel) 68 68 { 69 + evsel->idx = evlist->nr_entries; 69 70 list_add_tail(&evsel->node, &evlist->entries); 70 71 evlist->nr_entries += 1; 71 72 __perf_evlist__propagate_maps(evlist, evsel); ··· 641 640 return map->next; 642 641 643 642 return overwrite ? evlist->mmap_ovw_first : evlist->mmap_first; 643 + } 644 + 645 + void __perf_evlist__set_leader(struct list_head *list) 646 + { 647 + struct perf_evsel *evsel, *leader; 648 + 649 + leader = list_entry(list->next, struct perf_evsel, node); 650 + evsel = list_entry(list->prev, struct perf_evsel, node); 651 + 652 + leader->nr_members = evsel->idx - leader->idx + 1; 653 + 654 + __perf_evlist__for_each_entry(list, evsel) 655 + evsel->leader = leader; 656 + } 657 + 658 + void perf_evlist__set_leader(struct perf_evlist *evlist) 659 + { 660 + if (evlist->nr_entries) { 661 + evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0; 662 + __perf_evlist__set_leader(&evlist->entries); 663 + } 644 664 }
+38 -4
tools/lib/perf/evsel.c
··· 17 17 #include <linux/string.h> 18 18 #include <sys/ioctl.h> 19 19 #include <sys/mman.h> 20 + #include <asm/bug.h> 20 21 21 - void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr) 22 + void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, 23 + int idx) 22 24 { 23 25 INIT_LIST_HEAD(&evsel->node); 24 26 evsel->attr = *attr; 27 + evsel->idx = idx; 28 + evsel->leader = evsel; 25 29 } 26 30 27 31 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) ··· 33 29 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 34 30 35 31 if (evsel != NULL) 36 - perf_evsel__init(evsel, attr); 32 + perf_evsel__init(evsel, attr, 0); 37 33 38 34 return evsel; 39 35 } ··· 77 73 return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); 78 74 } 79 75 76 + static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread, int *group_fd) 77 + { 78 + struct perf_evsel *leader = evsel->leader; 79 + int fd; 80 + 81 + if (evsel == leader) { 82 + *group_fd = -1; 83 + return 0; 84 + } 85 + 86 + /* 87 + * Leader must be already processed/open, 88 + * if not it's a bug. 89 + */ 90 + if (!leader->fd) 91 + return -ENOTCONN; 92 + 93 + fd = FD(leader, cpu, thread); 94 + if (fd == -1) 95 + return -EBADF; 96 + 97 + *group_fd = fd; 98 + 99 + return 0; 100 + } 101 + 80 102 int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, 81 103 struct perf_thread_map *threads) 82 104 { ··· 138 108 139 109 for (cpu = 0; cpu < cpus->nr; cpu++) { 140 110 for (thread = 0; thread < threads->nr; thread++) { 141 - int fd; 111 + int fd, group_fd; 112 + 113 + err = get_group_fd(evsel, cpu, thread, &group_fd); 114 + if (err < 0) 115 + return err; 142 116 143 117 fd = sys_perf_event_open(&evsel->attr, 144 118 threads->map[thread].pid, 145 - cpus->map[cpu], -1, 0); 119 + cpus->map[cpu], group_fd, 0); 146 120 147 121 if (fd < 0) 148 122 return -errno;
+2
tools/lib/perf/include/internal/evlist.h
··· 16 16 struct perf_evlist { 17 17 struct list_head entries; 18 18 int nr_entries; 19 + int nr_groups; 19 20 bool has_user_cpus; 20 21 struct perf_cpu_map *cpus; 21 22 struct perf_cpu_map *all_cpus; ··· 127 126 128 127 void perf_evlist__reset_id_hash(struct perf_evlist *evlist); 129 128 129 + void __perf_evlist__set_leader(struct list_head *list); 130 130 #endif /* __LIBPERF_INTERNAL_EVLIST_H */
+4 -1
tools/lib/perf/include/internal/evsel.h
··· 45 45 struct xyarray *sample_id; 46 46 u64 *id; 47 47 u32 ids; 48 + struct perf_evsel *leader; 48 49 49 50 /* parse modifier helper */ 50 51 int nr_members; 51 52 bool system_wide; 53 + int idx; 52 54 }; 53 55 54 - void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr); 56 + void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, 57 + int idx); 55 58 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 56 59 void perf_evsel__close_fd(struct perf_evsel *evsel); 57 60 void perf_evsel__free_fd(struct perf_evsel *evsel);
+2 -2
tools/lib/perf/include/internal/tests.h
··· 5 5 #include <stdio.h> 6 6 #include <unistd.h> 7 7 8 - int tests_failed; 9 - int tests_verbose; 8 + extern int tests_failed; 9 + extern int tests_verbose; 10 10 11 11 static inline int get_verbose(char **argv, int argc) 12 12 {
+1
tools/lib/perf/include/perf/evlist.h
··· 46 46 (pos) != NULL; \ 47 47 (pos) = perf_evlist__next_mmap((evlist), (pos), overwrite)) 48 48 49 + LIBPERF_API void perf_evlist__set_leader(struct perf_evlist *evlist); 49 50 #endif /* __LIBPERF_EVLIST_H */
+1
tools/lib/perf/libperf.map
··· 45 45 perf_evlist__munmap; 46 46 perf_evlist__filter_pollfd; 47 47 perf_evlist__next_mmap; 48 + perf_evlist__set_leader; 48 49 perf_mmap__consume; 49 50 perf_mmap__read_init; 50 51 perf_mmap__read_done;
+5
tools/lib/perf/tests/Build
··· 1 + tests-y += main.o 2 + tests-y += test-evsel.o 3 + tests-y += test-evlist.o 4 + tests-y += test-cpumap.o 5 + tests-y += test-threadmap.o
-40
tools/lib/perf/tests/Makefile
··· 1 - # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 - 3 - TESTS = test-cpumap test-threadmap test-evlist test-evsel 4 - 5 - TESTS_SO := $(addsuffix -so,$(TESTS)) 6 - TESTS_A := $(addsuffix -a,$(TESTS)) 7 - 8 - TEST_ARGS := $(if $(V),-v) 9 - 10 - # Set compile option CFLAGS 11 - ifdef EXTRA_CFLAGS 12 - CFLAGS := $(EXTRA_CFLAGS) 13 - else 14 - CFLAGS := -g -Wall 15 - endif 16 - 17 - all: 18 - 19 - include $(srctree)/tools/scripts/Makefile.include 20 - 21 - INCLUDE = -I$(srctree)/tools/lib/perf/include -I$(srctree)/tools/include -I$(srctree)/tools/lib 22 - 23 - $(TESTS_A): FORCE 24 - $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -o $@ $(subst -a,.c,$@) ../libperf.a $(LIBAPI) 25 - 26 - $(TESTS_SO): FORCE 27 - $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -L.. -o $@ $(subst -so,.c,$@) $(LIBAPI) -lperf 28 - 29 - all: $(TESTS_A) $(TESTS_SO) 30 - 31 - run: 32 - @echo "running static:" 33 - @for i in $(TESTS_A); do ./$$i $(TEST_ARGS); done 34 - @echo "running dynamic:" 35 - @for i in $(TESTS_SO); do LD_LIBRARY_PATH=../ ./$$i $(TEST_ARGS); done 36 - 37 - clean: 38 - $(call QUIET_CLEAN, tests)$(RM) $(TESTS_A) $(TESTS_SO) 39 - 40 - .PHONY: all clean FORCE
+15
tools/lib/perf/tests/main.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <internal/tests.h> 3 + #include "tests.h" 4 + 5 + int tests_failed; 6 + int tests_verbose; 7 + 8 + int main(int argc, char **argv) 9 + { 10 + __T("test cpumap", !test_cpumap(argc, argv)); 11 + __T("test threadmap", !test_threadmap(argc, argv)); 12 + __T("test evlist", !test_evlist(argc, argv)); 13 + __T("test evsel", !test_evsel(argc, argv)); 14 + return 0; 15 + }
+2 -1
tools/lib/perf/tests/test-cpumap.c
··· 3 3 #include <stdio.h> 4 4 #include <perf/cpumap.h> 5 5 #include <internal/tests.h> 6 + #include "tests.h" 6 7 7 8 static int libperf_print(enum libperf_print_level level, 8 9 const char *fmt, va_list ap) ··· 11 10 return vfprintf(stderr, fmt, ap); 12 11 } 13 12 14 - int main(int argc, char **argv) 13 + int test_cpumap(int argc, char **argv) 15 14 { 16 15 struct perf_cpu_map *cpus; 17 16
+23 -7
tools/lib/perf/tests/test-evlist.c
··· 18 18 #include <perf/event.h> 19 19 #include <internal/tests.h> 20 20 #include <api/fs/fs.h> 21 + #include "tests.h" 22 + #include <internal/evsel.h> 21 23 22 24 static int libperf_print(enum libperf_print_level level, 23 25 const char *fmt, va_list ap) ··· 31 29 { 32 30 struct perf_cpu_map *cpus; 33 31 struct perf_evlist *evlist; 34 - struct perf_evsel *evsel; 32 + struct perf_evsel *evsel, *leader; 35 33 struct perf_event_attr attr1 = { 36 34 .type = PERF_TYPE_SOFTWARE, 37 35 .config = PERF_COUNT_SW_CPU_CLOCK, ··· 48 46 evlist = perf_evlist__new(); 49 47 __T("failed to create evlist", evlist); 50 48 51 - evsel = perf_evsel__new(&attr1); 49 + evsel = leader = perf_evsel__new(&attr1); 52 50 __T("failed to create evsel1", evsel); 53 51 54 52 perf_evlist__add(evlist, evsel); ··· 57 55 __T("failed to create evsel2", evsel); 58 56 59 57 perf_evlist__add(evlist, evsel); 58 + 59 + perf_evlist__set_leader(evlist); 60 + __T("failed to set leader", leader->leader == leader); 61 + __T("failed to set leader", evsel->leader == leader); 60 62 61 63 perf_evlist__set_maps(evlist, cpus, NULL); 62 64 ··· 90 84 struct perf_counts_values counts = { .val = 0 }; 91 85 struct perf_thread_map *threads; 92 86 struct perf_evlist *evlist; 93 - struct perf_evsel *evsel; 87 + struct perf_evsel *evsel, *leader; 94 88 struct perf_event_attr attr1 = { 95 89 .type = PERF_TYPE_SOFTWARE, 96 90 .config = PERF_COUNT_SW_CPU_CLOCK, ··· 109 103 evlist = perf_evlist__new(); 110 104 __T("failed to create evlist", evlist); 111 105 112 - evsel = perf_evsel__new(&attr1); 106 + evsel = leader = perf_evsel__new(&attr1); 113 107 __T("failed to create evsel1", evsel); 114 108 115 109 perf_evlist__add(evlist, evsel); ··· 118 112 __T("failed to create evsel2", evsel); 119 113 120 114 perf_evlist__add(evlist, evsel); 115 + 116 + perf_evlist__set_leader(evlist); 117 + __T("failed to set leader", leader->leader == leader); 118 + __T("failed to set leader", evsel->leader == leader); 121 119 122 120 perf_evlist__set_maps(evlist, NULL, threads); 123 121 ··· 145 135 struct perf_counts_values counts = { .val = 0 }; 146 136 struct perf_thread_map *threads; 147 137 struct perf_evlist *evlist; 148 - struct perf_evsel *evsel; 138 + struct perf_evsel *evsel, *leader; 149 139 struct perf_event_attr attr1 = { 150 140 .type = PERF_TYPE_SOFTWARE, 151 141 .config = PERF_COUNT_SW_CPU_CLOCK, ··· 166 156 evlist = perf_evlist__new(); 167 157 __T("failed to create evlist", evlist); 168 158 169 - evsel = perf_evsel__new(&attr1); 159 + evsel = leader = perf_evsel__new(&attr1); 170 160 __T("failed to create evsel1", evsel); 171 161 172 162 perf_evlist__add(evlist, evsel); ··· 175 165 __T("failed to create evsel2", evsel); 176 166 177 167 perf_evlist__add(evlist, evsel); 168 + 169 + perf_evlist__set_leader(evlist); 170 + __T("failed to set leader", leader->leader == leader); 171 + __T("failed to set leader", evsel->leader == leader); 178 172 179 173 perf_evlist__set_maps(evlist, NULL, threads); 180 174 ··· 267 253 268 254 evsel = perf_evsel__new(&attr); 269 255 __T("failed to create evsel1", evsel); 256 + __T("failed to set leader", evsel->leader == evsel); 270 257 271 258 perf_evlist__add(evlist, evsel); 272 259 ··· 353 338 354 339 evsel = perf_evsel__new(&attr); 355 340 __T("failed to create evsel1", evsel); 341 + __T("failed to set leader", evsel->leader == evsel); 356 342 357 343 perf_evlist__add(evlist, evsel); 358 344 ··· 413 397 return 0; 414 398 } 415 399 416 - int main(int argc, char **argv) 400 + int test_evlist(int argc, char **argv) 417 401 { 418 402 __T_START; 419 403
+2 -1
tools/lib/perf/tests/test-evsel.c
··· 6 6 #include <perf/threadmap.h> 7 7 #include <perf/evsel.h> 8 8 #include <internal/tests.h> 9 + #include "tests.h" 9 10 10 11 static int libperf_print(enum libperf_print_level level, 11 12 const char *fmt, va_list ap) ··· 185 184 return 0; 186 185 } 187 186 188 - int main(int argc, char **argv) 187 + int test_evsel(int argc, char **argv) 189 188 { 190 189 __T_START; 191 190
+2 -1
tools/lib/perf/tests/test-threadmap.c
··· 3 3 #include <stdio.h> 4 4 #include <perf/threadmap.h> 5 5 #include <internal/tests.h> 6 + #include "tests.h" 6 7 7 8 static int libperf_print(enum libperf_print_level level, 8 9 const char *fmt, va_list ap) ··· 11 10 return vfprintf(stderr, fmt, ap); 12 11 } 13 12 14 - int main(int argc, char **argv) 13 + int test_threadmap(int argc, char **argv) 15 14 { 16 15 struct perf_thread_map *threads; 17 16
+10
tools/lib/perf/tests/tests.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef TESTS_H 3 + #define TESTS_H 4 + 5 + int test_cpumap(int argc, char **argv); 6 + int test_threadmap(int argc, char **argv); 7 + int test_evlist(int argc, char **argv); 8 + int test_evsel(int argc, char **argv); 9 + 10 + #endif /* TESTS_H */
+6
tools/perf/Documentation/perf-config.txt
··· 706 706 If set, Intel PT decoder will set the mispred flag on all 707 707 branches. 708 708 709 + intel-pt.max-loops:: 710 + If set and non-zero, the maximum number of unconditional 711 + branches decoded without consuming any trace packets. If 712 + the maximum is exceeded there will be a "Never-ending loop" 713 + error. The default is 100000. 714 + 709 715 auxtrace.*:: 710 716 711 717 auxtrace.dumpdir::
+17 -2
tools/perf/Makefile.perf
··· 923 923 $(call QUIET_INSTALL, binaries) \ 924 924 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \ 925 925 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \ 926 - $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(dir_SQ)/trace'; \ 926 + $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace'; \ 927 927 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(includedir_SQ)/perf'; \ 928 928 $(INSTALL) util/perf_dlfilter.h -t '$(DESTDIR_SQ)$(includedir_SQ)/perf' 929 929 ifndef NO_PERF_READ_VDSO32 ··· 1017 1017 SKEL_TMP_OUT := $(abspath $(SKEL_OUT)/.tmp) 1018 1018 SKELETONS := $(SKEL_OUT)/bpf_prog_profiler.skel.h 1019 1019 SKELETONS += $(SKEL_OUT)/bperf_leader.skel.h $(SKEL_OUT)/bperf_follower.skel.h 1020 + SKELETONS += $(SKEL_OUT)/bperf_cgroup.skel.h 1020 1021 1021 1022 ifdef BUILD_BPF_SKEL 1022 1023 BPFTOOL := $(SKEL_TMP_OUT)/bootstrap/bpftool ··· 1031 1030 CFLAGS= $(MAKE) -C ../bpf/bpftool \ 1032 1031 OUTPUT=$(SKEL_TMP_OUT)/ bootstrap 1033 1032 1034 - $(SKEL_TMP_OUT)/%.bpf.o: util/bpf_skel/%.bpf.c $(LIBBPF) | $(SKEL_TMP_OUT) 1033 + VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux) \ 1034 + $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \ 1035 + ../../vmlinux \ 1036 + /sys/kernel/btf/vmlinux \ 1037 + /boot/vmlinux-$(shell uname -r) 1038 + VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS)))) 1039 + 1040 + $(SKEL_OUT)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) 1041 + ifeq ($(VMLINUX_H),) 1042 + $(QUIET_GEN)$(BPFTOOL) btf dump file $< format c > $@ 1043 + else 1044 + $(Q)cp "$(VMLINUX_H)" $@ 1045 + endif 1046 + 1047 + $(SKEL_TMP_OUT)/%.bpf.o: util/bpf_skel/%.bpf.c $(LIBBPF) $(SKEL_OUT)/vmlinux.h | $(SKEL_TMP_OUT) 1035 1048 $(QUIET_CLANG)$(CLANG) -g -O2 -target bpf -Wall -Werror $(BPF_INCLUDE) \ 1036 1049 -c $(filter util/bpf_skel/%.bpf.c,$^) -o $@ && $(LLVM_STRIP) -g $@ 1037 1050
+1 -1
tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
··· 357 357 440 n64 process_madvise sys_process_madvise 358 358 441 n64 epoll_pwait2 sys_epoll_pwait2 359 359 442 n64 mount_setattr sys_mount_setattr 360 - # 443 reserved for quotactl_path 360 + 443 n64 quotactl_fd sys_quotactl_fd 361 361 444 n64 landlock_create_ruleset sys_landlock_create_ruleset 362 362 445 n64 landlock_add_rule sys_landlock_add_rule 363 363 446 n64 landlock_restrict_self sys_landlock_restrict_self
+1 -1
tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
··· 522 522 440 common process_madvise sys_process_madvise 523 523 441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 524 524 442 common mount_setattr sys_mount_setattr 525 - # 443 reserved for quotactl_path 525 + 443 common quotactl_fd sys_quotactl_fd 526 526 444 common landlock_create_ruleset sys_landlock_create_ruleset 527 527 445 common landlock_add_rule sys_landlock_add_rule 528 528 446 common landlock_restrict_self sys_landlock_restrict_self
+1 -1
tools/perf/arch/s390/entry/syscalls/syscall.tbl
··· 445 445 440 common process_madvise sys_process_madvise sys_process_madvise 446 446 441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 447 447 442 common mount_setattr sys_mount_setattr sys_mount_setattr 448 - # 443 reserved for quotactl_path 448 + 443 common quotactl_fd sys_quotactl_fd sys_quotactl_fd 449 449 444 common landlock_create_ruleset sys_landlock_create_ruleset sys_landlock_create_ruleset 450 450 445 common landlock_add_rule sys_landlock_add_rule sys_landlock_add_rule 451 451 446 common landlock_restrict_self sys_landlock_restrict_self sys_landlock_restrict_self
+1 -1
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
··· 364 364 440 common process_madvise sys_process_madvise 365 365 441 common epoll_pwait2 sys_epoll_pwait2 366 366 442 common mount_setattr sys_mount_setattr 367 - # 443 reserved for quotactl_path 367 + 443 common quotactl_fd sys_quotactl_fd 368 368 444 common landlock_create_ruleset sys_landlock_create_ruleset 369 369 445 common landlock_add_rule sys_landlock_add_rule 370 370 446 common landlock_restrict_self sys_landlock_restrict_self
+5 -1
tools/perf/arch/x86/util/evlist.c
··· 5 5 #include "util/parse-events.h" 6 6 7 7 #define TOPDOWN_L1_EVENTS "{slots,topdown-retiring,topdown-bad-spec,topdown-fe-bound,topdown-be-bound}" 8 + #define TOPDOWN_L2_EVENTS "{slots,topdown-retiring,topdown-bad-spec,topdown-fe-bound,topdown-be-bound,topdown-heavy-ops,topdown-br-mispredict,topdown-fetch-lat,topdown-mem-bound}" 8 9 9 10 int arch_evlist__add_default_attrs(struct evlist *evlist) 10 11 { 11 12 if (!pmu_have_event("cpu", "slots")) 12 13 return 0; 13 14 14 - return parse_events(evlist, TOPDOWN_L1_EVENTS, NULL); 15 + if (pmu_have_event("cpu", "topdown-heavy-ops")) 16 + return parse_events(evlist, TOPDOWN_L2_EVENTS, NULL); 17 + else 18 + return parse_events(evlist, TOPDOWN_L1_EVENTS, NULL); 15 19 }
+2 -2
tools/perf/arch/x86/util/iostat.c
··· 322 322 } 323 323 324 324 evlist__for_each_entry(evl, evsel) { 325 - evsel->priv = list->rps[evsel->idx / metrics_count]; 325 + evsel->priv = list->rps[evsel->core.idx / metrics_count]; 326 326 } 327 327 list->nr_entries = 0; 328 328 err: ··· 428 428 { 429 429 double iostat_value = 0; 430 430 u64 prev_count_val = 0; 431 - const char *iostat_metric = iostat_metric_by_idx(evsel->idx); 431 + const char *iostat_metric = iostat_metric_by_idx(evsel->core.idx); 432 432 u8 die = ((struct iio_root_port *)evsel->priv)->die; 433 433 struct perf_counts_values *count = perf_counts(evsel->counts, die, 0); 434 434
+2 -2
tools/perf/builtin-diff.c
··· 1031 1031 continue; 1032 1032 1033 1033 es_base = evsel_streams__entry(data_base->evlist_streams, 1034 - evsel_base->idx); 1034 + evsel_base->core.idx); 1035 1035 if (!es_base) 1036 1036 return -1; 1037 1037 1038 1038 es_pair = evsel_streams__entry(data_pair->evlist_streams, 1039 - evsel_pair->idx); 1039 + evsel_pair->core.idx); 1040 1040 if (!es_pair) 1041 1041 return -1; 1042 1042
+1 -1
tools/perf/builtin-probe.c
··· 31 31 #include <linux/zalloc.h> 32 32 33 33 #define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*" 34 - #define DEFAULT_FUNC_FILTER "!_*" 34 + #define DEFAULT_FUNC_FILTER "!_* & !*@plt" 35 35 #define DEFAULT_LIST_FILTER "*" 36 36 37 37 /* Session management structure */
+7 -6
tools/perf/builtin-record.c
··· 891 891 int rc = 0; 892 892 893 893 /* 894 - * For initial_delay or system wide, we need to add a dummy event so 895 - * that we can track PERF_RECORD_MMAP to cover the delay of waiting or 896 - * event synthesis. 894 + * For initial_delay, system wide or a hybrid system, we need to add a 895 + * dummy event so that we can track PERF_RECORD_MMAP to cover the delay 896 + * of waiting or event synthesis. 897 897 */ 898 - if (opts->initial_delay || target__has_cpu(&opts->target)) { 898 + if (opts->initial_delay || target__has_cpu(&opts->target) || 899 + perf_pmu__has_hybrid()) { 899 900 pos = evlist__get_tracking_event(evlist); 900 901 if (!evsel__is_dummy_event(pos)) { 901 902 /* Set up dummy event. */ ··· 927 926 goto try_again; 928 927 } 929 928 if ((errno == EINVAL || errno == EBADF) && 930 - pos->leader != pos && 929 + pos->core.leader != &pos->core && 931 930 pos->weak_group) { 932 931 pos = evlist__reset_weak_group(evlist, pos, true); 933 932 goto try_again; ··· 1777 1776 rec->tool.ordered_events = false; 1778 1777 } 1779 1778 1780 - if (!rec->evlist->nr_groups) 1779 + if (!rec->evlist->core.nr_groups) 1781 1780 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 1782 1781 1783 1782 if (data->is_pipe) {
+10 -4
tools/perf/builtin-report.c
··· 332 332 const char *name = evsel__name(evsel); 333 333 int err = perf_read_values_add_value(&rep->show_threads_values, 334 334 event->read.pid, event->read.tid, 335 - evsel->idx, 335 + evsel->core.idx, 336 336 name, 337 337 event->read.value); 338 338 ··· 666 666 evlist__for_each_entry(rep->session->evlist, pos) { 667 667 struct hists *hists = evsel__hists(pos); 668 668 669 - if (pos->idx == 0) 669 + if (pos->core.idx == 0) 670 670 hists->symbol_filter_str = rep->symbol_filter_str; 671 671 672 672 hists->socket_filter = rep->socket_filter; ··· 677 677 678 678 /* Non-group events are considered as leader */ 679 679 if (symbol_conf.event_group && !evsel__is_group_leader(pos)) { 680 - struct hists *leader_hists = evsel__hists(pos->leader); 680 + struct hists *leader_hists = evsel__hists(evsel__leader(pos)); 681 681 682 682 hists__match(leader_hists, hists); 683 683 hists__link(leader_hists, hists); ··· 729 729 return 0; 730 730 } 731 731 732 + static int process_attr(struct perf_tool *tool __maybe_unused, 733 + union perf_event *event, 734 + struct evlist **pevlist); 735 + 732 736 static void stats_setup(struct report *rep) 733 737 { 734 738 memset(&rep->tool, 0, sizeof(rep->tool)); 739 + rep->tool.attr = process_attr; 735 740 rep->tool.sample = count_sample_event; 736 741 rep->tool.no_warn = true; 737 742 } ··· 758 753 rep->tool.mmap = perf_event__process_mmap; 759 754 rep->tool.mmap2 = perf_event__process_mmap2; 760 755 } 756 + rep->tool.attr = process_attr; 761 757 rep->tool.comm = perf_event__process_comm; 762 758 rep->tool.exit = perf_event__process_exit; 763 759 rep->tool.fork = perf_event__process_fork; ··· 1432 1426 1433 1427 setup_forced_leader(&report, session->evlist); 1434 1428 1435 - if (symbol_conf.group_sort_idx && !session->evlist->nr_groups) { 1429 + if (symbol_conf.group_sort_idx && !session->evlist->core.nr_groups) { 1436 1430 parse_options_usage(NULL, options, "group-sort-idx", 0); 1437 1431 ret = -EINVAL; 1438 1432 goto error;
+5 -4
tools/perf/builtin-script.c
··· 1899 1899 struct perf_sample *sample, 1900 1900 FILE *fp) 1901 1901 { 1902 + struct evsel *leader = evsel__leader(evsel); 1902 1903 struct perf_stat_output_ctx ctx = { 1903 1904 .print_metric = script_print_metric, 1904 1905 .new_line = script_new_line, ··· 1916 1915 1917 1916 if (!evsel->stats) 1918 1917 evlist__alloc_stats(script->session->evlist, false); 1919 - if (evsel_script(evsel->leader)->gnum++ == 0) 1918 + if (evsel_script(leader)->gnum++ == 0) 1920 1919 perf_stat__reset_shadow_stats(); 1921 1920 val = sample->period * evsel->scale; 1922 1921 perf_stat__update_shadow_stats(evsel, ··· 1924 1923 sample->cpu, 1925 1924 &rt_stat); 1926 1925 evsel_script(evsel)->val = val; 1927 - if (evsel_script(evsel->leader)->gnum == evsel->leader->core.nr_members) { 1928 - for_each_group_member (ev2, evsel->leader) { 1926 + if (evsel_script(leader)->gnum == leader->core.nr_members) { 1927 + for_each_group_member (ev2, leader) { 1929 1928 perf_stat__print_shadow_stats(&stat_config, ev2, 1930 1929 evsel_script(ev2)->val, 1931 1930 sample->cpu, ··· 1933 1932 NULL, 1934 1933 &rt_stat); 1935 1934 } 1936 - evsel_script(evsel->leader)->gnum = 0; 1935 + evsel_script(leader)->gnum = 0; 1937 1936 } 1938 1937 } 1939 1938
+9 -6
tools/perf/builtin-stat.c
··· 154 154 NULL, 155 155 }; 156 156 157 + #define TOPDOWN_MAX_LEVEL 2 158 + 157 159 static const char *smi_cost_attrs = { 158 160 "{" 159 161 "msr/aperf/," ··· 250 248 evlist__warn_hybrid_group(evlist); 251 249 252 250 evlist__for_each_entry(evlist, evsel) { 253 - leader = evsel->leader; 251 + leader = evsel__leader(evsel); 254 252 255 253 /* Check that leader matches cpus with each member. */ 256 254 if (leader == evsel) ··· 271 269 } 272 270 273 271 for_each_group_evsel(pos, leader) { 274 - pos->leader = pos; 272 + evsel__set_leader(pos, pos); 275 273 pos->core.nr_members = 0; 276 274 } 277 - evsel->leader->core.nr_members = 0; 275 + evsel->core.leader->nr_members = 0; 278 276 } 279 277 } 280 278 ··· 747 745 */ 748 746 counter->errored = true; 749 747 750 - if ((counter->leader != counter) || 751 - !(counter->leader->core.nr_members > 1)) 748 + if ((evsel__leader(counter) != counter) || 749 + !(counter->core.leader->nr_members > 1)) 752 750 return COUNTER_SKIP; 753 751 } else if (evsel__fallback(counter, errno, msg, sizeof(msg))) { 754 752 if (verbose > 0) ··· 841 839 * Don't close here because we're in the wrong affinity. 842 840 */ 843 841 if ((errno == EINVAL || errno == EBADF) && 844 - counter->leader != counter && 842 + evsel__leader(counter) != counter && 845 843 counter->weak_group) { 846 844 evlist__reset_weak_group(evsel_list, counter, false); 847 845 assert(counter->reset_group); ··· 1933 1931 if (evlist__add_default_attrs(evsel_list, default_attrs1) < 0) 1934 1932 return -1; 1935 1933 1934 + stat_config.topdown_level = TOPDOWN_MAX_LEVEL; 1936 1935 if (arch_evlist__add_default_attrs(evsel_list) < 0) 1937 1936 return -1; 1938 1937 }
+5 -5
tools/perf/builtin-top.c
··· 264 264 265 265 if (top->evlist->enabled) { 266 266 if (top->zero) 267 - symbol__annotate_zero_histogram(symbol, top->sym_evsel->idx); 267 + symbol__annotate_zero_histogram(symbol, top->sym_evsel->core.idx); 268 268 else 269 - symbol__annotate_decay_histogram(symbol, top->sym_evsel->idx); 269 + symbol__annotate_decay_histogram(symbol, top->sym_evsel->core.idx); 270 270 } 271 271 if (more != 0) 272 272 printf("%d lines not displayed, maybe increase display entries [e]\n", more); ··· 301 301 302 302 /* Non-group events are considered as leader */ 303 303 if (symbol_conf.event_group && !evsel__is_group_leader(pos)) { 304 - struct hists *leader_hists = evsel__hists(pos->leader); 304 + struct hists *leader_hists = evsel__hists(evsel__leader(pos)); 305 305 306 306 hists__match(leader_hists, hists); 307 307 hists__link(leader_hists, hists); ··· 530 530 fprintf(stderr, "\nAvailable events:"); 531 531 532 532 evlist__for_each_entry(top->evlist, top->sym_evsel) 533 - fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, evsel__name(top->sym_evsel)); 533 + fprintf(stderr, "\n\t%d %s", top->sym_evsel->core.idx, evsel__name(top->sym_evsel)); 534 534 535 535 prompt_integer(&counter, "Enter details event counter"); 536 536 ··· 541 541 break; 542 542 } 543 543 evlist__for_each_entry(top->evlist, top->sym_evsel) 544 - if (top->sym_evsel->idx == counter) 544 + if (top->sym_evsel->core.idx == counter) 545 545 break; 546 546 } else 547 547 top->sym_evsel = evlist__first(top->evlist);
+424
tools/perf/pmu-events/arch/powerpc/power10/nest_metrics.json
··· 1 + [ 2 + { 3 + "MetricName": "VEC_GROUP_PUMP_RETRY_RATIO_P01", 4 + "MetricExpr": "(hv_24x7@PM_PB_RTY_VG_PUMP01\\,chip\\=?@ / hv_24x7@PM_PB_VG_PUMP01\\,chip\\=?@) * 100", 5 + "ScaleUnit": "1%", 6 + "AggregationMode": "PerChip" 7 + }, 8 + { 9 + "MetricName": "VEC_GROUP_PUMP_RETRY_RATIO_P23", 10 + "MetricExpr": "(hv_24x7@PM_PB_RTY_VG_PUMP23\\,chip\\=?@ / hv_24x7@PM_PB_VG_PUMP23\\,chip\\=?@) * 100", 11 + "ScaleUnit": "1%", 12 + "AggregationMode": "PerChip" 13 + }, 14 + { 15 + "MetricName": "LOCAL_NODE_PUMP_RETRY_RATIO_P01", 16 + "MetricExpr": "(hv_24x7@PM_PB_RTY_LNS_PUMP01\\,chip\\=?@ / hv_24x7@PM_PB_LNS_PUMP01\\,chip\\=?@) * 100", 17 + "ScaleUnit": "1%", 18 + "AggregationMode": "PerChip" 19 + }, 20 + { 21 + "MetricName": "LOCAL_NODE_PUMP_RETRY_RATIO_P23", 22 + "MetricExpr": "(hv_24x7@PM_PB_RTY_LNS_PUMP23\\,chip\\=?@ / hv_24x7@PM_PB_LNS_PUMP23\\,chip\\=?@) * 100", 23 + "ScaleUnit": "1%", 24 + "AggregationMode": "PerChip" 25 + }, 26 + { 27 + "MetricName": "GROUP_PUMP_RETRY_RATIO_P01", 28 + "MetricExpr": "(hv_24x7@PM_PB_RTY_GROUP_PUMP01\\,chip\\=?@ / hv_24x7@PM_PB_GROUP_PUMP01\\,chip\\=?@) * 100", 29 + "ScaleUnit": "1%", 30 + "AggregationMode": "PerChip" 31 + }, 32 + { 33 + "MetricName": "GROUP_PUMP_RETRY_RATIO_P23", 34 + "MetricExpr": "(hv_24x7@PM_PB_RTY_GROUP_PUMP23\\,chip\\=?@ / hv_24x7@PM_PB_GROUP_PUMP23\\,chip\\=?@) * 100", 35 + "ScaleUnit": "1%", 36 + "AggregationMode": "PerChip" 37 + }, 38 + { 39 + "MetricName": "TOTAL_GROUP_PUMPS_P01", 40 + "MetricExpr": "(hv_24x7@PM_PB_GROUP_PUMP01\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 41 + "ScaleUnit": "4", 42 + "AggregationMode": "PerChip" 43 + }, 44 + { 45 + "MetricName": "TOTAL_GROUP_PUMPS_P23", 46 + "MetricExpr": "(hv_24x7@PM_PB_GROUP_PUMP23\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 47 + "ScaleUnit": "4", 48 + "AggregationMode": "PerChip" 49 + }, 50 + { 51 + "MetricName": "TOTAL_GROUP_PUMPS_RETRIES_P01", 52 + "MetricExpr": "(hv_24x7@PM_PB_RTY_GROUP_PUMP01\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 53 + "ScaleUnit": "4", 54 + "AggregationMode": "PerChip" 55 + }, 56 + { 57 + "MetricName": "TOTAL_GROUP_PUMPS_RETRIES_P23", 58 + "MetricExpr": "(hv_24x7@PM_PB_RTY_GROUP_PUMP23\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 59 + "ScaleUnit": "4", 60 + "AggregationMode": "PerChip" 61 + }, 62 + { 63 + "MetricName": "REMOTE_NODE_PUMPS_RETRIES_RATIO_P01", 64 + "MetricExpr": "(hv_24x7@PM_PB_RTY_RNS_PUMP01\\,chip\\=?@ / hv_24x7@PM_PB_RNS_PUMP01\\,chip\\=?@) * 100", 65 + "ScaleUnit": "1%", 66 + "AggregationMode": "PerChip" 67 + }, 68 + { 69 + "MetricName": "REMOTE_NODE_PUMPS_RETRIES_RATIO_P23", 70 + "MetricExpr": "(hv_24x7@PM_PB_RTY_RNS_PUMP23\\,chip\\=?@ / hv_24x7@PM_PB_RNS_PUMP23\\,chip\\=?@) * 100", 71 + "ScaleUnit": "1%", 72 + "AggregationMode": "PerChip" 73 + }, 74 + { 75 + "MetricName": "TOTAL_VECTOR_GROUP_PUMPS_P01", 76 + "MetricExpr": "(hv_24x7@PM_PB_VG_PUMP01\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 77 + "ScaleUnit": "4", 78 + "AggregationMode": "PerChip" 79 + }, 80 + { 81 + "MetricName": "TOTAL_VECTOR_GROUP_PUMPS_P23", 82 + "MetricExpr": "(hv_24x7@PM_PB_VG_PUMP23\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 83 + "ScaleUnit": "4", 84 + "AggregationMode": "PerChip" 85 + }, 86 + { 87 + "MetricName": "TOTAL_LOCAL_NODE_PUMPS_P01", 88 + "MetricExpr": "(hv_24x7@PM_PB_LNS_PUMP01\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 89 + "ScaleUnit": "4", 90 + "AggregationMode": "PerChip" 91 + }, 92 + { 93 + "MetricName": "TOTAL_LOCAL_NODE_PUMPS_P23", 94 + "MetricExpr": "(hv_24x7@PM_PB_LNS_PUMP23\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 95 + "ScaleUnit": "4", 96 + "AggregationMode": "PerChip" 97 + }, 98 + { 99 + "MetricName": "TOTAL_VECTOR_GROUP_PUMPS_RETRIES_P01", 100 + "MetricExpr": "(hv_24x7@PM_PB_RTY_VG_PUMP01\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 101 + "ScaleUnit": "4", 102 + "AggregationMode": "PerChip" 103 + }, 104 + { 105 + "MetricName": "TOTAL_VECTOR_GROUP_PUMPS_RETRIES_P23", 106 + "MetricExpr": "(hv_24x7@PM_PB_RTY_VG_PUMP23\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 107 + "ScaleUnit": "4", 108 + "AggregationMode": "PerChip" 109 + }, 110 + { 111 + "MetricName": "TOTAL_LOCAL_NODE_PUMPS_RETRIES_P01", 112 + "MetricExpr": "(hv_24x7@PM_PB_RTY_LNS_PUMP01\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 113 + "ScaleUnit": "4", 114 + "AggregationMode": "PerChip" 115 + }, 116 + { 117 + "MetricName": "TOTAL_LOCAL_NODE_PUMPS_RETRIES_P23", 118 + "MetricExpr": "(hv_24x7@PM_PB_RTY_LNS_PUMP23\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 119 + "ScaleUnit": "4", 120 + "AggregationMode": "PerChip" 121 + }, 122 + { 123 + "MetricName": "TOTAL_REMOTE_NODE_PUMPS_P01", 124 + "MetricExpr": "(hv_24x7@PM_PB_RNS_PUMP01\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 125 + "ScaleUnit": "4", 126 + "AggregationMode": "PerChip" 127 + }, 128 + { 129 + "MetricName": "TOTAL_REMOTE_NODE_PUMPS_P23", 130 + "MetricExpr": "(hv_24x7@PM_PB_RNS_PUMP23\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 131 + "ScaleUnit": "4", 132 + "AggregationMode": "PerChip" 133 + }, 134 + { 135 + "MetricName": "TOTAL_NEAR_NODE_PUMPS_P01", 136 + "MetricExpr": "(hv_24x7@PM_PB_NNS_PUMP01\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 137 + "ScaleUnit": "4", 138 + "AggregationMode": "PerChip" 139 + }, 140 + { 141 + "MetricName": "TOTAL_NEAR_NODE_PUMPS_P23", 142 + "MetricExpr": "(hv_24x7@PM_PB_NNS_PUMP23\\,chip\\=?@ / hv_24x7@PM_PAU_CYC\\,chip\\=?@)", 143 + "ScaleUnit": "4", 144 + "AggregationMode": "PerChip" 145 + }, 146 + { 147 + "MetricName": "TOTAL_INT_PB_BW", 148 + "MetricExpr": "(hv_24x7@PM_PB_INT_DATA_XFER\\,chip\\=?@)", 149 + "ScaleUnit": "2.09MB", 150 + "AggregationMode": "PerChip" 151 + }, 152 + { 153 + "MetricName": "XLINK0_OUT_TOTAL_UTILIZATION", 154 + "MetricExpr": "((hv_24x7@PM_XLINK0_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_XLINK0_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_XLINK0_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK0_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 155 + "ScaleUnit": "1%", 156 + "AggregationMode": "PerChip" 157 + }, 158 + { 159 + "MetricName": "XLINK1_OUT_TOTAL_UTILIZATION", 160 + "MetricExpr": "((hv_24x7@PM_XLINK1_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_XLINK1_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_XLINK1_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK1_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 161 + "ScaleUnit": "1%", 162 + "AggregationMode": "PerChip" 163 + }, 164 + { 165 + "MetricName": "XLINK2_OUT_TOTAL_UTILIZATION", 166 + "MetricExpr": "((hv_24x7@PM_XLINK2_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_XLINK2_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_XLINK2_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK2_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 167 + "ScaleUnit": "1%", 168 + "AggregationMode": "PerChip" 169 + }, 170 + { 171 + "MetricName": "XLINK3_OUT_TOTAL_UTILIZATION", 172 + "MetricExpr": "((hv_24x7@PM_XLINK3_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_XLINK3_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_XLINK3_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK3_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 173 + "ScaleUnit": "1%", 174 + "AggregationMode": "PerChip" 175 + }, 176 + { 177 + "MetricName": "XLINK4_OUT_TOTAL_UTILIZATION", 178 + "MetricExpr": "((hv_24x7@PM_XLINK4_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_XLINK4_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_XLINK4_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK4_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 179 + "ScaleUnit": "1%", 180 + "AggregationMode": "PerChip" 181 + }, 182 + { 183 + "MetricName": "XLINK5_OUT_TOTAL_UTILIZATION", 184 + "MetricExpr": "((hv_24x7@PM_XLINK5_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_XLINK5_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_XLINK5_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK5_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 185 + "ScaleUnit": "1%", 186 + "AggregationMode": "PerChip" 187 + }, 188 + { 189 + "MetricName": "XLINK6_OUT_TOTAL_UTILIZATION", 190 + "MetricExpr": "((hv_24x7@PM_XLINK6_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_XLINK6_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_XLINK6_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK6_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 191 + "ScaleUnit": "1%", 192 + "AggregationMode": "PerChip" 193 + }, 194 + { 195 + "MetricName": "XLINK7_OUT_TOTAL_UTILIZATION", 196 + "MetricExpr": "((hv_24x7@PM_XLINK7_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_XLINK7_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_XLINK7_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK7_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 197 + "ScaleUnit": "1%", 198 + "AggregationMode": "PerChip" 199 + }, 200 + { 201 + "MetricName": "XLINK0_OUT_DATA_UTILIZATION", 202 + "MetricExpr": "((hv_24x7@PM_XLINK0_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_XLINK0_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_XLINK0_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK0_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 203 + "ScaleUnit": "1.063%", 204 + "AggregationMode": "PerChip" 205 + }, 206 + { 207 + "MetricName": "XLINK1_OUT_DATA_UTILIZATION", 208 + "MetricExpr": "((hv_24x7@PM_XLINK1_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_XLINK1_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_XLINK1_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK1_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 209 + "ScaleUnit": "1.063%", 210 + "AggregationMode": "PerChip" 211 + }, 212 + { 213 + "MetricName": "XLINK2_OUT_DATA_UTILIZATION", 214 + "MetricExpr": "((hv_24x7@PM_XLINK2_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_XLINK2_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_XLINK2_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK2_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 215 + "ScaleUnit": "1.063%", 216 + "AggregationMode": "PerChip" 217 + }, 218 + { 219 + "MetricName": "XLINK3_OUT_DATA_UTILIZATION", 220 + "MetricExpr": "((hv_24x7@PM_XLINK3_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_XLINK3_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_XLINK3_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK3_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 221 + "ScaleUnit": "1.063%", 222 + "AggregationMode": "PerChip" 223 + }, 224 + { 225 + "MetricName": "XLINK4_OUT_DATA_UTILIZATION", 226 + "MetricExpr": "((hv_24x7@PM_XLINK4_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_XLINK4_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_XLINK4_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK4_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 227 + "ScaleUnit": "1.063%", 228 + "AggregationMode": "PerChip" 229 + }, 230 + { 231 + "MetricName": "XLINK5_OUT_DATA_UTILIZATION", 232 + "MetricExpr": "((hv_24x7@PM_XLINK5_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_XLINK5_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_XLINK5_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK5_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 233 + "ScaleUnit": "1.063%", 234 + "AggregationMode": "PerChip" 235 + }, 236 + { 237 + "MetricName": "XLINK6_OUT_DATA_UTILIZATION", 238 + "MetricExpr": "((hv_24x7@PM_XLINK6_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_XLINK6_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_XLINK6_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK6_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 239 + "ScaleUnit": "1.063%", 240 + "AggregationMode": "PerChip" 241 + }, 242 + { 243 + "MetricName": "XLINK7_OUT_DATA_UTILIZATION", 244 + "MetricExpr": "((hv_24x7@PM_XLINK7_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_XLINK7_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_XLINK7_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_XLINK7_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 245 + "ScaleUnit": "1.063%", 246 + "AggregationMode": "PerChip" 247 + }, 248 + { 249 + "MetricName": "ALINK0_OUT_TOTAL_UTILIZATION", 250 + "MetricExpr": "((hv_24x7@PM_ALINK0_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_ALINK0_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_ALINK0_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK0_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 251 + "ScaleUnit": "1%", 252 + "AggregationMode": "PerChip" 253 + }, 254 + { 255 + "MetricName": "ALINK1_OUT_TOTAL_UTILIZATION", 256 + "MetricExpr": "((hv_24x7@PM_ALINK1_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_ALINK1_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_ALINK1_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK1_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 257 + "ScaleUnit": "1%", 258 + "AggregationMode": "PerChip" 259 + }, 260 + { 261 + "MetricName": "ALINK2_OUT_TOTAL_UTILIZATION", 262 + "MetricExpr": "((hv_24x7@PM_ALINK2_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_ALINK2_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_ALINK2_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK2_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 263 + "ScaleUnit": "1%", 264 + "AggregationMode": "PerChip" 265 + }, 266 + { 267 + "MetricName": "ALINK3_OUT_TOTAL_UTILIZATION", 268 + "MetricExpr": "((hv_24x7@PM_ALINK3_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_ALINK3_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_ALINK3_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK3_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 269 + "ScaleUnit": "1%", 270 + "AggregationMode": "PerChip" 271 + }, 272 + { 273 + "MetricName": "ALINK4_OUT_TOTAL_UTILIZATION", 274 + "MetricExpr": "((hv_24x7@PM_ALINK4_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_ALINK4_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_ALINK4_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK4_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 275 + "ScaleUnit": "1%", 276 + "AggregationMode": "PerChip" 277 + }, 278 + { 279 + "MetricName": "ALINK5_OUT_TOTAL_UTILIZATION", 280 + "MetricExpr": "((hv_24x7@PM_ALINK5_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_ALINK5_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_ALINK5_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK5_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 281 + "ScaleUnit": "1%", 282 + "AggregationMode": "PerChip" 283 + }, 284 + { 285 + "MetricName": "ALINK6_OUT_TOTAL_UTILIZATION", 286 + "MetricExpr": "((hv_24x7@PM_ALINK6_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_ALINK6_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_ALINK6_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK6_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 287 + "ScaleUnit": "1%", 288 + "AggregationMode": "PerChip" 289 + }, 290 + { 291 + "MetricName": "ALINK7_OUT_TOTAL_UTILIZATION", 292 + "MetricExpr": "((hv_24x7@PM_ALINK7_OUT_ODD_TOTAL_UTIL\\,chip\\=?@ + hv_24x7@PM_ALINK7_OUT_EVEN_TOTAL_UTIL\\,chip\\=?@) / (hv_24x7@PM_ALINK7_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK7_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 293 + "ScaleUnit": "1%", 294 + "AggregationMode": "PerChip" 295 + }, 296 + { 297 + "MetricName": "ALINK0_OUT_DATA_UTILIZATION", 298 + "MetricExpr": "((hv_24x7@PM_ALINK0_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_ALINK0_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_ALINK0_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK0_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 299 + "ScaleUnit": "1.063%", 300 + "AggregationMode": "PerChip" 301 + }, 302 + { 303 + "MetricName": "ALINK1_OUT_DATA_UTILIZATION", 304 + "MetricExpr": "((hv_24x7@PM_ALINK1_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_ALINK1_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_ALINK1_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK1_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 305 + "ScaleUnit": "1.063%", 306 + "AggregationMode": "PerChip" 307 + }, 308 + { 309 + "MetricName": "ALINK2_OUT_DATA_UTILIZATION", 310 + "MetricExpr": "((hv_24x7@PM_ALINK2_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_ALINK2_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_ALINK2_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK2_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 311 + "ScaleUnit": "1.063%", 312 + "AggregationMode": "PerChip" 313 + }, 314 + { 315 + "MetricName": "ALINK3_OUT_DATA_UTILIZATION", 316 + "MetricExpr": "((hv_24x7@PM_ALINK3_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_ALINK3_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_ALINK3_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK3_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 317 + "ScaleUnit": "1.063%", 318 + "AggregationMode": "PerChip" 319 + }, 320 + { 321 + "MetricName": "ALINK4_OUT_DATA_UTILIZATION", 322 + "MetricExpr": "((hv_24x7@PM_ALINK4_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_ALINK4_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_ALINK4_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK4_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 323 + "ScaleUnit": "1.063%", 324 + "AggregationMode": "PerChip" 325 + }, 326 + { 327 + "MetricName": "ALINK5_OUT_DATA_UTILIZATION", 328 + "MetricExpr": "((hv_24x7@PM_ALINK5_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_ALINK5_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_ALINK5_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK5_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 329 + "ScaleUnit": "1.063%", 330 + "AggregationMode": "PerChip" 331 + }, 332 + { 333 + "MetricName": "ALINK6_OUT_DATA_UTILIZATION", 334 + "MetricExpr": "((hv_24x7@PM_ALINK6_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_ALINK6_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_ALINK6_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK6_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 335 + "ScaleUnit": "1.063%", 336 + "AggregationMode": "PerChip" 337 + }, 338 + { 339 + "MetricName": "ALINK7_OUT_DATA_UTILIZATION", 340 + "MetricExpr": "((hv_24x7@PM_ALINK7_OUT_ODD_DATA\\,chip\\=?@ + hv_24x7@PM_ALINK7_OUT_EVEN_DATA\\,chip\\=?@) / (hv_24x7@PM_ALINK7_OUT_ODD_AVLBL_CYCLES\\,chip\\=?@ + hv_24x7@PM_ALINK7_OUT_EVEN_AVLBL_CYCLES\\,chip\\=?@)) * 100", 341 + "ScaleUnit": "1.063%", 342 + "AggregationMode": "PerChip" 343 + }, 344 + { 345 + "MetricName": "TOTAL_DATA_BANDWIDTH_TRANSFERRED_OVER_PB_PCI1", 346 + "MetricExpr": "(hv_24x7@PM_PCI1_32B_INOUT\\,chip\\=?@)", 347 + "ScaleUnit": "3.28e-2MB", 348 + "AggregationMode": "PerChip" 349 + }, 350 + { 351 + "MetricName": "TOTAL_DATA_BANDWIDTH_TRANSFERRED_OVER_PB_PCI0", 352 + "MetricExpr": "(hv_24x7@PM_PCI0_32B_INOUT\\,chip\\=?@)", 353 + "ScaleUnit": "3.28e-2MB", 354 + "AggregationMode": "PerChip" 355 + }, 356 + { 357 + "MetricName": "TOTAL_MCS_READ_BW_MC0_CHAN01", 358 + "MetricExpr": "(hv_24x7@PM_MCS_128B_RD_DATA_BLOCKS_MC0_CHAN01\\,chip\\=?@)", 359 + "ScaleUnit": "5.24e-1MB", 360 + "AggregationMode": "PerChip" 361 + }, 362 + { 363 + "MetricName": "TOTAL_MCS_READ_BW_MC1_CHAN01", 364 + "MetricExpr": "(hv_24x7@PM_MCS_128B_RD_DATA_BLOCKS_MC1_CHAN01\\,chip\\=?@)", 365 + "ScaleUnit": "5.24e-1MB", 366 + "AggregationMode": "PerChip" 367 + }, 368 + { 369 + "MetricName": "TOTAL_MCS_READ_BW_MC2_CHAN01", 370 + "MetricExpr": "(hv_24x7@PM_MCS_128B_RD_DATA_BLOCKS_MC2_CHAN01\\,chip\\=?@)", 371 + "ScaleUnit": "5.24e-1MB", 372 + "AggregationMode": "PerChip" 373 + }, 374 + { 375 + "MetricName": "TOTAL_MCS_READ_BW_MC3_CHAN01", 376 + "MetricExpr": "(hv_24x7@PM_MCS_128B_RD_DATA_BLOCKS_MC3_CHAN01\\,chip\\=?@)", 377 + "ScaleUnit": "5.24e-1MB", 378 + "AggregationMode": "PerChip" 379 + }, 380 + { 381 + "MetricName": "TOTAL_MCS_WRITE_BW_MC0_CHAN01", 382 + "MetricExpr": "(hv_24x7@PM_MCS_64B_WR_DATA_BLOCKS_MC0_CHAN01\\,chip\\=?@)", 383 + "ScaleUnit": "2.6e-1MB", 384 + "AggregationMode": "PerChip" 385 + }, 386 + { 387 + "MetricName": "TOTAL_MCS_WRITE_BW_MC1_CHAN01", 388 + "MetricExpr": "(hv_24x7@PM_MCS_64B_WR_DATA_BLOCKS_MC1_CHAN01\\,chip\\=?@)", 389 + "ScaleUnit": "2.6e-1MB", 390 + "AggregationMode": "PerChip" 391 + }, 392 + { 393 + "MetricName": "TOTAL_MCS_WRITE_BW_MC2_CHAN01", 394 + "MetricExpr": "(hv_24x7@PM_MCS_64B_WR_DATA_BLOCKS_MC2_CHAN01\\,chip\\=?@)", 395 + "ScaleUnit": "2.6e-1MB", 396 + "AggregationMode": "PerChip" 397 + }, 398 + { 399 + "MetricName": "TOTAL_MCS_WRITE_BW_MC3_CHAN01", 400 + "MetricExpr": "(hv_24x7@PM_MCS_64B_WR_DATA_BLOCKS_MC3_CHAN01\\,chip\\=?@)", 401 + "ScaleUnit": "2.6e-1MB", 402 + "AggregationMode": "PerChip" 403 + }, 404 + { 405 + "MetricName": "Memory_RD_BW_Chip", 406 + "MetricExpr": "(hv_24x7@PM_MCS_128B_RD_DATA_BLOCKS_MC0_CHAN01\\,chip\\=?@ + hv_24x7@PM_MCS_128B_RD_DATA_BLOCKS_MC1_CHAN01\\,chip\\=?@ + hv_24x7@PM_MCS_128B_RD_DATA_BLOCKS_MC2_CHAN01\\,chip\\=?@ + hv_24x7@PM_MCS_128B_RD_DATA_BLOCKS_MC3_CHAN01\\,chip\\=?@)", 407 + "MetricGroup": "Memory_BW", 408 + "ScaleUnit": "5.24e-1MB", 409 + "AggregationMode": "PerChip" 410 + }, 411 + { 412 + "MetricName": "Memory_WR_BW_Chip", 413 + "MetricExpr": "(hv_24x7@PM_MCS_64B_WR_DATA_BLOCKS_MC0_CHAN01\\,chip\\=?@ + hv_24x7@PM_MCS_64B_WR_DATA_BLOCKS_MC1_CHAN01\\,chip\\=?@ + hv_24x7@PM_MCS_64B_WR_DATA_BLOCKS_MC2_CHAN01\\,chip\\=?@ + hv_24x7@PM_MCS_64B_WR_DATA_BLOCKS_MC3_CHAN01\\,chip\\=?@ )", 414 + "MetricGroup": "Memory_BW", 415 + "ScaleUnit": "2.6e-1MB", 416 + "AggregationMode": "PerChip" 417 + }, 418 + { 419 + "MetricName": "PowerBUS_Frequency", 420 + "MetricExpr": "(hv_24x7@PM_PAU_CYC\\,chip\\=?@ )", 421 + "ScaleUnit": "2.56e-7GHz", 422 + "AggregationMode": "PerChip" 423 + } 424 + ]
+1 -1
tools/perf/tests/bpf.c
··· 151 151 } 152 152 153 153 evlist__splice_list_tail(evlist, &parse_state.list); 154 - evlist->nr_groups = parse_state.nr_groups; 154 + evlist->core.nr_groups = parse_state.nr_groups; 155 155 156 156 evlist__config(evlist, &opts, NULL); 157 157
+11 -4
tools/perf/tests/builtin-test.c
··· 26 26 #include <linux/kernel.h> 27 27 #include <linux/string.h> 28 28 #include <subcmd/exec-cmd.h> 29 + #include <linux/zalloc.h> 29 30 30 31 static bool dont_fork; 31 32 ··· 541 540 { 542 541 struct dirent **entlist; 543 542 struct dirent *ent; 544 - int n_dirs; 543 + int n_dirs, e; 545 544 char path_dir[PATH_MAX]; 546 545 const char *path = shell_tests__dir(path_dir, sizeof(path_dir)); 547 546 int width = 0; ··· 565 564 } 566 565 } 567 566 567 + for (e = 0; e < n_dirs; e++) 568 + zfree(&entlist[e]); 568 569 free(entlist); 569 - 570 570 return width; 571 571 } 572 572 ··· 598 596 { 599 597 struct dirent **entlist; 600 598 struct dirent *ent; 601 - int n_dirs; 599 + int n_dirs, e; 602 600 char path_dir[PATH_MAX]; 603 601 struct shell_test st = { 604 602 .dir = shell_tests__dir(path_dir, sizeof(path_dir)), ··· 631 629 test_and_print(&test, false, -1); 632 630 } 633 631 632 + for (e = 0; e < n_dirs; e++) 633 + zfree(&entlist[e]); 634 634 free(entlist); 635 635 return 0; 636 636 } ··· 734 730 { 735 731 struct dirent **entlist; 736 732 struct dirent *ent; 737 - int n_dirs; 733 + int n_dirs, e; 738 734 char path_dir[PATH_MAX]; 739 735 const char *path = shell_tests__dir(path_dir, sizeof(path_dir)); 740 736 ··· 756 752 continue; 757 753 758 754 pr_info("%2d: %s\n", i, t.desc); 755 + 759 756 } 760 757 758 + for (e = 0; e < n_dirs; e++) 759 + zfree(&entlist[e]); 761 760 free(entlist); 762 761 return 0; 763 762 }
+3 -3
tools/perf/tests/evsel-roundtrip-name.c
··· 44 44 45 45 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 46 46 __evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name)); 47 - if (evsel->idx != idx) 47 + if (evsel->core.idx != idx) 48 48 continue; 49 49 50 50 ++idx; ··· 84 84 85 85 err = 0; 86 86 evlist__for_each_entry(evlist, evsel) { 87 - if (strcmp(evsel__name(evsel), names[evsel->idx / distance])) { 87 + if (strcmp(evsel__name(evsel), names[evsel->core.idx / distance])) { 88 88 --err; 89 - pr_debug("%s != %s\n", evsel__name(evsel), names[evsel->idx / distance]); 89 + pr_debug("%s != %s\n", evsel__name(evsel), names[evsel->core.idx / distance]); 90 90 } 91 91 } 92 92
+4 -4
tools/perf/tests/mmap-basic.c
··· 139 139 " doesn't map to an evsel\n", sample.id); 140 140 goto out_delete_evlist; 141 141 } 142 - nr_events[evsel->idx]++; 142 + nr_events[evsel->core.idx]++; 143 143 perf_mmap__consume(&md->core); 144 144 } 145 145 perf_mmap__read_done(&md->core); ··· 147 147 out_init: 148 148 err = 0; 149 149 evlist__for_each_entry(evlist, evsel) { 150 - if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { 150 + if (nr_events[evsel->core.idx] != expected_nr_events[evsel->core.idx]) { 151 151 pr_debug("expected %d %s events, got %d\n", 152 - expected_nr_events[evsel->idx], 153 - evsel__name(evsel), nr_events[evsel->idx]); 152 + expected_nr_events[evsel->core.idx], 153 + evsel__name(evsel), nr_events[evsel->core.idx]); 154 154 err = -1; 155 155 goto out_delete_evlist; 156 156 }
+37 -37
tools/perf/tests/parse-events.c
··· 49 49 struct evsel *evsel = evlist__first(evlist); 50 50 51 51 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); 52 - TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); 52 + TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->core.nr_groups); 53 53 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->core.attr.type); 54 54 TEST_ASSERT_VAL("wrong sample_type", 55 55 PERF_TP_SAMPLE_TYPE == evsel->core.attr.sample_type); ··· 62 62 struct evsel *evsel; 63 63 64 64 TEST_ASSERT_VAL("wrong number of entries", evlist->core.nr_entries > 1); 65 - TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); 65 + TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->core.nr_groups); 66 66 67 67 evlist__for_each_entry(evlist, evsel) { 68 68 TEST_ASSERT_VAL("wrong type", ··· 668 668 struct evsel *evsel, *leader; 669 669 670 670 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); 671 - TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); 671 + TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->core.nr_groups); 672 672 673 673 /* instructions:k */ 674 674 evsel = leader = evlist__first(evlist); ··· 698 698 TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 699 699 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 700 700 TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 2); 701 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 701 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 702 702 TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); 703 703 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); 704 704 ··· 710 710 struct evsel *evsel, *leader; 711 711 712 712 TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->core.nr_entries); 713 - TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); 713 + TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->core.nr_groups); 714 714 715 715 /* faults + :ku modifier */ 716 716 evsel = leader = evlist__first(evlist); ··· 739 739 TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 740 740 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 741 741 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 742 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 742 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 743 743 TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); 744 744 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); 745 745 ··· 765 765 struct evsel *evsel, *leader; 766 766 767 767 TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->core.nr_entries); 768 - TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups); 768 + TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->core.nr_groups); 769 769 770 770 /* group1 syscalls:sys_enter_openat:H */ 771 771 evsel = leader = evlist__first(evlist); ··· 798 798 TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 799 799 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 800 800 TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 3); 801 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 801 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 802 802 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 803 803 TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); 804 804 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); ··· 831 831 TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 832 832 TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); 833 833 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 834 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 834 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 835 835 TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); 836 836 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); 837 837 ··· 857 857 struct evsel *evsel, *leader; 858 858 859 859 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); 860 - TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); 860 + TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->core.nr_groups); 861 861 862 862 /* cycles:u + p */ 863 863 evsel = leader = evlist__first(evlist); ··· 889 889 TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 890 890 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 891 891 TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 2); 892 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 892 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 893 893 TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); 894 894 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); 895 895 ··· 901 901 struct evsel *evsel, *leader; 902 902 903 903 TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->core.nr_entries); 904 - TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups); 904 + TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->core.nr_groups); 905 905 906 906 /* cycles + G */ 907 907 evsel = leader = evlist__first(evlist); ··· 931 931 TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 932 932 TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); 933 933 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 934 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 934 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 935 935 TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); 936 936 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read); 937 937 ··· 963 963 TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 964 964 TEST_ASSERT_VAL("wrong exclude host", evsel->core.attr.exclude_host); 965 965 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 966 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 966 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 967 967 TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); 968 968 969 969 /* cycles */ ··· 987 987 struct evsel *evsel, *leader; 988 988 989 989 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); 990 - TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); 990 + TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->core.nr_groups); 991 991 992 992 /* cycles + :H group modifier */ 993 993 evsel = leader = evlist__first(evlist); ··· 1016 1016 TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 1017 1017 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1018 1018 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1019 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1019 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1020 1020 TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); 1021 1021 1022 1022 return 0; ··· 1027 1027 struct evsel *evsel, *leader; 1028 1028 1029 1029 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); 1030 - TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); 1030 + TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->core.nr_groups); 1031 1031 1032 1032 /* cycles + :G group modifier */ 1033 1033 evsel = leader = evlist__first(evlist); ··· 1056 1056 TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 1057 1057 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1058 1058 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1059 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1059 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1060 1060 TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); 1061 1061 1062 1062 return 0; ··· 1067 1067 struct evsel *evsel, *leader; 1068 1068 1069 1069 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); 1070 - TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); 1070 + TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->core.nr_groups); 1071 1071 1072 1072 /* cycles:G + :u group modifier */ 1073 1073 evsel = leader = evlist__first(evlist); ··· 1096 1096 TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 1097 1097 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1098 1098 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1099 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1099 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1100 1100 TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); 1101 1101 1102 1102 return 0; ··· 1107 1107 struct evsel *evsel, *leader; 1108 1108 1109 1109 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); 1110 - TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); 1110 + TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->core.nr_groups); 1111 1111 1112 1112 /* cycles:G + :uG group modifier */ 1113 1113 evsel = leader = evlist__first(evlist); ··· 1136 1136 TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 1137 1137 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1138 1138 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1139 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1139 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1140 1140 TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1); 1141 1141 1142 1142 return 0; ··· 1160 1160 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1161 1161 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1162 1162 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 1163 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1163 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1164 1164 TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); 1165 1165 1166 1166 /* cache-misses - not sampling */ ··· 1174 1174 TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 1175 1175 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1176 1176 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1177 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1177 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1178 1178 TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); 1179 1179 1180 1180 /* branch-misses - not sampling */ ··· 1189 1189 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1190 1190 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1191 1191 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 1192 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1192 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1193 1193 TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); 1194 1194 1195 1195 return 0; ··· 1213 1213 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1214 1214 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1215 1215 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 1216 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1216 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1217 1217 TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); 1218 1218 1219 1219 /* branch-misses - not sampling */ ··· 1228 1228 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1229 1229 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1230 1230 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 1231 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1231 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1232 1232 TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read); 1233 1233 1234 1234 return 0; ··· 1259 1259 TEST_ASSERT_VAL("wrong config", 1260 1260 PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); 1261 1261 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 1262 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1262 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1263 1263 TEST_ASSERT_VAL("wrong pinned", evsel->core.attr.pinned); 1264 1264 1265 1265 /* cache-misses - can not be pinned, but will go on with the leader */ ··· 1303 1303 TEST_ASSERT_VAL("wrong config", 1304 1304 PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); 1305 1305 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 1306 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1306 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1307 1307 TEST_ASSERT_VAL("wrong exclusive", evsel->core.attr.exclusive); 1308 1308 1309 1309 /* cache-misses - can not be pinned, but will go on with the leader */ ··· 1530 1530 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); 1531 1531 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); 1532 1532 TEST_ASSERT_VAL("wrong config", 0x3c == evsel->core.attr.config); 1533 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1533 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1534 1534 1535 1535 evsel = evsel__next(evsel); 1536 1536 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); 1537 1537 TEST_ASSERT_VAL("wrong config", 0xc0 == evsel->core.attr.config); 1538 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1538 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1539 1539 return 0; 1540 1540 } 1541 1541 ··· 1546 1546 evsel = leader = evlist__first(evlist); 1547 1547 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); 1548 1548 TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type); 1549 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1549 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1550 1550 1551 1551 evsel = evsel__next(evsel); 1552 1552 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); 1553 1553 TEST_ASSERT_VAL("wrong config", 0x3c == evsel->core.attr.config); 1554 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1554 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1555 1555 return 0; 1556 1556 } 1557 1557 ··· 1563 1563 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); 1564 1564 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); 1565 1565 TEST_ASSERT_VAL("wrong config", 0x3c == evsel->core.attr.config); 1566 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1566 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1567 1567 1568 1568 evsel = evsel__next(evsel); 1569 1569 TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type); 1570 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1570 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1571 1571 return 0; 1572 1572 } 1573 1573 ··· 1579 1579 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries); 1580 1580 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); 1581 1581 TEST_ASSERT_VAL("wrong config", 0x3c == evsel->core.attr.config); 1582 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1582 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1583 1583 TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); 1584 1584 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1585 1585 1586 1586 evsel = evsel__next(evsel); 1587 1587 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); 1588 1588 TEST_ASSERT_VAL("wrong config", 0xc0 == evsel->core.attr.config); 1589 - TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 1589 + TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1590 1590 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1591 1591 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1592 1592 return 0;
+2 -2
tools/perf/tests/pfm.c
··· 96 96 count_pfm_events(&evlist->core), 97 97 table[i].nr_events); 98 98 TEST_ASSERT_EQUAL(table[i].events, 99 - evlist->nr_groups, 99 + evlist->core.nr_groups, 100 100 0); 101 101 102 102 evlist__delete(evlist); ··· 180 180 count_pfm_events(&evlist->core), 181 181 table[i].nr_events); 182 182 TEST_ASSERT_EQUAL(table[i].events, 183 - evlist->nr_groups, 183 + evlist->core.nr_groups, 184 184 table[i].nr_groups); 185 185 186 186 evlist__delete(evlist);
+3 -3
tools/perf/ui/browsers/annotate.c
··· 350 350 struct annotation_line *it = al; 351 351 352 352 /* find next asm line */ 353 - list_for_each_entry_continue(it, browser->b.top, node) { 353 + list_for_each_entry_continue(it, browser->b.entries, node) { 354 354 if (it->idx_asm >= 0) 355 355 return it; 356 356 } 357 357 358 358 /* no asm line found forwards, try backwards */ 359 359 it = al; 360 - list_for_each_entry_continue_reverse(it, browser->b.top, node) { 360 + list_for_each_entry_continue_reverse(it, browser->b.entries, node) { 361 361 if (it->idx_asm >= 0) 362 362 return it; 363 363 } ··· 749 749 hbt->timer(hbt->arg); 750 750 751 751 if (delay_secs != 0) { 752 - symbol__annotate_decay_histogram(sym, evsel->idx); 752 + symbol__annotate_decay_histogram(sym, evsel->core.idx); 753 753 hists__scnprintf_title(hists, title, sizeof(title)); 754 754 annotate_browser__show(&browser->b, title, help); 755 755 }
+2 -2
tools/perf/ui/gtk/annotate.c
··· 135 135 ret += perf_gtk__get_percent(s + ret, 136 136 sizeof(s) - ret, 137 137 sym, pos, 138 - evsel->idx + i); 138 + evsel->core.idx + i); 139 139 ret += scnprintf(s + ret, sizeof(s) - ret, " "); 140 140 } 141 141 } else { 142 142 ret = perf_gtk__get_percent(s, sizeof(s), sym, pos, 143 - evsel->idx); 143 + evsel->core.idx); 144 144 } 145 145 146 146 if (ret)
+1
tools/perf/util/Build
··· 141 141 perf-$(CONFIG_LIBBPF) += bpf-loader.o 142 142 perf-$(CONFIG_LIBBPF) += bpf_map.o 143 143 perf-$(CONFIG_PERF_BPF_SKEL) += bpf_counter.o 144 + perf-$(CONFIG_PERF_BPF_SKEL) += bpf_counter_cgroup.o 144 145 perf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o 145 146 perf-$(CONFIG_LIBELF) += symbol-elf.o 146 147 perf-$(CONFIG_LIBELF) += probe-file.o
+4 -4
tools/perf/util/annotate.c
··· 961 961 if (sym == NULL) 962 962 return 0; 963 963 src = symbol__hists(sym, evsel->evlist->core.nr_entries); 964 - return src ? __symbol__inc_addr_samples(ms, src, evsel->idx, addr, sample) : 0; 964 + return src ? __symbol__inc_addr_samples(ms, src, evsel->core.idx, addr, sample) : 0; 965 965 } 966 966 967 967 static int symbol__account_cycles(u64 addr, u64 start, ··· 2159 2159 2160 2160 BUG_ON(i >= al->data_nr); 2161 2161 2162 - sym_hist = annotation__histogram(notes, evsel->idx); 2162 + sym_hist = annotation__histogram(notes, evsel->core.idx); 2163 2163 data = &al->data[i++]; 2164 2164 2165 2165 calc_percent(sym_hist, hists, data, al->offset, end); ··· 2340 2340 static void symbol__annotate_hits(struct symbol *sym, struct evsel *evsel) 2341 2341 { 2342 2342 struct annotation *notes = symbol__annotation(sym); 2343 - struct sym_hist *h = annotation__histogram(notes, evsel->idx); 2343 + struct sym_hist *h = annotation__histogram(notes, evsel->core.idx); 2344 2344 u64 len = symbol__size(sym), offset; 2345 2345 2346 2346 for (offset = 0; offset < len; ++offset) ··· 2373 2373 const char *d_filename; 2374 2374 const char *evsel_name = evsel__name(evsel); 2375 2375 struct annotation *notes = symbol__annotation(sym); 2376 - struct sym_hist *h = annotation__histogram(notes, evsel->idx); 2376 + struct sym_hist *h = annotation__histogram(notes, evsel->core.idx); 2377 2377 struct annotation_line *pos, *queue = NULL; 2378 2378 u64 start = map__rip_2objdump(map, sym->start); 2379 2379 int printed = 2, queue_len = 0, addr_fmt_width;
+6 -6
tools/perf/util/auxtrace.c
··· 73 73 grp = false; 74 74 evlist__for_each_entry(evlist, evsel) { 75 75 if (grp) { 76 - if (!(evsel->leader == leader || 77 - (evsel->leader == evsel && 76 + if (!(evsel__leader(evsel) == leader || 77 + (evsel__leader(evsel) == evsel && 78 78 evsel->core.nr_members <= 1))) 79 79 return -EINVAL; 80 80 } else if (evsel == leader) { ··· 87 87 grp = false; 88 88 evlist__for_each_entry(evlist, evsel) { 89 89 if (grp) { 90 - if (evsel->leader != leader) { 91 - evsel->leader = leader; 90 + if (!evsel__has_leader(evsel, leader)) { 91 + evsel__set_leader(evsel, leader); 92 92 if (leader->core.nr_members < 1) 93 93 leader->core.nr_members = 1; 94 94 leader->core.nr_members += 1; ··· 1231 1231 1232 1232 /* Find new leader for the group */ 1233 1233 evlist__for_each_entry(evlist, evsel) { 1234 - if (evsel->leader != leader || evsel == leader) 1234 + if (!evsel__has_leader(evsel, leader) || evsel == leader) 1235 1235 continue; 1236 1236 if (!new_leader) 1237 1237 new_leader = evsel; 1238 - evsel->leader = new_leader; 1238 + evsel__set_leader(evsel, new_leader); 1239 1239 } 1240 1240 1241 1241 /* Update group information */
+6 -1
tools/perf/util/bpf_counter.c
··· 18 18 #include "evsel.h" 19 19 #include "evlist.h" 20 20 #include "target.h" 21 + #include "cgroup.h" 21 22 #include "cpumap.h" 22 23 #include "thread_map.h" 23 24 ··· 353 352 enum bperf_filter_type *filter_type, 354 353 __u32 *filter_entry_cnt) 355 354 { 356 - if (evsel->leader->core.nr_members > 1) { 355 + if (evsel->core.leader->nr_members > 1) { 357 356 pr_err("bpf managed perf events do not yet support groups.\n"); 358 357 return -1; 359 358 } ··· 743 742 .destroy = bperf__destroy, 744 743 }; 745 744 745 + extern struct bpf_counter_ops bperf_cgrp_ops; 746 + 746 747 static inline bool bpf_counter_skip(struct evsel *evsel) 747 748 { 748 749 return list_empty(&evsel->bpf_counter_list) && ··· 762 759 { 763 760 if (target->bpf_str) 764 761 evsel->bpf_counter_ops = &bpf_program_profiler_ops; 762 + else if (cgrp_event_expanded && target->use_bpf) 763 + evsel->bpf_counter_ops = &bperf_cgrp_ops; 765 764 else if (target->use_bpf || evsel->bpf_counter || 766 765 evsel__match_bpf_counter_events(evsel->name)) 767 766 evsel->bpf_counter_ops = &bperf_ops;
+307
tools/perf/util/bpf_counter_cgroup.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + /* Copyright (c) 2021 Facebook */ 4 + /* Copyright (c) 2021 Google */ 5 + 6 + #include <assert.h> 7 + #include <limits.h> 8 + #include <unistd.h> 9 + #include <sys/file.h> 10 + #include <sys/time.h> 11 + #include <sys/resource.h> 12 + #include <linux/err.h> 13 + #include <linux/zalloc.h> 14 + #include <linux/perf_event.h> 15 + #include <api/fs/fs.h> 16 + #include <perf/bpf_perf.h> 17 + 18 + #include "affinity.h" 19 + #include "bpf_counter.h" 20 + #include "cgroup.h" 21 + #include "counts.h" 22 + #include "debug.h" 23 + #include "evsel.h" 24 + #include "evlist.h" 25 + #include "target.h" 26 + #include "cpumap.h" 27 + #include "thread_map.h" 28 + 29 + #include "bpf_skel/bperf_cgroup.skel.h" 30 + 31 + static struct perf_event_attr cgrp_switch_attr = { 32 + .type = PERF_TYPE_SOFTWARE, 33 + .config = PERF_COUNT_SW_CGROUP_SWITCHES, 34 + .size = sizeof(cgrp_switch_attr), 35 + .sample_period = 1, 36 + .disabled = 1, 37 + }; 38 + 39 + static struct evsel *cgrp_switch; 40 + static struct bperf_cgroup_bpf *skel; 41 + 42 + #define FD(evt, cpu) (*(int *)xyarray__entry(evt->core.fd, cpu, 0)) 43 + 44 + static int bperf_load_program(struct evlist *evlist) 45 + { 46 + struct bpf_link *link; 47 + struct evsel *evsel; 48 + struct cgroup *cgrp, *leader_cgrp; 49 + __u32 i, cpu; 50 + __u32 nr_cpus = evlist->core.all_cpus->nr; 51 + int total_cpus = cpu__max_cpu(); 52 + int map_size, map_fd; 53 + int prog_fd, err; 54 + 55 + skel = bperf_cgroup_bpf__open(); 56 + if (!skel) { 57 + pr_err("Failed to open cgroup skeleton\n"); 58 + return -1; 59 + } 60 + 61 + skel->rodata->num_cpus = total_cpus; 62 + skel->rodata->num_events = evlist->core.nr_entries / nr_cgroups; 63 + 64 + BUG_ON(evlist->core.nr_entries % nr_cgroups != 0); 65 + 66 + /* we need one copy of events per cpu for reading */ 67 + map_size = total_cpus * evlist->core.nr_entries / nr_cgroups; 68 + bpf_map__resize(skel->maps.events, map_size); 69 + bpf_map__resize(skel->maps.cgrp_idx, nr_cgroups); 70 + /* previous result is saved in a per-cpu array */ 71 + map_size = evlist->core.nr_entries / nr_cgroups; 72 + bpf_map__resize(skel->maps.prev_readings, map_size); 73 + /* cgroup result needs all events (per-cpu) */ 74 + map_size = evlist->core.nr_entries; 75 + bpf_map__resize(skel->maps.cgrp_readings, map_size); 76 + 77 + set_max_rlimit(); 78 + 79 + err = bperf_cgroup_bpf__load(skel); 80 + if (err) { 81 + pr_err("Failed to load cgroup skeleton\n"); 82 + goto out; 83 + } 84 + 85 + if (cgroup_is_v2("perf_event") > 0) 86 + skel->bss->use_cgroup_v2 = 1; 87 + 88 + err = -1; 89 + 90 + cgrp_switch = evsel__new(&cgrp_switch_attr); 91 + if (evsel__open_per_cpu(cgrp_switch, evlist->core.all_cpus, -1) < 0) { 92 + pr_err("Failed to open cgroup switches event\n"); 93 + goto out; 94 + } 95 + 96 + for (i = 0; i < nr_cpus; i++) { 97 + link = bpf_program__attach_perf_event(skel->progs.on_cgrp_switch, 98 + FD(cgrp_switch, i)); 99 + if (IS_ERR(link)) { 100 + pr_err("Failed to attach cgroup program\n"); 101 + err = PTR_ERR(link); 102 + goto out; 103 + } 104 + } 105 + 106 + /* 107 + * Update cgrp_idx map from cgroup-id to event index. 108 + */ 109 + cgrp = NULL; 110 + i = 0; 111 + 112 + evlist__for_each_entry(evlist, evsel) { 113 + if (cgrp == NULL || evsel->cgrp == leader_cgrp) { 114 + leader_cgrp = evsel->cgrp; 115 + evsel->cgrp = NULL; 116 + 117 + /* open single copy of the events w/o cgroup */ 118 + err = evsel__open_per_cpu(evsel, evlist->core.all_cpus, -1); 119 + if (err) { 120 + pr_err("Failed to open first cgroup events\n"); 121 + goto out; 122 + } 123 + 124 + map_fd = bpf_map__fd(skel->maps.events); 125 + for (cpu = 0; cpu < nr_cpus; cpu++) { 126 + int fd = FD(evsel, cpu); 127 + __u32 idx = evsel->core.idx * total_cpus + 128 + evlist->core.all_cpus->map[cpu]; 129 + 130 + err = bpf_map_update_elem(map_fd, &idx, &fd, 131 + BPF_ANY); 132 + if (err < 0) { 133 + pr_err("Failed to update perf_event fd\n"); 134 + goto out; 135 + } 136 + } 137 + 138 + evsel->cgrp = leader_cgrp; 139 + } 140 + evsel->supported = true; 141 + 142 + if (evsel->cgrp == cgrp) 143 + continue; 144 + 145 + cgrp = evsel->cgrp; 146 + 147 + if (read_cgroup_id(cgrp) < 0) { 148 + pr_err("Failed to get cgroup id\n"); 149 + err = -1; 150 + goto out; 151 + } 152 + 153 + map_fd = bpf_map__fd(skel->maps.cgrp_idx); 154 + err = bpf_map_update_elem(map_fd, &cgrp->id, &i, BPF_ANY); 155 + if (err < 0) { 156 + pr_err("Failed to update cgroup index map\n"); 157 + goto out; 158 + } 159 + 160 + i++; 161 + } 162 + 163 + /* 164 + * bperf uses BPF_PROG_TEST_RUN to get accurate reading. Check 165 + * whether the kernel support it 166 + */ 167 + prog_fd = bpf_program__fd(skel->progs.trigger_read); 168 + err = bperf_trigger_reading(prog_fd, 0); 169 + if (err) { 170 + pr_warning("The kernel does not support test_run for raw_tp BPF programs.\n" 171 + "Therefore, --for-each-cgroup might show inaccurate readings\n"); 172 + err = 0; 173 + } 174 + 175 + out: 176 + return err; 177 + } 178 + 179 + static int bperf_cgrp__load(struct evsel *evsel, 180 + struct target *target __maybe_unused) 181 + { 182 + static bool bperf_loaded = false; 183 + 184 + evsel->bperf_leader_prog_fd = -1; 185 + evsel->bperf_leader_link_fd = -1; 186 + 187 + if (!bperf_loaded && bperf_load_program(evsel->evlist)) 188 + return -1; 189 + 190 + bperf_loaded = true; 191 + /* just to bypass bpf_counter_skip() */ 192 + evsel->follower_skel = (struct bperf_follower_bpf *)skel; 193 + 194 + return 0; 195 + } 196 + 197 + static int bperf_cgrp__install_pe(struct evsel *evsel __maybe_unused, 198 + int cpu __maybe_unused, int fd __maybe_unused) 199 + { 200 + /* nothing to do */ 201 + return 0; 202 + } 203 + 204 + /* 205 + * trigger the leader prog on each cpu, so the cgrp_reading map could get 206 + * the latest results. 207 + */ 208 + static int bperf_cgrp__sync_counters(struct evlist *evlist) 209 + { 210 + int i, cpu; 211 + int nr_cpus = evlist->core.all_cpus->nr; 212 + int prog_fd = bpf_program__fd(skel->progs.trigger_read); 213 + 214 + for (i = 0; i < nr_cpus; i++) { 215 + cpu = evlist->core.all_cpus->map[i]; 216 + bperf_trigger_reading(prog_fd, cpu); 217 + } 218 + 219 + return 0; 220 + } 221 + 222 + static int bperf_cgrp__enable(struct evsel *evsel) 223 + { 224 + if (evsel->core.idx) 225 + return 0; 226 + 227 + bperf_cgrp__sync_counters(evsel->evlist); 228 + 229 + skel->bss->enabled = 1; 230 + return 0; 231 + } 232 + 233 + static int bperf_cgrp__disable(struct evsel *evsel) 234 + { 235 + if (evsel->core.idx) 236 + return 0; 237 + 238 + bperf_cgrp__sync_counters(evsel->evlist); 239 + 240 + skel->bss->enabled = 0; 241 + return 0; 242 + } 243 + 244 + static int bperf_cgrp__read(struct evsel *evsel) 245 + { 246 + struct evlist *evlist = evsel->evlist; 247 + int i, cpu, nr_cpus = evlist->core.all_cpus->nr; 248 + int total_cpus = cpu__max_cpu(); 249 + struct perf_counts_values *counts; 250 + struct bpf_perf_event_value *values; 251 + int reading_map_fd, err = 0; 252 + __u32 idx; 253 + 254 + if (evsel->core.idx) 255 + return 0; 256 + 257 + bperf_cgrp__sync_counters(evsel->evlist); 258 + 259 + values = calloc(total_cpus, sizeof(*values)); 260 + if (values == NULL) 261 + return -ENOMEM; 262 + 263 + reading_map_fd = bpf_map__fd(skel->maps.cgrp_readings); 264 + 265 + evlist__for_each_entry(evlist, evsel) { 266 + idx = evsel->core.idx; 267 + err = bpf_map_lookup_elem(reading_map_fd, &idx, values); 268 + if (err) { 269 + pr_err("bpf map lookup falied: idx=%u, event=%s, cgrp=%s\n", 270 + idx, evsel__name(evsel), evsel->cgrp->name); 271 + goto out; 272 + } 273 + 274 + for (i = 0; i < nr_cpus; i++) { 275 + cpu = evlist->core.all_cpus->map[i]; 276 + 277 + counts = perf_counts(evsel->counts, i, 0); 278 + counts->val = values[cpu].counter; 279 + counts->ena = values[cpu].enabled; 280 + counts->run = values[cpu].running; 281 + } 282 + } 283 + 284 + out: 285 + free(values); 286 + return err; 287 + } 288 + 289 + static int bperf_cgrp__destroy(struct evsel *evsel) 290 + { 291 + if (evsel->core.idx) 292 + return 0; 293 + 294 + bperf_cgroup_bpf__destroy(skel); 295 + evsel__delete(cgrp_switch); // it'll destroy on_switch progs too 296 + 297 + return 0; 298 + } 299 + 300 + struct bpf_counter_ops bperf_cgrp_ops = { 301 + .load = bperf_cgrp__load, 302 + .enable = bperf_cgrp__enable, 303 + .disable = bperf_cgrp__disable, 304 + .read = bperf_cgrp__read, 305 + .install_pe = bperf_cgrp__install_pe, 306 + .destroy = bperf_cgrp__destroy, 307 + };
+191
tools/perf/util/bpf_skel/bperf_cgroup.bpf.c
··· 1 + // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + // Copyright (c) 2021 Facebook 3 + // Copyright (c) 2021 Google 4 + #include "vmlinux.h" 5 + #include <bpf/bpf_helpers.h> 6 + #include <bpf/bpf_tracing.h> 7 + #include <bpf/bpf_core_read.h> 8 + 9 + #define MAX_LEVELS 10 // max cgroup hierarchy level: arbitrary 10 + #define MAX_EVENTS 32 // max events per cgroup: arbitrary 11 + 12 + // NOTE: many of map and global data will be modified before loading 13 + // from the userspace (perf tool) using the skeleton helpers. 14 + 15 + // single set of global perf events to measure 16 + struct { 17 + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); 18 + __uint(key_size, sizeof(__u32)); 19 + __uint(value_size, sizeof(int)); 20 + __uint(max_entries, 1); 21 + } events SEC(".maps"); 22 + 23 + // from cgroup id to event index 24 + struct { 25 + __uint(type, BPF_MAP_TYPE_HASH); 26 + __uint(key_size, sizeof(__u64)); 27 + __uint(value_size, sizeof(__u32)); 28 + __uint(max_entries, 1); 29 + } cgrp_idx SEC(".maps"); 30 + 31 + // per-cpu event snapshots to calculate delta 32 + struct { 33 + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 34 + __uint(key_size, sizeof(__u32)); 35 + __uint(value_size, sizeof(struct bpf_perf_event_value)); 36 + } prev_readings SEC(".maps"); 37 + 38 + // aggregated event values for each cgroup (per-cpu) 39 + // will be read from the user-space 40 + struct { 41 + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 42 + __uint(key_size, sizeof(__u32)); 43 + __uint(value_size, sizeof(struct bpf_perf_event_value)); 44 + } cgrp_readings SEC(".maps"); 45 + 46 + const volatile __u32 num_events = 1; 47 + const volatile __u32 num_cpus = 1; 48 + 49 + int enabled = 0; 50 + int use_cgroup_v2 = 0; 51 + 52 + static inline int get_cgroup_v1_idx(__u32 *cgrps, int size) 53 + { 54 + struct task_struct *p = (void *)bpf_get_current_task(); 55 + struct cgroup *cgrp; 56 + register int i = 0; 57 + __u32 *elem; 58 + int level; 59 + int cnt; 60 + 61 + cgrp = BPF_CORE_READ(p, cgroups, subsys[perf_event_cgrp_id], cgroup); 62 + level = BPF_CORE_READ(cgrp, level); 63 + 64 + for (cnt = 0; i < MAX_LEVELS; i++) { 65 + __u64 cgrp_id; 66 + 67 + if (i > level) 68 + break; 69 + 70 + // convert cgroup-id to a map index 71 + cgrp_id = BPF_CORE_READ(cgrp, ancestor_ids[i]); 72 + elem = bpf_map_lookup_elem(&cgrp_idx, &cgrp_id); 73 + if (!elem) 74 + continue; 75 + 76 + cgrps[cnt++] = *elem; 77 + if (cnt == size) 78 + break; 79 + } 80 + 81 + return cnt; 82 + } 83 + 84 + static inline int get_cgroup_v2_idx(__u32 *cgrps, int size) 85 + { 86 + register int i = 0; 87 + __u32 *elem; 88 + int cnt; 89 + 90 + for (cnt = 0; i < MAX_LEVELS; i++) { 91 + __u64 cgrp_id = bpf_get_current_ancestor_cgroup_id(i); 92 + 93 + if (cgrp_id == 0) 94 + break; 95 + 96 + // convert cgroup-id to a map index 97 + elem = bpf_map_lookup_elem(&cgrp_idx, &cgrp_id); 98 + if (!elem) 99 + continue; 100 + 101 + cgrps[cnt++] = *elem; 102 + if (cnt == size) 103 + break; 104 + } 105 + 106 + return cnt; 107 + } 108 + 109 + static int bperf_cgroup_count(void) 110 + { 111 + register __u32 idx = 0; // to have it in a register to pass BPF verifier 112 + register int c = 0; 113 + struct bpf_perf_event_value val, delta, *prev_val, *cgrp_val; 114 + __u32 cpu = bpf_get_smp_processor_id(); 115 + __u32 cgrp_idx[MAX_LEVELS]; 116 + int cgrp_cnt; 117 + __u32 key, cgrp; 118 + long err; 119 + 120 + if (use_cgroup_v2) 121 + cgrp_cnt = get_cgroup_v2_idx(cgrp_idx, MAX_LEVELS); 122 + else 123 + cgrp_cnt = get_cgroup_v1_idx(cgrp_idx, MAX_LEVELS); 124 + 125 + for ( ; idx < MAX_EVENTS; idx++) { 126 + if (idx == num_events) 127 + break; 128 + 129 + // XXX: do not pass idx directly (for verifier) 130 + key = idx; 131 + // this is per-cpu array for diff 132 + prev_val = bpf_map_lookup_elem(&prev_readings, &key); 133 + if (!prev_val) { 134 + val.counter = val.enabled = val.running = 0; 135 + bpf_map_update_elem(&prev_readings, &key, &val, BPF_ANY); 136 + 137 + prev_val = bpf_map_lookup_elem(&prev_readings, &key); 138 + if (!prev_val) 139 + continue; 140 + } 141 + 142 + // read from global perf_event array 143 + key = idx * num_cpus + cpu; 144 + err = bpf_perf_event_read_value(&events, key, &val, sizeof(val)); 145 + if (err) 146 + continue; 147 + 148 + if (enabled) { 149 + delta.counter = val.counter - prev_val->counter; 150 + delta.enabled = val.enabled - prev_val->enabled; 151 + delta.running = val.running - prev_val->running; 152 + 153 + for (c = 0; c < MAX_LEVELS; c++) { 154 + if (c == cgrp_cnt) 155 + break; 156 + 157 + cgrp = cgrp_idx[c]; 158 + 159 + // aggregate the result by cgroup 160 + key = cgrp * num_events + idx; 161 + cgrp_val = bpf_map_lookup_elem(&cgrp_readings, &key); 162 + if (cgrp_val) { 163 + cgrp_val->counter += delta.counter; 164 + cgrp_val->enabled += delta.enabled; 165 + cgrp_val->running += delta.running; 166 + } else { 167 + bpf_map_update_elem(&cgrp_readings, &key, 168 + &delta, BPF_ANY); 169 + } 170 + } 171 + } 172 + 173 + *prev_val = val; 174 + } 175 + return 0; 176 + } 177 + 178 + // This will be attached to cgroup-switches event for each cpu 179 + SEC("perf_events") 180 + int BPF_PROG(on_cgrp_switch) 181 + { 182 + return bperf_cgroup_count(); 183 + } 184 + 185 + SEC("raw_tp/sched_switch") 186 + int BPF_PROG(trigger_read) 187 + { 188 + return bperf_cgroup_count(); 189 + } 190 + 191 + char LICENSE[] SEC("license") = "Dual BSD/GPL";
+3 -1
tools/perf/util/cgroup.c
··· 18 18 #include <regex.h> 19 19 20 20 int nr_cgroups; 21 + bool cgrp_event_expanded; 21 22 22 23 /* used to match cgroup name with patterns */ 23 24 struct cgroup_name { ··· 459 458 460 459 if (evsel__is_group_leader(pos)) 461 460 leader = evsel; 462 - evsel->leader = leader; 461 + evsel__set_leader(evsel, leader); 463 462 464 463 evlist__add(tmp_list, evsel); 465 464 } ··· 485 484 } 486 485 487 486 ret = 0; 487 + cgrp_event_expanded = true; 488 488 489 489 out_err: 490 490 evlist__delete(orig_list);
+1
tools/perf/util/cgroup.h
··· 18 18 }; 19 19 20 20 extern int nr_cgroups; /* number of explicit cgroups defined */ 21 + extern bool cgrp_event_expanded; 21 22 22 23 struct cgroup *cgroup__get(struct cgroup *cgroup); 23 24 void cgroup__put(struct cgroup *cgroup);
+13 -31
tools/perf/util/evlist.c
··· 165 165 166 166 void evlist__add(struct evlist *evlist, struct evsel *entry) 167 167 { 168 - entry->evlist = evlist; 169 - entry->idx = evlist->core.nr_entries; 170 - entry->tracking = !entry->idx; 171 - 172 168 perf_evlist__add(&evlist->core, &entry->core); 169 + entry->evlist = evlist; 170 + entry->tracking = !entry->core.idx; 173 171 174 172 if (evlist->core.nr_entries == 1) 175 173 evlist__set_id_pos(evlist); ··· 192 194 } 193 195 194 196 __evlist__for_each_entry_safe(list, temp, evsel) { 195 - if (evsel->leader == leader) { 197 + if (evsel__has_leader(evsel, leader)) { 196 198 list_del_init(&evsel->core.node); 197 199 evlist__add(evlist, evsel); 198 200 } ··· 223 225 return err; 224 226 } 225 227 226 - void __evlist__set_leader(struct list_head *list) 227 - { 228 - struct evsel *evsel, *leader; 229 - 230 - leader = list_entry(list->next, struct evsel, core.node); 231 - evsel = list_entry(list->prev, struct evsel, core.node); 232 - 233 - leader->core.nr_members = evsel->idx - leader->idx + 1; 234 - 235 - __evlist__for_each_entry(list, evsel) { 236 - evsel->leader = leader; 237 - } 238 - } 239 - 240 228 void evlist__set_leader(struct evlist *evlist) 241 229 { 242 - if (evlist->core.nr_entries) { 243 - evlist->nr_groups = evlist->core.nr_entries > 1 ? 1 : 0; 244 - __evlist__set_leader(&evlist->core.entries); 245 - } 230 + perf_evlist__set_leader(&evlist->core); 246 231 } 247 232 248 233 int __evlist__add_default(struct evlist *evlist, bool precise) ··· 1607 1626 return; 1608 1627 1609 1628 evlist__for_each_entry_safe(evlist, n, evsel) { 1610 - if (evsel->leader == move_evsel->leader) 1629 + if (evsel__leader(evsel) == evsel__leader(move_evsel)) 1611 1630 list_move_tail(&evsel->core.node, &move); 1612 1631 } 1613 1632 ··· 1731 1750 */ 1732 1751 void evlist__force_leader(struct evlist *evlist) 1733 1752 { 1734 - if (!evlist->nr_groups) { 1753 + if (!evlist->core.nr_groups) { 1735 1754 struct evsel *leader = evlist__first(evlist); 1736 1755 1737 1756 evlist__set_leader(evlist); ··· 1744 1763 struct evsel *c2, *leader; 1745 1764 bool is_open = true; 1746 1765 1747 - leader = evsel->leader; 1766 + leader = evsel__leader(evsel); 1767 + 1748 1768 pr_debug("Weak group for %s/%d failed\n", 1749 1769 leader->name, leader->core.nr_members); 1750 1770 ··· 1756 1774 evlist__for_each_entry(evsel_list, c2) { 1757 1775 if (c2 == evsel) 1758 1776 is_open = false; 1759 - if (c2->leader == leader) { 1777 + if (evsel__has_leader(c2, leader)) { 1760 1778 if (is_open && close) 1761 1779 perf_evsel__close(&c2->core); 1762 - c2->leader = c2; 1780 + evsel__set_leader(c2, c2); 1763 1781 c2->core.nr_members = 0; 1764 1782 /* 1765 1783 * Set this for all former members of the group ··· 2119 2137 struct evsel *evsel; 2120 2138 2121 2139 evlist__for_each_entry(evlist, evsel) { 2122 - if (evsel->idx == idx) 2140 + if (evsel->core.idx == idx) 2123 2141 return evsel; 2124 2142 } 2125 2143 return NULL; ··· 2156 2174 * any valid memory load information. 2157 2175 */ 2158 2176 evlist__for_each_entry(evlist, evsel) { 2159 - leader = evsel->leader; 2177 + leader = evsel__leader(evsel); 2160 2178 if (leader == evsel) 2161 2179 continue; 2162 2180 2163 2181 if (leader->name && strstr(leader->name, "mem-loads-aux")) { 2164 2182 for_each_group_evsel(pos, leader) { 2165 - pos->leader = pos; 2183 + evsel__set_leader(pos, pos); 2166 2184 pos->core.nr_members = 0; 2167 2185 } 2168 2186 }
-2
tools/perf/util/evlist.h
··· 50 50 51 51 struct evlist { 52 52 struct perf_evlist core; 53 - int nr_groups; 54 53 bool enabled; 55 54 int id_pos; 56 55 int is_pos; ··· 201 202 int evlist__create_maps(struct evlist *evlist, struct target *target); 202 203 int evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel); 203 204 204 - void __evlist__set_leader(struct list_head *list); 205 205 void evlist__set_leader(struct evlist *evlist); 206 206 207 207 u64 __evlist__combined_sample_type(struct evlist *evlist);
+25 -7
tools/perf/util/evsel.c
··· 239 239 void evsel__init(struct evsel *evsel, 240 240 struct perf_event_attr *attr, int idx) 241 241 { 242 - perf_evsel__init(&evsel->core, attr); 243 - evsel->idx = idx; 242 + perf_evsel__init(&evsel->core, attr, idx); 244 243 evsel->tracking = !idx; 245 - evsel->leader = evsel; 246 244 evsel->unit = ""; 247 245 evsel->scale = 1.0; 248 246 evsel->max_events = ULONG_MAX; ··· 408 410 evsel->cgrp = cgroup__get(orig->cgrp); 409 411 evsel->tp_format = orig->tp_format; 410 412 evsel->handler = orig->handler; 411 - evsel->leader = orig->leader; 413 + evsel->core.leader = orig->core.leader; 412 414 413 415 evsel->max_events = orig->max_events; 414 416 evsel->tool_event = orig->tool_event; ··· 1073 1075 void evsel__config(struct evsel *evsel, struct record_opts *opts, 1074 1076 struct callchain_param *callchain) 1075 1077 { 1076 - struct evsel *leader = evsel->leader; 1078 + struct evsel *leader = evsel__leader(evsel); 1077 1079 struct perf_event_attr *attr = &evsel->core.attr; 1078 1080 int track = evsel->tracking; 1079 1081 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; ··· 1591 1593 1592 1594 static int evsel__hybrid_group_cpu(struct evsel *evsel, int cpu) 1593 1595 { 1594 - struct evsel *leader = evsel->leader; 1596 + struct evsel *leader = evsel__leader(evsel); 1595 1597 1596 1598 if ((evsel__is_hybrid(evsel) && !evsel__is_hybrid(leader)) || 1597 1599 (!evsel__is_hybrid(evsel) && evsel__is_hybrid(leader))) { ··· 1603 1605 1604 1606 static int get_group_fd(struct evsel *evsel, int cpu, int thread) 1605 1607 { 1606 - struct evsel *leader = evsel->leader; 1608 + struct evsel *leader = evsel__leader(evsel); 1607 1609 int fd; 1608 1610 1609 1611 if (evsel__is_group_leader(evsel)) ··· 2848 2850 bool evsel__is_hybrid(struct evsel *evsel) 2849 2851 { 2850 2852 return evsel->pmu_name && perf_pmu__is_hybrid(evsel->pmu_name); 2853 + } 2854 + 2855 + struct evsel *evsel__leader(struct evsel *evsel) 2856 + { 2857 + return container_of(evsel->core.leader, struct evsel, core); 2858 + } 2859 + 2860 + bool evsel__has_leader(struct evsel *evsel, struct evsel *leader) 2861 + { 2862 + return evsel->core.leader == &leader->core; 2863 + } 2864 + 2865 + bool evsel__is_leader(struct evsel *evsel) 2866 + { 2867 + return evsel__has_leader(evsel, evsel); 2868 + } 2869 + 2870 + void evsel__set_leader(struct evsel *evsel, struct evsel *leader) 2871 + { 2872 + evsel->core.leader = &leader->core; 2851 2873 }
+8 -6
tools/perf/util/evsel.h
··· 49 49 struct perf_evsel core; 50 50 struct evlist *evlist; 51 51 off_t id_offset; 52 - int idx; 53 52 int id_pos; 54 53 int is_pos; 55 54 unsigned int sample_size; ··· 118 119 bool reset_group; 119 120 bool errored; 120 121 struct hashmap *per_pkg_mask; 121 - struct evsel *leader; 122 122 int err; 123 123 int cpu_iter; 124 124 struct { ··· 366 368 */ 367 369 static inline bool evsel__is_group_leader(const struct evsel *evsel) 368 370 { 369 - return evsel->leader == evsel; 371 + return evsel->core.leader == &evsel->core; 370 372 } 371 373 372 374 /** ··· 404 406 405 407 static inline int evsel__group_idx(struct evsel *evsel) 406 408 { 407 - return evsel->idx - evsel->leader->idx; 409 + return evsel->core.idx - evsel->core.leader->idx; 408 410 } 409 411 410 412 /* Iterates group WITHOUT the leader. */ 411 413 #define for_each_group_member(_evsel, _leader) \ 412 414 for ((_evsel) = list_entry((_leader)->core.node.next, struct evsel, core.node); \ 413 - (_evsel) && (_evsel)->leader == (_leader); \ 415 + (_evsel) && (_evsel)->core.leader == (&_leader->core); \ 414 416 (_evsel) = list_entry((_evsel)->core.node.next, struct evsel, core.node)) 415 417 416 418 /* Iterates group WITH the leader. */ 417 419 #define for_each_group_evsel(_evsel, _leader) \ 418 420 for ((_evsel) = _leader; \ 419 - (_evsel) && (_evsel)->leader == (_leader); \ 421 + (_evsel) && (_evsel)->core.leader == (&_leader->core); \ 420 422 (_evsel) = list_entry((_evsel)->core.node.next, struct evsel, core.node)) 421 423 422 424 static inline bool evsel__has_branch_callstack(const struct evsel *evsel) ··· 461 463 462 464 void evsel__zero_per_pkg(struct evsel *evsel); 463 465 bool evsel__is_hybrid(struct evsel *evsel); 466 + struct evsel *evsel__leader(struct evsel *evsel); 467 + bool evsel__has_leader(struct evsel *evsel, struct evsel *leader); 468 + bool evsel__is_leader(struct evsel *evsel); 469 + void evsel__set_leader(struct evsel *evsel, struct evsel *leader); 464 470 #endif /* __PERF_EVSEL_H */
+9 -9
tools/perf/util/header.c
··· 778 778 static int write_group_desc(struct feat_fd *ff, 779 779 struct evlist *evlist) 780 780 { 781 - u32 nr_groups = evlist->nr_groups; 781 + u32 nr_groups = evlist->core.nr_groups; 782 782 struct evsel *evsel; 783 783 int ret; 784 784 ··· 789 789 evlist__for_each_entry(evlist, evsel) { 790 790 if (evsel__is_group_leader(evsel) && evsel->core.nr_members > 1) { 791 791 const char *name = evsel->group_name ?: "{anon_group}"; 792 - u32 leader_idx = evsel->idx; 792 + u32 leader_idx = evsel->core.idx; 793 793 u32 nr_members = evsel->core.nr_members; 794 794 795 795 ret = do_write_string(ff, name); ··· 1844 1844 msz = sz; 1845 1845 1846 1846 for (i = 0, evsel = events; i < nre; evsel++, i++) { 1847 - evsel->idx = i; 1847 + evsel->core.idx = i; 1848 1848 1849 1849 /* 1850 1850 * must read entire on-file attr struct to ··· 2379 2379 struct evsel *evsel; 2380 2380 2381 2381 evlist__for_each_entry(evlist, evsel) { 2382 - if (evsel->idx == idx) 2382 + if (evsel->core.idx == idx) 2383 2383 return evsel; 2384 2384 } 2385 2385 ··· 2393 2393 if (!event->name) 2394 2394 return; 2395 2395 2396 - evsel = evlist__find_by_index(evlist, event->idx); 2396 + evsel = evlist__find_by_index(evlist, event->core.idx); 2397 2397 if (!evsel) 2398 2398 return; 2399 2399 ··· 2735 2735 * Rebuild group relationship based on the group_desc 2736 2736 */ 2737 2737 session = container_of(ff->ph, struct perf_session, header); 2738 - session->evlist->nr_groups = nr_groups; 2738 + session->evlist->core.nr_groups = nr_groups; 2739 2739 2740 2740 i = nr = 0; 2741 2741 evlist__for_each_entry(session->evlist, evsel) { 2742 - if (evsel->idx == (int) desc[i].leader_idx) { 2743 - evsel->leader = evsel; 2742 + if (evsel->core.idx == (int) desc[i].leader_idx) { 2743 + evsel__set_leader(evsel, evsel); 2744 2744 /* {anon_group} is a dummy name */ 2745 2745 if (strcmp(desc[i].name, "{anon_group}")) { 2746 2746 evsel->group_name = desc[i].name; ··· 2758 2758 i++; 2759 2759 } else if (nr) { 2760 2760 /* This is a group member */ 2761 - evsel->leader = leader; 2761 + evsel__set_leader(evsel, leader); 2762 2762 2763 2763 nr--; 2764 2764 }
+9 -4
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
··· 41 41 42 42 #define INTEL_PT_RETURN 1 43 43 44 - /* Maximum number of loops with no packets consumed i.e. stuck in a loop */ 45 - #define INTEL_PT_MAX_LOOPS 10000 44 + /* 45 + * Default maximum number of loops with no packets consumed i.e. stuck in a 46 + * loop. 47 + */ 48 + #define INTEL_PT_MAX_LOOPS 100000 46 49 47 50 struct intel_pt_blk { 48 51 struct intel_pt_blk *prev; ··· 223 220 uint64_t timestamp_insn_cnt; 224 221 uint64_t sample_insn_cnt; 225 222 uint64_t stuck_ip; 223 + int max_loops; 226 224 int no_progress; 227 225 int stuck_ip_prd; 228 226 int stuck_ip_cnt; ··· 319 315 decoder->vm_tm_corr_dry_run = params->vm_tm_corr_dry_run; 320 316 decoder->first_timestamp = params->first_timestamp; 321 317 decoder->last_reliable_timestamp = params->first_timestamp; 318 + decoder->max_loops = params->max_loops ? params->max_loops : INTEL_PT_MAX_LOOPS; 322 319 323 320 decoder->flags = params->flags; 324 321 ··· 488 483 [INTEL_PT_ERR_OVR] = "Overflow packet", 489 484 [INTEL_PT_ERR_LOST] = "Lost trace data", 490 485 [INTEL_PT_ERR_UNK] = "Unknown error!", 491 - [INTEL_PT_ERR_NELOOP] = "Never-ending loop", 486 + [INTEL_PT_ERR_NELOOP] = "Never-ending loop (refer perf config intel-pt.max-loops)", 492 487 }; 493 488 494 489 int intel_pt__strerror(int code, char *buf, size_t buflen) ··· 1173 1168 decoder->stuck_ip = decoder->state.to_ip; 1174 1169 decoder->stuck_ip_prd = 1; 1175 1170 decoder->stuck_ip_cnt = 1; 1176 - } else if (cnt > INTEL_PT_MAX_LOOPS || 1171 + } else if (cnt > decoder->max_loops || 1177 1172 decoder->state.to_ip == decoder->stuck_ip) { 1178 1173 intel_pt_log_at("ERROR: Never-ending loop", 1179 1174 decoder->state.to_ip);
+1
tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
··· 270 270 uint32_t tsc_ctc_ratio_d; 271 271 enum intel_pt_param_flags flags; 272 272 unsigned int quick; 273 + int max_loops; 273 274 }; 274 275 275 276 struct intel_pt_decoder;
+5
tools/perf/util/intel-pt.c
··· 123 123 u64 noretcomp_bit; 124 124 unsigned max_non_turbo_ratio; 125 125 unsigned cbr2khz; 126 + int max_loops; 126 127 127 128 unsigned long num_events; 128 129 ··· 1201 1200 params.vm_time_correlation = pt->synth_opts.vm_time_correlation; 1202 1201 params.vm_tm_corr_dry_run = pt->synth_opts.vm_tm_corr_dry_run; 1203 1202 params.first_timestamp = pt->first_timestamp; 1203 + params.max_loops = pt->max_loops; 1204 1204 1205 1205 if (pt->filts.cnt > 0) 1206 1206 params.pgd_ip = intel_pt_pgd_ip; ··· 3432 3430 3433 3431 if (!strcmp(var, "intel-pt.mispred-all")) 3434 3432 pt->mispred_all = perf_config_bool(var, value); 3433 + 3434 + if (!strcmp(var, "intel-pt.max-loops")) 3435 + perf_config_int(&pt->max_loops, var, value); 3435 3436 3436 3437 return 0; 3437 3438 }
+11 -11
tools/perf/util/metricgroup.c
··· 219 219 if (has_constraint && ev->weak_group) 220 220 continue; 221 221 /* Ignore event if already used and merging is disabled. */ 222 - if (metric_no_merge && test_bit(ev->idx, evlist_used)) 222 + if (metric_no_merge && test_bit(ev->core.idx, evlist_used)) 223 223 continue; 224 - if (!has_constraint && ev->leader != current_leader) { 224 + if (!has_constraint && !evsel__has_leader(ev, current_leader)) { 225 225 /* 226 226 * Start of a new group, discard the whole match and 227 227 * start again. ··· 229 229 matched_events = 0; 230 230 memset(metric_events, 0, 231 231 sizeof(struct evsel *) * idnum); 232 - current_leader = ev->leader; 232 + current_leader = evsel__leader(ev); 233 233 } 234 234 /* 235 235 * Check for duplicate events with the same name. For example, ··· 269 269 for (i = 0; i < idnum; i++) { 270 270 ev = metric_events[i]; 271 271 /* Don't free the used events. */ 272 - set_bit(ev->idx, evlist_used); 272 + set_bit(ev->core.idx, evlist_used); 273 273 /* 274 274 * The metric leader points to the identically named event in 275 275 * metric_events. ··· 287 287 * when then group is left. 288 288 */ 289 289 if (!has_constraint && 290 - ev->leader != metric_events[i]->leader && 291 - evsel_same_pmu_or_none(ev->leader, metric_events[i]->leader)) 290 + ev->core.leader != metric_events[i]->core.leader && 291 + evsel_same_pmu_or_none(evsel__leader(ev), evsel__leader(metric_events[i]))) 292 292 break; 293 293 if (!strcmp(metric_events[i]->name, ev->name)) { 294 - set_bit(ev->idx, evlist_used); 294 + set_bit(ev->core.idx, evlist_used); 295 295 ev->metric_leader = metric_events[i]; 296 296 } 297 297 } ··· 391 391 } 392 392 393 393 evlist__for_each_entry_safe(perf_evlist, tmp, evsel) { 394 - if (!test_bit(evsel->idx, evlist_used)) { 394 + if (!test_bit(evsel->core.idx, evlist_used)) { 395 395 evlist__remove(perf_evlist, evsel); 396 396 evsel__delete(evsel); 397 397 } ··· 1312 1312 nd = rblist__entry(old_metric_events, i); 1313 1313 old_me = container_of(nd, struct metric_event, nd); 1314 1314 1315 - evsel = evlist__find_evsel(evlist, old_me->evsel->idx); 1315 + evsel = evlist__find_evsel(evlist, old_me->evsel->core.idx); 1316 1316 if (!evsel) 1317 1317 return -EINVAL; 1318 1318 new_me = metricgroup__lookup(new_metric_events, evsel, true); ··· 1320 1320 return -ENOMEM; 1321 1321 1322 1322 pr_debug("copying metric event for cgroup '%s': %s (idx=%d)\n", 1323 - cgrp ? cgrp->name : "root", evsel->name, evsel->idx); 1323 + cgrp ? cgrp->name : "root", evsel->name, evsel->core.idx); 1324 1324 1325 1325 list_for_each_entry(old_expr, &old_me->head, nd) { 1326 1326 new_expr = malloc(sizeof(*new_expr)); ··· 1363 1363 /* copy evsel in the same position */ 1364 1364 for (idx = 0; idx < nr; idx++) { 1365 1365 evsel = old_expr->metric_events[idx]; 1366 - evsel = evlist__find_evsel(evlist, evsel->idx); 1366 + evsel = evlist__find_evsel(evlist, evsel->core.idx); 1367 1367 if (evsel == NULL) { 1368 1368 free(new_expr->metric_events); 1369 1369 free(new_expr->metric_refs);
+4 -4
tools/perf/util/parse-events.c
··· 1740 1740 1741 1741 leader = list_first_entry(list, struct evsel, core.node); 1742 1742 evsel = list_last_entry(list, struct evsel, core.node); 1743 - total_members = evsel->idx - leader->idx + 1; 1743 + total_members = evsel->core.idx - leader->core.idx + 1; 1744 1744 1745 1745 leaders = calloc(total_members, sizeof(uintptr_t)); 1746 1746 if (WARN_ON(!leaders)) ··· 1800 1800 __evlist__for_each_entry(list, evsel) { 1801 1801 if (i >= nr_pmu) 1802 1802 i = 0; 1803 - evsel->leader = (struct evsel *) leaders[i++]; 1803 + evsel__set_leader(evsel, (struct evsel *) leaders[i++]); 1804 1804 } 1805 1805 1806 1806 /* The number of members and group name are same for each group */ ··· 1833 1833 if (parse_events__set_leader_for_uncore_aliase(name, list, parse_state)) 1834 1834 return; 1835 1835 1836 - __evlist__set_leader(list); 1836 + __perf_evlist__set_leader(list); 1837 1837 leader = list_entry(list->next, struct evsel, core.node); 1838 1838 leader->group_name = name ? strdup(name) : NULL; 1839 1839 } ··· 2285 2285 if (!ret) { 2286 2286 struct evsel *last; 2287 2287 2288 - evlist->nr_groups += parse_state.nr_groups; 2288 + evlist->core.nr_groups += parse_state.nr_groups; 2289 2289 last = evlist__last(evlist); 2290 2290 last->cmdline_group_boundary = true; 2291 2291
+1 -1
tools/perf/util/parse-events.y
··· 316 316 if (!strncmp(name, "uncore_", 7) && 317 317 strncmp($1, "uncore_", 7)) 318 318 name += 7; 319 - if (!fnmatch(pattern, name, 0)) { 319 + if (!perf_pmu__match(pattern, name, $1)) { 320 320 if (parse_events_copy_term_list(orig_terms, &terms)) 321 321 CLEANUP_YYABORT; 322 322 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true, false))
+1 -1
tools/perf/util/pfm.c
··· 110 110 "cannot close a non-existing event group\n"); 111 111 goto error; 112 112 } 113 - evlist->nr_groups++; 113 + evlist->core.nr_groups++; 114 114 grp_leader = NULL; 115 115 grp_evt = -1; 116 116 }
+35 -1
tools/perf/util/pmu.c
··· 3 3 #include <linux/compiler.h> 4 4 #include <linux/string.h> 5 5 #include <linux/zalloc.h> 6 + #include <linux/ctype.h> 6 7 #include <subcmd/pager.h> 7 8 #include <sys/types.h> 8 9 #include <errno.h> ··· 18 17 #include <locale.h> 19 18 #include <regex.h> 20 19 #include <perf/cpumap.h> 20 + #include <fnmatch.h> 21 21 #include "debug.h" 22 22 #include "evsel.h" 23 23 #include "pmu.h" ··· 742 740 return perf_pmu__find_map(NULL); 743 741 } 744 742 743 + static bool perf_pmu__valid_suffix(char *pmu_name, char *tok) 744 + { 745 + char *p; 746 + 747 + if (strncmp(pmu_name, tok, strlen(tok))) 748 + return false; 749 + 750 + p = pmu_name + strlen(tok); 751 + if (*p == 0) 752 + return true; 753 + 754 + if (*p != '_') 755 + return false; 756 + 757 + ++p; 758 + if (*p == 0 || !isdigit(*p)) 759 + return false; 760 + 761 + return true; 762 + } 763 + 745 764 bool pmu_uncore_alias_match(const char *pmu_name, const char *name) 746 765 { 747 766 char *tmp = NULL, *tok, *str; ··· 791 768 */ 792 769 for (; tok; name += strlen(tok), tok = strtok_r(NULL, ",", &tmp)) { 793 770 name = strstr(name, tok); 794 - if (!name) { 771 + if (!name || !perf_pmu__valid_suffix((char *)name, tok)) { 795 772 res = false; 796 773 goto out; 797 774 } ··· 1894 1871 } 1895 1872 1896 1873 return !list_empty(&perf_pmu__hybrid_pmus); 1874 + } 1875 + 1876 + int perf_pmu__match(char *pattern, char *name, char *tok) 1877 + { 1878 + if (fnmatch(pattern, name, 0)) 1879 + return -1; 1880 + 1881 + if (tok && !perf_pmu__valid_suffix(name, tok)) 1882 + return -1; 1883 + 1884 + return 0; 1897 1885 }
+1
tools/perf/util/pmu.h
··· 133 133 char *name); 134 134 135 135 bool perf_pmu__has_hybrid(void); 136 + int perf_pmu__match(char *pattern, char *name, char *tok); 136 137 137 138 #endif /* __PMU_H */
+5
tools/perf/util/probe-finder.c
··· 118 118 char buf[PATH_MAX], nil = '\0'; 119 119 struct dso *dso; 120 120 struct debuginfo *dinfo = NULL; 121 + struct build_id bid; 121 122 122 123 /* Try to open distro debuginfo files */ 123 124 dso = dso__new(path); 124 125 if (!dso) 125 126 goto out; 127 + 128 + /* Set the build id for DSO_BINARY_TYPE__BUILDID_DEBUGINFO */ 129 + if (is_regular_file(path) && filename__read_build_id(path, &bid) > 0) 130 + dso__set_build_id(dso, &bid); 126 131 127 132 for (type = distro_dwarf_types; 128 133 !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND;
+1 -1
tools/perf/util/python.c
··· 1032 1032 1033 1033 Py_INCREF(pevsel); 1034 1034 evsel = &((struct pyrf_evsel *)pevsel)->evsel; 1035 - evsel->idx = evlist->core.nr_entries; 1035 + evsel->core.idx = evlist->core.nr_entries; 1036 1036 evlist__add(evlist, evsel); 1037 1037 1038 1038 return Py_BuildValue("i", evlist->core.nr_entries);
+3 -3
tools/perf/util/record.c
··· 25 25 */ 26 26 static struct evsel *evsel__read_sampler(struct evsel *evsel, struct evlist *evlist) 27 27 { 28 - struct evsel *leader = evsel->leader; 28 + struct evsel *leader = evsel__leader(evsel); 29 29 30 30 if (evsel__is_aux_event(leader) || arch_topdown_sample_read(leader) || 31 31 is_mem_loads_aux_event(leader)) { 32 32 evlist__for_each_entry(evlist, evsel) { 33 - if (evsel->leader == leader && evsel != evsel->leader) 33 + if (evsel__leader(evsel) == leader && evsel != evsel__leader(evsel)) 34 34 return evsel; 35 35 } 36 36 } ··· 53 53 static void evsel__config_leader_sampling(struct evsel *evsel, struct evlist *evlist) 54 54 { 55 55 struct perf_event_attr *attr = &evsel->core.attr; 56 - struct evsel *leader = evsel->leader; 56 + struct evsel *leader = evsel__leader(evsel); 57 57 struct evsel *read_sampler; 58 58 u64 term_types, freq_mask; 59 59
+12 -5
tools/perf/util/scripting-engines/trace-event-python.c
··· 687 687 _PyUnicode_FromString(decode)); 688 688 } 689 689 690 - static int regs_map(struct regs_dump *regs, uint64_t mask, char *bf, int size) 690 + static void regs_map(struct regs_dump *regs, uint64_t mask, char *bf, int size) 691 691 { 692 692 unsigned int i = 0, r; 693 693 int printed = 0; ··· 695 695 bf[0] = 0; 696 696 697 697 if (!regs || !regs->regs) 698 - return 0; 698 + return; 699 699 700 700 for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) { 701 701 u64 val = regs->regs[i++]; ··· 704 704 "%5s:0x%" PRIx64 " ", 705 705 perf_reg_name(r), val); 706 706 } 707 - 708 - return printed; 709 707 } 710 708 711 709 static void set_regs_in_dict(PyObject *dict, ··· 711 713 struct evsel *evsel) 712 714 { 713 715 struct perf_event_attr *attr = &evsel->core.attr; 714 - char bf[512]; 716 + 717 + /* 718 + * Here value 28 is a constant size which can be used to print 719 + * one register value and its corresponds to: 720 + * 16 chars is to specify 64 bit register in hexadecimal. 721 + * 2 chars is for appending "0x" to the hexadecimal value and 722 + * 10 chars is for register name. 723 + */ 724 + int size = __sw_hweight64(attr->sample_regs_intr) * 28; 725 + char bf[size]; 715 726 716 727 regs_map(&sample->intr_regs, attr->sample_regs_intr, bf, sizeof(bf)); 717 728
+6 -3
tools/perf/util/stat-display.c
··· 19 19 #include "util.h" 20 20 #include "iostat.h" 21 21 #include "pmu-hybrid.h" 22 + #include "evlist-hybrid.h" 22 23 23 24 #define CNTR_NOT_SUPPORTED "<not supported>" 24 25 #define CNTR_NOT_COUNTED "<not counted>" ··· 466 465 config->csv_sep); 467 466 468 467 if (counter->supported) { 469 - config->print_free_counters_hint = 1; 470 - if (is_mixed_hw_group(counter)) 471 - config->print_mixed_hw_group_error = 1; 468 + if (!evlist__has_hybrid(counter->evlist)) { 469 + config->print_free_counters_hint = 1; 470 + if (is_mixed_hw_group(counter)) 471 + config->print_mixed_hw_group_error = 1; 472 + } 472 473 } 473 474 474 475 fprintf(config->output, "%-*s%s",
+1 -1
tools/perf/util/stat-shadow.c
··· 379 379 evlist__for_each_entry(evsel_list, counter) { 380 380 bool invalid = false; 381 381 382 - leader = counter->leader; 382 + leader = evsel__leader(counter); 383 383 if (!counter->metric_expr) 384 384 continue; 385 385
+1 -1
tools/perf/util/stat.c
··· 534 534 int cpu) 535 535 { 536 536 struct perf_event_attr *attr = &evsel->core.attr; 537 - struct evsel *leader = evsel->leader; 537 + struct evsel *leader = evsel__leader(evsel); 538 538 539 539 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 540 540 PERF_FORMAT_TOTAL_TIME_RUNNING;
+1 -1
tools/perf/util/stream.c
··· 139 139 140 140 hists__output_resort(hists, NULL); 141 141 init_hot_callchain(hists, &es[i]); 142 - es[i].evsel_idx = pos->idx; 142 + es[i].evsel_idx = pos->core.idx; 143 143 i++; 144 144 } 145 145
+68 -31
tools/perf/util/symbol-elf.c
··· 1074 1074 return 0; 1075 1075 } 1076 1076 1077 - int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 1078 - struct symsrc *runtime_ss, int kmodule) 1077 + static int 1078 + dso__load_sym_internal(struct dso *dso, struct map *map, struct symsrc *syms_ss, 1079 + struct symsrc *runtime_ss, int kmodule, int dynsym) 1079 1080 { 1080 1081 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; 1081 1082 struct maps *kmaps = kmap ? map__kmaps(map) : NULL; 1082 1083 struct map *curr_map = map; 1083 1084 struct dso *curr_dso = dso; 1084 - Elf_Data *symstrs, *secstrs; 1085 + Elf_Data *symstrs, *secstrs, *secstrs_run, *secstrs_sym; 1085 1086 uint32_t nr_syms; 1086 1087 int err = -1; 1087 1088 uint32_t idx; ··· 1099 1098 if (kmap && !kmaps) 1100 1099 return -1; 1101 1100 1102 - dso->symtab_type = syms_ss->type; 1103 - dso->is_64_bit = syms_ss->is_64_bit; 1104 - dso->rel = syms_ss->ehdr.e_type == ET_REL; 1105 - 1106 - /* 1107 - * Modules may already have symbols from kallsyms, but those symbols 1108 - * have the wrong values for the dso maps, so remove them. 1109 - */ 1110 - if (kmodule && syms_ss->symtab) 1111 - symbols__delete(&dso->symbols); 1112 - 1113 - if (!syms_ss->symtab) { 1114 - /* 1115 - * If the vmlinux is stripped, fail so we will fall back 1116 - * to using kallsyms. The vmlinux runtime symbols aren't 1117 - * of much use. 1118 - */ 1119 - if (dso->kernel) 1120 - goto out_elf_end; 1121 - 1122 - syms_ss->symtab = syms_ss->dynsym; 1123 - syms_ss->symshdr = syms_ss->dynshdr; 1124 - } 1125 - 1126 1101 elf = syms_ss->elf; 1127 1102 ehdr = syms_ss->ehdr; 1128 - sec = syms_ss->symtab; 1129 - shdr = syms_ss->symshdr; 1103 + if (dynsym) { 1104 + sec = syms_ss->dynsym; 1105 + shdr = syms_ss->dynshdr; 1106 + } else { 1107 + sec = syms_ss->symtab; 1108 + shdr = syms_ss->symshdr; 1109 + } 1130 1110 1131 1111 if (elf_section_by_name(runtime_ss->elf, &runtime_ss->ehdr, &tshdr, 1132 1112 ".text", NULL)) ··· 1132 1150 if (sec_strndx == NULL) 1133 1151 goto out_elf_end; 1134 1152 1135 - secstrs = elf_getdata(sec_strndx, NULL); 1136 - if (secstrs == NULL) 1153 + secstrs_run = elf_getdata(sec_strndx, NULL); 1154 + if (secstrs_run == NULL) 1155 + goto out_elf_end; 1156 + 1157 + sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); 1158 + if (sec_strndx == NULL) 1159 + goto out_elf_end; 1160 + 1161 + secstrs_sym = elf_getdata(sec_strndx, NULL); 1162 + if (secstrs_sym == NULL) 1137 1163 goto out_elf_end; 1138 1164 1139 1165 nr_syms = shdr.sh_size / shdr.sh_entsize; ··· 1227 1237 1228 1238 gelf_getshdr(sec, &shdr); 1229 1239 1240 + secstrs = secstrs_sym; 1241 + 1230 1242 /* 1231 1243 * We have to fallback to runtime when syms' section header has 1232 1244 * NOBITS set. NOBITS results in file offset (sh_offset) not ··· 1241 1249 goto out_elf_end; 1242 1250 1243 1251 gelf_getshdr(sec, &shdr); 1252 + secstrs = secstrs_run; 1244 1253 } 1245 1254 1246 1255 if (is_label && !elf_sec__filter(&shdr, secstrs)) ··· 1302 1309 } 1303 1310 err = nr; 1304 1311 out_elf_end: 1312 + return err; 1313 + } 1314 + 1315 + int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 1316 + struct symsrc *runtime_ss, int kmodule) 1317 + { 1318 + int nr = 0; 1319 + int err = -1; 1320 + 1321 + dso->symtab_type = syms_ss->type; 1322 + dso->is_64_bit = syms_ss->is_64_bit; 1323 + dso->rel = syms_ss->ehdr.e_type == ET_REL; 1324 + 1325 + /* 1326 + * Modules may already have symbols from kallsyms, but those symbols 1327 + * have the wrong values for the dso maps, so remove them. 1328 + */ 1329 + if (kmodule && syms_ss->symtab) 1330 + symbols__delete(&dso->symbols); 1331 + 1332 + if (!syms_ss->symtab) { 1333 + /* 1334 + * If the vmlinux is stripped, fail so we will fall back 1335 + * to using kallsyms. The vmlinux runtime symbols aren't 1336 + * of much use. 1337 + */ 1338 + if (dso->kernel) 1339 + return err; 1340 + } else { 1341 + err = dso__load_sym_internal(dso, map, syms_ss, runtime_ss, 1342 + kmodule, 0); 1343 + if (err < 0) 1344 + return err; 1345 + nr = err; 1346 + } 1347 + 1348 + if (syms_ss->dynsym) { 1349 + err = dso__load_sym_internal(dso, map, syms_ss, runtime_ss, 1350 + kmodule, 1); 1351 + if (err < 0) 1352 + return err; 1353 + err += nr; 1354 + } 1355 + 1305 1356 return err; 1306 1357 } 1307 1358