1794f594eSArnaldo Carvalho de Melo // SPDX-License-Identifier: LGPL-2.1
21cc47f2dSArnaldo Carvalho de Melo /*
31cc47f2dSArnaldo Carvalho de Melo * trace/beauty/ioctl.c
41cc47f2dSArnaldo Carvalho de Melo *
51cc47f2dSArnaldo Carvalho de Melo * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
61cc47f2dSArnaldo Carvalho de Melo */
71cc47f2dSArnaldo Carvalho de Melo
81cc47f2dSArnaldo Carvalho de Melo #include "trace/beauty/beauty.h"
91cc47f2dSArnaldo Carvalho de Melo #include <linux/kernel.h>
101cc47f2dSArnaldo Carvalho de Melo
111cc47f2dSArnaldo Carvalho de Melo /*
121cc47f2dSArnaldo Carvalho de Melo * FIXME: to support all arches we have to improve this, for
131cc47f2dSArnaldo Carvalho de Melo * now, to build on older systems without things like TIOCGEXCL,
141cc47f2dSArnaldo Carvalho de Melo * get it directly from our copy.
151cc47f2dSArnaldo Carvalho de Melo *
161cc47f2dSArnaldo Carvalho de Melo * Right now only x86 is being supported for beautifying ioctl args
171cc47f2dSArnaldo Carvalho de Melo * in 'perf trace', see tools/perf/trace/beauty/Build and builtin-trace.c
181cc47f2dSArnaldo Carvalho de Melo */
191cc47f2dSArnaldo Carvalho de Melo #include <uapi/asm-generic/ioctls.h>
201cc47f2dSArnaldo Carvalho de Melo
ioctl__scnprintf_tty_cmd(int nr,int dir,char * bf,size_t size)218ff69577SArnaldo Carvalho de Melo static size_t ioctl__scnprintf_tty_cmd(int nr, int dir, char *bf, size_t size)
221cc47f2dSArnaldo Carvalho de Melo {
231cc47f2dSArnaldo Carvalho de Melo static const char *ioctl_tty_cmd[] = {
24b92675f4SBenjamin Peterson [_IOC_NR(TCGETS)] = "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
251cc47f2dSArnaldo Carvalho de Melo "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL", "TIOCSCTTY",
261cc47f2dSArnaldo Carvalho de Melo "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI", "TIOCGWINSZ", "TIOCSWINSZ",
271cc47f2dSArnaldo Carvalho de Melo "TIOCMGET", "TIOCMBIS", "TIOCMBIC", "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR",
281cc47f2dSArnaldo Carvalho de Melo "FIONREAD", "TIOCLINUX", "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT",
291cc47f2dSArnaldo Carvalho de Melo "FIONBIO", "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP",
301cc47f2dSArnaldo Carvalho de Melo [_IOC_NR(TIOCSBRK)] = "TIOCSBRK", "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2",
311cc47f2dSArnaldo Carvalho de Melo "TCSETSW2", "TCSETSF2", "TIOCGRS48", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
321cc47f2dSArnaldo Carvalho de Melo "TIOCGDEV", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG", "TIOCVHANGUP", "TIOCGPKT",
331cc47f2dSArnaldo Carvalho de Melo "TIOCGPTLCK", [_IOC_NR(TIOCGEXCL)] = "TIOCGEXCL", "TIOCGPTPEER",
34a4243e14SArnaldo Carvalho de Melo "TIOCGISO7816", "TIOCSISO7816",
351cc47f2dSArnaldo Carvalho de Melo [_IOC_NR(FIONCLEX)] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
361cc47f2dSArnaldo Carvalho de Melo "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
371cc47f2dSArnaldo Carvalho de Melo "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
381cc47f2dSArnaldo Carvalho de Melo "TIOCMIWAIT", "TIOCGICOUNT", };
392e3d7facSArnaldo Carvalho de Melo static DEFINE_STRARRAY(ioctl_tty_cmd, "");
401cc47f2dSArnaldo Carvalho de Melo
411cc47f2dSArnaldo Carvalho de Melo if (nr < strarray__ioctl_tty_cmd.nr_entries && strarray__ioctl_tty_cmd.entries[nr] != NULL)
421cc47f2dSArnaldo Carvalho de Melo return scnprintf(bf, size, "%s", strarray__ioctl_tty_cmd.entries[nr]);
431cc47f2dSArnaldo Carvalho de Melo
448ff69577SArnaldo Carvalho de Melo return scnprintf(bf, size, "(%#x, %#x, %#x)", 'T', nr, dir);
451cc47f2dSArnaldo Carvalho de Melo }
461cc47f2dSArnaldo Carvalho de Melo
ioctl__scnprintf_drm_cmd(int nr,int dir,char * bf,size_t size)478ff69577SArnaldo Carvalho de Melo static size_t ioctl__scnprintf_drm_cmd(int nr, int dir, char *bf, size_t size)
48ef9811f0SArnaldo Carvalho de Melo {
49ef9811f0SArnaldo Carvalho de Melo #include "trace/beauty/generated/ioctl/drm_ioctl_array.c"
502e3d7facSArnaldo Carvalho de Melo static DEFINE_STRARRAY(drm_ioctl_cmds, "");
51ef9811f0SArnaldo Carvalho de Melo
52ef9811f0SArnaldo Carvalho de Melo if (nr < strarray__drm_ioctl_cmds.nr_entries && strarray__drm_ioctl_cmds.entries[nr] != NULL)
53ef9811f0SArnaldo Carvalho de Melo return scnprintf(bf, size, "DRM_%s", strarray__drm_ioctl_cmds.entries[nr]);
54ef9811f0SArnaldo Carvalho de Melo
558ff69577SArnaldo Carvalho de Melo return scnprintf(bf, size, "(%#x, %#x, %#x)", 'd', nr, dir);
56ef9811f0SArnaldo Carvalho de Melo }
57ef9811f0SArnaldo Carvalho de Melo
ioctl__scnprintf_sndrv_pcm_cmd(int nr,int dir,char * bf,size_t size)588ff69577SArnaldo Carvalho de Melo static size_t ioctl__scnprintf_sndrv_pcm_cmd(int nr, int dir, char *bf, size_t size)
592c3e9629SArnaldo Carvalho de Melo {
602c3e9629SArnaldo Carvalho de Melo #include "trace/beauty/generated/ioctl/sndrv_pcm_ioctl_array.c"
612e3d7facSArnaldo Carvalho de Melo static DEFINE_STRARRAY(sndrv_pcm_ioctl_cmds, "");
622c3e9629SArnaldo Carvalho de Melo
632c3e9629SArnaldo Carvalho de Melo if (nr < strarray__sndrv_pcm_ioctl_cmds.nr_entries && strarray__sndrv_pcm_ioctl_cmds.entries[nr] != NULL)
642c3e9629SArnaldo Carvalho de Melo return scnprintf(bf, size, "SNDRV_PCM_%s", strarray__sndrv_pcm_ioctl_cmds.entries[nr]);
652c3e9629SArnaldo Carvalho de Melo
668ff69577SArnaldo Carvalho de Melo return scnprintf(bf, size, "(%#x, %#x, %#x)", 'A', nr, dir);
672c3e9629SArnaldo Carvalho de Melo }
682c3e9629SArnaldo Carvalho de Melo
ioctl__scnprintf_sndrv_ctl_cmd(int nr,int dir,char * bf,size_t size)698ff69577SArnaldo Carvalho de Melo static size_t ioctl__scnprintf_sndrv_ctl_cmd(int nr, int dir, char *bf, size_t size)
702c3e9629SArnaldo Carvalho de Melo {
712c3e9629SArnaldo Carvalho de Melo #include "trace/beauty/generated/ioctl/sndrv_ctl_ioctl_array.c"
722e3d7facSArnaldo Carvalho de Melo static DEFINE_STRARRAY(sndrv_ctl_ioctl_cmds, "");
732c3e9629SArnaldo Carvalho de Melo
742c3e9629SArnaldo Carvalho de Melo if (nr < strarray__sndrv_ctl_ioctl_cmds.nr_entries && strarray__sndrv_ctl_ioctl_cmds.entries[nr] != NULL)
752c3e9629SArnaldo Carvalho de Melo return scnprintf(bf, size, "SNDRV_CTL_%s", strarray__sndrv_ctl_ioctl_cmds.entries[nr]);
762c3e9629SArnaldo Carvalho de Melo
778ff69577SArnaldo Carvalho de Melo return scnprintf(bf, size, "(%#x, %#x, %#x)", 'U', nr, dir);
782c3e9629SArnaldo Carvalho de Melo }
792c3e9629SArnaldo Carvalho de Melo
ioctl__scnprintf_kvm_cmd(int nr,int dir,char * bf,size_t size)808ff69577SArnaldo Carvalho de Melo static size_t ioctl__scnprintf_kvm_cmd(int nr, int dir, char *bf, size_t size)
8145717b7fSArnaldo Carvalho de Melo {
8245717b7fSArnaldo Carvalho de Melo #include "trace/beauty/generated/ioctl/kvm_ioctl_array.c"
832e3d7facSArnaldo Carvalho de Melo static DEFINE_STRARRAY(kvm_ioctl_cmds, "");
8445717b7fSArnaldo Carvalho de Melo
8545717b7fSArnaldo Carvalho de Melo if (nr < strarray__kvm_ioctl_cmds.nr_entries && strarray__kvm_ioctl_cmds.entries[nr] != NULL)
8645717b7fSArnaldo Carvalho de Melo return scnprintf(bf, size, "KVM_%s", strarray__kvm_ioctl_cmds.entries[nr]);
8745717b7fSArnaldo Carvalho de Melo
888ff69577SArnaldo Carvalho de Melo return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir);
8945717b7fSArnaldo Carvalho de Melo }
9045717b7fSArnaldo Carvalho de Melo
ioctl__scnprintf_vhost_virtio_cmd(int nr,int dir,char * bf,size_t size)91ec6dd85fSArnaldo Carvalho de Melo static size_t ioctl__scnprintf_vhost_virtio_cmd(int nr, int dir, char *bf, size_t size)
92ec6dd85fSArnaldo Carvalho de Melo {
93ec6dd85fSArnaldo Carvalho de Melo #include "trace/beauty/generated/ioctl/vhost_virtio_ioctl_array.c"
942e3d7facSArnaldo Carvalho de Melo static DEFINE_STRARRAY(vhost_virtio_ioctl_cmds, "");
952e3d7facSArnaldo Carvalho de Melo static DEFINE_STRARRAY(vhost_virtio_ioctl_read_cmds, "");
96ec6dd85fSArnaldo Carvalho de Melo struct strarray *s = (dir & _IOC_READ) ? &strarray__vhost_virtio_ioctl_read_cmds : &strarray__vhost_virtio_ioctl_cmds;
97ec6dd85fSArnaldo Carvalho de Melo
98ec6dd85fSArnaldo Carvalho de Melo if (nr < s->nr_entries && s->entries[nr] != NULL)
99ec6dd85fSArnaldo Carvalho de Melo return scnprintf(bf, size, "VHOST_%s", s->entries[nr]);
100ec6dd85fSArnaldo Carvalho de Melo
101ec6dd85fSArnaldo Carvalho de Melo return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAF, nr, dir);
102ec6dd85fSArnaldo Carvalho de Melo }
103ec6dd85fSArnaldo Carvalho de Melo
ioctl__scnprintf_perf_cmd(int nr,int dir,char * bf,size_t size)10481e3d8b2SArnaldo Carvalho de Melo static size_t ioctl__scnprintf_perf_cmd(int nr, int dir, char *bf, size_t size)
10581e3d8b2SArnaldo Carvalho de Melo {
10681e3d8b2SArnaldo Carvalho de Melo #include "trace/beauty/generated/ioctl/perf_ioctl_array.c"
1072e3d7facSArnaldo Carvalho de Melo static DEFINE_STRARRAY(perf_ioctl_cmds, "");
10881e3d8b2SArnaldo Carvalho de Melo
10981e3d8b2SArnaldo Carvalho de Melo if (nr < strarray__perf_ioctl_cmds.nr_entries && strarray__perf_ioctl_cmds.entries[nr] != NULL)
11081e3d8b2SArnaldo Carvalho de Melo return scnprintf(bf, size, "PERF_%s", strarray__perf_ioctl_cmds.entries[nr]);
11181e3d8b2SArnaldo Carvalho de Melo
11281e3d8b2SArnaldo Carvalho de Melo return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir);
11381e3d8b2SArnaldo Carvalho de Melo }
11481e3d8b2SArnaldo Carvalho de Melo
ioctl__scnprintf_usbdevfs_cmd(int nr,int dir,char * bf,size_t size)11538fc9da6SArnaldo Carvalho de Melo static size_t ioctl__scnprintf_usbdevfs_cmd(int nr, int dir, char *bf, size_t size)
11638fc9da6SArnaldo Carvalho de Melo {
11738fc9da6SArnaldo Carvalho de Melo #include "trace/beauty/generated/ioctl/usbdevfs_ioctl_array.c"
11838fc9da6SArnaldo Carvalho de Melo static DEFINE_STRARRAY(usbdevfs_ioctl_cmds, "");
11938fc9da6SArnaldo Carvalho de Melo
12038fc9da6SArnaldo Carvalho de Melo if (nr < strarray__usbdevfs_ioctl_cmds.nr_entries && strarray__usbdevfs_ioctl_cmds.entries[nr] != NULL)
12138fc9da6SArnaldo Carvalho de Melo return scnprintf(bf, size, "USBDEVFS_%s", strarray__usbdevfs_ioctl_cmds.entries[nr]);
12238fc9da6SArnaldo Carvalho de Melo
12338fc9da6SArnaldo Carvalho de Melo return scnprintf(bf, size, "(%c, %#x, %#x)", 'U', nr, dir);
12438fc9da6SArnaldo Carvalho de Melo }
12538fc9da6SArnaldo Carvalho de Melo
ioctl__scnprintf_cmd(unsigned long cmd,char * bf,size_t size,bool show_prefix)126c65c83ffSArnaldo Carvalho de Melo static size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size, bool show_prefix)
1271cc47f2dSArnaldo Carvalho de Melo {
128c65c83ffSArnaldo Carvalho de Melo const char *prefix = "_IOC_";
1291cc47f2dSArnaldo Carvalho de Melo int dir = _IOC_DIR(cmd),
1301cc47f2dSArnaldo Carvalho de Melo type = _IOC_TYPE(cmd),
1311cc47f2dSArnaldo Carvalho de Melo nr = _IOC_NR(cmd),
1321cc47f2dSArnaldo Carvalho de Melo sz = _IOC_SIZE(cmd);
1331cc47f2dSArnaldo Carvalho de Melo int printed = 0;
1341cc47f2dSArnaldo Carvalho de Melo static const struct ioctl_type {
1351cc47f2dSArnaldo Carvalho de Melo int type;
1368ff69577SArnaldo Carvalho de Melo size_t (*scnprintf)(int nr, int dir, char *bf, size_t size);
1371cc47f2dSArnaldo Carvalho de Melo } ioctl_types[] = { /* Must be ordered by type */
13881e3d8b2SArnaldo Carvalho de Melo { .type = '$', .scnprintf = ioctl__scnprintf_perf_cmd, },
13981e3d8b2SArnaldo Carvalho de Melo ['A' - '$'] = { .type = 'A', .scnprintf = ioctl__scnprintf_sndrv_pcm_cmd, },
14081e3d8b2SArnaldo Carvalho de Melo ['T' - '$'] = { .type = 'T', .scnprintf = ioctl__scnprintf_tty_cmd, },
14181e3d8b2SArnaldo Carvalho de Melo ['U' - '$'] = { .type = 'U', .scnprintf = ioctl__scnprintf_sndrv_ctl_cmd, },
14281e3d8b2SArnaldo Carvalho de Melo ['d' - '$'] = { .type = 'd', .scnprintf = ioctl__scnprintf_drm_cmd, },
14381e3d8b2SArnaldo Carvalho de Melo [0xAE - '$'] = { .type = 0xAE, .scnprintf = ioctl__scnprintf_kvm_cmd, },
14481e3d8b2SArnaldo Carvalho de Melo [0xAF - '$'] = { .type = 0xAF, .scnprintf = ioctl__scnprintf_vhost_virtio_cmd, },
1451cc47f2dSArnaldo Carvalho de Melo };
1461cc47f2dSArnaldo Carvalho de Melo const int nr_types = ARRAY_SIZE(ioctl_types);
1471cc47f2dSArnaldo Carvalho de Melo
1481cc47f2dSArnaldo Carvalho de Melo if (type >= ioctl_types[0].type && type <= ioctl_types[nr_types - 1].type) {
1491cc47f2dSArnaldo Carvalho de Melo const int index = type - ioctl_types[0].type;
1501cc47f2dSArnaldo Carvalho de Melo
1511cc47f2dSArnaldo Carvalho de Melo if (ioctl_types[index].scnprintf != NULL)
1528ff69577SArnaldo Carvalho de Melo return ioctl_types[index].scnprintf(nr, dir, bf, size);
1531cc47f2dSArnaldo Carvalho de Melo }
1541cc47f2dSArnaldo Carvalho de Melo
1551cc47f2dSArnaldo Carvalho de Melo printed += scnprintf(bf + printed, size - printed, "%c", '(');
1561cc47f2dSArnaldo Carvalho de Melo
1571cc47f2dSArnaldo Carvalho de Melo if (dir == _IOC_NONE) {
158c65c83ffSArnaldo Carvalho de Melo printed += scnprintf(bf + printed, size - printed, "%s%s", show_prefix ? prefix : "", "NONE");
1591cc47f2dSArnaldo Carvalho de Melo } else {
1601cc47f2dSArnaldo Carvalho de Melo if (dir & _IOC_READ)
161c65c83ffSArnaldo Carvalho de Melo printed += scnprintf(bf + printed, size - printed, "%s%s", show_prefix ? prefix : "", "READ");
162c65c83ffSArnaldo Carvalho de Melo if (dir & _IOC_WRITE) {
163c65c83ffSArnaldo Carvalho de Melo printed += scnprintf(bf + printed, size - printed, "%s%s%s", dir & _IOC_READ ? "|" : "",
164c65c83ffSArnaldo Carvalho de Melo show_prefix ? prefix : "", "WRITE");
165c65c83ffSArnaldo Carvalho de Melo }
1661cc47f2dSArnaldo Carvalho de Melo }
1671cc47f2dSArnaldo Carvalho de Melo
1681cc47f2dSArnaldo Carvalho de Melo return printed + scnprintf(bf + printed, size - printed, ", %#x, %#x, %#x)", type, nr, sz);
1691cc47f2dSArnaldo Carvalho de Melo }
1701cc47f2dSArnaldo Carvalho de Melo
17138fc9da6SArnaldo Carvalho de Melo #ifndef USB_DEVICE_MAJOR
17238fc9da6SArnaldo Carvalho de Melo #define USB_DEVICE_MAJOR 189
17338fc9da6SArnaldo Carvalho de Melo #endif // USB_DEVICE_MAJOR
17438fc9da6SArnaldo Carvalho de Melo
syscall_arg__scnprintf_ioctl_cmd(char * bf,size_t size,struct syscall_arg * arg)1751cc47f2dSArnaldo Carvalho de Melo size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg)
1761cc47f2dSArnaldo Carvalho de Melo {
1771cc47f2dSArnaldo Carvalho de Melo unsigned long cmd = arg->val;
178e1be4a5cSArnaldo Carvalho de Melo int fd = syscall_arg__val(arg, 0);
17938fc9da6SArnaldo Carvalho de Melo struct file *file = thread__files_entry(arg->thread, fd);
18038fc9da6SArnaldo Carvalho de Melo
18138fc9da6SArnaldo Carvalho de Melo if (file != NULL) {
18238fc9da6SArnaldo Carvalho de Melo if (file->dev_maj == USB_DEVICE_MAJOR)
18338fc9da6SArnaldo Carvalho de Melo return ioctl__scnprintf_usbdevfs_cmd(_IOC_NR(cmd), _IOC_DIR(cmd), bf, size);
18438fc9da6SArnaldo Carvalho de Melo }
1851cc47f2dSArnaldo Carvalho de Melo
186c65c83ffSArnaldo Carvalho de Melo return ioctl__scnprintf_cmd(cmd, bf, size, arg->show_string_prefix);
1871cc47f2dSArnaldo Carvalho de Melo }
188