Home | History | Annotate | Line # | Download | only in intrctl
intrctl.c revision 1.10
      1  1.10       mrg /*	$NetBSD: intrctl.c,v 1.10 2019/09/23 20:15:31 mrg Exp $	*/
      2   1.1  knakahar 
      3   1.1  knakahar /*
      4   1.1  knakahar  * Copyright (c) 2015 Internet Initiative Japan Inc.
      5   1.1  knakahar  * All rights reserved.
      6   1.1  knakahar  *
      7   1.1  knakahar  * Redistribution and use in source and binary forms, with or without
      8   1.1  knakahar  * modification, are permitted provided that the following conditions
      9   1.1  knakahar  * are met:
     10   1.1  knakahar  * 1. Redistributions of source code must retain the above copyright
     11   1.1  knakahar  *    notice, this list of conditions and the following disclaimer.
     12   1.1  knakahar  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1  knakahar  *    notice, this list of conditions and the following disclaimer in the
     14   1.1  knakahar  *    documentation and/or other materials provided with the distribution.
     15   1.1  knakahar  *
     16   1.1  knakahar  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17   1.1  knakahar  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18   1.1  knakahar  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19   1.1  knakahar  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20   1.1  knakahar  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21   1.1  knakahar  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22   1.1  knakahar  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23   1.1  knakahar  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24   1.1  knakahar  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25   1.1  knakahar  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26   1.1  knakahar  * POSSIBILITY OF SUCH DAMAGE.
     27   1.1  knakahar  */
     28   1.1  knakahar 
     29   1.1  knakahar #include <sys/cdefs.h>
     30  1.10       mrg __RCSID("$NetBSD: intrctl.c,v 1.10 2019/09/23 20:15:31 mrg Exp $");
     31   1.1  knakahar 
     32   1.1  knakahar #include <sys/param.h>
     33   1.1  knakahar #include <sys/sysctl.h>
     34   1.1  knakahar #include <sys/intrio.h>
     35   1.1  knakahar #include <sys/types.h>
     36   1.1  knakahar 
     37   1.1  knakahar #include <err.h>
     38   1.1  knakahar #include <errno.h>
     39   1.1  knakahar #include <fcntl.h>
     40   1.1  knakahar #include <limits.h>
     41   1.1  knakahar #include <paths.h>
     42   1.1  knakahar #include <sched.h>
     43   1.1  knakahar #include <stdint.h>
     44   1.1  knakahar #include <stdio.h>
     45   1.1  knakahar #include <stdlib.h>
     46   1.1  knakahar #include <string.h>
     47   1.1  knakahar #include <unistd.h>
     48   1.1  knakahar 
     49   1.1  knakahar #include "intrctl_io.h"
     50   1.1  knakahar 
     51   1.1  knakahar __dead static void	usage(void);
     52   1.1  knakahar 
     53   1.1  knakahar int		verbose;
     54   1.1  knakahar 
     55   1.1  knakahar static void	intrctl_list(int, char **);
     56   1.1  knakahar static void	intrctl_affinity(int, char **);
     57   1.1  knakahar static void	intrctl_intr(int, char **);
     58   1.1  knakahar static void	intrctl_nointr(int, char **);
     59   1.1  knakahar 
     60   1.1  knakahar static struct cmdtab {
     61   1.1  knakahar 	const char	*label;
     62   1.1  knakahar 	void	(*func)(int, char **);
     63   1.1  knakahar } const intrctl_cmdtab[] = {
     64   1.1  knakahar 	{ "list", intrctl_list },
     65   1.1  knakahar 	{ "affinity", intrctl_affinity },
     66   1.1  knakahar 	{ "intr", intrctl_intr },
     67   1.1  knakahar 	{ "nointr", intrctl_nointr },
     68   1.1  knakahar 	{ NULL, NULL },
     69   1.1  knakahar };
     70   1.1  knakahar 
     71   1.1  knakahar int
     72   1.1  knakahar main(int argc, char **argv)
     73   1.1  knakahar {
     74   1.1  knakahar 	const struct cmdtab *ct;
     75   1.1  knakahar 	char *cmdname;
     76   1.1  knakahar 
     77   1.1  knakahar 	if (argc < 2)
     78   1.1  knakahar 		usage();
     79   1.1  knakahar 
     80   1.1  knakahar 	cmdname = argv[1];
     81   1.1  knakahar 	argv += 1;
     82   1.1  knakahar 	argc -= 1;
     83   1.1  knakahar 
     84   1.1  knakahar 	for (ct = intrctl_cmdtab; ct->label != NULL; ct++) {
     85   1.1  knakahar 		if (strcmp(cmdname, ct->label) == 0) {
     86   1.1  knakahar 			break;
     87   1.1  knakahar 		}
     88   1.1  knakahar 	}
     89   1.1  knakahar 	if (ct->label == NULL)
     90   1.1  knakahar 		errx(EXIT_FAILURE, "unknown command ``%s''", cmdname);
     91   1.1  knakahar 
     92   1.1  knakahar 	(*ct->func)(argc, argv);
     93   1.1  knakahar 	exit(EXIT_SUCCESS);
     94   1.1  knakahar 	/* NOTREACHED */
     95   1.1  knakahar }
     96   1.1  knakahar 
     97   1.1  knakahar static void
     98   1.1  knakahar usage(void)
     99   1.1  knakahar {
    100   1.1  knakahar 	const char *progname = getprogname();
    101   1.1  knakahar 
    102  1.10       mrg 	fprintf(stderr, "usage: %s list [-c] [-w secs] [-z]\n", progname);
    103  1.10       mrg 	fprintf(stderr, "       %s affinity -i interrupt_name -c cpu_index\n",
    104  1.10       mrg 	    progname);
    105   1.1  knakahar 	fprintf(stderr, "       %s intr -c cpu_index\n", progname);
    106   1.1  knakahar 	fprintf(stderr, "       %s nointr -c cpu_index\n", progname);
    107   1.1  knakahar 	exit(EXIT_FAILURE);
    108   1.1  knakahar 	/* NOTREACHED */
    109   1.1  knakahar }
    110   1.1  knakahar 
    111   1.1  knakahar static int intrctl_io_alloc_retry_count = 4;
    112   1.1  knakahar 
    113   1.1  knakahar static void
    114  1.10       mrg intrctl_list_one(bool compact, bool skipzero)
    115   1.1  knakahar {
    116   1.3       ryo 	char buf[64];
    117   1.1  knakahar 	struct intrio_list_line *illine;
    118   1.3       ryo 	int i, ncpus, *cpucol;
    119   1.1  knakahar 	void *handle;
    120   1.2  knakahar 	size_t intridlen;
    121   1.1  knakahar 
    122   1.1  knakahar 	handle = intrctl_io_alloc(intrctl_io_alloc_retry_count);
    123   1.1  knakahar 	if (handle == NULL)
    124   1.1  knakahar 		err(EXIT_FAILURE, "intrctl_io_alloc");
    125   1.1  knakahar 
    126   1.2  knakahar 	/* calc columns */
    127   1.2  knakahar 	ncpus = intrctl_io_ncpus(handle);
    128   1.2  knakahar 	intridlen = strlen("interrupt id");
    129   1.3       ryo 	for (illine = intrctl_io_firstline(handle); illine != NULL;
    130   1.3       ryo 	    illine = intrctl_io_nextline(handle, illine)) {
    131   1.2  knakahar 		size_t len = strlen(illine->ill_intrid);
    132   1.2  knakahar 		if (intridlen < len)
    133   1.2  knakahar 			intridlen = len;
    134   1.2  knakahar 	}
    135   1.2  knakahar 
    136   1.3       ryo 	cpucol = malloc(sizeof(*cpucol) * (size_t)ncpus);
    137   1.3       ryo 	if (cpucol == NULL)
    138   1.3       ryo 		err(EXIT_FAILURE, "malloc");
    139   1.3       ryo 	for (i = 0; i < ncpus; i++) {
    140   1.3       ryo 		snprintf(buf, sizeof(buf), "CPU%u", i);
    141   1.3       ryo 		cpucol[i] = strlen(buf);
    142   1.3       ryo 	}
    143   1.3       ryo 	for (illine = intrctl_io_firstline(handle); illine != NULL;
    144   1.3       ryo 	    illine = intrctl_io_nextline(handle, illine)) {
    145   1.3       ryo 		for (i = 0; i < ncpus; i++) {
    146   1.3       ryo 			int len;
    147   1.3       ryo 			snprintf(buf, sizeof(buf), "%" PRIu64,
    148   1.3       ryo 			    illine->ill_cpu[i].illc_count);
    149   1.3       ryo 			len = (int)strlen(buf);
    150   1.3       ryo 			if (cpucol[i] < len)
    151   1.3       ryo 				cpucol[i] = len;
    152   1.3       ryo 		}
    153   1.3       ryo 	}
    154   1.3       ryo 
    155   1.1  knakahar 	/* header */
    156   1.7       ryo 	printf("%-*s ", (int)intridlen, "interrupt id");
    157   1.4  jdolecek 	if (compact) {
    158   1.7       ryo 		printf("%20s ", "total");
    159   1.7       ryo 		printf("%5s ", "aff");
    160   1.4  jdolecek 	} else {
    161   1.4  jdolecek 		for (i = 0; i < ncpus; i++) {
    162   1.4  jdolecek 			snprintf(buf, sizeof(buf), "CPU%u", i);
    163   1.4  jdolecek 			printf("%*s  ", cpucol[i], buf);
    164   1.4  jdolecek 		}
    165   1.1  knakahar 	}
    166   1.3       ryo 	printf("device name(s)\n");
    167   1.1  knakahar 
    168   1.1  knakahar 	/* body */
    169   1.3       ryo 	for (illine = intrctl_io_firstline(handle); illine != NULL;
    170   1.3       ryo 	    illine = intrctl_io_nextline(handle, illine)) {
    171   1.4  jdolecek 		struct intrio_list_line_cpu *illc;
    172   1.4  jdolecek 
    173  1.10       mrg 		if (skipzero) {
    174  1.10       mrg 			bool is_zero = true;
    175  1.10       mrg 
    176  1.10       mrg 			for (i = 0; i < ncpus; i++) {
    177  1.10       mrg 				illc = &illine->ill_cpu[i];
    178  1.10       mrg 				if (illc->illc_count != 0) {
    179  1.10       mrg 					is_zero = false;
    180  1.10       mrg 					break;
    181  1.10       mrg 				}
    182  1.10       mrg 			}
    183  1.10       mrg 			if (is_zero)
    184  1.10       mrg 				continue;
    185  1.10       mrg 		}
    186  1.10       mrg 
    187   1.4  jdolecek 		printf("%-*s ", (int)intridlen, illine->ill_intrid);
    188   1.4  jdolecek 		if (compact) {
    189   1.4  jdolecek 			uint64_t total = 0;
    190   1.8  jdolecek 			char *affinity = NULL, *oaffinity = NULL;
    191   1.4  jdolecek 			for (i = 0; i < ncpus; i++) {
    192   1.4  jdolecek 				illc = &illine->ill_cpu[i];
    193   1.4  jdolecek 				total += illc->illc_count;
    194   1.4  jdolecek 				if (illc->illc_assigned) {
    195   1.4  jdolecek 					asprintf(&affinity, "%s%s%d",
    196   1.4  jdolecek 					    oaffinity ? oaffinity : "",
    197   1.4  jdolecek 					    oaffinity ? ", " : "",
    198   1.4  jdolecek 					    i);
    199   1.4  jdolecek 					if (oaffinity)
    200   1.4  jdolecek 						free(oaffinity);
    201   1.4  jdolecek 					oaffinity = affinity;
    202   1.4  jdolecek 				}
    203   1.4  jdolecek 			}
    204   1.4  jdolecek 			printf("%20" PRIu64 " ", total);
    205   1.5  jdolecek 			printf("%5s ", affinity ? affinity : "none");
    206   1.8  jdolecek 			if (affinity)
    207   1.8  jdolecek 				free(affinity);
    208   1.4  jdolecek 		} else {
    209   1.4  jdolecek 			for (i = 0; i < ncpus; i++) {
    210   1.4  jdolecek 				illc = &illine->ill_cpu[i];
    211   1.4  jdolecek 				printf("%*" PRIu64 "%c ", cpucol[i], illc->illc_count,
    212   1.4  jdolecek 				    illc->illc_assigned ? '*' : ' ');
    213   1.4  jdolecek 			}
    214   1.1  knakahar 		}
    215   1.1  knakahar 		printf("%s\n", illine->ill_xname);
    216   1.1  knakahar 	}
    217   1.1  knakahar 
    218   1.3       ryo 	free(cpucol);
    219   1.1  knakahar 	intrctl_io_free(handle);
    220   1.1  knakahar }
    221   1.1  knakahar 
    222   1.1  knakahar static void
    223   1.9       mrg intrctl_list(int argc, char **argv)
    224   1.9       mrg {
    225   1.9       mrg 	int seconds = 0;
    226   1.9       mrg 	bool compact = false;
    227  1.10       mrg 	bool skipzero = false;
    228   1.9       mrg 	int ch;
    229   1.9       mrg 
    230  1.10       mrg 	while ((ch = getopt(argc, argv, "cw:z")) != -1) {
    231   1.9       mrg 		switch (ch) {
    232   1.9       mrg 		case 'c':
    233   1.9       mrg 			compact = true;
    234   1.9       mrg 			break;
    235  1.10       mrg 		case 'z':
    236  1.10       mrg 			skipzero = true;
    237  1.10       mrg 			break;
    238   1.9       mrg 		case 'w':
    239   1.9       mrg 			seconds = atoi(optarg);
    240   1.9       mrg 			if (seconds < 0)
    241   1.9       mrg 				errx(1, "seconds must be positive.");
    242   1.9       mrg 			break;
    243   1.9       mrg 		default:
    244   1.9       mrg 			usage();
    245   1.9       mrg 		}
    246   1.9       mrg 	}
    247   1.9       mrg 
    248  1.10       mrg 	for (;;) {
    249  1.10       mrg 		intrctl_list_one(compact, skipzero);
    250  1.10       mrg 		if (seconds == 0)
    251  1.10       mrg 			break;
    252   1.9       mrg 		sleep(seconds);
    253  1.10       mrg 	}
    254   1.9       mrg }
    255   1.9       mrg 
    256   1.9       mrg static void
    257   1.1  knakahar intrctl_affinity(int argc, char **argv)
    258   1.1  knakahar {
    259   1.1  knakahar 	struct intrio_set iset;
    260   1.1  knakahar 	cpuset_t *cpuset;
    261   1.1  knakahar 	unsigned long index;
    262   1.1  knakahar 	int ch, error;
    263   1.1  knakahar 
    264   1.1  knakahar 	index = ULONG_MAX;
    265   1.1  knakahar 	memset(&iset.intrid, 0, sizeof(iset.intrid));
    266   1.1  knakahar 
    267   1.1  knakahar 	while ((ch = getopt(argc, argv, "c:i:")) != -1) {
    268   1.1  knakahar 		switch (ch) {
    269   1.1  knakahar 		case 'c':
    270   1.1  knakahar 			index = strtoul(optarg, NULL, 10);
    271   1.1  knakahar 			break;
    272   1.1  knakahar 		case 'i':
    273   1.1  knakahar 			if (strnlen(optarg, ARG_MAX) > INTRIDBUF)
    274   1.1  knakahar 				usage();
    275   1.1  knakahar 			strlcpy(iset.intrid, optarg, INTRIDBUF);
    276   1.1  knakahar 			break;
    277   1.1  knakahar 		default:
    278   1.1  knakahar 			usage();
    279   1.1  knakahar 		}
    280   1.1  knakahar 	}
    281   1.1  knakahar 
    282   1.1  knakahar 	if (iset.intrid[0] == '\0' || index == ULONG_MAX)
    283   1.1  knakahar 		usage();
    284   1.1  knakahar 
    285   1.1  knakahar 	if (index >= (u_long)sysconf(_SC_NPROCESSORS_CONF))
    286   1.1  knakahar 		err(EXIT_FAILURE, "invalid cpu index");
    287   1.1  knakahar 
    288   1.1  knakahar 	cpuset = cpuset_create();
    289   1.1  knakahar 	if (cpuset == NULL)
    290   1.1  knakahar 		err(EXIT_FAILURE, "create_cpuset()");
    291   1.1  knakahar 
    292   1.1  knakahar 	cpuset_zero(cpuset);
    293   1.1  knakahar 	cpuset_set(index, cpuset);
    294   1.1  knakahar 	iset.cpuset = cpuset;
    295   1.1  knakahar 	iset.cpuset_size = cpuset_size(cpuset);
    296   1.1  knakahar 	error = sysctlbyname("kern.intr.affinity", NULL, NULL, &iset, sizeof(iset));
    297   1.1  knakahar 	cpuset_destroy(cpuset);
    298   1.1  knakahar 	if (error < 0)
    299   1.1  knakahar 		err(EXIT_FAILURE, "sysctl kern.intr.affinity");
    300   1.1  knakahar }
    301   1.1  knakahar 
    302   1.1  knakahar static void
    303   1.1  knakahar intrctl_intr(int argc, char **argv)
    304   1.1  knakahar {
    305   1.1  knakahar 	struct intrio_set iset;
    306   1.1  knakahar 	cpuset_t *cpuset;
    307   1.1  knakahar 	unsigned long index;
    308   1.1  knakahar 	int ch, error;
    309   1.1  knakahar 
    310   1.1  knakahar 	index = ULONG_MAX;
    311   1.1  knakahar 
    312   1.1  knakahar 	while ((ch = getopt(argc, argv, "c:")) != -1) {
    313   1.1  knakahar 		switch (ch) {
    314   1.1  knakahar 		case 'c':
    315   1.1  knakahar 			index = strtoul(optarg, NULL, 10);
    316   1.1  knakahar 			break;
    317   1.1  knakahar 		default:
    318   1.1  knakahar 			usage();
    319   1.1  knakahar 		}
    320   1.1  knakahar 	}
    321   1.1  knakahar 
    322   1.1  knakahar 	if (index == ULONG_MAX)
    323   1.1  knakahar 		usage();
    324   1.1  knakahar 
    325   1.1  knakahar 	if (index >= (u_long)sysconf(_SC_NPROCESSORS_CONF))
    326   1.1  knakahar 		err(EXIT_FAILURE, "invalid cpu index");
    327   1.1  knakahar 
    328   1.1  knakahar 	cpuset = cpuset_create();
    329   1.1  knakahar 	if (cpuset == NULL)
    330   1.1  knakahar 		err(EXIT_FAILURE, "create_cpuset()");
    331   1.1  knakahar 
    332   1.1  knakahar 	cpuset_zero(cpuset);
    333   1.1  knakahar 	cpuset_set(index, cpuset);
    334   1.1  knakahar 	iset.cpuset = cpuset;
    335   1.1  knakahar 	iset.cpuset_size = cpuset_size(cpuset);
    336   1.1  knakahar 	error = sysctlbyname("kern.intr.intr", NULL, NULL, &iset, sizeof(iset));
    337   1.1  knakahar 	cpuset_destroy(cpuset);
    338   1.1  knakahar 	if (error < 0)
    339   1.1  knakahar 		err(EXIT_FAILURE, "sysctl kern.intr.intr");
    340   1.1  knakahar }
    341   1.1  knakahar 
    342   1.1  knakahar static void
    343   1.1  knakahar intrctl_nointr(int argc, char **argv)
    344   1.1  knakahar {
    345   1.1  knakahar 	struct intrio_set iset;
    346   1.1  knakahar 	cpuset_t *cpuset;
    347   1.1  knakahar 	unsigned long index;
    348   1.1  knakahar 	int ch, error;
    349   1.1  knakahar 
    350   1.1  knakahar 	index = ULONG_MAX;
    351   1.1  knakahar 
    352   1.1  knakahar 	while ((ch = getopt(argc, argv, "c:")) != -1) {
    353   1.1  knakahar 		switch (ch) {
    354   1.1  knakahar 		case 'c':
    355   1.1  knakahar 			index = strtoul(optarg, NULL, 10);
    356   1.1  knakahar 			break;
    357   1.1  knakahar 		default:
    358   1.1  knakahar 			usage();
    359   1.1  knakahar 		}
    360   1.1  knakahar 	}
    361   1.1  knakahar 
    362   1.1  knakahar 	if (index == ULONG_MAX)
    363   1.1  knakahar 		usage();
    364   1.1  knakahar 
    365   1.1  knakahar 	if (index >= (u_long)sysconf(_SC_NPROCESSORS_CONF))
    366   1.1  knakahar 		err(EXIT_FAILURE, "invalid cpu index");
    367   1.1  knakahar 
    368   1.1  knakahar 	cpuset = cpuset_create();
    369   1.1  knakahar 	if (cpuset == NULL)
    370   1.1  knakahar 		err(EXIT_FAILURE, "create_cpuset()");
    371   1.1  knakahar 
    372   1.1  knakahar 	cpuset_zero(cpuset);
    373   1.1  knakahar 	cpuset_set(index, cpuset);
    374   1.1  knakahar 	iset.cpuset = cpuset;
    375   1.1  knakahar 	iset.cpuset_size = cpuset_size(cpuset);
    376   1.1  knakahar 	error = sysctlbyname("kern.intr.nointr", NULL, NULL, &iset, sizeof(iset));
    377   1.1  knakahar 	cpuset_destroy(cpuset);
    378   1.1  knakahar 	if (error < 0)
    379   1.1  knakahar 		err(EXIT_FAILURE, "sysctl kern.intr.nointr");
    380   1.1  knakahar }
    381