18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/types.h> 38c2ecf20Sopenharmony_ci#include <linux/string.h> 48c2ecf20Sopenharmony_ci#include <linux/zalloc.h> 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include "../../../util/event.h" 78c2ecf20Sopenharmony_ci#include "../../../util/synthetic-events.h" 88c2ecf20Sopenharmony_ci#include "../../../util/machine.h" 98c2ecf20Sopenharmony_ci#include "../../../util/tool.h" 108c2ecf20Sopenharmony_ci#include "../../../util/map.h" 118c2ecf20Sopenharmony_ci#include "../../../util/debug.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#if defined(__x86_64__) 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ciint perf_event__synthesize_extra_kmaps(struct perf_tool *tool, 168c2ecf20Sopenharmony_ci perf_event__handler_t process, 178c2ecf20Sopenharmony_ci struct machine *machine) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci int rc = 0; 208c2ecf20Sopenharmony_ci struct map *pos; 218c2ecf20Sopenharmony_ci struct maps *kmaps = &machine->kmaps; 228c2ecf20Sopenharmony_ci union perf_event *event = zalloc(sizeof(event->mmap) + 238c2ecf20Sopenharmony_ci machine->id_hdr_size); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci if (!event) { 268c2ecf20Sopenharmony_ci pr_debug("Not enough memory synthesizing mmap event " 278c2ecf20Sopenharmony_ci "for extra kernel maps\n"); 288c2ecf20Sopenharmony_ci return -1; 298c2ecf20Sopenharmony_ci } 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci maps__for_each_entry(kmaps, pos) { 328c2ecf20Sopenharmony_ci struct kmap *kmap; 338c2ecf20Sopenharmony_ci size_t size; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci if (!__map__is_extra_kernel_map(pos)) 368c2ecf20Sopenharmony_ci continue; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci kmap = map__kmap(pos); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci size = sizeof(event->mmap) - sizeof(event->mmap.filename) + 418c2ecf20Sopenharmony_ci PERF_ALIGN(strlen(kmap->name) + 1, sizeof(u64)) + 428c2ecf20Sopenharmony_ci machine->id_hdr_size; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci memset(event, 0, size); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci event->mmap.header.type = PERF_RECORD_MMAP; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci /* 498c2ecf20Sopenharmony_ci * kernel uses 0 for user space maps, see kernel/perf_event.c 508c2ecf20Sopenharmony_ci * __perf_event_mmap 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci if (machine__is_host(machine)) 538c2ecf20Sopenharmony_ci event->header.misc = PERF_RECORD_MISC_KERNEL; 548c2ecf20Sopenharmony_ci else 558c2ecf20Sopenharmony_ci event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci event->mmap.header.size = size; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci event->mmap.start = pos->start; 608c2ecf20Sopenharmony_ci event->mmap.len = pos->end - pos->start; 618c2ecf20Sopenharmony_ci event->mmap.pgoff = pos->pgoff; 628c2ecf20Sopenharmony_ci event->mmap.pid = machine->pid; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci strlcpy(event->mmap.filename, kmap->name, PATH_MAX); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci if (perf_tool__process_synth_event(tool, event, machine, 678c2ecf20Sopenharmony_ci process) != 0) { 688c2ecf20Sopenharmony_ci rc = -1; 698c2ecf20Sopenharmony_ci break; 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci free(event); 748c2ecf20Sopenharmony_ci return rc; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#endif 78