18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: LGPL-2.1 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * trace/beauty/ioctl.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "trace/beauty/beauty.h" 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* 128c2ecf20Sopenharmony_ci * FIXME: to support all arches we have to improve this, for 138c2ecf20Sopenharmony_ci * now, to build on older systems without things like TIOCGEXCL, 148c2ecf20Sopenharmony_ci * get it directly from our copy. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * Right now only x86 is being supported for beautifying ioctl args 178c2ecf20Sopenharmony_ci * in 'perf trace', see tools/perf/trace/beauty/Build and builtin-trace.c 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci#include <uapi/asm-generic/ioctls.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic size_t ioctl__scnprintf_tty_cmd(int nr, int dir, char *bf, size_t size) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci static const char *ioctl_tty_cmd[] = { 248c2ecf20Sopenharmony_ci [_IOC_NR(TCGETS)] = "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW", 258c2ecf20Sopenharmony_ci "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL", "TIOCSCTTY", 268c2ecf20Sopenharmony_ci "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI", "TIOCGWINSZ", "TIOCSWINSZ", 278c2ecf20Sopenharmony_ci "TIOCMGET", "TIOCMBIS", "TIOCMBIC", "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", 288c2ecf20Sopenharmony_ci "FIONREAD", "TIOCLINUX", "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", 298c2ecf20Sopenharmony_ci "FIONBIO", "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", 308c2ecf20Sopenharmony_ci [_IOC_NR(TIOCSBRK)] = "TIOCSBRK", "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", 318c2ecf20Sopenharmony_ci "TCSETSW2", "TCSETSF2", "TIOCGRS48", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK", 328c2ecf20Sopenharmony_ci "TIOCGDEV", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG", "TIOCVHANGUP", "TIOCGPKT", 338c2ecf20Sopenharmony_ci "TIOCGPTLCK", [_IOC_NR(TIOCGEXCL)] = "TIOCGEXCL", "TIOCGPTPEER", 348c2ecf20Sopenharmony_ci "TIOCGISO7816", "TIOCSISO7816", 358c2ecf20Sopenharmony_ci [_IOC_NR(FIONCLEX)] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG", 368c2ecf20Sopenharmony_ci "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS", 378c2ecf20Sopenharmony_ci "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI", 388c2ecf20Sopenharmony_ci "TIOCMIWAIT", "TIOCGICOUNT", }; 398c2ecf20Sopenharmony_ci static DEFINE_STRARRAY(ioctl_tty_cmd, ""); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci if (nr < strarray__ioctl_tty_cmd.nr_entries && strarray__ioctl_tty_cmd.entries[nr] != NULL) 428c2ecf20Sopenharmony_ci return scnprintf(bf, size, "%s", strarray__ioctl_tty_cmd.entries[nr]); 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci return scnprintf(bf, size, "(%#x, %#x, %#x)", 'T', nr, dir); 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic size_t ioctl__scnprintf_drm_cmd(int nr, int dir, char *bf, size_t size) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci#include "trace/beauty/generated/ioctl/drm_ioctl_array.c" 508c2ecf20Sopenharmony_ci static DEFINE_STRARRAY(drm_ioctl_cmds, ""); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (nr < strarray__drm_ioctl_cmds.nr_entries && strarray__drm_ioctl_cmds.entries[nr] != NULL) 538c2ecf20Sopenharmony_ci return scnprintf(bf, size, "DRM_%s", strarray__drm_ioctl_cmds.entries[nr]); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci return scnprintf(bf, size, "(%#x, %#x, %#x)", 'd', nr, dir); 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic size_t ioctl__scnprintf_sndrv_pcm_cmd(int nr, int dir, char *bf, size_t size) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci#include "trace/beauty/generated/ioctl/sndrv_pcm_ioctl_array.c" 618c2ecf20Sopenharmony_ci static DEFINE_STRARRAY(sndrv_pcm_ioctl_cmds, ""); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (nr < strarray__sndrv_pcm_ioctl_cmds.nr_entries && strarray__sndrv_pcm_ioctl_cmds.entries[nr] != NULL) 648c2ecf20Sopenharmony_ci return scnprintf(bf, size, "SNDRV_PCM_%s", strarray__sndrv_pcm_ioctl_cmds.entries[nr]); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci return scnprintf(bf, size, "(%#x, %#x, %#x)", 'A', nr, dir); 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic size_t ioctl__scnprintf_sndrv_ctl_cmd(int nr, int dir, char *bf, size_t size) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci#include "trace/beauty/generated/ioctl/sndrv_ctl_ioctl_array.c" 728c2ecf20Sopenharmony_ci static DEFINE_STRARRAY(sndrv_ctl_ioctl_cmds, ""); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (nr < strarray__sndrv_ctl_ioctl_cmds.nr_entries && strarray__sndrv_ctl_ioctl_cmds.entries[nr] != NULL) 758c2ecf20Sopenharmony_ci return scnprintf(bf, size, "SNDRV_CTL_%s", strarray__sndrv_ctl_ioctl_cmds.entries[nr]); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci return scnprintf(bf, size, "(%#x, %#x, %#x)", 'U', nr, dir); 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic size_t ioctl__scnprintf_kvm_cmd(int nr, int dir, char *bf, size_t size) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci#include "trace/beauty/generated/ioctl/kvm_ioctl_array.c" 838c2ecf20Sopenharmony_ci static DEFINE_STRARRAY(kvm_ioctl_cmds, ""); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (nr < strarray__kvm_ioctl_cmds.nr_entries && strarray__kvm_ioctl_cmds.entries[nr] != NULL) 868c2ecf20Sopenharmony_ci return scnprintf(bf, size, "KVM_%s", strarray__kvm_ioctl_cmds.entries[nr]); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir); 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic size_t ioctl__scnprintf_vhost_virtio_cmd(int nr, int dir, char *bf, size_t size) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci#include "trace/beauty/generated/ioctl/vhost_virtio_ioctl_array.c" 948c2ecf20Sopenharmony_ci static DEFINE_STRARRAY(vhost_virtio_ioctl_cmds, ""); 958c2ecf20Sopenharmony_ci static DEFINE_STRARRAY(vhost_virtio_ioctl_read_cmds, ""); 968c2ecf20Sopenharmony_ci struct strarray *s = (dir & _IOC_READ) ? &strarray__vhost_virtio_ioctl_read_cmds : &strarray__vhost_virtio_ioctl_cmds; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if (nr < s->nr_entries && s->entries[nr] != NULL) 998c2ecf20Sopenharmony_ci return scnprintf(bf, size, "VHOST_%s", s->entries[nr]); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAF, nr, dir); 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic size_t ioctl__scnprintf_perf_cmd(int nr, int dir, char *bf, size_t size) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci#include "trace/beauty/generated/ioctl/perf_ioctl_array.c" 1078c2ecf20Sopenharmony_ci static DEFINE_STRARRAY(perf_ioctl_cmds, ""); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci if (nr < strarray__perf_ioctl_cmds.nr_entries && strarray__perf_ioctl_cmds.entries[nr] != NULL) 1108c2ecf20Sopenharmony_ci return scnprintf(bf, size, "PERF_%s", strarray__perf_ioctl_cmds.entries[nr]); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir); 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic size_t ioctl__scnprintf_usbdevfs_cmd(int nr, int dir, char *bf, size_t size) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci#include "trace/beauty/generated/ioctl/usbdevfs_ioctl_array.c" 1188c2ecf20Sopenharmony_ci static DEFINE_STRARRAY(usbdevfs_ioctl_cmds, ""); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci if (nr < strarray__usbdevfs_ioctl_cmds.nr_entries && strarray__usbdevfs_ioctl_cmds.entries[nr] != NULL) 1218c2ecf20Sopenharmony_ci return scnprintf(bf, size, "USBDEVFS_%s", strarray__usbdevfs_ioctl_cmds.entries[nr]); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci return scnprintf(bf, size, "(%c, %#x, %#x)", 'U', nr, dir); 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistatic size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size, bool show_prefix) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci const char *prefix = "_IOC_"; 1298c2ecf20Sopenharmony_ci int dir = _IOC_DIR(cmd), 1308c2ecf20Sopenharmony_ci type = _IOC_TYPE(cmd), 1318c2ecf20Sopenharmony_ci nr = _IOC_NR(cmd), 1328c2ecf20Sopenharmony_ci sz = _IOC_SIZE(cmd); 1338c2ecf20Sopenharmony_ci int printed = 0; 1348c2ecf20Sopenharmony_ci static const struct ioctl_type { 1358c2ecf20Sopenharmony_ci int type; 1368c2ecf20Sopenharmony_ci size_t (*scnprintf)(int nr, int dir, char *bf, size_t size); 1378c2ecf20Sopenharmony_ci } ioctl_types[] = { /* Must be ordered by type */ 1388c2ecf20Sopenharmony_ci { .type = '$', .scnprintf = ioctl__scnprintf_perf_cmd, }, 1398c2ecf20Sopenharmony_ci ['A' - '$'] = { .type = 'A', .scnprintf = ioctl__scnprintf_sndrv_pcm_cmd, }, 1408c2ecf20Sopenharmony_ci ['T' - '$'] = { .type = 'T', .scnprintf = ioctl__scnprintf_tty_cmd, }, 1418c2ecf20Sopenharmony_ci ['U' - '$'] = { .type = 'U', .scnprintf = ioctl__scnprintf_sndrv_ctl_cmd, }, 1428c2ecf20Sopenharmony_ci ['d' - '$'] = { .type = 'd', .scnprintf = ioctl__scnprintf_drm_cmd, }, 1438c2ecf20Sopenharmony_ci [0xAE - '$'] = { .type = 0xAE, .scnprintf = ioctl__scnprintf_kvm_cmd, }, 1448c2ecf20Sopenharmony_ci [0xAF - '$'] = { .type = 0xAF, .scnprintf = ioctl__scnprintf_vhost_virtio_cmd, }, 1458c2ecf20Sopenharmony_ci }; 1468c2ecf20Sopenharmony_ci const int nr_types = ARRAY_SIZE(ioctl_types); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (type >= ioctl_types[0].type && type <= ioctl_types[nr_types - 1].type) { 1498c2ecf20Sopenharmony_ci const int index = type - ioctl_types[0].type; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (ioctl_types[index].scnprintf != NULL) 1528c2ecf20Sopenharmony_ci return ioctl_types[index].scnprintf(nr, dir, bf, size); 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci printed += scnprintf(bf + printed, size - printed, "%c", '('); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (dir == _IOC_NONE) { 1588c2ecf20Sopenharmony_ci printed += scnprintf(bf + printed, size - printed, "%s%s", show_prefix ? prefix : "", "NONE"); 1598c2ecf20Sopenharmony_ci } else { 1608c2ecf20Sopenharmony_ci if (dir & _IOC_READ) 1618c2ecf20Sopenharmony_ci printed += scnprintf(bf + printed, size - printed, "%s%s", show_prefix ? prefix : "", "READ"); 1628c2ecf20Sopenharmony_ci if (dir & _IOC_WRITE) { 1638c2ecf20Sopenharmony_ci printed += scnprintf(bf + printed, size - printed, "%s%s%s", dir & _IOC_READ ? "|" : "", 1648c2ecf20Sopenharmony_ci show_prefix ? prefix : "", "WRITE"); 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci return printed + scnprintf(bf + printed, size - printed, ", %#x, %#x, %#x)", type, nr, sz); 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci#ifndef USB_DEVICE_MAJOR 1728c2ecf20Sopenharmony_ci#define USB_DEVICE_MAJOR 189 1738c2ecf20Sopenharmony_ci#endif // USB_DEVICE_MAJOR 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cisize_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci unsigned long cmd = arg->val; 1788c2ecf20Sopenharmony_ci int fd = syscall_arg__val(arg, 0); 1798c2ecf20Sopenharmony_ci struct file *file = thread__files_entry(arg->thread, fd); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci if (file != NULL) { 1828c2ecf20Sopenharmony_ci if (file->dev_maj == USB_DEVICE_MAJOR) 1838c2ecf20Sopenharmony_ci return ioctl__scnprintf_usbdevfs_cmd(_IOC_NR(cmd), _IOC_DIR(cmd), bf, size); 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci return ioctl__scnprintf_cmd(cmd, bf, size, arg->show_string_prefix); 1878c2ecf20Sopenharmony_ci} 188