xref: /openbmc/linux/tools/perf/trace/beauty/ioctl.c (revision b92675f4)
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