17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5004388ebScasper * Common Development and Distribution License (the "License"). 6004388ebScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*e5ba14ffSstephh * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <sys/time_impl.h> 297c478bd9Sstevel@tonic-gate #include <sys/wait.h> 307c478bd9Sstevel@tonic-gate #include <stdio.h> 31004388ebScasper #include <stdio_ext.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <stdarg.h> 347c478bd9Sstevel@tonic-gate #include <ctype.h> 357c478bd9Sstevel@tonic-gate #include <time.h> 367c478bd9Sstevel@tonic-gate #include <fcntl.h> 377c478bd9Sstevel@tonic-gate #include <sys/stat.h> 387c478bd9Sstevel@tonic-gate #include <sys/resource.h> 397c478bd9Sstevel@tonic-gate #include <limits.h> 407c478bd9Sstevel@tonic-gate #include <string.h> 417c478bd9Sstevel@tonic-gate #include <unistd.h> 427c478bd9Sstevel@tonic-gate #include <errno.h> 437c478bd9Sstevel@tonic-gate #include <signal.h> 447c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 457c478bd9Sstevel@tonic-gate #define _KERNEL 467c478bd9Sstevel@tonic-gate #include <sys/dditypes.h> 477c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 487c478bd9Sstevel@tonic-gate #include <sys/bofi.h> 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #define BOFI_DEV "/devices/pseudo/bofi@0:bofi,ctl" 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #define GETSTRUCT(s, num) \ 537c478bd9Sstevel@tonic-gate ((s *) memalign(sizeof (void*), (num) * sizeof (s))) 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate #define MAXEDEFS (0x64) /* controls max no of concurent edefs */ 567c478bd9Sstevel@tonic-gate #define DFLTLOGSZ (0x4000) /* default size of an access log */ 577c478bd9Sstevel@tonic-gate #define DFLT_NONPIO_LOGSZ (0x400) /* default size of a log */ 587c478bd9Sstevel@tonic-gate #define MAXALRMCALL (0x1000ull) /* alarm does not permit big values */ 597c478bd9Sstevel@tonic-gate #define MIN_REPORT_TIME (5) /* min time to wait for edef status */ 607c478bd9Sstevel@tonic-gate #define DISTRIB_CUTOFF (3) /* useful when reducing a log */ 617c478bd9Sstevel@tonic-gate #define myLLMAX (0x7fffffffffffffffll) 627c478bd9Sstevel@tonic-gate #define myULLMAX (0xffffffffffffffffull) 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate /* 657c478bd9Sstevel@tonic-gate * default interval to wait between kicking off workload and injecting fault 667c478bd9Sstevel@tonic-gate */ 677c478bd9Sstevel@tonic-gate #define DEFAULT_EDEF_SLEEP 3 687c478bd9Sstevel@tonic-gate /* 697c478bd9Sstevel@tonic-gate * when generating dma corruptions, it is best to corrupt each double word 707c478bd9Sstevel@tonic-gate * individually for control areas - however for data areas this can be 717c478bd9Sstevel@tonic-gate * excessive and would generate so many cases we would never finish the run. 727c478bd9Sstevel@tonic-gate * So set a cut-off value where we switch from corrupting each double word 737c478bd9Sstevel@tonic-gate * separately to corrupting th elot in one go. 0x100 bytes seems a good value 747c478bd9Sstevel@tonic-gate * on the drivers we have seen so far. 757c478bd9Sstevel@tonic-gate */ 767c478bd9Sstevel@tonic-gate #define DMA_INDIVIDUAL_CORRUPT_CUTOFF 0x100 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate struct collector_def { 797c478bd9Sstevel@tonic-gate struct bofi_errdef ed; /* definition of the log criteria */ 807c478bd9Sstevel@tonic-gate struct bofi_errstate es; /* the current status of the log */ 817c478bd9Sstevel@tonic-gate struct acc_log_elem *lp; /* array of logged accesses */ 827c478bd9Sstevel@tonic-gate pid_t pid; 837c478bd9Sstevel@tonic-gate }; 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate static uint16_t policy; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate #define BYTEPOLICY (0xf) 887c478bd9Sstevel@tonic-gate #define MULTIPOLICY (0x10) 897c478bd9Sstevel@tonic-gate #define SIZEPOLICY (BYTEPOLICY|MULTIPOLICY) 907c478bd9Sstevel@tonic-gate #define UNBIASEDPOLICY 0x20 917c478bd9Sstevel@tonic-gate #define UNCOMMONPOLICY 0x40 927c478bd9Sstevel@tonic-gate #define COMMONPOLICY 0x80 937c478bd9Sstevel@tonic-gate #define MEDIANPOLICY 0x100 947c478bd9Sstevel@tonic-gate #define MAXIMALPOLICY 0x200 957c478bd9Sstevel@tonic-gate #define OPERATORSPOLICY 0x400 967c478bd9Sstevel@tonic-gate #define VALIDPOLICY (0x7ff) 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate typedef 997c478bd9Sstevel@tonic-gate struct coding { 1007c478bd9Sstevel@tonic-gate char *str; 1017c478bd9Sstevel@tonic-gate uint_t code; 1027c478bd9Sstevel@tonic-gate } coding_t; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate static coding_t ptypes[] = { 1057c478bd9Sstevel@tonic-gate {"onebyte", 0x1}, {"twobyte", 0x2}, 1067c478bd9Sstevel@tonic-gate {"fourbyte", 0x4}, {"eightbyte", 0x8}, 1077c478bd9Sstevel@tonic-gate {"multibyte", 0x10}, {"unbiased", 0x20}, {"uncommon", 0x40}, 1087c478bd9Sstevel@tonic-gate {"common", 0x80}, {"median", 0x100}, {"maximal", 0x200}, 1097c478bd9Sstevel@tonic-gate {"operators", 0x400}, {0, 0} 1107c478bd9Sstevel@tonic-gate }; 1117c478bd9Sstevel@tonic-gate static coding_t atypes[] = { 1127c478bd9Sstevel@tonic-gate {"pio_r", BOFI_PIO_R}, {"pio_w", BOFI_PIO_W}, 1137c478bd9Sstevel@tonic-gate {"dma_r", BOFI_DMA_R}, {"dma_w", BOFI_DMA_W}, 1147c478bd9Sstevel@tonic-gate {"pio", BOFI_PIO_RW}, {"dma", BOFI_DMA_RW}, 1157c478bd9Sstevel@tonic-gate {"log", BOFI_LOG}, {"intr", BOFI_INTR}, 1167c478bd9Sstevel@tonic-gate {"PIO_R", BOFI_PIO_R}, {"PIO_W", BOFI_PIO_W}, 1177c478bd9Sstevel@tonic-gate {"DMA_R", BOFI_DMA_R}, {"DMA_W", BOFI_DMA_W}, 1187c478bd9Sstevel@tonic-gate {"PIO", BOFI_PIO_RW}, {"DMA", BOFI_DMA_RW}, 1197c478bd9Sstevel@tonic-gate {"LOG", BOFI_LOG}, {"INTR", BOFI_INTR}, {0, 0} 1207c478bd9Sstevel@tonic-gate }; 1217c478bd9Sstevel@tonic-gate static coding_t optypes[] = { 1227c478bd9Sstevel@tonic-gate {"EQ", BOFI_EQUAL}, {"AND", BOFI_AND}, {"OR", BOFI_OR}, 1237c478bd9Sstevel@tonic-gate {"XOR", BOFI_XOR}, {"NO", BOFI_NO_TRANSFER}, 1247c478bd9Sstevel@tonic-gate {"DELAY", BOFI_DELAY_INTR}, {"LOSE", BOFI_LOSE_INTR}, 1257c478bd9Sstevel@tonic-gate {"EXTRA", BOFI_EXTRA_INTR}, {0, 0} 1267c478bd9Sstevel@tonic-gate }; 1277c478bd9Sstevel@tonic-gate static coding_t doptypes[] = { 1287c478bd9Sstevel@tonic-gate {"EQ", BOFI_EQUAL}, {"AND", BOFI_AND}, {"OR", BOFI_OR}, 1297c478bd9Sstevel@tonic-gate {"XOR", BOFI_XOR}, {0, 0} 1307c478bd9Sstevel@tonic-gate }; 1317c478bd9Sstevel@tonic-gate static coding_t ioptypes[] = { 1327c478bd9Sstevel@tonic-gate {"DELAY", BOFI_DELAY_INTR}, {"LOSE", BOFI_LOSE_INTR}, 1337c478bd9Sstevel@tonic-gate {"EXTRA", BOFI_EXTRA_INTR}, {0, 0} 1347c478bd9Sstevel@tonic-gate }; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate static const unsigned long long DFLTLOGTIME = -1ull; /* log forever */ 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * This global controls the generation of errdefs for PIO_W. The default should 1407c478bd9Sstevel@tonic-gate * be to only perform an access check errdef but not to corrupt writes - this 1417c478bd9Sstevel@tonic-gate * may trash non-FT platforms. 1427c478bd9Sstevel@tonic-gate */ 1437c478bd9Sstevel@tonic-gate static uint_t atype_is_default; /* do not corrupt PIO_W by default */ 1447c478bd9Sstevel@tonic-gate static uint_t lsize_is_default; /* set when the user has not given a size */ 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate static uint64_t random_operand = 0xdeadbeafdeadbeafull; 1477c478bd9Sstevel@tonic-gate #define NPIO_DEFAULTS (3) /* number of default corruption values */ 1487c478bd9Sstevel@tonic-gate static longlong_t pio_default_values[NPIO_DEFAULTS] = { 1497c478bd9Sstevel@tonic-gate 0x0ull, /* corresponds to a line going high/low */ 1507c478bd9Sstevel@tonic-gate 0x32f1f03232f1f032ull, /* the value returned when the fake ta is set */ 1517c478bd9Sstevel@tonic-gate (longlong_t)(~0) /* corresponds to a line going high/low */ 1527c478bd9Sstevel@tonic-gate }; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate static uint_t dbglvl = 0; /* debug this program */ 1557c478bd9Sstevel@tonic-gate static int alarmed = 0; 1567c478bd9Sstevel@tonic-gate static int killed = 0; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate /* 1597c478bd9Sstevel@tonic-gate * name of a script to call before offlining a driver being tested 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate static char **fixup_script = 0; 1627c478bd9Sstevel@tonic-gate static int scriptargs = 0; 1637c478bd9Sstevel@tonic-gate static char **pargv; 1647c478bd9Sstevel@tonic-gate static int pargc; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate static int max_edef_wait = 0; 1677c478bd9Sstevel@tonic-gate static int edef_sleep = 0; 1687c478bd9Sstevel@tonic-gate static int do_status = 0; /* report edef status in parsable format */ 1697c478bd9Sstevel@tonic-gate static char *user_comment = 0; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate static char *Progname; 1727c478bd9Sstevel@tonic-gate static FILE *errfile; 1737c478bd9Sstevel@tonic-gate static FILE *outfile; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * The th_define utility provides an interface to the bus_ops fault injection 1777c478bd9Sstevel@tonic-gate * bofi device driver for defining error injection specifications (referred to 1787c478bd9Sstevel@tonic-gate * as errdefs). An errdef corresponds to a specification of how to corrupt a 1797c478bd9Sstevel@tonic-gate * device driver's accesses to its hardware. The command line arguments 1807c478bd9Sstevel@tonic-gate * determine the precise nature of the fault to be injected. If the supplied 1817c478bd9Sstevel@tonic-gate * arguments define a consistent errdef, the th_define process will store the 1827c478bd9Sstevel@tonic-gate * errdef with the bofi driver and suspend itself until the criteria given by 1837c478bd9Sstevel@tonic-gate * the errdef become satisfied (in practice, this will occur when the access 1847c478bd9Sstevel@tonic-gate * counts go to zero). 1857c478bd9Sstevel@tonic-gate * 1867c478bd9Sstevel@tonic-gate * When the resulting errdef is activated using the th_manage(1M) user command 1877c478bd9Sstevel@tonic-gate * utility, the bofi driver will act upon the errdef by matching the number of 1887c478bd9Sstevel@tonic-gate * hardware accesses - specified in count, that are of the type specified in 1897c478bd9Sstevel@tonic-gate * acc_types, made by instance number instance - of the driver whose name is 1907c478bd9Sstevel@tonic-gate * name, (or by the driver instance specified by * path ) to the register set 1917c478bd9Sstevel@tonic-gate * (or DMA handle) specified by rnumber, that lie within the range offset to 1927c478bd9Sstevel@tonic-gate * offset + length from the beginning of the register set or DMA handle. It then 1937c478bd9Sstevel@tonic-gate * applies operator and operand to the next failcount matching accesses. 1947c478bd9Sstevel@tonic-gate * 1957c478bd9Sstevel@tonic-gate * If acc_types includes LOG, th_define runs in automatic test script generation 1967c478bd9Sstevel@tonic-gate * mode, and a set of test scripts (written in the Korn shell) is created and 1977c478bd9Sstevel@tonic-gate * placed in a sub-directory of the current directory with the name 1987c478bd9Sstevel@tonic-gate * driver.test.<id>. A separate, executable script is generated for each access 1997c478bd9Sstevel@tonic-gate * handle that matches the logging criteria. The log of accesses is placed at 2007c478bd9Sstevel@tonic-gate * the top of each script as a record of the session. If the current directory 2017c478bd9Sstevel@tonic-gate * is not writable, file output is written to standard output. The base name of 2027c478bd9Sstevel@tonic-gate * each test file is the driver name, and the extension is a number that 2037c478bd9Sstevel@tonic-gate * discriminates between different access handles. A control script (with the 2047c478bd9Sstevel@tonic-gate * same name as the created test directory) is generated that will run all the 2057c478bd9Sstevel@tonic-gate * test scripts sequentially. 2067c478bd9Sstevel@tonic-gate * 2077c478bd9Sstevel@tonic-gate * Executing the scripts will install, and then activate, the resulting error 2087c478bd9Sstevel@tonic-gate * definitions. Error definitions are activated sequentially and the driver 2097c478bd9Sstevel@tonic-gate * instance under test is taken offline and brought back online before each test 2107c478bd9Sstevel@tonic-gate * (refer to the -e option for more information). By default, logging will apply 2117c478bd9Sstevel@tonic-gate * to all PIO accesses, interrupts and DMA accesses to and from areas mapped 2127c478bd9Sstevel@tonic-gate * for both reading and writing, but it can be constrained by specifying 2137c478bd9Sstevel@tonic-gate * additional acc_types, rnumber, offset and length. Logging will continue for 2147c478bd9Sstevel@tonic-gate * count matching accesses, with an optional time limit of collect_time seconds. 2157c478bd9Sstevel@tonic-gate * 2167c478bd9Sstevel@tonic-gate * Either the -n or -P option must be provided. The other options are optional. 2177c478bd9Sstevel@tonic-gate * If an option (other than the -a option) is specified multiple times, only 2187c478bd9Sstevel@tonic-gate * the final value for the option is used. If an option is not specified, its 2197c478bd9Sstevel@tonic-gate * associated value is set to an appropriate default, which will provide 2207c478bd9Sstevel@tonic-gate * maximal error coverage as described below. 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 2247c478bd9Sstevel@tonic-gate static void 2257c478bd9Sstevel@tonic-gate msg(uint_t lvl, char *msg, ...) 2267c478bd9Sstevel@tonic-gate { 2277c478bd9Sstevel@tonic-gate #define BUFSZ 128 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate if (lvl <= dbglvl) { 2307c478bd9Sstevel@tonic-gate int count; 2317c478bd9Sstevel@tonic-gate va_list args; 2327c478bd9Sstevel@tonic-gate char buf[BUFSZ]; 2337c478bd9Sstevel@tonic-gate int pos = 0; 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate va_start(args, msg); 2367c478bd9Sstevel@tonic-gate count = vsnprintf(buf, BUFSZ, msg, args); 2377c478bd9Sstevel@tonic-gate va_end(args); 2387c478bd9Sstevel@tonic-gate if (count > 0) { 2397c478bd9Sstevel@tonic-gate count += pos; 2407c478bd9Sstevel@tonic-gate if (count >= sizeof (buf)) 2417c478bd9Sstevel@tonic-gate count = BUFSZ - 1; 2427c478bd9Sstevel@tonic-gate buf[count] = '\0'; 2437c478bd9Sstevel@tonic-gate (void) fprintf(errfile, "%s", buf); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate static void 2497c478bd9Sstevel@tonic-gate kill_sighandler(int sig) 2507c478bd9Sstevel@tonic-gate { 2517c478bd9Sstevel@tonic-gate switch (sig) { 2527c478bd9Sstevel@tonic-gate case SIGALRM: 2537c478bd9Sstevel@tonic-gate alarmed = 1; 2547c478bd9Sstevel@tonic-gate break; 2557c478bd9Sstevel@tonic-gate default: 2567c478bd9Sstevel@tonic-gate killed = 1; 2577c478bd9Sstevel@tonic-gate break; 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate static void 2627c478bd9Sstevel@tonic-gate set_handler(int sig) 2637c478bd9Sstevel@tonic-gate { 2647c478bd9Sstevel@tonic-gate struct sigaction sa; 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate (void) sigfillset(&(sa.sa_mask)); 2677c478bd9Sstevel@tonic-gate sa.sa_flags = 0; 2687c478bd9Sstevel@tonic-gate sa.sa_handler = kill_sighandler; 2697c478bd9Sstevel@tonic-gate if (sigaction(sig, &sa, NULL) != 0) 2707c478bd9Sstevel@tonic-gate /* install handler */ 2717c478bd9Sstevel@tonic-gate msg(0, "bad sigaction: %s\n", strerror(errno)); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* 2757c478bd9Sstevel@tonic-gate * Compare two driver access handles 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate static int 2787c478bd9Sstevel@tonic-gate hdl_cmp(const void *p1, const void *p2) 2797c478bd9Sstevel@tonic-gate { 2807c478bd9Sstevel@tonic-gate struct handle_info *e1 = (struct handle_info *)p1; 2817c478bd9Sstevel@tonic-gate struct handle_info *e2 = (struct handle_info *)p2; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate if (e1->instance < e2->instance) 2847c478bd9Sstevel@tonic-gate return (-1); 2857c478bd9Sstevel@tonic-gate else if (e1->instance > e2->instance) 2867c478bd9Sstevel@tonic-gate return (1); 2877c478bd9Sstevel@tonic-gate else if (e1->access_type < e2->access_type) 2887c478bd9Sstevel@tonic-gate return (-1); 2897c478bd9Sstevel@tonic-gate else if (e1->access_type > e2->access_type) 2907c478bd9Sstevel@tonic-gate return (1); 2917c478bd9Sstevel@tonic-gate else if (e1->rnumber < e2->rnumber) 2927c478bd9Sstevel@tonic-gate return (-1); 2937c478bd9Sstevel@tonic-gate else if (e1->rnumber > e2->rnumber) 2947c478bd9Sstevel@tonic-gate return (1); 2957c478bd9Sstevel@tonic-gate else if (e1->len < e2->len) 2967c478bd9Sstevel@tonic-gate return (-1); 2977c478bd9Sstevel@tonic-gate else if (e1->len > e2->len) 2987c478bd9Sstevel@tonic-gate return (1); 2997c478bd9Sstevel@tonic-gate else if (e1->offset < e2->offset) 3007c478bd9Sstevel@tonic-gate return (-1); 3017c478bd9Sstevel@tonic-gate else if (e1->offset > e2->offset) 3027c478bd9Sstevel@tonic-gate return (1); 3037c478bd9Sstevel@tonic-gate else if (e1->addr_cookie < e2->addr_cookie) 3047c478bd9Sstevel@tonic-gate return (-1); 3057c478bd9Sstevel@tonic-gate else if (e1->addr_cookie > e2->addr_cookie) 3067c478bd9Sstevel@tonic-gate return (1); 3077c478bd9Sstevel@tonic-gate else 3087c478bd9Sstevel@tonic-gate return (0); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate /* 3127c478bd9Sstevel@tonic-gate * Compare two hardware accesses. 3137c478bd9Sstevel@tonic-gate */ 3147c478bd9Sstevel@tonic-gate static int 3157c478bd9Sstevel@tonic-gate elem_cmp(const void *p1, const void *p2) 3167c478bd9Sstevel@tonic-gate { 3177c478bd9Sstevel@tonic-gate struct acc_log_elem *e1 = (struct acc_log_elem *)p1; 3187c478bd9Sstevel@tonic-gate struct acc_log_elem *e2 = (struct acc_log_elem *)p2; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate if (e1->access_type < e2->access_type) 3217c478bd9Sstevel@tonic-gate return (-1); 3227c478bd9Sstevel@tonic-gate else if (e1->access_type > e2->access_type) 3237c478bd9Sstevel@tonic-gate return (1); 3247c478bd9Sstevel@tonic-gate else if (e1->offset < e2->offset) 3257c478bd9Sstevel@tonic-gate return (-1); 3267c478bd9Sstevel@tonic-gate else if (e1->offset > e2->offset) 3277c478bd9Sstevel@tonic-gate return (1); 3287c478bd9Sstevel@tonic-gate else if (e1->size < e2->size) 3297c478bd9Sstevel@tonic-gate return (-1); 3307c478bd9Sstevel@tonic-gate else if (e1->size > e2->size) 3317c478bd9Sstevel@tonic-gate return (1); 3327c478bd9Sstevel@tonic-gate else 3337c478bd9Sstevel@tonic-gate return (0); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /* 3377c478bd9Sstevel@tonic-gate * Another way of comparing two hardware accesses. 3387c478bd9Sstevel@tonic-gate */ 3397c478bd9Sstevel@tonic-gate static int 3407c478bd9Sstevel@tonic-gate log_cmp(const void *p1, const void *p2) 3417c478bd9Sstevel@tonic-gate { 3427c478bd9Sstevel@tonic-gate struct acc_log_elem *e1 = (struct acc_log_elem *)p1; 3437c478bd9Sstevel@tonic-gate struct acc_log_elem *e2 = (struct acc_log_elem *)p2; 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate int rval = elem_cmp(p1, p2); 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate if (rval == 0) 3487c478bd9Sstevel@tonic-gate if (e1->repcount < e2->repcount) 3497c478bd9Sstevel@tonic-gate return (-1); 3507c478bd9Sstevel@tonic-gate else if (e1->repcount > e2->repcount) 3517c478bd9Sstevel@tonic-gate return (1); 3527c478bd9Sstevel@tonic-gate else 3537c478bd9Sstevel@tonic-gate return (0); 3547c478bd9Sstevel@tonic-gate else 3557c478bd9Sstevel@tonic-gate return (rval); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate /* 3597c478bd9Sstevel@tonic-gate * And a final way of sorting a log (by access type followed by repcount). 3607c478bd9Sstevel@tonic-gate */ 3617c478bd9Sstevel@tonic-gate static int 3627c478bd9Sstevel@tonic-gate log_cmp2(const void *p1, const void *p2) 3637c478bd9Sstevel@tonic-gate { 3647c478bd9Sstevel@tonic-gate struct acc_log_elem *e1 = (struct acc_log_elem *)p1; 3657c478bd9Sstevel@tonic-gate struct acc_log_elem *e2 = (struct acc_log_elem *)p2; 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate if (e1->access_type < e2->access_type) 3687c478bd9Sstevel@tonic-gate return (-1); 3697c478bd9Sstevel@tonic-gate else if (e1->access_type > e2->access_type) 3707c478bd9Sstevel@tonic-gate return (1); 3717c478bd9Sstevel@tonic-gate else if (e1->repcount < e2->repcount) 3727c478bd9Sstevel@tonic-gate return (-1); 3737c478bd9Sstevel@tonic-gate else if (e1->repcount > e2->repcount) 3747c478bd9Sstevel@tonic-gate return (1); 3757c478bd9Sstevel@tonic-gate else 3767c478bd9Sstevel@tonic-gate return (0); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate static void 3807c478bd9Sstevel@tonic-gate dump_log(uint_t lvl, FILE *fp, struct acc_log_elem *items, 3817c478bd9Sstevel@tonic-gate size_t nitems, uint_t logflags) 3827c478bd9Sstevel@tonic-gate { 3837c478bd9Sstevel@tonic-gate if (lvl <= dbglvl) { 3847c478bd9Sstevel@tonic-gate int i; 3857c478bd9Sstevel@tonic-gate uint_t offset, allthesame = 1; 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate if (logflags & BOFI_LOG_TIMESTAMP && 3887c478bd9Sstevel@tonic-gate getenv("DUMP_FULL_LOG") != 0) 3897c478bd9Sstevel@tonic-gate allthesame = 0; 3907c478bd9Sstevel@tonic-gate else 3917c478bd9Sstevel@tonic-gate for (i = 1; i < nitems; i++) 3927c478bd9Sstevel@tonic-gate if (elem_cmp(items+i, items) != 0) 3937c478bd9Sstevel@tonic-gate allthesame = 0; 3947c478bd9Sstevel@tonic-gate if (fp != 0) 3957c478bd9Sstevel@tonic-gate (void) fprintf(fp, 3967c478bd9Sstevel@tonic-gate "# Logged Accesses:\n# %-4s\t%-12s\t%-4s\t%-18s" 3977c478bd9Sstevel@tonic-gate " (%-1s)\t%-10s\n\n", "type", 3987c478bd9Sstevel@tonic-gate (items->access_type & BOFI_DMA_RW) ? 3997c478bd9Sstevel@tonic-gate "address" : "offset", 4007c478bd9Sstevel@tonic-gate "size", "value", "repcnt", "time"); 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate for (i = 0; i < nitems; i++, items++) { 4037c478bd9Sstevel@tonic-gate offset = items->offset; 4047c478bd9Sstevel@tonic-gate if (fp != 0) { 4057c478bd9Sstevel@tonic-gate (void) fprintf(fp, 4067c478bd9Sstevel@tonic-gate "# 0x%-2x\t0x%-10x\t%-4d\t0x%-16llx" 4077c478bd9Sstevel@tonic-gate " (0x%-1x)\t%-8llu\n", 4087c478bd9Sstevel@tonic-gate items->access_type, offset, items->size, 4097c478bd9Sstevel@tonic-gate items->value, items->repcount, 4107c478bd9Sstevel@tonic-gate (logflags & BOFI_LOG_TIMESTAMP) ? 4117c478bd9Sstevel@tonic-gate items->access_time : 0ull); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate if (allthesame) { 4147c478bd9Sstevel@tonic-gate (void) fprintf(fp, 4157c478bd9Sstevel@tonic-gate "# Access duplicated %d times\n", 4167c478bd9Sstevel@tonic-gate nitems); 4177c478bd9Sstevel@tonic-gate break; 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate } else 4207c478bd9Sstevel@tonic-gate msg(lvl, "# 0x%x 0x%x %d 0x%llx(0x%x) %llu\n", 4217c478bd9Sstevel@tonic-gate items->access_type, offset, items->size, 4227c478bd9Sstevel@tonic-gate items->value, items->repcount, 4237c478bd9Sstevel@tonic-gate (logflags & BOFI_LOG_TIMESTAMP) ? 4247c478bd9Sstevel@tonic-gate items->access_time : 0ull); 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate static int 4307c478bd9Sstevel@tonic-gate str_to_bm(char *optarg, coding_t *c, uint_t *bm) 4317c478bd9Sstevel@tonic-gate { 4327c478bd9Sstevel@tonic-gate char *str; 4337c478bd9Sstevel@tonic-gate char *s = "\t\n "; 4347c478bd9Sstevel@tonic-gate int err = EINVAL; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate msg(2, "str_to_bm: optarg %s\n", optarg); 4377c478bd9Sstevel@tonic-gate if (optarg != NULL && (str = strtok(optarg, s))) { 4387c478bd9Sstevel@tonic-gate msg(2, "str_to_bm: str %s\n", str); 4397c478bd9Sstevel@tonic-gate do { 4407c478bd9Sstevel@tonic-gate for (; c->str != 0; c++) 4417c478bd9Sstevel@tonic-gate if (strcmp(str, c->str) == 0) { 4427c478bd9Sstevel@tonic-gate *bm |= c->code; 4437c478bd9Sstevel@tonic-gate msg(2, "str_to_bm: %s matches\n", 4447c478bd9Sstevel@tonic-gate c->str); 4457c478bd9Sstevel@tonic-gate err = 0; 4467c478bd9Sstevel@tonic-gate break; 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate } while ((str = strtok(NULL, s))); 4497c478bd9Sstevel@tonic-gate } else 4507c478bd9Sstevel@tonic-gate return (EINVAL); 4517c478bd9Sstevel@tonic-gate msg(2, "str_to_bm: done 0x%x\n", *bm); 4527c478bd9Sstevel@tonic-gate return (err); 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate /* 4577c478bd9Sstevel@tonic-gate * Generic routine for commands that apply to a particular instance of 4587c478bd9Sstevel@tonic-gate * a driver under test (e.g. activate all errdefs defined on an instance). 4597c478bd9Sstevel@tonic-gate */ 4607c478bd9Sstevel@tonic-gate static int 4617c478bd9Sstevel@tonic-gate manage_instance(int fd, char *namep, int instance, int cmd) 4627c478bd9Sstevel@tonic-gate { 4637c478bd9Sstevel@tonic-gate struct bofi_errctl errctl; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate errctl.namesize = strlen(namep); 4667c478bd9Sstevel@tonic-gate (void) strncpy(errctl.name, namep, MAXNAMELEN); 4677c478bd9Sstevel@tonic-gate errctl.instance = instance; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate msg(8, "manage_instance: %s %d\n", namep, instance); 4707c478bd9Sstevel@tonic-gate if (ioctl(fd, cmd, &errctl) == -1) { 4717c478bd9Sstevel@tonic-gate msg(0, "bofi ioctl %d failed: %s\n", cmd, strerror(errno)); 4727c478bd9Sstevel@tonic-gate return (-1); 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate return (0); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate static int 4797c478bd9Sstevel@tonic-gate define_one_error( 4807c478bd9Sstevel@tonic-gate FILE *fp, 4817c478bd9Sstevel@tonic-gate struct bofi_errdef *edp, 4827c478bd9Sstevel@tonic-gate struct acc_log_elem *item, 4837c478bd9Sstevel@tonic-gate ulong_t nttime, 4847c478bd9Sstevel@tonic-gate ulong_t interval, 4857c478bd9Sstevel@tonic-gate char *type, 4867c478bd9Sstevel@tonic-gate int fon, /* corrupt after this many accesses */ 4877c478bd9Sstevel@tonic-gate size_t fcnt, /* and then fail it fcnt times */ 4887c478bd9Sstevel@tonic-gate uint_t acc_chk, 4897c478bd9Sstevel@tonic-gate char *opname, 4907c478bd9Sstevel@tonic-gate uint64_t operand) 4917c478bd9Sstevel@tonic-gate { 4927c478bd9Sstevel@tonic-gate (void) fprintf(fp, 4937c478bd9Sstevel@tonic-gate "-n %s -i %d -r %d -l 0x%llx 0x%x -a %s -c %d %d -f %d" 4947c478bd9Sstevel@tonic-gate " -o %s 0x%llx", 4957c478bd9Sstevel@tonic-gate (char *)edp->name, 4967c478bd9Sstevel@tonic-gate edp->instance, 4977c478bd9Sstevel@tonic-gate edp->rnumber, 4987c478bd9Sstevel@tonic-gate edp->offset + item->offset, /* offset into the regset */ 4997c478bd9Sstevel@tonic-gate item->size, /* corrupt addrs from offset to offset+size */ 5007c478bd9Sstevel@tonic-gate type, 5017c478bd9Sstevel@tonic-gate fon, /* corrupt after this many accesses */ 5027c478bd9Sstevel@tonic-gate fcnt, /* and then fail it fcnt times */ 5037c478bd9Sstevel@tonic-gate acc_chk, 5047c478bd9Sstevel@tonic-gate opname, 5057c478bd9Sstevel@tonic-gate operand); 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate (void) fprintf(fp, " -w %lu %lu\n", nttime, interval); 5087c478bd9Sstevel@tonic-gate return (0); 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate static void 5127c478bd9Sstevel@tonic-gate define_op_err(FILE *fp, int *ecnt, struct bofi_errdef *edp, 5137c478bd9Sstevel@tonic-gate struct acc_log_elem *item, ulong_t nttime, ulong_t interval, char *type, 5147c478bd9Sstevel@tonic-gate int fon, size_t fcnt) 5157c478bd9Sstevel@tonic-gate { 5167c478bd9Sstevel@tonic-gate coding_t *ct; 5177c478bd9Sstevel@tonic-gate char *opname; 5187c478bd9Sstevel@tonic-gate uint_t op; 5197c478bd9Sstevel@tonic-gate uint64_t operand; 5207c478bd9Sstevel@tonic-gate int k, save_size; 5217c478bd9Sstevel@tonic-gate uint64_t save_offset; 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if (item->access_type & BOFI_INTR) 5247c478bd9Sstevel@tonic-gate ct = &ioptypes[0]; 5257c478bd9Sstevel@tonic-gate else 5267c478bd9Sstevel@tonic-gate ct = &doptypes[0]; 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate /* 5297c478bd9Sstevel@tonic-gate * errdefs for dma accesses are too numerous so assume that dma writes 5307c478bd9Sstevel@tonic-gate * (DDI_DMA_SYNC_FORDEV) create less exposure to potential errors than 5317c478bd9Sstevel@tonic-gate * do dma reads (DDI_DMA_SYNC_FORCPU). 5327c478bd9Sstevel@tonic-gate * 5337c478bd9Sstevel@tonic-gate * also by default do not corrupt PIO_W - it may hang a non-FT platform. 5347c478bd9Sstevel@tonic-gate */ 5357c478bd9Sstevel@tonic-gate if (item->access_type != BOFI_DMA_W && 5367c478bd9Sstevel@tonic-gate ((item->access_type & BOFI_PIO_W) == 0 || !atype_is_default)) { 5377c478bd9Sstevel@tonic-gate /* 5387c478bd9Sstevel@tonic-gate * user has asked for PIO_W 5397c478bd9Sstevel@tonic-gate */ 5407c478bd9Sstevel@tonic-gate for (; ct->str != 0; ct++) { 5417c478bd9Sstevel@tonic-gate op = ct->code; 5427c478bd9Sstevel@tonic-gate opname = ct->str; 5437c478bd9Sstevel@tonic-gate switch (op) { 5447c478bd9Sstevel@tonic-gate case BOFI_EQUAL: 5457c478bd9Sstevel@tonic-gate operand = random_operand; /* a random value */ 5467c478bd9Sstevel@tonic-gate random_operand = lrand48() | ((uint64_t) 5477c478bd9Sstevel@tonic-gate (lrand48()) << 32); 5487c478bd9Sstevel@tonic-gate break; 5497c478bd9Sstevel@tonic-gate case BOFI_AND: 5507c478bd9Sstevel@tonic-gate operand = 0xaddedabadb00bull; 5517c478bd9Sstevel@tonic-gate break; 5527c478bd9Sstevel@tonic-gate case BOFI_OR: 5537c478bd9Sstevel@tonic-gate operand = 0x1; 5547c478bd9Sstevel@tonic-gate break; 5557c478bd9Sstevel@tonic-gate case BOFI_XOR: 5567c478bd9Sstevel@tonic-gate default: 5577c478bd9Sstevel@tonic-gate operand = myULLMAX; 5587c478bd9Sstevel@tonic-gate break; 5597c478bd9Sstevel@tonic-gate case BOFI_DELAY_INTR: /* delay for 1 msec */ 5607c478bd9Sstevel@tonic-gate operand = 1000000; 5617c478bd9Sstevel@tonic-gate break; 5627c478bd9Sstevel@tonic-gate case BOFI_LOSE_INTR: /* op not applicable */ 5637c478bd9Sstevel@tonic-gate operand = 0; 5647c478bd9Sstevel@tonic-gate break; 5657c478bd9Sstevel@tonic-gate case BOFI_EXTRA_INTR: /* extra intrs */ 5667c478bd9Sstevel@tonic-gate operand = 0xfff; 5677c478bd9Sstevel@tonic-gate break; 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate *ecnt = *ecnt + 1; 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate if ((item->access_type == BOFI_DMA_W || 5727c478bd9Sstevel@tonic-gate item->access_type == BOFI_DMA_R) && 5737c478bd9Sstevel@tonic-gate item->size > sizeof (uint64_t) && item->size < 5747c478bd9Sstevel@tonic-gate DMA_INDIVIDUAL_CORRUPT_CUTOFF) { 5757c478bd9Sstevel@tonic-gate save_size = item->size; 5767c478bd9Sstevel@tonic-gate save_offset = item->offset; 5777c478bd9Sstevel@tonic-gate for (k = (item->size + 5787c478bd9Sstevel@tonic-gate sizeof (uint64_t) - 1) & 5797c478bd9Sstevel@tonic-gate ~(sizeof (uint64_t) - 1); 5807c478bd9Sstevel@tonic-gate k > 0; k -= sizeof (uint64_t)) { 5817c478bd9Sstevel@tonic-gate item->size = sizeof (uint64_t); 5827c478bd9Sstevel@tonic-gate (void) define_one_error(fp, edp, 5837c478bd9Sstevel@tonic-gate item, nttime, interval, type, fon, 5847c478bd9Sstevel@tonic-gate fcnt, edp->acc_chk, opname, 5857c478bd9Sstevel@tonic-gate operand); 5867c478bd9Sstevel@tonic-gate item->offset += sizeof (uint64_t); 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate item->size = save_size; 5897c478bd9Sstevel@tonic-gate item->offset = save_offset; 5907c478bd9Sstevel@tonic-gate } else { 5917c478bd9Sstevel@tonic-gate (void) define_one_error(fp, edp, item, 5927c478bd9Sstevel@tonic-gate nttime, interval, type, fon, fcnt, 5937c478bd9Sstevel@tonic-gate edp->acc_chk, opname, operand); 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate if (op == BOFI_EQUAL) { 5977c478bd9Sstevel@tonic-gate uint_t cnt; 5987c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < NPIO_DEFAULTS; 5997c478bd9Sstevel@tonic-gate cnt++, *ecnt = *ecnt + 1) { 6007c478bd9Sstevel@tonic-gate if ((item->access_type == BOFI_DMA_W || 6017c478bd9Sstevel@tonic-gate item->access_type == BOFI_DMA_R) && 6027c478bd9Sstevel@tonic-gate item->size > sizeof (uint64_t) && 6037c478bd9Sstevel@tonic-gate item->size < 6047c478bd9Sstevel@tonic-gate DMA_INDIVIDUAL_CORRUPT_CUTOFF) { 6057c478bd9Sstevel@tonic-gate save_size = item->size; 6067c478bd9Sstevel@tonic-gate save_offset = item->offset; 6077c478bd9Sstevel@tonic-gate for (k = (item->size + 6087c478bd9Sstevel@tonic-gate sizeof (uint64_t) - 1) & 6097c478bd9Sstevel@tonic-gate ~(sizeof (uint64_t) - 1); 6107c478bd9Sstevel@tonic-gate k > 0; 6117c478bd9Sstevel@tonic-gate k -= sizeof (uint64_t)) { 6127c478bd9Sstevel@tonic-gate item->size = 6137c478bd9Sstevel@tonic-gate sizeof (uint64_t); 6147c478bd9Sstevel@tonic-gate (void) define_one_error( 6157c478bd9Sstevel@tonic-gate fp, edp, item, 6167c478bd9Sstevel@tonic-gate nttime, interval, 6177c478bd9Sstevel@tonic-gate type, fon, fcnt, 6187c478bd9Sstevel@tonic-gate edp->acc_chk, 6197c478bd9Sstevel@tonic-gate opname, 6207c478bd9Sstevel@tonic-gate pio_default_values 6217c478bd9Sstevel@tonic-gate [cnt]); 6227c478bd9Sstevel@tonic-gate item->offset += 6237c478bd9Sstevel@tonic-gate sizeof (uint64_t); 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate item->size = save_size; 6267c478bd9Sstevel@tonic-gate item->offset = save_offset; 6277c478bd9Sstevel@tonic-gate } else { 6287c478bd9Sstevel@tonic-gate (void) define_one_error(fp, 6297c478bd9Sstevel@tonic-gate edp, item, nttime, interval, 6307c478bd9Sstevel@tonic-gate type, fon, fcnt, 6317c478bd9Sstevel@tonic-gate edp->acc_chk, opname, 6327c478bd9Sstevel@tonic-gate pio_default_values[cnt]); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate if ((item->access_type & BOFI_PIO_W) && !atype_is_default) { 6407c478bd9Sstevel@tonic-gate /* 6417c478bd9Sstevel@tonic-gate * user has asked for PIO_W 6427c478bd9Sstevel@tonic-gate */ 6437c478bd9Sstevel@tonic-gate (void) define_one_error(fp, edp, item, nttime, interval, 6447c478bd9Sstevel@tonic-gate type, fon, fcnt, edp->acc_chk, "NO", 0); 6457c478bd9Sstevel@tonic-gate *ecnt = *ecnt + 1; 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate /* 6497c478bd9Sstevel@tonic-gate * and finally an access check errdef 6507c478bd9Sstevel@tonic-gate */ 6517c478bd9Sstevel@tonic-gate if (item->access_type & BOFI_PIO_RW) 6527c478bd9Sstevel@tonic-gate (void) define_one_error(fp, edp, item, nttime, interval, 6537c478bd9Sstevel@tonic-gate type, fon, fcnt, 1, "OR", 0); 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate if (item->access_type & BOFI_DMA_RW) 6567c478bd9Sstevel@tonic-gate (void) define_one_error(fp, edp, item, nttime, interval, 6577c478bd9Sstevel@tonic-gate type, fon, fcnt, 2, "OR", 0); 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate /* 6627c478bd9Sstevel@tonic-gate * Convert a collection of log entries into error definitions. 6637c478bd9Sstevel@tonic-gate */ 6647c478bd9Sstevel@tonic-gate /* ARGSUSED */ 6657c478bd9Sstevel@tonic-gate static int 6667c478bd9Sstevel@tonic-gate define_nerrs(int fd, FILE *fp, int *ecnt, struct bofi_errdef *edp, 6677c478bd9Sstevel@tonic-gate struct acc_log_elem *items, 6687c478bd9Sstevel@tonic-gate size_t nitems, 6697c478bd9Sstevel@tonic-gate uint_t naccess, 6707c478bd9Sstevel@tonic-gate uint_t minac, 6717c478bd9Sstevel@tonic-gate uint_t maxac, 6727c478bd9Sstevel@tonic-gate ulong_t logtime, 6737c478bd9Sstevel@tonic-gate ulong_t logsize) 6747c478bd9Sstevel@tonic-gate { 6757c478bd9Sstevel@tonic-gate char *type; 6767c478bd9Sstevel@tonic-gate uint_t at; 6777c478bd9Sstevel@tonic-gate int i; 6787c478bd9Sstevel@tonic-gate struct acc_log_elem *item; 6797c478bd9Sstevel@tonic-gate char *opname; 6807c478bd9Sstevel@tonic-gate uint_t op; 6817c478bd9Sstevel@tonic-gate uint64_t operand; 6827c478bd9Sstevel@tonic-gate int cycleiops, cycledops; 6837c478bd9Sstevel@tonic-gate int intrs = 0; 6847c478bd9Sstevel@tonic-gate ulong_t ttime, nttime, interval; 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate op = edp->optype; 6877c478bd9Sstevel@tonic-gate operand = edp->operand; 6887c478bd9Sstevel@tonic-gate msg(3, "define_nerrs: nitems %d (ac %d at 0x%x): (%d %d)" 6897c478bd9Sstevel@tonic-gate " (op 0x%x 0x%llx)\n\n", nitems, naccess, items->access_type, 6907c478bd9Sstevel@tonic-gate minac, maxac, op, operand); 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate /* 6937c478bd9Sstevel@tonic-gate * all items are guaranteed have values in the two element set {0, at} 6947c478bd9Sstevel@tonic-gate * where at is a valid access type (so find the value of at) 6957c478bd9Sstevel@tonic-gate */ 6967c478bd9Sstevel@tonic-gate for (i = 0, item = items, at = 0; i < nitems; i++, item++) 6977c478bd9Sstevel@tonic-gate if (item->access_type != 0) { 6987c478bd9Sstevel@tonic-gate at = item->access_type; 6997c478bd9Sstevel@tonic-gate break; 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate if (at == 0) 7027c478bd9Sstevel@tonic-gate return (-1); 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate /* 7057c478bd9Sstevel@tonic-gate * find the string form of the access type 7067c478bd9Sstevel@tonic-gate */ 7077c478bd9Sstevel@tonic-gate for (i = 0, type = 0; atypes[i].str != 0; i++) { 7087c478bd9Sstevel@tonic-gate if (atypes[i].code == at) { 7097c478bd9Sstevel@tonic-gate type = atypes[i].str; 7107c478bd9Sstevel@tonic-gate break; 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate if (type == 0) { 7147c478bd9Sstevel@tonic-gate msg(0, "Unknown access type returned from bofi\n\t"); 7157c478bd9Sstevel@tonic-gate dump_log(0, 0, item, 1, BOFI_LOG_TIMESTAMP); 7167c478bd9Sstevel@tonic-gate msg(1, "0x%x 0x%x 0x%x 0x%x\n", BOFI_LOG, BOFI_INTR, 7177c478bd9Sstevel@tonic-gate BOFI_DMA_RW, BOFI_PIO_RW); 7187c478bd9Sstevel@tonic-gate return (-1); 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate msg(1, "define_n: at = 0x%d (%s)\n", at, type == 0 ? "null" : type); 7227c478bd9Sstevel@tonic-gate /* 7237c478bd9Sstevel@tonic-gate * find the string form of the operator 7247c478bd9Sstevel@tonic-gate */ 7257c478bd9Sstevel@tonic-gate for (i = 0, opname = 0; optypes[i].str != 0; i++) { 7267c478bd9Sstevel@tonic-gate if (op == optypes[i].code) { 7277c478bd9Sstevel@tonic-gate opname = optypes[i].str; 7287c478bd9Sstevel@tonic-gate break; 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate /* 7337c478bd9Sstevel@tonic-gate * if not found or inconsistent default to XOR 7347c478bd9Sstevel@tonic-gate */ 7357c478bd9Sstevel@tonic-gate if (opname == 0 || 7367c478bd9Sstevel@tonic-gate (op == BOFI_NO_TRANSFER && 7377c478bd9Sstevel@tonic-gate (at & (BOFI_DMA_RW|BOFI_PIO_R))) || 7387c478bd9Sstevel@tonic-gate (op >= BOFI_DELAY_INTR && (at & BOFI_INTR) == 0)) { 7397c478bd9Sstevel@tonic-gate opname = optypes[3].str; /* "XOR" */ 7407c478bd9Sstevel@tonic-gate operand = myULLMAX; 7417c478bd9Sstevel@tonic-gate op = optypes[3].code; 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate /* 7457c478bd9Sstevel@tonic-gate * if operator and access type are inconsistent choose a sensible 7467c478bd9Sstevel@tonic-gate * default 7477c478bd9Sstevel@tonic-gate */ 7487c478bd9Sstevel@tonic-gate cycleiops = 0; 7497c478bd9Sstevel@tonic-gate if (at & BOFI_INTR) 7507c478bd9Sstevel@tonic-gate if (op < BOFI_DELAY_INTR) 7517c478bd9Sstevel@tonic-gate cycleiops = 1; 7527c478bd9Sstevel@tonic-gate else if (op == BOFI_LOSE_INTR) 7537c478bd9Sstevel@tonic-gate operand = 0; 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate cycledops = 0; 7567c478bd9Sstevel@tonic-gate if (nitems == 1 && (at & BOFI_DMA_RW)) 7577c478bd9Sstevel@tonic-gate cycledops = 1; 7587c478bd9Sstevel@tonic-gate /* 7597c478bd9Sstevel@tonic-gate * for each access in the list define one or more error definitions 7607c478bd9Sstevel@tonic-gate */ 7617c478bd9Sstevel@tonic-gate for (i = 0, item = items; i < nitems; i++, item++) { 7627c478bd9Sstevel@tonic-gate size_t acnt, fcnt; 7637c478bd9Sstevel@tonic-gate int j, fon; 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate if (item->access_type == 0) 7667c478bd9Sstevel@tonic-gate continue; 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate /* 7697c478bd9Sstevel@tonic-gate * base number of errors to inject on 3% of number of 7707c478bd9Sstevel@tonic-gate * similar accesses seen during LOG phase 7717c478bd9Sstevel@tonic-gate */ 7727c478bd9Sstevel@tonic-gate acnt = item->repcount / 10 + 1; /* 10% */ 7737c478bd9Sstevel@tonic-gate fcnt = (acnt >= 3) ? acnt / 3 : 1; /* 3% */ 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate /* 7767c478bd9Sstevel@tonic-gate * wait for twice the time it took during LOG phase 7777c478bd9Sstevel@tonic-gate */ 7787c478bd9Sstevel@tonic-gate if ((ttime = (item->access_time * 2)) < MIN_REPORT_TIME) 7797c478bd9Sstevel@tonic-gate ttime = MIN_REPORT_TIME; 7807c478bd9Sstevel@tonic-gate else if (max_edef_wait != 0 && ttime > max_edef_wait) 7817c478bd9Sstevel@tonic-gate ttime = max_edef_wait; 7827c478bd9Sstevel@tonic-gate /* 7837c478bd9Sstevel@tonic-gate * if edef_sleep set (-w) the use that, otherwise use default 7847c478bd9Sstevel@tonic-gate */ 7857c478bd9Sstevel@tonic-gate interval = edef_sleep ? edef_sleep : DEFAULT_EDEF_SLEEP; 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate msg(10, 7887c478bd9Sstevel@tonic-gate "define_n: item %d limit %d step %d (intr %d) tt(%lu)\n", 7897c478bd9Sstevel@tonic-gate i, item->repcount, acnt, intrs, ttime); 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate for (j = 0, fon = 1, nttime = ttime; j < item->repcount; 7927c478bd9Sstevel@tonic-gate j += acnt) { 7937c478bd9Sstevel@tonic-gate if (policy & OPERATORSPOLICY) { 7947c478bd9Sstevel@tonic-gate define_op_err(fp, ecnt, edp, item, 7957c478bd9Sstevel@tonic-gate nttime, interval, type, fon, fcnt); 7967c478bd9Sstevel@tonic-gate } else { 7977c478bd9Sstevel@tonic-gate if (cycleiops) { 7987c478bd9Sstevel@tonic-gate op = ioptypes[intrs].code; 7997c478bd9Sstevel@tonic-gate opname = ioptypes[intrs++].str; 8007c478bd9Sstevel@tonic-gate switch (op) { 8017c478bd9Sstevel@tonic-gate case BOFI_DELAY_INTR: 8027c478bd9Sstevel@tonic-gate /* delay for 1 sec */ 8037c478bd9Sstevel@tonic-gate operand = 1000000; 8047c478bd9Sstevel@tonic-gate break; 8057c478bd9Sstevel@tonic-gate case BOFI_LOSE_INTR: 8067c478bd9Sstevel@tonic-gate /* op not applicable */ 8077c478bd9Sstevel@tonic-gate operand = 0; 8087c478bd9Sstevel@tonic-gate break; 8097c478bd9Sstevel@tonic-gate case BOFI_EXTRA_INTR: 8107c478bd9Sstevel@tonic-gate default: 8117c478bd9Sstevel@tonic-gate /* generate 2 extra intrs */ 8127c478bd9Sstevel@tonic-gate operand = 0xfff; 8137c478bd9Sstevel@tonic-gate break; 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate intrs %= 3; 8167c478bd9Sstevel@tonic-gate } else if (cycledops) { 8177c478bd9Sstevel@tonic-gate op = doptypes[intrs].code; 8187c478bd9Sstevel@tonic-gate opname = doptypes[intrs++].str; 8197c478bd9Sstevel@tonic-gate switch (op) { 8207c478bd9Sstevel@tonic-gate case BOFI_EQUAL: 8217c478bd9Sstevel@tonic-gate random_operand = lrand48() | 8227c478bd9Sstevel@tonic-gate ((uint64_t) 8237c478bd9Sstevel@tonic-gate (lrand48()) << 32); 8247c478bd9Sstevel@tonic-gate break; /* a random value */ 8257c478bd9Sstevel@tonic-gate case BOFI_AND: 8267c478bd9Sstevel@tonic-gate operand = 0xaddedabadb00bull; 8277c478bd9Sstevel@tonic-gate break; 8287c478bd9Sstevel@tonic-gate case BOFI_OR: 8297c478bd9Sstevel@tonic-gate operand = 0xd1ab011c0af1a5c0ull; 8307c478bd9Sstevel@tonic-gate break; 8317c478bd9Sstevel@tonic-gate case BOFI_XOR: 8327c478bd9Sstevel@tonic-gate default: 8337c478bd9Sstevel@tonic-gate operand = myULLMAX; 8347c478bd9Sstevel@tonic-gate break; 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate intrs %= 4; 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate (void) define_one_error(fp, edp, item, 8397c478bd9Sstevel@tonic-gate nttime, interval, type, fon, 8407c478bd9Sstevel@tonic-gate fcnt, edp->acc_chk, opname, operand); 8417c478bd9Sstevel@tonic-gate *ecnt = *ecnt + 1; 8427c478bd9Sstevel@tonic-gate if (op == BOFI_EQUAL) { 8437c478bd9Sstevel@tonic-gate uint_t cnt; 8447c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < NPIO_DEFAULTS; 8457c478bd9Sstevel@tonic-gate cnt++, *ecnt = *ecnt + 1) 8467c478bd9Sstevel@tonic-gate (void) define_one_error(fp, 8477c478bd9Sstevel@tonic-gate edp, item, nttime, 8487c478bd9Sstevel@tonic-gate interval, type, fon, fcnt, 8497c478bd9Sstevel@tonic-gate edp->acc_chk, opname, 8507c478bd9Sstevel@tonic-gate pio_default_values[cnt]); 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate /* 8557c478bd9Sstevel@tonic-gate * all non maximal policies should only generate 8567c478bd9Sstevel@tonic-gate * a single error definition set per access. 8577c478bd9Sstevel@tonic-gate */ 8587c478bd9Sstevel@tonic-gate if (!(policy & MAXIMALPOLICY)) 8597c478bd9Sstevel@tonic-gate break; 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate nttime = (logtime - item->access_time) * 8627c478bd9Sstevel@tonic-gate (j + acnt + fcnt - 1) / logsize; 8637c478bd9Sstevel@tonic-gate if (nttime < MIN_REPORT_TIME) 8647c478bd9Sstevel@tonic-gate nttime = MIN_REPORT_TIME; 8657c478bd9Sstevel@tonic-gate else if (nttime > max_edef_wait) 8667c478bd9Sstevel@tonic-gate nttime = max_edef_wait; 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate msg(11, "define_nerrs: %lu %d %d %d %llu\n", nttime, 8697c478bd9Sstevel@tonic-gate max_edef_wait, fon, fcnt, item->access_time); 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate if (item->access_type != BOFI_INTR) 8727c478bd9Sstevel@tonic-gate fon += j; 8737c478bd9Sstevel@tonic-gate } 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate return (0); 8777c478bd9Sstevel@tonic-gate } 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate static int 8807c478bd9Sstevel@tonic-gate reduce_log(uint16_t pol, struct acc_log *log, /* input args */ 8817c478bd9Sstevel@tonic-gate struct acc_log_elem **llp, size_t *cntp) /* output args */ 8827c478bd9Sstevel@tonic-gate { 8837c478bd9Sstevel@tonic-gate ulong_t logtime; 8847c478bd9Sstevel@tonic-gate struct acc_log_elem *items, *item, *elem; 8857c478bd9Sstevel@tonic-gate int cnt, nitems, acnt; 8867c478bd9Sstevel@tonic-gate int i, j, k, lb, ub, mina, maxa, cutoff[2], mean; 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate if (llp == 0 || cntp == 0) /* subroutine interface violated */ 8897c478bd9Sstevel@tonic-gate return (-1); 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate if (*llp == 0) { 8927c478bd9Sstevel@tonic-gate items = (void *)log->logbase; 8937c478bd9Sstevel@tonic-gate nitems = log->entries; 8947c478bd9Sstevel@tonic-gate } else { 8957c478bd9Sstevel@tonic-gate items = *llp; /* outputs double up as inputs */ 8967c478bd9Sstevel@tonic-gate nitems = *cntp; 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate /* has the utc time wrapped over ULMAX - unlikely so fix it at 10 */ 8997c478bd9Sstevel@tonic-gate logtime = (log->stop_time >= log->start_time) ? 9007c478bd9Sstevel@tonic-gate log->stop_time - log->start_time : 10ul; 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate msg(1, "reduce %d: logtime %lu\n", nitems, logtime); 9037c478bd9Sstevel@tonic-gate /* 9047c478bd9Sstevel@tonic-gate * Sort the log by access type - do not remove duplicates yet (but do 9057c478bd9Sstevel@tonic-gate * remove access that do not match the requested log -> errdef policy 9067c478bd9Sstevel@tonic-gate * (defined by union pu pol). Set the repcount field of each entry to a 9077c478bd9Sstevel@tonic-gate * unique value (in the control statement of the for loop) - this 9087c478bd9Sstevel@tonic-gate * ensures that the qsort (following the for loop) will not remove any 9097c478bd9Sstevel@tonic-gate * entries. 9107c478bd9Sstevel@tonic-gate */ 9117c478bd9Sstevel@tonic-gate for (i = 0, cnt = 0, elem = items; i < nitems; 9127c478bd9Sstevel@tonic-gate elem->repcount = i, i++, elem++) { 9137c478bd9Sstevel@tonic-gate /* 9147c478bd9Sstevel@tonic-gate * If interested in the I/O transfer size and this access 9157c478bd9Sstevel@tonic-gate * does not match the requested size then ignore the access 9167c478bd9Sstevel@tonic-gate */ 9177c478bd9Sstevel@tonic-gate if ((pol & SIZEPOLICY) && 9187c478bd9Sstevel@tonic-gate (!(pol & MULTIPOLICY) || elem->repcount == 1) && 9197c478bd9Sstevel@tonic-gate /* req for DMA / ddi_rep */ 9207c478bd9Sstevel@tonic-gate (pol & elem->size) == 0) 9217c478bd9Sstevel@tonic-gate elem->access_type = 0; 9227c478bd9Sstevel@tonic-gate /* these will end up sorted at the head */ 9237c478bd9Sstevel@tonic-gate else { 9247c478bd9Sstevel@tonic-gate cnt += 1; 9257c478bd9Sstevel@tonic-gate elem->size *= elem->repcount; 9267c478bd9Sstevel@tonic-gate if (log->flags & BOFI_LOG_TIMESTAMP) 9277c478bd9Sstevel@tonic-gate /* real access time */ 9287c478bd9Sstevel@tonic-gate elem->access_time -= log->start_time; 9297c478bd9Sstevel@tonic-gate else 9307c478bd9Sstevel@tonic-gate /* linear fit */ 9317c478bd9Sstevel@tonic-gate elem->access_time = logtime * (i + 1) / nitems; 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate } 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate qsort((void *)items, nitems, sizeof (*items), log_cmp); 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate msg(5, "qsorted log raw (nitems %d cnt %d:\n", nitems, cnt); 9387c478bd9Sstevel@tonic-gate dump_log(14, 0, items, nitems, log->flags); 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate if (cnt != nitems) { /* some items should be ignored */ 9417c478bd9Sstevel@tonic-gate items += (nitems - cnt); /* ignore these ones */ 9427c478bd9Sstevel@tonic-gate if ((nitems = cnt) == 0) { 9437c478bd9Sstevel@tonic-gate *cntp = 0; 9447c478bd9Sstevel@tonic-gate *llp = 0; 9457c478bd9Sstevel@tonic-gate return (0); 9467c478bd9Sstevel@tonic-gate /* the chosen policy has ignored everything */ 9477c478bd9Sstevel@tonic-gate } 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate /* 9517c478bd9Sstevel@tonic-gate * Now remove duplicate entries based on access type, address and size. 9527c478bd9Sstevel@tonic-gate * Reuse the repcount field to store the no. of duplicate accesses. 9537c478bd9Sstevel@tonic-gate * Store the average access time in the single remaining 9547c478bd9Sstevel@tonic-gate * representative of the duplicate set. 9557c478bd9Sstevel@tonic-gate */ 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate for (i = 1, cnt = 1, elem = items, elem->repcount = 1, item = elem + 1; 9587c478bd9Sstevel@tonic-gate i < nitems; i++, item++) { 9597c478bd9Sstevel@tonic-gate if (elem_cmp(elem, item) == 0) { 9607c478bd9Sstevel@tonic-gate elem->access_time += item->access_time; 9617c478bd9Sstevel@tonic-gate elem->repcount++; 9627c478bd9Sstevel@tonic-gate } else { /* not a duplicate */ 9637c478bd9Sstevel@tonic-gate elem->access_time = logtime / elem->repcount; 9647c478bd9Sstevel@tonic-gate elem++; 9657c478bd9Sstevel@tonic-gate *elem = *item; 9667c478bd9Sstevel@tonic-gate cnt++; 9677c478bd9Sstevel@tonic-gate elem->repcount = 1; 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate elem->access_time = logtime / elem->repcount; 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate /* 9737c478bd9Sstevel@tonic-gate * The log is sorted by access type - now resort to order by frequency 9747c478bd9Sstevel@tonic-gate * of accesses (ie for a given access type uncommon access will come 9757c478bd9Sstevel@tonic-gate * first. 9767c478bd9Sstevel@tonic-gate */ 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate qsort((void *)items, cnt, sizeof (*items), log_cmp2); 9797c478bd9Sstevel@tonic-gate msg(4, "qsorted log2: cnt is %d\n", cnt); 9807c478bd9Sstevel@tonic-gate dump_log(4, 0, items, cnt, log->flags); 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate for (i = 0; i < cnt; i = j) { 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate /* 9857c478bd9Sstevel@tonic-gate * Pick out the set [i, j) consisting of elements with the same 9867c478bd9Sstevel@tonic-gate * access type 9877c478bd9Sstevel@tonic-gate */ 9887c478bd9Sstevel@tonic-gate for (j = i + 1, acnt = items[i].repcount; j < cnt && 9897c478bd9Sstevel@tonic-gate items[j].access_type == items[i].access_type; j++) 9907c478bd9Sstevel@tonic-gate acnt += items[j].repcount; 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate if (j - i == 1) /* never ignore solo accesses of a given type */ 9937c478bd9Sstevel@tonic-gate continue; 9947c478bd9Sstevel@tonic-gate /* 9957c478bd9Sstevel@tonic-gate * Now determine what constitutes uncommon and common accesses: 9967c478bd9Sstevel@tonic-gate */ 9977c478bd9Sstevel@tonic-gate mina = items[i].repcount; 9987c478bd9Sstevel@tonic-gate maxa = items[j-1].repcount; 9997c478bd9Sstevel@tonic-gate mean = acnt / (j - i); /* mean value */ 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate if (pol & (UNCOMMONPOLICY|MEDIANPOLICY)) { 10027c478bd9Sstevel@tonic-gate cutoff[0] = (mean - mina) / DISTRIB_CUTOFF + mina; 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate for (ub = i; ub < j; ub++) 10057c478bd9Sstevel@tonic-gate if (items[ub].repcount > cutoff[0]) 10067c478bd9Sstevel@tonic-gate break; 10077c478bd9Sstevel@tonic-gate lb = j - 1; 10087c478bd9Sstevel@tonic-gate } else { 10097c478bd9Sstevel@tonic-gate lb = i; 10107c478bd9Sstevel@tonic-gate ub = j-1; 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate if (pol & (COMMONPOLICY|MEDIANPOLICY)) { 10147c478bd9Sstevel@tonic-gate cutoff[1] = maxa - (maxa - mean) / DISTRIB_CUTOFF; 10157c478bd9Sstevel@tonic-gate for (lb = j - 1; lb >= i; lb--) 10167c478bd9Sstevel@tonic-gate if (items[lb].repcount < cutoff[1]) 10177c478bd9Sstevel@tonic-gate break; 10187c478bd9Sstevel@tonic-gate if (!(pol & (UNCOMMONPOLICY|MEDIANPOLICY))) 10197c478bd9Sstevel@tonic-gate ub = i; 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate msg(3, "reduce_log: p 0x%x at %d:0x%x %d:0x%x acnt mina maxa" 10237c478bd9Sstevel@tonic-gate " (%d %d %d)" 10247c478bd9Sstevel@tonic-gate " mean %d cutoffs(%d %d) bnds(%d, %d)\n", 10257c478bd9Sstevel@tonic-gate pol, i, items[i].access_type, j, items[j].access_type, 10267c478bd9Sstevel@tonic-gate acnt, mina, maxa, mean, cutoff[0], cutoff[1], lb, ub); 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate if (ub <= lb) 10297c478bd9Sstevel@tonic-gate if (!(pol & MEDIANPOLICY)) 10307c478bd9Sstevel@tonic-gate /* delete all the mid accesses */ 10317c478bd9Sstevel@tonic-gate for (k = ub; k <= lb; k++) 10327c478bd9Sstevel@tonic-gate items[k].access_type = 0; 10337c478bd9Sstevel@tonic-gate else { 10347c478bd9Sstevel@tonic-gate if (!(pol & UNCOMMONPOLICY)) 10357c478bd9Sstevel@tonic-gate /* delete uncommon accesses */ 10367c478bd9Sstevel@tonic-gate for (k = i; k < ub; k++) 10377c478bd9Sstevel@tonic-gate items[k].access_type = 0; 10387c478bd9Sstevel@tonic-gate if (!(pol & COMMONPOLICY)) 10397c478bd9Sstevel@tonic-gate /* delete common accesses */ 10407c478bd9Sstevel@tonic-gate for (k = lb+1; k < j; k++) 10417c478bd9Sstevel@tonic-gate items[k].access_type = 0; 10427c478bd9Sstevel@tonic-gate } 10437c478bd9Sstevel@tonic-gate } 10447c478bd9Sstevel@tonic-gate msg(4, "reduce_log: returning %d items\n", cnt); 10457c478bd9Sstevel@tonic-gate dump_log(5, 0, items, cnt, log->flags); 10467c478bd9Sstevel@tonic-gate *cntp = cnt; 10477c478bd9Sstevel@tonic-gate *llp = items; 10487c478bd9Sstevel@tonic-gate return (0); 10497c478bd9Sstevel@tonic-gate } 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate static void 10527c478bd9Sstevel@tonic-gate log2errdefs(int fd, struct bofi_errdef *edp, struct acc_log *log, 10537c478bd9Sstevel@tonic-gate char *devpath) 10547c478bd9Sstevel@tonic-gate { 10557c478bd9Sstevel@tonic-gate struct acc_log_elem *items; 10567c478bd9Sstevel@tonic-gate size_t nitems; 10577c478bd9Sstevel@tonic-gate int i, j; 10587c478bd9Sstevel@tonic-gate uint_t acc_cnt; 10597c478bd9Sstevel@tonic-gate char fname[_POSIX_PATH_MAX]; 10607c478bd9Sstevel@tonic-gate FILE *fp = 0; 10617c478bd9Sstevel@tonic-gate time_t utc = time(NULL); 10627c478bd9Sstevel@tonic-gate int ecnt = 0; 10637c478bd9Sstevel@tonic-gate int err; 10647c478bd9Sstevel@tonic-gate ulong_t logtime; 10657c478bd9Sstevel@tonic-gate char *buffer; 10667c478bd9Sstevel@tonic-gate struct stat statbuf; 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate items = (void *)log->logbase; 10697c478bd9Sstevel@tonic-gate nitems = log->entries; 10707c478bd9Sstevel@tonic-gate logtime = (log->stop_time >= log->start_time) ? 10717c478bd9Sstevel@tonic-gate log->stop_time - log->start_time : 10ul; 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate if (nitems == 0) 10747c478bd9Sstevel@tonic-gate return; 10757c478bd9Sstevel@tonic-gate 10767c478bd9Sstevel@tonic-gate /* ensure that generated errdefs complete in bounded time */ 10777c478bd9Sstevel@tonic-gate if (max_edef_wait == 0) 10787c478bd9Sstevel@tonic-gate max_edef_wait = 10797c478bd9Sstevel@tonic-gate logtime > MIN_REPORT_TIME ? logtime : MIN_REPORT_TIME * 2; 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate msg(4, "log2errdefs(0x%p, 0x%p, %d, 0x%x):\n", 10827c478bd9Sstevel@tonic-gate (void *) edp, (void *) items, nitems, policy); 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate (void) snprintf(fname, sizeof (fname), "%s.%d", (char *)edp->name, 10857c478bd9Sstevel@tonic-gate (int)getpid()); 10867c478bd9Sstevel@tonic-gate if ((fp = fopen(fname, "w")) == 0) 10877c478bd9Sstevel@tonic-gate fp = outfile; 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate (void) fprintf(fp, "#!/bin/ksh -p\n\n"); 10907c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s%s\n", "Script creation time:", ctime(&utc)); 10917c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s%llu\n", 10927c478bd9Sstevel@tonic-gate "Activation time:", log->start_time); 10937c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s%llu\n", 10947c478bd9Sstevel@tonic-gate "Deactivation time:", log->stop_time); 10957c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s%d\n", "Log size:", nitems); 10967c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s", "Errdef policy:"); 10977c478bd9Sstevel@tonic-gate for (i = 0; ptypes[i].str != 0; i++) 10987c478bd9Sstevel@tonic-gate if (policy & ptypes[i].code) 10997c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s ", ptypes[i].str); 11007c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n"); 11017c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s%s\n", "Driver:", (char *)edp->name); 11027c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s%d\n", "Instance:", edp->instance); 11037c478bd9Sstevel@tonic-gate if (edp->access_type & BOFI_PIO_RW) { 11047c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s%d\n", 11057c478bd9Sstevel@tonic-gate "Register set:", edp->rnumber); 11067c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s0x%llx\n", "Offset:", edp->offset); 11077c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s0x%llx\n", "Length:", edp->len); 11087c478bd9Sstevel@tonic-gate } else if (edp->access_type & BOFI_DMA_RW) { 11097c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s%d\n", "DMA handle:", edp->rnumber); 11107c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s0x%llx\n", "Offset:", edp->offset); 11117c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s0x%llx\n", "Length:", edp->len); 11127c478bd9Sstevel@tonic-gate } else if ((edp->access_type & BOFI_INTR) == 0) { 11137c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s%d\n", 11147c478bd9Sstevel@tonic-gate "Unknown Handle Type:", edp->rnumber); 11157c478bd9Sstevel@tonic-gate } 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s0x%x ( ", "Access type:", 11187c478bd9Sstevel@tonic-gate (edp->access_type & ~BOFI_LOG)); 11197c478bd9Sstevel@tonic-gate if (edp->access_type & BOFI_PIO_R) 11207c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s ", "pio_r"); 11217c478bd9Sstevel@tonic-gate if (edp->access_type & BOFI_PIO_W) 11227c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s ", "pio_w"); 11237c478bd9Sstevel@tonic-gate if (edp->access_type & BOFI_DMA_W) 11247c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s ", "dma_w"); 11257c478bd9Sstevel@tonic-gate if (edp->access_type & BOFI_DMA_R) 11267c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s ", "dma_r"); 11277c478bd9Sstevel@tonic-gate if (edp->access_type & BOFI_INTR) 11287c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s ", "intr"); 11297c478bd9Sstevel@tonic-gate (void) fprintf(fp, ")\n\n"); 11307c478bd9Sstevel@tonic-gate if (user_comment) 11317c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# %-24s%s\n\n", 11327c478bd9Sstevel@tonic-gate "Test Comment:", user_comment); 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate dump_log(0, fp, items, nitems, log->flags); 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate items = 0; 11377c478bd9Sstevel@tonic-gate if ((err = reduce_log(policy, log, &items, &nitems)) < 0 || 11387c478bd9Sstevel@tonic-gate nitems == 0) { 11397c478bd9Sstevel@tonic-gate msg(4, "log2errdefs: reduce_log err %d nitems %d\n", 11407c478bd9Sstevel@tonic-gate err, nitems); 11417c478bd9Sstevel@tonic-gate return; 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\nerror() { echo \"" 11447c478bd9Sstevel@tonic-gate "${0##*/}: $@\"" 11457c478bd9Sstevel@tonic-gate " >&2; exit 2; }\n"); 11467c478bd9Sstevel@tonic-gate (void) fprintf(fp, 11477c478bd9Sstevel@tonic-gate "trap ' ' 16\t# ignore - it is trapped by abort monitor_edef\n"); 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\nfixup_script()\n{\n"); 11507c478bd9Sstevel@tonic-gate if (scriptargs > 0) { 11517c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\tif [[ $1 -eq 1 ]]\n\tthen\n"); 11527c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t\t# Call a user defined workload\n"); 11537c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t\t# while injecting errors\n\t\t"); 11547c478bd9Sstevel@tonic-gate for (i = 0; i < scriptargs; i++) 11557c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s ", fixup_script[i]); 11567c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n\tfi\n"); 11577c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\treturn 0\n"); 11587c478bd9Sstevel@tonic-gate } else { 11597c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\tif [[ $1 -eq 0 ]]\n\tthen\n"); 11607c478bd9Sstevel@tonic-gate (void) fprintf(fp, 11617c478bd9Sstevel@tonic-gate "\t\t# terminate any outstanding workload\n"); 11627c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t\tif [ $script_pid -gt 0 ]; then\n"); 11637c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t\t\tkill $script_pid\n"); 11647c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t\t\tscript_pid=0\n"); 11657c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t\tfi\n"); 11667c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\tfi\n"); 11677c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\treturn -1\n"); 11687c478bd9Sstevel@tonic-gate } 11697c478bd9Sstevel@tonic-gate (void) fprintf(fp, "}\n\n"); 11707c478bd9Sstevel@tonic-gate (void) fprintf(fp, "devpath=/devices%s\n\n", devpath); 11717c478bd9Sstevel@tonic-gate (void) fprintf(fp, "#\n"); 11727c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# following text extracted from th_script\n"); 11737c478bd9Sstevel@tonic-gate (void) fprintf(fp, "#\n"); 11747c478bd9Sstevel@tonic-gate if (stat("/usr/lib/th_script", &statbuf) == -1) { 11757c478bd9Sstevel@tonic-gate msg(0, "log2errdefs: stat of /usr/lib/th_script failed\n"); 11767c478bd9Sstevel@tonic-gate return; 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate fd = open("/usr/lib/th_script", O_RDONLY); 11797c478bd9Sstevel@tonic-gate if (fd == -1) { 11807c478bd9Sstevel@tonic-gate msg(0, "log2errdefs: open of /usr/lib/th_script failed\n"); 11817c478bd9Sstevel@tonic-gate return; 11827c478bd9Sstevel@tonic-gate } 11837c478bd9Sstevel@tonic-gate buffer = malloc(statbuf.st_size); 11847c478bd9Sstevel@tonic-gate if (!buffer) { 11857c478bd9Sstevel@tonic-gate msg(0, "log2errdefs: malloc for /usr/lib/th_script failed\n"); 11867c478bd9Sstevel@tonic-gate return; 11877c478bd9Sstevel@tonic-gate } 11887c478bd9Sstevel@tonic-gate if (read(fd, buffer, statbuf.st_size) != statbuf.st_size) { 11897c478bd9Sstevel@tonic-gate msg(0, "log2errdefs: read of /usr/lib/th_script failed\n"); 11907c478bd9Sstevel@tonic-gate return; 11917c478bd9Sstevel@tonic-gate } 11927c478bd9Sstevel@tonic-gate (void) fwrite(buffer, statbuf.st_size, 1, fp); 11937c478bd9Sstevel@tonic-gate (void) close(fd); 11947c478bd9Sstevel@tonic-gate (void) fprintf(fp, "#\n"); 11957c478bd9Sstevel@tonic-gate (void) fprintf(fp, "# end of extracted text\n"); 11967c478bd9Sstevel@tonic-gate (void) fprintf(fp, "#\n"); 11977c478bd9Sstevel@tonic-gate (void) fprintf(fp, "run_subtest %s %d <<ERRDEFS\n", 11987c478bd9Sstevel@tonic-gate (char *)edp->name, edp->instance); 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate for (i = 0; i < nitems; i = j) { 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate acc_cnt = items[i].repcount; 12037c478bd9Sstevel@tonic-gate for (j = i + 1; 12047c478bd9Sstevel@tonic-gate j < nitems && items[j].access_type == items[i].access_type; 12057c478bd9Sstevel@tonic-gate j++) 12067c478bd9Sstevel@tonic-gate acc_cnt += items[j].repcount; 12077c478bd9Sstevel@tonic-gate msg(1, "l2e: nitems %d i %d j %d at 0x%x\n", 12087c478bd9Sstevel@tonic-gate nitems, i, j, items[i].access_type); 12097c478bd9Sstevel@tonic-gate if (items[i].access_type != 0) 12107c478bd9Sstevel@tonic-gate (void) define_nerrs(fd, fp, &ecnt, edp, items+i, j-i, 12117c478bd9Sstevel@tonic-gate acc_cnt, items[i].repcount, items[j-1].repcount, 12127c478bd9Sstevel@tonic-gate logtime, log->entries); 12137c478bd9Sstevel@tonic-gate } 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate (void) fprintf(fp, "ERRDEFS\n"); 12167c478bd9Sstevel@tonic-gate (void) fprintf(fp, "exit 0\n"); 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate if (fp != stdout && fp != stderr) { 12197c478bd9Sstevel@tonic-gate if (fchmod(fileno(fp), S_IRWXU|S_IRGRP|S_IROTH)) 12207c478bd9Sstevel@tonic-gate msg(0, "fchmod failed: %s\n", strerror(errno)); 12217c478bd9Sstevel@tonic-gate if (fclose(fp) != 0) 12227c478bd9Sstevel@tonic-gate msg(0, "close of %s failed: %s\n", fname, 12237c478bd9Sstevel@tonic-gate strerror(errno)); 12247c478bd9Sstevel@tonic-gate } 12257c478bd9Sstevel@tonic-gate msg(10, "log2errdefs: done\n"); 12267c478bd9Sstevel@tonic-gate } 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate #define LLSZMASK (sizeof (longlong_t) -1) 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate static int 12317c478bd9Sstevel@tonic-gate add_edef(int fd, 12327c478bd9Sstevel@tonic-gate struct bofi_errdef *errdef, /* returned access criteria */ 12337c478bd9Sstevel@tonic-gate struct bofi_errstate *errstate, 12347c478bd9Sstevel@tonic-gate struct handle_info *hdl, /* handle to match against request */ 12357c478bd9Sstevel@tonic-gate struct bofi_errdef *edp) /* requested access criteria */ 12367c478bd9Sstevel@tonic-gate { 12377c478bd9Sstevel@tonic-gate *errdef = *edp; 12387c478bd9Sstevel@tonic-gate errdef->instance = hdl->instance; 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate 12417c478bd9Sstevel@tonic-gate if (hdl->access_type == 0) 12427c478bd9Sstevel@tonic-gate return (EINVAL); 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate errdef->access_type = 12457c478bd9Sstevel@tonic-gate errdef->access_type & (hdl->access_type|BOFI_LOG); 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate /* use a big log for PIO and a small one otherwise */ 12487c478bd9Sstevel@tonic-gate if (lsize_is_default && 12497c478bd9Sstevel@tonic-gate (errdef->access_type & BOFI_PIO_RW) == 0) { 12507c478bd9Sstevel@tonic-gate errdef->access_count = DFLT_NONPIO_LOGSZ; 12517c478bd9Sstevel@tonic-gate errdef->fail_count = 0; 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate errdef->log.logsize = errstate->log.logsize = 12547c478bd9Sstevel@tonic-gate errdef->access_count + errdef->fail_count - 1; 12557c478bd9Sstevel@tonic-gate if (errdef->log.logsize == -1U) { 12567c478bd9Sstevel@tonic-gate errdef->log.logsize = errstate->log.logsize = 0; 12577c478bd9Sstevel@tonic-gate } 12587c478bd9Sstevel@tonic-gate errdef->log.logbase = errstate->log.logbase = 12597c478bd9Sstevel@tonic-gate (caddr_t)GETSTRUCT(struct acc_log_elem, errdef->log.logsize); 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate if (errdef->log.logbase == 0) 12627c478bd9Sstevel@tonic-gate return (EAGAIN); 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate errdef->rnumber = hdl->rnumber; 12657c478bd9Sstevel@tonic-gate errdef->offset = hdl->offset; 12667c478bd9Sstevel@tonic-gate errdef->len = hdl->len; 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate msg(4, "creating errdef: %d %s %d %d 0x%llx 0x%llx 0x%x 0x%x 0x%x" 12697c478bd9Sstevel@tonic-gate " 0x%x 0x%x 0x%llx\n", 12707c478bd9Sstevel@tonic-gate errdef->namesize, (char *)errdef->name, 12717c478bd9Sstevel@tonic-gate errdef->instance, errdef->rnumber, 12727c478bd9Sstevel@tonic-gate errdef->offset, errdef->len, 12737c478bd9Sstevel@tonic-gate errdef->access_type, 12747c478bd9Sstevel@tonic-gate errdef->access_count, errdef->fail_count, 12757c478bd9Sstevel@tonic-gate errdef->acc_chk, errdef->optype, errdef->operand); 12767c478bd9Sstevel@tonic-gate if (ioctl(fd, BOFI_ADD_DEF, errdef) == -1) { 12777c478bd9Sstevel@tonic-gate perror("th_define - adding errdef failed"); 12787c478bd9Sstevel@tonic-gate return (errno); 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate errdef->optype = edp->optype; /* driver clears it if fcnt is zero */ 12817c478bd9Sstevel@tonic-gate errstate->errdef_handle = errdef->errdef_handle; 12827c478bd9Sstevel@tonic-gate return (0); 12837c478bd9Sstevel@tonic-gate } 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate static void 12867c478bd9Sstevel@tonic-gate collect_state(int fd, int cmd, 12877c478bd9Sstevel@tonic-gate struct bofi_errstate *errstate, 12887c478bd9Sstevel@tonic-gate struct bofi_errdef *errdef, 12897c478bd9Sstevel@tonic-gate char *devpath) 12907c478bd9Sstevel@tonic-gate { 12917c478bd9Sstevel@tonic-gate int rval; 12927c478bd9Sstevel@tonic-gate size_t ls = errstate->log.logsize; 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate msg(2, "collect_state: pre: edp->access_type 0x%x (logsize %d)\n", 12957c478bd9Sstevel@tonic-gate errdef->access_type, errdef->log.logsize); 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate do { 12987c478bd9Sstevel@tonic-gate errstate->log.logsize = 0; /* only copy the driver log once */ 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate msg(10, "collecting state (lsize %d) ...\n", 13017c478bd9Sstevel@tonic-gate errstate->log.logsize); 13027c478bd9Sstevel@tonic-gate errno = 0; 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate if (ioctl(fd, cmd, errstate) == -1 && errno != EINTR) { 13057c478bd9Sstevel@tonic-gate perror("th_define (collect) -" 13067c478bd9Sstevel@tonic-gate " waiting for error report failed"); 13077c478bd9Sstevel@tonic-gate break; 13087c478bd9Sstevel@tonic-gate } 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate (void) fprintf(outfile, "Logged %d out of %d accesses" 13117c478bd9Sstevel@tonic-gate " (%s %d %d 0x%x %d).\n", 13127c478bd9Sstevel@tonic-gate errstate->log.entries, ls, 13137c478bd9Sstevel@tonic-gate (char *)errdef->name, errdef->instance, errdef->rnumber, 13147c478bd9Sstevel@tonic-gate errdef->access_type, errstate->log.wrapcnt); 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate (void) msg(1, "\t(ac %d fc %d lf 0x%x wc %d).\n", 13177c478bd9Sstevel@tonic-gate errstate->access_count, errstate->fail_count, 13187c478bd9Sstevel@tonic-gate errstate->log.flags, errstate->log.wrapcnt); 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate rval = errno; 13217c478bd9Sstevel@tonic-gate if ((errstate->log.flags & BOFI_LOG_WRAP) && 13227c478bd9Sstevel@tonic-gate errstate->access_count > 0) 13237c478bd9Sstevel@tonic-gate continue; 13247c478bd9Sstevel@tonic-gate if (errstate->access_count <= 1 && 13257c478bd9Sstevel@tonic-gate errstate->fail_count == 0 && 13267c478bd9Sstevel@tonic-gate errstate->acc_chk == 0) { 13277c478bd9Sstevel@tonic-gate msg(3, "collecting state complete entries %d\n", 13287c478bd9Sstevel@tonic-gate errstate->log.entries); 13297c478bd9Sstevel@tonic-gate break; 13307c478bd9Sstevel@tonic-gate } 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate msg(5, "still collecting state: %d, %d, %d\n", 13337c478bd9Sstevel@tonic-gate errstate->access_count, errstate->fail_count, 13347c478bd9Sstevel@tonic-gate errstate->acc_chk); 13357c478bd9Sstevel@tonic-gate (void) msg(2, "Log: errno %d size %d entries %d " 13367c478bd9Sstevel@tonic-gate "(off 0x%llx len 0x%llx) ac %d\n", errno, 13377c478bd9Sstevel@tonic-gate errstate->log.logsize, errstate->log.entries, 13387c478bd9Sstevel@tonic-gate errdef->offset, errdef->len, errstate->access_count); 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate } while (rval == 0 && errstate->log.entries < ls); 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate /* now grab the log itself */ 13437c478bd9Sstevel@tonic-gate errstate->log.logsize = ls; 13447c478bd9Sstevel@tonic-gate if (errstate->log.entries != 0) { 13457c478bd9Sstevel@tonic-gate if (ioctl(fd, BOFI_CHK_STATE, errstate) == -1) { 13467c478bd9Sstevel@tonic-gate msg(0, 13477c478bd9Sstevel@tonic-gate "%s: errorwhile retrieving %d log entries: %s\n", 13487c478bd9Sstevel@tonic-gate Progname, errstate->log.entries, strerror(errno)); 13497c478bd9Sstevel@tonic-gate } else { 13507c478bd9Sstevel@tonic-gate msg(2, "collect_state: post: edp->access_type 0x%x" 13517c478bd9Sstevel@tonic-gate " (log entries %d %d) (%llu - %llu)\n", 13527c478bd9Sstevel@tonic-gate errdef->access_type, 13537c478bd9Sstevel@tonic-gate errstate->log.entries, errstate->access_count, 13547c478bd9Sstevel@tonic-gate errstate->log.start_time, errstate->log.stop_time); 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate log2errdefs(fd, errdef, &(errstate->log), devpath); 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate } 13597c478bd9Sstevel@tonic-gate } 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate static void 13627c478bd9Sstevel@tonic-gate print_err_reports(FILE *fp, struct bofi_errstate *esp, 13637c478bd9Sstevel@tonic-gate char *fname, char *cmt, int id) 13647c478bd9Sstevel@tonic-gate { 13657c478bd9Sstevel@tonic-gate if (fname != 0 && *fname != 0) 13667c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%sErrdef file %s definition %d:", 13677c478bd9Sstevel@tonic-gate cmt, fname, id); 13687c478bd9Sstevel@tonic-gate else 13697c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s", cmt); 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate if (esp->access_count != 0) { 13727c478bd9Sstevel@tonic-gate (void) fprintf(fp, " (access count %d).\n", esp->access_count); 13737c478bd9Sstevel@tonic-gate } else { 13747c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n%s\tremaining fail count %d acc_chk %d\n", 13757c478bd9Sstevel@tonic-gate cmt, esp->fail_count, esp->acc_chk); 13767c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\tfail time 0x%llx error reported time" 13777c478bd9Sstevel@tonic-gate " 0x%llx errors reported %d\n", cmt, 13787c478bd9Sstevel@tonic-gate esp->fail_time, esp->msg_time, 13797c478bd9Sstevel@tonic-gate esp->errmsg_count); 13807c478bd9Sstevel@tonic-gate if (esp->msg_time) 13817c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\tmessage \"%s\" severity 0x%x\n", 13827c478bd9Sstevel@tonic-gate cmt, esp->buffer, (uint_t)esp->severity); 13837c478bd9Sstevel@tonic-gate } 13847c478bd9Sstevel@tonic-gate } 13857c478bd9Sstevel@tonic-gate 13867c478bd9Sstevel@tonic-gate static void 13877c478bd9Sstevel@tonic-gate thr_collect(void *arg, char *devpath) 13887c478bd9Sstevel@tonic-gate { 13897c478bd9Sstevel@tonic-gate int fd; 13907c478bd9Sstevel@tonic-gate struct collector_def *hi = (struct collector_def *)arg; 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate msg(4, "thr_collect: collecting %s inst %d rn %d at = 0x%x.\n", 13937c478bd9Sstevel@tonic-gate hi->ed.name, hi->ed.instance, 13947c478bd9Sstevel@tonic-gate hi->ed.rnumber, hi->ed.access_type); 13957c478bd9Sstevel@tonic-gate 13967c478bd9Sstevel@tonic-gate if ((fd = open(BOFI_DEV, O_RDWR)) == -1) { 13977c478bd9Sstevel@tonic-gate if (errno == EAGAIN) 13987c478bd9Sstevel@tonic-gate msg(0, "Too many instances of bofi currently open\n"); 13997c478bd9Sstevel@tonic-gate else 14007c478bd9Sstevel@tonic-gate msg(0, "Error while opening bofi driver: %s", 14017c478bd9Sstevel@tonic-gate strerror(errno)); 14027c478bd9Sstevel@tonic-gate } else { 14037c478bd9Sstevel@tonic-gate /* 14047c478bd9Sstevel@tonic-gate * Activate the logging errdefs - then collect the results. 14057c478bd9Sstevel@tonic-gate */ 14067c478bd9Sstevel@tonic-gate (void) manage_instance(fd, hi->ed.name, 14077c478bd9Sstevel@tonic-gate hi->ed.instance, BOFI_START); 14087c478bd9Sstevel@tonic-gate collect_state(fd, BOFI_CHK_STATE_W, &hi->es, &hi->ed, devpath); 14097c478bd9Sstevel@tonic-gate } 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate /* 14127c478bd9Sstevel@tonic-gate * there is no more work to do on this access handle so clean up / exit. 14137c478bd9Sstevel@tonic-gate */ 14147c478bd9Sstevel@tonic-gate msg(3, "thr_collect: closing and broadcasting.\n"); 14157c478bd9Sstevel@tonic-gate exit(0); 14167c478bd9Sstevel@tonic-gate } 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate /* 14197c478bd9Sstevel@tonic-gate * Given an access handle known to the bofi driver see if the user has 14207c478bd9Sstevel@tonic-gate * specified access criteria that match that handle. Note: this matching 14217c478bd9Sstevel@tonic-gate * algorithm should be kept consistent with the drivers alogorithm. 14227c478bd9Sstevel@tonic-gate */ 14237c478bd9Sstevel@tonic-gate static int 14247c478bd9Sstevel@tonic-gate match_hinfo(struct handle_info *hp, int instance, uint_t access_type, 14257c478bd9Sstevel@tonic-gate int rnumber, offset_t offset, offset_t len) 14267c478bd9Sstevel@tonic-gate { 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate msg(9, "matching (%d %d) 0x%x %d offset (%llx, %llx) len (%llx %llx)\n", 14297c478bd9Sstevel@tonic-gate hp->instance, instance, access_type, rnumber, 14307c478bd9Sstevel@tonic-gate hp->offset, offset, hp->len, len); 14317c478bd9Sstevel@tonic-gate 14327c478bd9Sstevel@tonic-gate if (instance != -1 && hp->instance != instance) 14337c478bd9Sstevel@tonic-gate return (0); 14347c478bd9Sstevel@tonic-gate if ((access_type & BOFI_DMA_RW) && 14357c478bd9Sstevel@tonic-gate (hp->access_type & BOFI_DMA_RW) && 1436*e5ba14ffSstephh (rnumber == -1 || hp->rnumber == rnumber)) 14377c478bd9Sstevel@tonic-gate return (1); 14387c478bd9Sstevel@tonic-gate else if ((access_type & BOFI_INTR) && 14397c478bd9Sstevel@tonic-gate (hp->access_type & BOFI_INTR)) 14407c478bd9Sstevel@tonic-gate return (1); 14417c478bd9Sstevel@tonic-gate else if ((access_type & BOFI_PIO_RW) && 14427c478bd9Sstevel@tonic-gate (hp->access_type & BOFI_PIO_RW) && 14437c478bd9Sstevel@tonic-gate (rnumber == -1 || hp->rnumber == rnumber) && 14447c478bd9Sstevel@tonic-gate (len == 0 || hp->offset < offset + len) && 14457c478bd9Sstevel@tonic-gate (hp->len == 0 || hp->offset + hp->len > offset)) 14467c478bd9Sstevel@tonic-gate return (1); 14477c478bd9Sstevel@tonic-gate else 14487c478bd9Sstevel@tonic-gate return (0); 14497c478bd9Sstevel@tonic-gate } 14507c478bd9Sstevel@tonic-gate 14517c478bd9Sstevel@tonic-gate /* 14527c478bd9Sstevel@tonic-gate * Obtain all the handles created by the driver specified by the name parameter 14537c478bd9Sstevel@tonic-gate * that match the remaining arguments. The output parameter nhdls indicates how 14547c478bd9Sstevel@tonic-gate * many of the structures pointed to by the output parameter hip match the 14557c478bd9Sstevel@tonic-gate * specification. 14567c478bd9Sstevel@tonic-gate * 14577c478bd9Sstevel@tonic-gate * It is the responsibility of the caller to free *hip when *nhdls != 0. 14587c478bd9Sstevel@tonic-gate */ 14597c478bd9Sstevel@tonic-gate static int 14607c478bd9Sstevel@tonic-gate get_hinfo(int fd, char *name, struct handle_info **hip, size_t *nhdls, 14617c478bd9Sstevel@tonic-gate int instance, int atype, int rset, offset_t offset, offset_t len, 14627c478bd9Sstevel@tonic-gate int new_semantics) 14637c478bd9Sstevel@tonic-gate { 14647c478bd9Sstevel@tonic-gate struct bofi_get_hdl_info hdli; 14657c478bd9Sstevel@tonic-gate int command; 14667c478bd9Sstevel@tonic-gate 14677c478bd9Sstevel@tonic-gate command = BOFI_GET_HANDLE_INFO; 14687c478bd9Sstevel@tonic-gate hdli.namesize = strlen(name); 14697c478bd9Sstevel@tonic-gate (void) strncpy(hdli.name, name, MAXNAMELEN); 14707c478bd9Sstevel@tonic-gate /* 14717c478bd9Sstevel@tonic-gate * Initially ask for the number of access handles (not the structures) 14727c478bd9Sstevel@tonic-gate * in order to allocate memory 14737c478bd9Sstevel@tonic-gate */ 14747c478bd9Sstevel@tonic-gate hdli.hdli = 0; 14757c478bd9Sstevel@tonic-gate *hip = 0; 14767c478bd9Sstevel@tonic-gate hdli.count = 0; 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate /* 14797c478bd9Sstevel@tonic-gate * Ask the bofi driver for all handles created by the driver under test. 14807c478bd9Sstevel@tonic-gate */ 14817c478bd9Sstevel@tonic-gate if (ioctl(fd, command, &hdli) == -1) { 14827c478bd9Sstevel@tonic-gate *nhdls = 0; 14837c478bd9Sstevel@tonic-gate msg(0, "driver failed to return handles: %s\n", 14847c478bd9Sstevel@tonic-gate strerror(errno)); 14857c478bd9Sstevel@tonic-gate return (errno); 14867c478bd9Sstevel@tonic-gate } else if ((*nhdls = hdli.count) == 0) { 14877c478bd9Sstevel@tonic-gate msg(1, "get_hinfo: no registered handles\n"); 14887c478bd9Sstevel@tonic-gate return (0); /* no handles */ 14897c478bd9Sstevel@tonic-gate } else if ((*hip = GETSTRUCT(struct handle_info, *nhdls)) == 0) { 14907c478bd9Sstevel@tonic-gate return (EAGAIN); 14917c478bd9Sstevel@tonic-gate } else { 14927c478bd9Sstevel@tonic-gate struct handle_info *hp, **chosen; 14937c478bd9Sstevel@tonic-gate int i; 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate /* Ask for *nhdls handles */ 14967c478bd9Sstevel@tonic-gate hdli.hdli = (caddr_t)*hip; 14977c478bd9Sstevel@tonic-gate if (ioctl(fd, command, &hdli) == -1) { 14987c478bd9Sstevel@tonic-gate int err = errno; 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate msg(0, "BOFI_GET_HANDLE_INFO ioctl returned error %d\n", 15017c478bd9Sstevel@tonic-gate err); 15027c478bd9Sstevel@tonic-gate free(*hip); 15037c478bd9Sstevel@tonic-gate return (err); 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate if (hdli.count < *nhdls) 15077c478bd9Sstevel@tonic-gate *nhdls = hdli.count; /* some handles have gone away */ 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate msg(4, "qsorting %d handles\n", *nhdls); 15107c478bd9Sstevel@tonic-gate if (*nhdls > 1) 15117c478bd9Sstevel@tonic-gate /* sort them naturally (NB ordering is not mandatory) */ 15127c478bd9Sstevel@tonic-gate qsort((void *)*hip, *nhdls, sizeof (**hip), hdl_cmp); 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate if ((chosen = malloc(sizeof (hp) * *nhdls)) != NULL) { 15157c478bd9Sstevel@tonic-gate struct handle_info **ip; 15167c478bd9Sstevel@tonic-gate /* the selected handles */ 15177c478bd9Sstevel@tonic-gate struct handle_info *prev = 0; 15187c478bd9Sstevel@tonic-gate int scnt = 0; 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate for (i = 0, hp = *hip, ip = chosen; i < *nhdls; 15217c478bd9Sstevel@tonic-gate i++, hp++) { 15227c478bd9Sstevel@tonic-gate /* 15237c478bd9Sstevel@tonic-gate * Remark: unbound handles never match 15247c478bd9Sstevel@tonic-gate * (access_type == 0) 15257c478bd9Sstevel@tonic-gate */ 15267c478bd9Sstevel@tonic-gate if (match_hinfo(hp, instance, atype, rset, 15277c478bd9Sstevel@tonic-gate offset&0x7fffffff, len&0x7fffffff)) { 15287c478bd9Sstevel@tonic-gate msg(3, "match: 0x%x 0x%llx 0x%llx" 15297c478bd9Sstevel@tonic-gate " 0x%llx (0x%llx)\n", 15307c478bd9Sstevel@tonic-gate hp->access_type, hp->addr_cookie, 15317c478bd9Sstevel@tonic-gate hp->offset, hp->len, 15327c478bd9Sstevel@tonic-gate (hp->len & 0x7fffffff)); 15337c478bd9Sstevel@tonic-gate if (prev && 15347c478bd9Sstevel@tonic-gate (prev->access_type & BOFI_DMA_RW) && 15357c478bd9Sstevel@tonic-gate (hp->access_type & BOFI_DMA_RW) && 15367c478bd9Sstevel@tonic-gate hp->instance == prev->instance && 15377c478bd9Sstevel@tonic-gate hp->len == prev->len && 15387c478bd9Sstevel@tonic-gate hp->addr_cookie == 15397c478bd9Sstevel@tonic-gate prev->addr_cookie) 15407c478bd9Sstevel@tonic-gate continue; 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate if ((hp->access_type & BOFI_DMA_RW) && 15437c478bd9Sstevel@tonic-gate (atype & BOFI_DMA_RW) != 15447c478bd9Sstevel@tonic-gate hp->access_type) 15457c478bd9Sstevel@tonic-gate if (new_semantics) 15467c478bd9Sstevel@tonic-gate continue; 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate if (prev) 15497c478bd9Sstevel@tonic-gate msg(3, "match_hinfo: match:" 15507c478bd9Sstevel@tonic-gate " 0x%llx (%d %d) (%d %d)" 15517c478bd9Sstevel@tonic-gate " (0x%x 0x%x) (0x%llx," 15527c478bd9Sstevel@tonic-gate " 0x%llx)\n", 15537c478bd9Sstevel@tonic-gate hp->addr_cookie, 15547c478bd9Sstevel@tonic-gate prev->instance, 15557c478bd9Sstevel@tonic-gate hp->instance, prev->rnumber, 15567c478bd9Sstevel@tonic-gate hp->rnumber, 15577c478bd9Sstevel@tonic-gate prev->access_type, 15587c478bd9Sstevel@tonic-gate hp->access_type, prev->len, 15597c478bd9Sstevel@tonic-gate hp->len); 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate /* it matches so remember it */ 15627c478bd9Sstevel@tonic-gate prev = *ip++ = hp; 15637c478bd9Sstevel@tonic-gate scnt += 1; 15647c478bd9Sstevel@tonic-gate } 15657c478bd9Sstevel@tonic-gate } 15667c478bd9Sstevel@tonic-gate 15677c478bd9Sstevel@tonic-gate if (*nhdls != scnt) { 15687c478bd9Sstevel@tonic-gate /* 15697c478bd9Sstevel@tonic-gate * Reuse the alloc'ed memory to return 15707c478bd9Sstevel@tonic-gate * only those handles the user has asked for. 15717c478bd9Sstevel@tonic-gate * But first prune the handles to get rid of 15727c478bd9Sstevel@tonic-gate * overlapping ranges (they are ordered by 15737c478bd9Sstevel@tonic-gate * offset and length). 15747c478bd9Sstevel@tonic-gate */ 15757c478bd9Sstevel@tonic-gate *nhdls = scnt; 15767c478bd9Sstevel@tonic-gate for (i = 0, hp = *hip, ip = chosen; i < scnt; 15777c478bd9Sstevel@tonic-gate i++, ip++, hp++) 15787c478bd9Sstevel@tonic-gate if (hp != *ip) 15797c478bd9Sstevel@tonic-gate (void) memcpy(hp, *ip, 15807c478bd9Sstevel@tonic-gate sizeof (*hp)); 15817c478bd9Sstevel@tonic-gate } 15827c478bd9Sstevel@tonic-gate free(chosen); 15837c478bd9Sstevel@tonic-gate } 15847c478bd9Sstevel@tonic-gate 15857c478bd9Sstevel@tonic-gate for (i = 0, hp = *hip; i < *nhdls; i++, hp++) { 15867c478bd9Sstevel@tonic-gate msg(4, "\t%d 0x%x %d 0x%llx 0x%llx 0x%llx\n", 15877c478bd9Sstevel@tonic-gate hp->instance, hp->access_type, hp->rnumber, 15887c478bd9Sstevel@tonic-gate hp->len, hp->offset, hp->addr_cookie); 15897c478bd9Sstevel@tonic-gate } 15907c478bd9Sstevel@tonic-gate } 15917c478bd9Sstevel@tonic-gate if (*nhdls == 0 && *hip) 15927c478bd9Sstevel@tonic-gate free(*hip); 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate msg(4, "get_info: %s got %d handles\n", name, *nhdls); 15957c478bd9Sstevel@tonic-gate return (0); 15967c478bd9Sstevel@tonic-gate } 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate static void 15997c478bd9Sstevel@tonic-gate init_sigs() 16007c478bd9Sstevel@tonic-gate { 16017c478bd9Sstevel@tonic-gate struct sigaction sa; 16027c478bd9Sstevel@tonic-gate int *ip, sigs[] = {SIGINT, SIGTERM, 0}; 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate sa.sa_handler = kill_sighandler; 16057c478bd9Sstevel@tonic-gate (void) sigemptyset(&sa.sa_mask); 16067c478bd9Sstevel@tonic-gate for (ip = sigs; *ip; ip++) 16077c478bd9Sstevel@tonic-gate (void) sigaddset(&sa.sa_mask, *ip); 16087c478bd9Sstevel@tonic-gate sa.sa_flags = 0; 16097c478bd9Sstevel@tonic-gate for (ip = sigs; *ip; ip++) 16107c478bd9Sstevel@tonic-gate (void) sigaction(*ip, &sa, NULL); 16117c478bd9Sstevel@tonic-gate } 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate static void 16147c478bd9Sstevel@tonic-gate up_resources() 16157c478bd9Sstevel@tonic-gate { 16167c478bd9Sstevel@tonic-gate struct rlimit rl; 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate /* Potentially hungry on resources so up them all to their maximums */ 16197c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rl) < 0) 16207c478bd9Sstevel@tonic-gate msg(0, "failed to obtain RLIMIT_NOFILE: %s\n", strerror(errno)); 16217c478bd9Sstevel@tonic-gate else { 16227c478bd9Sstevel@tonic-gate msg(12, "RLIMIT_NOFILE\t %lu (%lu)\n", 16237c478bd9Sstevel@tonic-gate rl.rlim_cur, rl.rlim_max); 16247c478bd9Sstevel@tonic-gate rl.rlim_cur = rl.rlim_max; 16257c478bd9Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rl) < 0) 16267c478bd9Sstevel@tonic-gate msg(0, "failed to set RLIMIT_NOFILE: %s\n", 16277c478bd9Sstevel@tonic-gate strerror(errno)); 1628004388ebScasper (void) enable_extended_FILE_stdio(-1, -1); 16297c478bd9Sstevel@tonic-gate } 16307c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_DATA, &rl) < 0) 16317c478bd9Sstevel@tonic-gate msg(0, "failed to obtain RLIMIT_DATA: %s\n", strerror(errno)); 16327c478bd9Sstevel@tonic-gate else { 16337c478bd9Sstevel@tonic-gate msg(12, "RLIMIT_DATA\t %lu (%lu)\n", rl.rlim_cur, rl.rlim_max); 16347c478bd9Sstevel@tonic-gate rl.rlim_cur = rl.rlim_max; 16357c478bd9Sstevel@tonic-gate if (setrlimit(RLIMIT_DATA, &rl) < 0) 16367c478bd9Sstevel@tonic-gate msg(0, "failed to set RLIMIT_DATA: %s\n", 16377c478bd9Sstevel@tonic-gate strerror(errno)); 16387c478bd9Sstevel@tonic-gate } 16397c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_FSIZE, &rl) < 0) 16407c478bd9Sstevel@tonic-gate msg(0, "failed to obtain RLIMIT_FSIZE: %s\n", strerror(errno)); 16417c478bd9Sstevel@tonic-gate else { 16427c478bd9Sstevel@tonic-gate msg(12, "RLIMIT_FSIZE\t %lu (%lu)\n", rl.rlim_cur, rl.rlim_max); 16437c478bd9Sstevel@tonic-gate rl.rlim_cur = rl.rlim_max; 16447c478bd9Sstevel@tonic-gate if (setrlimit(RLIMIT_FSIZE, &rl) < 0) 16457c478bd9Sstevel@tonic-gate msg(0, "failed to set RLIMIT_FSIZE: %s\n", 16467c478bd9Sstevel@tonic-gate strerror(errno)); 16477c478bd9Sstevel@tonic-gate } 16487c478bd9Sstevel@tonic-gate } 16497c478bd9Sstevel@tonic-gate 16507c478bd9Sstevel@tonic-gate static FILE * 16517c478bd9Sstevel@tonic-gate create_test_file(char *drvname) 16527c478bd9Sstevel@tonic-gate { 16537c478bd9Sstevel@tonic-gate char dirname[_POSIX_PATH_MAX]; 16547c478bd9Sstevel@tonic-gate char testname[_POSIX_PATH_MAX]; 16557c478bd9Sstevel@tonic-gate FILE *fp = 0; 16567c478bd9Sstevel@tonic-gate time_t utc = time(NULL); 16577c478bd9Sstevel@tonic-gate 16587c478bd9Sstevel@tonic-gate if (snprintf(dirname, sizeof (dirname), "%s.test.%lu", 16597c478bd9Sstevel@tonic-gate drvname, utc) == -1 || 16607c478bd9Sstevel@tonic-gate snprintf(testname, sizeof (testname), "%s.test.%lu", 16617c478bd9Sstevel@tonic-gate drvname, utc) == -1) 16627c478bd9Sstevel@tonic-gate return (0); 16637c478bd9Sstevel@tonic-gate 16647c478bd9Sstevel@tonic-gate if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IROTH)) { 16657c478bd9Sstevel@tonic-gate msg(0, "Error creating %s: %s\n", dirname, strerror(errno)); 16667c478bd9Sstevel@tonic-gate return (0); 16677c478bd9Sstevel@tonic-gate } 16687c478bd9Sstevel@tonic-gate if (chdir(dirname)) { 16697c478bd9Sstevel@tonic-gate (void) rmdir(dirname); 16707c478bd9Sstevel@tonic-gate return (0); 16717c478bd9Sstevel@tonic-gate } 16727c478bd9Sstevel@tonic-gate if ((fp = fopen(testname, "w")) == 0) 16737c478bd9Sstevel@tonic-gate return (0); /* leave created directory intact */ 16747c478bd9Sstevel@tonic-gate 16757c478bd9Sstevel@tonic-gate return (fp); 16767c478bd9Sstevel@tonic-gate } 16777c478bd9Sstevel@tonic-gate 16787c478bd9Sstevel@tonic-gate struct walk_arg { 16797c478bd9Sstevel@tonic-gate char *path; 16807c478bd9Sstevel@tonic-gate int instance; 16817c478bd9Sstevel@tonic-gate char name[MAXPATHLEN]; 16827c478bd9Sstevel@tonic-gate int pathlen; 16837c478bd9Sstevel@tonic-gate }; 16847c478bd9Sstevel@tonic-gate 16857c478bd9Sstevel@tonic-gate static int 16867c478bd9Sstevel@tonic-gate walk_callback(di_node_t node, void *arg) 16877c478bd9Sstevel@tonic-gate { 16887c478bd9Sstevel@tonic-gate struct walk_arg *warg = (struct walk_arg *)arg; 16897c478bd9Sstevel@tonic-gate char *driver_name; 16907c478bd9Sstevel@tonic-gate char *path; 16917c478bd9Sstevel@tonic-gate 16927c478bd9Sstevel@tonic-gate driver_name = di_driver_name(node); 16937c478bd9Sstevel@tonic-gate if (driver_name != NULL) { 16947c478bd9Sstevel@tonic-gate if (strcmp(driver_name, warg->name) == NULL && 16957c478bd9Sstevel@tonic-gate di_instance(node) == warg->instance) { 16967c478bd9Sstevel@tonic-gate path = di_devfs_path(node); 16977c478bd9Sstevel@tonic-gate if (path == NULL) 16987c478bd9Sstevel@tonic-gate warg->path = NULL; 16997c478bd9Sstevel@tonic-gate else 17007c478bd9Sstevel@tonic-gate (void) strncpy(warg->path, path, warg->pathlen); 17017c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 17027c478bd9Sstevel@tonic-gate } 17037c478bd9Sstevel@tonic-gate } 17047c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 17057c478bd9Sstevel@tonic-gate } 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate static int 17087c478bd9Sstevel@tonic-gate getpath(char *path, int instance, char *name, int pathlen) 17097c478bd9Sstevel@tonic-gate { 17107c478bd9Sstevel@tonic-gate di_node_t node; 17117c478bd9Sstevel@tonic-gate struct walk_arg warg; 17127c478bd9Sstevel@tonic-gate 17137c478bd9Sstevel@tonic-gate warg.instance = instance; 17147c478bd9Sstevel@tonic-gate (void) strncpy(warg.name, name, MAXPATHLEN); 17157c478bd9Sstevel@tonic-gate warg.path = path; 17167c478bd9Sstevel@tonic-gate warg.pathlen = pathlen; 17177c478bd9Sstevel@tonic-gate if ((node = di_init("/", DINFOSUBTREE)) == DI_NODE_NIL) 17187c478bd9Sstevel@tonic-gate return (-1); 17197c478bd9Sstevel@tonic-gate if (di_walk_node(node, DI_WALK_CLDFIRST, &warg, walk_callback) == -1) { 17207c478bd9Sstevel@tonic-gate di_fini(node); 17217c478bd9Sstevel@tonic-gate return (-1); 17227c478bd9Sstevel@tonic-gate } 17237c478bd9Sstevel@tonic-gate if (warg.path == NULL) { 17247c478bd9Sstevel@tonic-gate di_fini(node); 17257c478bd9Sstevel@tonic-gate return (-1); 17267c478bd9Sstevel@tonic-gate } 17277c478bd9Sstevel@tonic-gate di_fini(node); 17287c478bd9Sstevel@tonic-gate return (0); 17297c478bd9Sstevel@tonic-gate } 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate /* 17327c478bd9Sstevel@tonic-gate * Record logsize h/w accesses of type 'edp->access_type' made by instance 17337c478bd9Sstevel@tonic-gate * 'edp->instance' of driver 'edp->name' to the register set (or dma handle) 17347c478bd9Sstevel@tonic-gate * 'edp->rnumber' that lie within the range 'edp->offset' to 17357c478bd9Sstevel@tonic-gate * 'edp->offset' + 'edp->len'. 17367c478bd9Sstevel@tonic-gate * Access criteria may be mixed and matched: 17377c478bd9Sstevel@tonic-gate * - access types may be combined (PIO read/write, DMA read write or intrs); 17387c478bd9Sstevel@tonic-gate * - if 'edp->instance' is -1 all instances are checked for the criteria; 17397c478bd9Sstevel@tonic-gate * - if 'edp->rnumber' is -1 all register sets and dma handles are matched; 17407c478bd9Sstevel@tonic-gate * - 'offset' and 'len' indicate that only PIO and DMA accesses within the 17417c478bd9Sstevel@tonic-gate * range 'edp->offset' to 'edp->len' will be logged. Putting 'edp->offset' 17427c478bd9Sstevel@tonic-gate * to zero and 'edp->len' to -1ull gives maximal coverage. 17437c478bd9Sstevel@tonic-gate * 17447c478bd9Sstevel@tonic-gate * 'collecttime' is the number of seconds used to log accesses 17457c478bd9Sstevel@tonic-gate * (default is infinity). 17467c478bd9Sstevel@tonic-gate */ 17477c478bd9Sstevel@tonic-gate static void 17487c478bd9Sstevel@tonic-gate test_driver(struct bofi_errdef *edp, 17497c478bd9Sstevel@tonic-gate unsigned long long collecttime) 17507c478bd9Sstevel@tonic-gate { 17517c478bd9Sstevel@tonic-gate pid_t pid; 17527c478bd9Sstevel@tonic-gate int statloc; 17537c478bd9Sstevel@tonic-gate struct collector_def *cdefs, *cdp; 17547c478bd9Sstevel@tonic-gate struct handle_info *hdls, *hdl; 17557c478bd9Sstevel@tonic-gate int i, fd; 17567c478bd9Sstevel@tonic-gate size_t cnt; 17577c478bd9Sstevel@tonic-gate size_t nchildren; 17587c478bd9Sstevel@tonic-gate unsigned long long timechunk; 17597c478bd9Sstevel@tonic-gate FILE *sfp; /* generated control test file */ 17607c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 17617c478bd9Sstevel@tonic-gate char devpath[MAXPATHLEN]; 17627c478bd9Sstevel@tonic-gate char *devpathp = "NULL"; 17637c478bd9Sstevel@tonic-gate int drv_inst; 17647c478bd9Sstevel@tonic-gate int got_it = 0; 17657c478bd9Sstevel@tonic-gate 17667c478bd9Sstevel@tonic-gate char *name = (char *)edp->name; 17677c478bd9Sstevel@tonic-gate uint_t logsize = edp->access_count + edp->fail_count - 1; 17687c478bd9Sstevel@tonic-gate int inst = edp->instance; 17697c478bd9Sstevel@tonic-gate uint_t atype = edp->access_type; 17707c478bd9Sstevel@tonic-gate int rset = edp->rnumber; 17717c478bd9Sstevel@tonic-gate offset_t offset = edp->offset; 17727c478bd9Sstevel@tonic-gate offset_t len = edp->len; 17737c478bd9Sstevel@tonic-gate 17747c478bd9Sstevel@tonic-gate msg(4, "test_driver: %s %d inst %d 0x%x rset %d %llx %llx\n", 17757c478bd9Sstevel@tonic-gate name, logsize, inst, atype, rset, offset, len); 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate drv_inst = inst; 17787c478bd9Sstevel@tonic-gate if (getpath(devpath, inst, name, MAXPATHLEN) != -1) { 17797c478bd9Sstevel@tonic-gate devpathp = devpath; 17807c478bd9Sstevel@tonic-gate got_it = 1; 17817c478bd9Sstevel@tonic-gate } 17827c478bd9Sstevel@tonic-gate if (logsize == -1U) 17837c478bd9Sstevel@tonic-gate logsize = 0; 17847c478bd9Sstevel@tonic-gate fd = open(BOFI_DEV, O_RDWR); 17857c478bd9Sstevel@tonic-gate if (fd == -1) { 17867c478bd9Sstevel@tonic-gate perror("get_hdl_info - bad open of bofi driver"); 17877c478bd9Sstevel@tonic-gate return; 17887c478bd9Sstevel@tonic-gate } 17897c478bd9Sstevel@tonic-gate if (got_it) { 17907c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 17917c478bd9Sstevel@tonic-gate "th_manage /devices%s offline", devpathp); 17927c478bd9Sstevel@tonic-gate (void) system(buf); 17937c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 17947c478bd9Sstevel@tonic-gate "th_manage /devices%s online", devpathp); 17957c478bd9Sstevel@tonic-gate (void) system(buf); 17967c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 17977c478bd9Sstevel@tonic-gate "th_manage /devices%s getstate >/dev/null", devpathp); 17987c478bd9Sstevel@tonic-gate (void) system(buf); 17997c478bd9Sstevel@tonic-gate } 18007c478bd9Sstevel@tonic-gate if (get_hinfo(fd, name, &hdls, &cnt, 18017c478bd9Sstevel@tonic-gate inst, atype, rset, offset, len, 1) != 0) { 18027c478bd9Sstevel@tonic-gate msg(0, "driver_test: bad get_info for %d hdls\n", cnt); 18037c478bd9Sstevel@tonic-gate return; 18047c478bd9Sstevel@tonic-gate } else if (logsize == 0 || collecttime == 0 || cnt == 0) { 18057c478bd9Sstevel@tonic-gate if (cnt == 0) 18067c478bd9Sstevel@tonic-gate msg(1, "No matching handles.\n"); 18077c478bd9Sstevel@tonic-gate return; 18087c478bd9Sstevel@tonic-gate } 18097c478bd9Sstevel@tonic-gate if ((cdefs = GETSTRUCT(struct collector_def, cnt)) == 0) { 18107c478bd9Sstevel@tonic-gate msg(0, "driver_test: can't get memory for %d cdefs\n", cnt); 18117c478bd9Sstevel@tonic-gate return; 18127c478bd9Sstevel@tonic-gate } 18137c478bd9Sstevel@tonic-gate up_resources(); 18147c478bd9Sstevel@tonic-gate if (got_it) { 18157c478bd9Sstevel@tonic-gate if (scriptargs > 0) { 18167c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 18177c478bd9Sstevel@tonic-gate "DRIVER_PATH=/devices%s DRIVER_INSTANCE=%d" 18187c478bd9Sstevel@tonic-gate " DRIVER_UNCONFIGURE=0 DRIVER_CONFIGURE=1", 18197c478bd9Sstevel@tonic-gate devpathp, drv_inst); 18207c478bd9Sstevel@tonic-gate for (i = 0; i < scriptargs; i++) { 18217c478bd9Sstevel@tonic-gate (void) strcat(buf, " "); 18227c478bd9Sstevel@tonic-gate (void) strcat(buf, fixup_script[i]); 18237c478bd9Sstevel@tonic-gate } 18247c478bd9Sstevel@tonic-gate (void) strcat(buf, " &"); 18257c478bd9Sstevel@tonic-gate } else { 18267c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 18277c478bd9Sstevel@tonic-gate "while : ; do th_manage /devices%s online;" 18287c478bd9Sstevel@tonic-gate " th_manage /devices%s getstate >/dev/null;" 18297c478bd9Sstevel@tonic-gate " th_manage /devices%s offline;done &" 18307c478bd9Sstevel@tonic-gate " echo $! >/tmp/bofi.pid", 18317c478bd9Sstevel@tonic-gate devpathp, devpathp, devpathp); 18327c478bd9Sstevel@tonic-gate } 18337c478bd9Sstevel@tonic-gate (void) system(buf); 18347c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "sleep %d", 18357c478bd9Sstevel@tonic-gate edef_sleep ? edef_sleep : DEFAULT_EDEF_SLEEP); 18367c478bd9Sstevel@tonic-gate (void) system(buf); 18377c478bd9Sstevel@tonic-gate } 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate (void) fprintf(outfile, 18407c478bd9Sstevel@tonic-gate "Logging accesses to instances "); 18417c478bd9Sstevel@tonic-gate for (i = 0, inst = -1, hdl = hdls; i < cnt; 18427c478bd9Sstevel@tonic-gate i++, hdl++) { 18437c478bd9Sstevel@tonic-gate if (inst != hdl->instance) { 18447c478bd9Sstevel@tonic-gate inst = hdl->instance; 18457c478bd9Sstevel@tonic-gate (void) fprintf(outfile, "%d ", inst); 18467c478bd9Sstevel@tonic-gate } 18477c478bd9Sstevel@tonic-gate } 18487c478bd9Sstevel@tonic-gate (void) fprintf(outfile, " (%d logs of size 0x%x).\n\t" 18497c478bd9Sstevel@tonic-gate "(Use th_manage ... clear_errdefs to terminate" 18507c478bd9Sstevel@tonic-gate " logging)\n", cnt, logsize); 18517c478bd9Sstevel@tonic-gate 18527c478bd9Sstevel@tonic-gate sfp = create_test_file(name); 18537c478bd9Sstevel@tonic-gate /* 18547c478bd9Sstevel@tonic-gate * Install a logging errdef for each matching handle, 18557c478bd9Sstevel@tonic-gate * and then create a child to collect the log. 18567c478bd9Sstevel@tonic-gate * The child is responsible for activating the log. 18577c478bd9Sstevel@tonic-gate */ 18587c478bd9Sstevel@tonic-gate for (i = 0, cdp = cdefs, hdl = hdls, nchildren = 0; 18597c478bd9Sstevel@tonic-gate i < cnt; i++, cdp++, hdl++) { 18607c478bd9Sstevel@tonic-gate if (add_edef(fd, &cdp->ed, &cdp->es, hdl, edp) != 0) { 18617c478bd9Sstevel@tonic-gate cdp->lp = 0; 18627c478bd9Sstevel@tonic-gate cdp->pid = 0; 18637c478bd9Sstevel@tonic-gate } else { 18647c478bd9Sstevel@tonic-gate cdp->lp = (void *)cdp->ed.log.logbase; 18657c478bd9Sstevel@tonic-gate msg(1, "test_driver: thr_create:" 18667c478bd9Sstevel@tonic-gate " lsize 0x%x 0x%x at 0x%x\n", 18677c478bd9Sstevel@tonic-gate cdp->es.log.logsize, 18687c478bd9Sstevel@tonic-gate cdp->ed.log.logsize, 18697c478bd9Sstevel@tonic-gate cdp->ed.access_type); 18707c478bd9Sstevel@tonic-gate if ((pid = fork()) == -1) { 18717c478bd9Sstevel@tonic-gate msg(0, "fork failed for handle" 18727c478bd9Sstevel@tonic-gate " %d: %s\n", i, strerror(errno)); 18737c478bd9Sstevel@tonic-gate cdp->pid = 0; /* ignore */ 18747c478bd9Sstevel@tonic-gate } else if (pid == 0) { 18757c478bd9Sstevel@tonic-gate thr_collect(cdp, devpathp); 18767c478bd9Sstevel@tonic-gate } else { 18777c478bd9Sstevel@tonic-gate cdp->pid = pid; 18787c478bd9Sstevel@tonic-gate nchildren += 1; 18797c478bd9Sstevel@tonic-gate } 18807c478bd9Sstevel@tonic-gate } 18817c478bd9Sstevel@tonic-gate } 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate if (nchildren != 0) { 18847c478bd9Sstevel@tonic-gate if (sfp) { 18857c478bd9Sstevel@tonic-gate (void) fprintf(sfp, "#!/bin/ksh -p\n\n"); 18867c478bd9Sstevel@tonic-gate (void) fprintf(sfp, 18877c478bd9Sstevel@tonic-gate "\n# Test control script generated using:\n#"); 18887c478bd9Sstevel@tonic-gate for (i = 0; i < pargc; i++) 18897c478bd9Sstevel@tonic-gate (void) fprintf(sfp, " %s", pargv[i]); 18907c478bd9Sstevel@tonic-gate (void) fprintf(sfp, "\n\n"); 18917c478bd9Sstevel@tonic-gate (void) fprintf(sfp, "\nrun_tests()\n{\n"); 18927c478bd9Sstevel@tonic-gate for (i = 0, cdp = cdefs; i < cnt; i++, cdp++) 18937c478bd9Sstevel@tonic-gate if (cdp->pid) { 18947c478bd9Sstevel@tonic-gate (void) fprintf(sfp, 18957c478bd9Sstevel@tonic-gate "\tif [ -x ./%s.%d ]\n\tthen\n", 18967c478bd9Sstevel@tonic-gate name, (int)cdp->pid); 18977c478bd9Sstevel@tonic-gate (void) fprintf(sfp, 18987c478bd9Sstevel@tonic-gate "\t\techo \"Starting test" 18997c478bd9Sstevel@tonic-gate " %d (id %d)\"\n", 19007c478bd9Sstevel@tonic-gate i, (int)cdp->pid); 19017c478bd9Sstevel@tonic-gate (void) fprintf(sfp, "\t\t./%s.%d\n", 19027c478bd9Sstevel@tonic-gate name, (int)cdp->pid); 19037c478bd9Sstevel@tonic-gate (void) fprintf(sfp, "\t\techo \"" 19047c478bd9Sstevel@tonic-gate "Test %d (id %d) complete\"\n", 19057c478bd9Sstevel@tonic-gate i, (int)cdp->pid); 19067c478bd9Sstevel@tonic-gate (void) fprintf(sfp, "\tfi\n"); 19077c478bd9Sstevel@tonic-gate } 19087c478bd9Sstevel@tonic-gate (void) fprintf(sfp, "}\n\nrun_tests\n"); 19097c478bd9Sstevel@tonic-gate if (fchmod(fileno(sfp), S_IRWXU|S_IRGRP|S_IROTH)) 19107c478bd9Sstevel@tonic-gate msg(0, "fchmod on control script failed: %s\n", 19117c478bd9Sstevel@tonic-gate strerror(errno)); 19127c478bd9Sstevel@tonic-gate if (fclose(sfp) != 0) 19137c478bd9Sstevel@tonic-gate msg(0, "Error closing control script: %s\n", 19147c478bd9Sstevel@tonic-gate strerror(errno)); 19157c478bd9Sstevel@tonic-gate } 19167c478bd9Sstevel@tonic-gate 19177c478bd9Sstevel@tonic-gate set_handler(SIGALRM); /* handle it */ 19187c478bd9Sstevel@tonic-gate /* 19197c478bd9Sstevel@tonic-gate * The user may want to terminate logging before the log fills 19207c478bd9Sstevel@tonic-gate * so use a timer to signal the logging children to handle this 19217c478bd9Sstevel@tonic-gate * case. 19227c478bd9Sstevel@tonic-gate */ 19237c478bd9Sstevel@tonic-gate timechunk = collecttime / MAXALRMCALL; 19247c478bd9Sstevel@tonic-gate collecttime = collecttime - timechunk * MAXALRMCALL; 19257c478bd9Sstevel@tonic-gate 19267c478bd9Sstevel@tonic-gate msg(2, "logging for (0x%llx 0x%llx)\n", timechunk, collecttime); 19277c478bd9Sstevel@tonic-gate 19287c478bd9Sstevel@tonic-gate (void) alarm(collecttime); /* odd bit of collect time */ 19297c478bd9Sstevel@tonic-gate 19307c478bd9Sstevel@tonic-gate /* wait for the log to fill or deadline satisfied */ 19317c478bd9Sstevel@tonic-gate for (;;) { 19327c478bd9Sstevel@tonic-gate pid = wait(&statloc); 19337c478bd9Sstevel@tonic-gate for (i = 0, nchildren = 0, cdp = cdefs; 19347c478bd9Sstevel@tonic-gate i < cnt; i++, cdp++) 19357c478bd9Sstevel@tonic-gate if (cdp->pid == pid) 19367c478bd9Sstevel@tonic-gate cdp->pid = 0; 19377c478bd9Sstevel@tonic-gate for (i = 0, nchildren = 0, cdp = cdefs; 19387c478bd9Sstevel@tonic-gate i < cnt; i++, cdp++) 19397c478bd9Sstevel@tonic-gate if (cdp->pid) 19407c478bd9Sstevel@tonic-gate nchildren++; 19417c478bd9Sstevel@tonic-gate if (nchildren == 0) 19427c478bd9Sstevel@tonic-gate break; 19437c478bd9Sstevel@tonic-gate if (killed) 19447c478bd9Sstevel@tonic-gate break; 19457c478bd9Sstevel@tonic-gate if (alarmed) { 19467c478bd9Sstevel@tonic-gate if (timechunk-- > 0) { 19477c478bd9Sstevel@tonic-gate /* 19487c478bd9Sstevel@tonic-gate * prepare for the next timeslice by 19497c478bd9Sstevel@tonic-gate * rearming the clock 19507c478bd9Sstevel@tonic-gate */ 19517c478bd9Sstevel@tonic-gate if (alarm(MAXALRMCALL) == 0) 19527c478bd9Sstevel@tonic-gate alarmed = 0; 19537c478bd9Sstevel@tonic-gate else { 19547c478bd9Sstevel@tonic-gate /* 19557c478bd9Sstevel@tonic-gate * must have been a user abort 19567c478bd9Sstevel@tonic-gate * (via SIGALRM) 19577c478bd9Sstevel@tonic-gate */ 19587c478bd9Sstevel@tonic-gate (void) alarm(0); 19597c478bd9Sstevel@tonic-gate break; 19607c478bd9Sstevel@tonic-gate } 19617c478bd9Sstevel@tonic-gate } else 19627c478bd9Sstevel@tonic-gate break; 19637c478bd9Sstevel@tonic-gate } 19647c478bd9Sstevel@tonic-gate } 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate (void) fprintf(outfile, "Logging complete.\n"); 19677c478bd9Sstevel@tonic-gate } 19687c478bd9Sstevel@tonic-gate if (got_it) { 19697c478bd9Sstevel@tonic-gate if (scriptargs > 0) { 19707c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 19717c478bd9Sstevel@tonic-gate "DRIVER_PATH=/devices%s DRIVER_INSTANCE=%d" 19727c478bd9Sstevel@tonic-gate " DRIVER_UNCONFIGURE=1 DRIVER_CONFIGURE=0", 19737c478bd9Sstevel@tonic-gate devpathp, drv_inst); 19747c478bd9Sstevel@tonic-gate for (i = 0; i < scriptargs; i++) { 19757c478bd9Sstevel@tonic-gate (void) strcat(buf, " "); 19767c478bd9Sstevel@tonic-gate (void) strcat(buf, fixup_script[i]); 19777c478bd9Sstevel@tonic-gate } 19787c478bd9Sstevel@tonic-gate (void) system(buf); 19797c478bd9Sstevel@tonic-gate } else { 19807c478bd9Sstevel@tonic-gate (void) system("kill `cat /tmp/bofi.pid`"); 19817c478bd9Sstevel@tonic-gate } 19827c478bd9Sstevel@tonic-gate } 19837c478bd9Sstevel@tonic-gate msg(2, "test_driver: terminating\n"); 19847c478bd9Sstevel@tonic-gate } 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate static int 19877c478bd9Sstevel@tonic-gate getnameinst(char *orig_path, int *instance, char *name, int namelen) 19887c478bd9Sstevel@tonic-gate { 19897c478bd9Sstevel@tonic-gate di_node_t node; 19907c478bd9Sstevel@tonic-gate char *binding_name; 19917c478bd9Sstevel@tonic-gate 19927c478bd9Sstevel@tonic-gate if ((node = di_init(&orig_path[8], DINFOSUBTREE|DINFOMINOR)) == 19937c478bd9Sstevel@tonic-gate DI_NODE_NIL) 19947c478bd9Sstevel@tonic-gate return (-1); 19957c478bd9Sstevel@tonic-gate if ((binding_name = di_driver_name(node)) == NULL) 19967c478bd9Sstevel@tonic-gate return (-1); 19977c478bd9Sstevel@tonic-gate *instance = di_instance(node); 19987c478bd9Sstevel@tonic-gate (void) strncpy(name, binding_name, namelen); 19997c478bd9Sstevel@tonic-gate di_fini(node); 20007c478bd9Sstevel@tonic-gate return (0); 20017c478bd9Sstevel@tonic-gate } 20027c478bd9Sstevel@tonic-gate 20037c478bd9Sstevel@tonic-gate static char syntax[] = 20047c478bd9Sstevel@tonic-gate " [ -n name [ -i instance ] | -P path ]\n" 20057c478bd9Sstevel@tonic-gate " [ -a acc_types ] [ -r rnumber ]\n" 20067c478bd9Sstevel@tonic-gate " [ -l offset [ length ] ] [ -c count [ failcount ] ]\n" 20077c478bd9Sstevel@tonic-gate " [ -o operator [ operand ] ] [ -f acc_chk ]\n" 20087c478bd9Sstevel@tonic-gate " [ -w max_wait_period [ report_interval ] ]\n" 20097c478bd9Sstevel@tonic-gate " or\n" 20107c478bd9Sstevel@tonic-gate " [ -n name [ -i instance ] | -P path ]\n" 20117c478bd9Sstevel@tonic-gate " -a LOG [ acc_types ] [ -r rnumber]\n" 20127c478bd9Sstevel@tonic-gate " [ -l offset [ length ] ] [ -c count [ failcount ] ]\n" 20137c478bd9Sstevel@tonic-gate " [ -s collect_time ] [ -p policy ] [ -x flags ]\n" 20147c478bd9Sstevel@tonic-gate " [ -C ] [-e fixup_script ]\n" 20157c478bd9Sstevel@tonic-gate " or\n" 20167c478bd9Sstevel@tonic-gate " -h"; 20177c478bd9Sstevel@tonic-gate 20187c478bd9Sstevel@tonic-gate int 20197c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 20207c478bd9Sstevel@tonic-gate { 20217c478bd9Sstevel@tonic-gate extern char *optarg; 20227c478bd9Sstevel@tonic-gate extern int optind; 20237c478bd9Sstevel@tonic-gate 20247c478bd9Sstevel@tonic-gate char c; /* for parsing getopts */ 20257c478bd9Sstevel@tonic-gate int nopts = 0; /* for backward compatibility */ 20267c478bd9Sstevel@tonic-gate int err = 0; 20277c478bd9Sstevel@tonic-gate 20287c478bd9Sstevel@tonic-gate /* use a maximal set of defaults for logging or injecting */ 20297c478bd9Sstevel@tonic-gate struct bofi_errdef errdef = { 20307c478bd9Sstevel@tonic-gate 0, /* length of driver name */ 20317c478bd9Sstevel@tonic-gate {0}, /* driver name */ 20327c478bd9Sstevel@tonic-gate -1, /* monitor all instances */ 20337c478bd9Sstevel@tonic-gate -1, /* monitor all register sets and DMA handles */ 20347c478bd9Sstevel@tonic-gate (offset_t)0, /* monitor from start of reg. set or DMA hd */ 20357c478bd9Sstevel@tonic-gate myLLMAX, /* monitor whole reg set or DMA hdl(no LLMAX) */ 20367c478bd9Sstevel@tonic-gate 0, /* qualify all */ 20377c478bd9Sstevel@tonic-gate DFLTLOGSZ, /* default no. of accesses before corrupting */ 20387c478bd9Sstevel@tonic-gate 0u, /* default no. of accesses to corrupt */ 20397c478bd9Sstevel@tonic-gate 0u, /* no check access corruption */ 20407c478bd9Sstevel@tonic-gate BOFI_NOP, /* no corruption operator by default */ 20417c478bd9Sstevel@tonic-gate myULLMAX, /* default operand */ 20427c478bd9Sstevel@tonic-gate {0, 0, BOFI_LOG_TIMESTAMP, /* timestamp by default */ 20437c478bd9Sstevel@tonic-gate 0, 0, 0, 0}, /* no logging by default */ 20447c478bd9Sstevel@tonic-gate 0}; 20457c478bd9Sstevel@tonic-gate 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate /* specify the default no of seconds for which to monitor */ 20487c478bd9Sstevel@tonic-gate unsigned long long collecttime = DFLTLOGTIME; 20497c478bd9Sstevel@tonic-gate 20507c478bd9Sstevel@tonic-gate char *str; /* temporary variable */ 20517c478bd9Sstevel@tonic-gate long tmpl; /* another one */ 20527c478bd9Sstevel@tonic-gate int i; 20537c478bd9Sstevel@tonic-gate uint_t tmpui; 20547c478bd9Sstevel@tonic-gate 20557c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate Progname = (char *)strrchr(*argv, '/'); 20587c478bd9Sstevel@tonic-gate Progname = (Progname == NULL) ? *argv : Progname + 1; 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate errfile = stderr; 20617c478bd9Sstevel@tonic-gate outfile = stdout; 20627c478bd9Sstevel@tonic-gate policy = 0; 20637c478bd9Sstevel@tonic-gate lsize_is_default = 1; 20647c478bd9Sstevel@tonic-gate pargv = argv; 20657c478bd9Sstevel@tonic-gate pargc = argc; 20667c478bd9Sstevel@tonic-gate 20677c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "a:c:C:dD:e:f:h:i:l:n:o:p:P:r:s:tw:x")) 20687c478bd9Sstevel@tonic-gate != EOF) { 20697c478bd9Sstevel@tonic-gate nopts++; 20707c478bd9Sstevel@tonic-gate switch (c) { 20717c478bd9Sstevel@tonic-gate case 'a': 20727c478bd9Sstevel@tonic-gate msg(2, "option a: optarg %s optind %d argc %d\n", 20737c478bd9Sstevel@tonic-gate optarg, optind, argc); 20747c478bd9Sstevel@tonic-gate if ((err = str_to_bm(optarg, atypes, 20757c478bd9Sstevel@tonic-gate &errdef.access_type)) == 0) 20767c478bd9Sstevel@tonic-gate while (optind < argc && *argv[optind] != '-') { 20777c478bd9Sstevel@tonic-gate if ((err = str_to_bm(argv[optind++], 20787c478bd9Sstevel@tonic-gate atypes, &errdef.access_type))) 20797c478bd9Sstevel@tonic-gate break; 20807c478bd9Sstevel@tonic-gate } 20817c478bd9Sstevel@tonic-gate break; 20827c478bd9Sstevel@tonic-gate case 'c': 20837c478bd9Sstevel@tonic-gate lsize_is_default = 0; 20847c478bd9Sstevel@tonic-gate /* zero is valid */ 20857c478bd9Sstevel@tonic-gate errdef.access_count = strtoul(optarg, &str, 0); 20867c478bd9Sstevel@tonic-gate if (str == optarg) 20877c478bd9Sstevel@tonic-gate err = EINVAL; 20887c478bd9Sstevel@tonic-gate else if (optind < argc && (argv[optind][0] != '-' || 20897c478bd9Sstevel@tonic-gate (strlen(argv[optind]) > 1 && 20907c478bd9Sstevel@tonic-gate isdigit(argv[optind][1])))) 20917c478bd9Sstevel@tonic-gate errdef.fail_count = 20927c478bd9Sstevel@tonic-gate strtoull(argv[optind++], 0, 0); 20937c478bd9Sstevel@tonic-gate break; 20947c478bd9Sstevel@tonic-gate case 'C': 20957c478bd9Sstevel@tonic-gate user_comment = optarg; 20967c478bd9Sstevel@tonic-gate if (optind < argc && argv[optind][0] != '-') 20977c478bd9Sstevel@tonic-gate err = EINVAL; 20987c478bd9Sstevel@tonic-gate break; 20997c478bd9Sstevel@tonic-gate case 'D': 21007c478bd9Sstevel@tonic-gate dbglvl = strtoul(optarg, &str, 0); 21017c478bd9Sstevel@tonic-gate break; 21027c478bd9Sstevel@tonic-gate case 'e': 21037c478bd9Sstevel@tonic-gate fixup_script = 0; 21047c478bd9Sstevel@tonic-gate scriptargs = 0; 21057c478bd9Sstevel@tonic-gate fixup_script = &argv[optind - 1]; 21067c478bd9Sstevel@tonic-gate scriptargs += 1; 21077c478bd9Sstevel@tonic-gate while (optind < argc) { 21087c478bd9Sstevel@tonic-gate optind += 1; 21097c478bd9Sstevel@tonic-gate scriptargs += 1; 21107c478bd9Sstevel@tonic-gate } 21117c478bd9Sstevel@tonic-gate break; 21127c478bd9Sstevel@tonic-gate case 'f': 21137c478bd9Sstevel@tonic-gate tmpl = strtol(optarg, &str, 0); 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate if (str != optarg) 21167c478bd9Sstevel@tonic-gate errdef.acc_chk = tmpl; 21177c478bd9Sstevel@tonic-gate else if (strcmp(optarg, "PIO") == NULL) 21187c478bd9Sstevel@tonic-gate errdef.acc_chk = 1; 21197c478bd9Sstevel@tonic-gate else if (strcmp(optarg, "DMA") == NULL) 21207c478bd9Sstevel@tonic-gate errdef.acc_chk = 2; 21217c478bd9Sstevel@tonic-gate else if (strcmp(optarg, "U4FT_ACC_NO_PIO") == NULL) 21227c478bd9Sstevel@tonic-gate errdef.acc_chk = 1; 21237c478bd9Sstevel@tonic-gate else if (strcmp(optarg, "U4FT_ACC_NO_DMA") == NULL) 21247c478bd9Sstevel@tonic-gate errdef.acc_chk = 2; 21257c478bd9Sstevel@tonic-gate else 21267c478bd9Sstevel@tonic-gate err = EINVAL; 21277c478bd9Sstevel@tonic-gate break; 21287c478bd9Sstevel@tonic-gate case 'i': 21297c478bd9Sstevel@tonic-gate if ((errdef.instance = strtol(optarg, &str, 0)) < 0) 21307c478bd9Sstevel@tonic-gate errdef.instance = -1; 21317c478bd9Sstevel@tonic-gate else if (str == optarg) 21327c478bd9Sstevel@tonic-gate err = EINVAL; 21337c478bd9Sstevel@tonic-gate break; 21347c478bd9Sstevel@tonic-gate case 'l': 21357c478bd9Sstevel@tonic-gate errdef.offset = strtoull(optarg, &str, 0); 21367c478bd9Sstevel@tonic-gate if (str == optarg) 21377c478bd9Sstevel@tonic-gate err = EINVAL; 21387c478bd9Sstevel@tonic-gate else if (optind < argc && 21397c478bd9Sstevel@tonic-gate (argv[optind][0] != '-' || 21407c478bd9Sstevel@tonic-gate (strlen(argv[optind]) > 1 && 21417c478bd9Sstevel@tonic-gate isdigit(argv[optind][1])))) { 21427c478bd9Sstevel@tonic-gate /* -1 indicates the rest of register set */ 21437c478bd9Sstevel@tonic-gate errdef.len = strtoull(argv[optind++], 0, 0); 21447c478bd9Sstevel@tonic-gate } 21457c478bd9Sstevel@tonic-gate break; 21467c478bd9Sstevel@tonic-gate case 'n': 21477c478bd9Sstevel@tonic-gate (void) strncpy(errdef.name, optarg, MAXNAMELEN); 21487c478bd9Sstevel@tonic-gate if ((errdef.namesize = strlen(errdef.name)) == 0) 21497c478bd9Sstevel@tonic-gate err = EINVAL; 21507c478bd9Sstevel@tonic-gate break; 21517c478bd9Sstevel@tonic-gate case 'o': 21527c478bd9Sstevel@tonic-gate for (i = 0; optypes[i].str != 0; i++) 21537c478bd9Sstevel@tonic-gate if (strcmp(optarg, optypes[i].str) == 0) { 21547c478bd9Sstevel@tonic-gate errdef.optype = optypes[i].code; 21557c478bd9Sstevel@tonic-gate break; 21567c478bd9Sstevel@tonic-gate } 21577c478bd9Sstevel@tonic-gate if (optypes[i].str == 0) 21587c478bd9Sstevel@tonic-gate err = EINVAL; 21597c478bd9Sstevel@tonic-gate else if (optind < argc && 21607c478bd9Sstevel@tonic-gate (argv[optind][0] != '-' || 21617c478bd9Sstevel@tonic-gate (strlen(argv[optind]) > 1 && 21627c478bd9Sstevel@tonic-gate isdigit(argv[optind][1])))) 21637c478bd9Sstevel@tonic-gate errdef.operand = 21647c478bd9Sstevel@tonic-gate strtoull(argv[optind++], 0, 0); 21657c478bd9Sstevel@tonic-gate break; 21667c478bd9Sstevel@tonic-gate case 'p': 21677c478bd9Sstevel@tonic-gate tmpui = 0x0u; 21687c478bd9Sstevel@tonic-gate if ((err = str_to_bm(optarg, ptypes, &tmpui)) == 0) { 21697c478bd9Sstevel@tonic-gate while (optind < argc && *argv[optind] != '-') 21707c478bd9Sstevel@tonic-gate if ((err = str_to_bm(argv[optind++], 21717c478bd9Sstevel@tonic-gate ptypes, &tmpui))) 21727c478bd9Sstevel@tonic-gate break; 21737c478bd9Sstevel@tonic-gate policy = (uint16_t)tmpui; 21747c478bd9Sstevel@tonic-gate } 21757c478bd9Sstevel@tonic-gate if (err == 0 && (policy & BYTEPOLICY)) 21767c478bd9Sstevel@tonic-gate errdef.log.flags |= BOFI_LOG_REPIO; 21777c478bd9Sstevel@tonic-gate break; 21787c478bd9Sstevel@tonic-gate case 'P': 21797c478bd9Sstevel@tonic-gate if (getnameinst(optarg, &errdef.instance, buf, 21807c478bd9Sstevel@tonic-gate MAXPATHLEN) == -1) 21817c478bd9Sstevel@tonic-gate err = EINVAL; 21827c478bd9Sstevel@tonic-gate else 21837c478bd9Sstevel@tonic-gate (void) strncpy(errdef.name, buf, MAXNAMELEN); 21847c478bd9Sstevel@tonic-gate break; 21857c478bd9Sstevel@tonic-gate case 'r': 21867c478bd9Sstevel@tonic-gate if ((errdef.rnumber = strtol(optarg, &str, 0)) < 0) 21877c478bd9Sstevel@tonic-gate errdef.rnumber = -1; 21887c478bd9Sstevel@tonic-gate if (str == optarg) err = EINVAL; 21897c478bd9Sstevel@tonic-gate break; 21907c478bd9Sstevel@tonic-gate case 's': 21917c478bd9Sstevel@tonic-gate collecttime = strtoull(optarg, &str, 0); 21927c478bd9Sstevel@tonic-gate if (str == optarg) 21937c478bd9Sstevel@tonic-gate err = EINVAL; /* zero is valid */ 21947c478bd9Sstevel@tonic-gate break; 21957c478bd9Sstevel@tonic-gate case 'w': 21967c478bd9Sstevel@tonic-gate do_status = 1; 21977c478bd9Sstevel@tonic-gate max_edef_wait = strtoul(optarg, &str, 0); 21987c478bd9Sstevel@tonic-gate /* zero is valid */ 21997c478bd9Sstevel@tonic-gate if (str == optarg) 22007c478bd9Sstevel@tonic-gate err = EINVAL; 22017c478bd9Sstevel@tonic-gate else if (optind < argc && 22027c478bd9Sstevel@tonic-gate (argv[optind][0] != '-' || 22037c478bd9Sstevel@tonic-gate (strlen(argv[optind]) > 1 && 22047c478bd9Sstevel@tonic-gate isdigit(argv[optind][1])))) 22057c478bd9Sstevel@tonic-gate edef_sleep = strtoull(argv[optind++], 0, 0); 22067c478bd9Sstevel@tonic-gate 22077c478bd9Sstevel@tonic-gate break; 22087c478bd9Sstevel@tonic-gate case 'x': 22097c478bd9Sstevel@tonic-gate if ((optind < argc && *argv[optind] == '-') || 22107c478bd9Sstevel@tonic-gate optind == argc) 22117c478bd9Sstevel@tonic-gate errdef.log.flags |= BOFI_LOG_WRAP; 22127c478bd9Sstevel@tonic-gate else { 22137c478bd9Sstevel@tonic-gate if (strchr(argv[optind], 'w') != 0) 22147c478bd9Sstevel@tonic-gate errdef.log.flags |= BOFI_LOG_WRAP; 22157c478bd9Sstevel@tonic-gate if (strchr(argv[optind], 'r') != 0) 22167c478bd9Sstevel@tonic-gate errdef.log.flags |= BOFI_LOG_REPIO; 22177c478bd9Sstevel@tonic-gate if (strchr(argv[optind], 't') != 0) 22187c478bd9Sstevel@tonic-gate errdef.log.flags |= BOFI_LOG_TIMESTAMP; 22197c478bd9Sstevel@tonic-gate if (strstr(argv[optind], "~t") != 0) 22207c478bd9Sstevel@tonic-gate errdef.log.flags &= ~BOFI_LOG_TIMESTAMP; 22217c478bd9Sstevel@tonic-gate optind++; 22227c478bd9Sstevel@tonic-gate } 22237c478bd9Sstevel@tonic-gate break; 22247c478bd9Sstevel@tonic-gate case 'h': 22257c478bd9Sstevel@tonic-gate (void) fprintf(errfile, "usage: %s %s\n", 22267c478bd9Sstevel@tonic-gate Progname, syntax); 22277c478bd9Sstevel@tonic-gate exit(0); 22287c478bd9Sstevel@tonic-gate break; 22297c478bd9Sstevel@tonic-gate case '?': /* also picks up missing parameters */ 22307c478bd9Sstevel@tonic-gate default: 22317c478bd9Sstevel@tonic-gate (void) fprintf(errfile, "usage: %s %s\n", 22327c478bd9Sstevel@tonic-gate Progname, syntax); 22337c478bd9Sstevel@tonic-gate exit(2); 22347c478bd9Sstevel@tonic-gate } 22357c478bd9Sstevel@tonic-gate 22367c478bd9Sstevel@tonic-gate if (err) { 22377c478bd9Sstevel@tonic-gate (void) fprintf(errfile, "usage: %s %s\n", 22387c478bd9Sstevel@tonic-gate Progname, syntax); 22397c478bd9Sstevel@tonic-gate exit(2); 22407c478bd9Sstevel@tonic-gate } 22417c478bd9Sstevel@tonic-gate if (c == 'e') 22427c478bd9Sstevel@tonic-gate break; /* the -e option must be the final option */ 22437c478bd9Sstevel@tonic-gate } 22447c478bd9Sstevel@tonic-gate 22457c478bd9Sstevel@tonic-gate 22467c478bd9Sstevel@tonic-gate if (errdef.name[0] == 0) { 22477c478bd9Sstevel@tonic-gate msg(0, "%s - invalid name parameter\n", Progname); 22487c478bd9Sstevel@tonic-gate exit(1); 22497c478bd9Sstevel@tonic-gate } 22507c478bd9Sstevel@tonic-gate errdef.namesize = strlen(errdef.name); 22517c478bd9Sstevel@tonic-gate 22527c478bd9Sstevel@tonic-gate if (policy == 0) { 22537c478bd9Sstevel@tonic-gate policy |= UNBIASEDPOLICY; 22547c478bd9Sstevel@tonic-gate policy |= OPERATORSPOLICY; 22557c478bd9Sstevel@tonic-gate } 22567c478bd9Sstevel@tonic-gate 22577c478bd9Sstevel@tonic-gate if (errdef.optype == BOFI_NOP) 22587c478bd9Sstevel@tonic-gate errdef.optype = BOFI_XOR; 22597c478bd9Sstevel@tonic-gate if (errdef.access_type == BOFI_LOG) { /* qualify all accesses */ 22607c478bd9Sstevel@tonic-gate errdef.access_type = 22617c478bd9Sstevel@tonic-gate (BOFI_LOG|BOFI_DMA_RW|BOFI_PIO_RW|BOFI_INTR); 22627c478bd9Sstevel@tonic-gate atype_is_default = 1; 22637c478bd9Sstevel@tonic-gate } else if (errdef.access_type == 0) { /* qualify all accesses */ 22647c478bd9Sstevel@tonic-gate errdef.access_type = 22657c478bd9Sstevel@tonic-gate (BOFI_DMA_RW|BOFI_PIO_RW|BOFI_INTR); 22667c478bd9Sstevel@tonic-gate atype_is_default = 1; 22677c478bd9Sstevel@tonic-gate } else 22687c478bd9Sstevel@tonic-gate atype_is_default = 0; 22697c478bd9Sstevel@tonic-gate 22707c478bd9Sstevel@tonic-gate init_sigs(); 22717c478bd9Sstevel@tonic-gate if ((errdef.access_type & BOFI_LOG) == 0) { 22727c478bd9Sstevel@tonic-gate int fd, i, instance; 22737c478bd9Sstevel@tonic-gate size_t cnt; 22747c478bd9Sstevel@tonic-gate struct handle_info *hdls, *hp; 22757c478bd9Sstevel@tonic-gate 22767c478bd9Sstevel@tonic-gate if ((fd = open(BOFI_DEV, O_RDWR)) == -1) { 22777c478bd9Sstevel@tonic-gate msg(0, "%s: error opening bofi driver: %s\n", 22787c478bd9Sstevel@tonic-gate Progname, strerror(errno)); 22797c478bd9Sstevel@tonic-gate exit(1); 22807c478bd9Sstevel@tonic-gate } 22817c478bd9Sstevel@tonic-gate if ((err = get_hinfo(fd, errdef.name, &hdls, &cnt, 22827c478bd9Sstevel@tonic-gate errdef.instance, errdef.access_type, errdef.rnumber, 22837c478bd9Sstevel@tonic-gate errdef.offset, errdef.len, 0)) != 0) { 22847c478bd9Sstevel@tonic-gate msg(0, "%s: Bad lookup on bofi driver.\n", Progname); 22857c478bd9Sstevel@tonic-gate (void) close(fd); 22867c478bd9Sstevel@tonic-gate exit(1); 22877c478bd9Sstevel@tonic-gate } else if (cnt == 0) { 22887c478bd9Sstevel@tonic-gate msg(0, 22897c478bd9Sstevel@tonic-gate "%s: No handles match request access criteria.\n", 22907c478bd9Sstevel@tonic-gate Progname); 22917c478bd9Sstevel@tonic-gate (void) close(fd); 22927c478bd9Sstevel@tonic-gate exit(1); 22937c478bd9Sstevel@tonic-gate } 22947c478bd9Sstevel@tonic-gate if (errdef.instance == -1) 22957c478bd9Sstevel@tonic-gate instance = -1; 22967c478bd9Sstevel@tonic-gate else { 22977c478bd9Sstevel@tonic-gate instance = hdls->instance; 22987c478bd9Sstevel@tonic-gate for (i = 0, hp = hdls; i < cnt; i++, hp++) { 22997c478bd9Sstevel@tonic-gate if (instance != hp->instance) { 23007c478bd9Sstevel@tonic-gate instance = -1; 23017c478bd9Sstevel@tonic-gate break; 23027c478bd9Sstevel@tonic-gate } 23037c478bd9Sstevel@tonic-gate } 23047c478bd9Sstevel@tonic-gate } 23057c478bd9Sstevel@tonic-gate if (instance == -1) { 23067c478bd9Sstevel@tonic-gate msg(0, "Multiple instances match access criteria" 23077c478bd9Sstevel@tonic-gate " (only allowed when logging):\n"); 23087c478bd9Sstevel@tonic-gate msg(0, "\tinst\taccess\trnumber\toffset\tlength\n"); 23097c478bd9Sstevel@tonic-gate for (i = 0, hp = hdls; i < cnt; i++, hp++) 23107c478bd9Sstevel@tonic-gate msg(0, "\t%d\t0x%x\t%d\t0x%llx\t0x%llx\n", 23117c478bd9Sstevel@tonic-gate hp->instance, hp->access_type, 23127c478bd9Sstevel@tonic-gate hp->rnumber, hp->offset, hp->len); 23137c478bd9Sstevel@tonic-gate } else { 23147c478bd9Sstevel@tonic-gate struct bofi_errstate es; 23157c478bd9Sstevel@tonic-gate int timeleft = max_edef_wait; 23167c478bd9Sstevel@tonic-gate 23177c478bd9Sstevel@tonic-gate if (ioctl(fd, BOFI_ADD_DEF, &errdef) == -1) { 23187c478bd9Sstevel@tonic-gate perror("th_define - adding errdef failed"); 23197c478bd9Sstevel@tonic-gate } else { 23207c478bd9Sstevel@tonic-gate es.errdef_handle = errdef.errdef_handle; 23217c478bd9Sstevel@tonic-gate msg(4, "waiting for edef:" 23227c478bd9Sstevel@tonic-gate " %d %s %d %d 0x%llx 0x%llx 0x%x 0x%x" 23237c478bd9Sstevel@tonic-gate " 0x%x 0x%x 0x%x 0x%llx\n", 23247c478bd9Sstevel@tonic-gate errdef.namesize, errdef.name, 23257c478bd9Sstevel@tonic-gate errdef.instance, errdef.rnumber, 23267c478bd9Sstevel@tonic-gate errdef.offset, errdef.len, 23277c478bd9Sstevel@tonic-gate errdef.access_type, errdef.access_count, 23287c478bd9Sstevel@tonic-gate errdef.fail_count, errdef.acc_chk, 23297c478bd9Sstevel@tonic-gate errdef.optype, errdef.operand); 23307c478bd9Sstevel@tonic-gate 23317c478bd9Sstevel@tonic-gate set_handler(SIGALRM); /* handle it */ 23327c478bd9Sstevel@tonic-gate 23337c478bd9Sstevel@tonic-gate do { 23347c478bd9Sstevel@tonic-gate if (do_status) 23357c478bd9Sstevel@tonic-gate (void) alarm(edef_sleep); 23367c478bd9Sstevel@tonic-gate if (ioctl(fd, BOFI_CHK_STATE_W, 23377c478bd9Sstevel@tonic-gate &es) == -1) { 23387c478bd9Sstevel@tonic-gate if (errno != EINTR) { 23397c478bd9Sstevel@tonic-gate perror("bad" 23407c478bd9Sstevel@tonic-gate " BOFI_CHK_STATE"); 23417c478bd9Sstevel@tonic-gate break; 23427c478bd9Sstevel@tonic-gate } else if (!do_status) { 23437c478bd9Sstevel@tonic-gate break; 23447c478bd9Sstevel@tonic-gate } 23457c478bd9Sstevel@tonic-gate } 23467c478bd9Sstevel@tonic-gate if (do_status) 23477c478bd9Sstevel@tonic-gate (void) fprintf(outfile, 23487c478bd9Sstevel@tonic-gate "%llu:%llu:%u:%u:%u:" 23497c478bd9Sstevel@tonic-gate "%u:%d:\"%s\"\n", 23507c478bd9Sstevel@tonic-gate es.fail_time, es.msg_time, 23517c478bd9Sstevel@tonic-gate es.access_count, 23527c478bd9Sstevel@tonic-gate es.fail_count, 23537c478bd9Sstevel@tonic-gate es.acc_chk, es.errmsg_count, 23547c478bd9Sstevel@tonic-gate (uint_t)es.severity, 23557c478bd9Sstevel@tonic-gate (es.msg_time) ? 23567c478bd9Sstevel@tonic-gate es.buffer : ""); 23577c478bd9Sstevel@tonic-gate if (es.acc_chk == 0 && 23587c478bd9Sstevel@tonic-gate es.fail_count == 0 && !do_status) 23597c478bd9Sstevel@tonic-gate print_err_reports(outfile, 23607c478bd9Sstevel@tonic-gate &es, "", "", -1); 23617c478bd9Sstevel@tonic-gate else if (alarmed) { 23627c478bd9Sstevel@tonic-gate alarmed = 0; 23637c478bd9Sstevel@tonic-gate if ((timeleft -= edef_sleep) <= 23647c478bd9Sstevel@tonic-gate 0) { 2365*e5ba14ffSstephh if (do_status) 2366*e5ba14ffSstephh break; 23677c478bd9Sstevel@tonic-gate print_err_reports( 2368*e5ba14ffSstephh outfile, &es, "", 23697c478bd9Sstevel@tonic-gate "", -1); 23707c478bd9Sstevel@tonic-gate break; 23717c478bd9Sstevel@tonic-gate } 23727c478bd9Sstevel@tonic-gate } else if (!do_status) 23737c478bd9Sstevel@tonic-gate print_err_reports(outfile, 23747c478bd9Sstevel@tonic-gate &es, "", "", -1); 23757c478bd9Sstevel@tonic-gate } while (es.acc_chk != 0 || es.fail_count != 0); 23767c478bd9Sstevel@tonic-gate 23777c478bd9Sstevel@tonic-gate msg(2, "done: acc_chk 0x%x fcnt %d\n", 23787c478bd9Sstevel@tonic-gate es.acc_chk, es.fail_count); 23797c478bd9Sstevel@tonic-gate } 23807c478bd9Sstevel@tonic-gate 23817c478bd9Sstevel@tonic-gate (void) close(fd); 23827c478bd9Sstevel@tonic-gate } 23837c478bd9Sstevel@tonic-gate free(hdls); 23847c478bd9Sstevel@tonic-gate return (0); 23857c478bd9Sstevel@tonic-gate } 23867c478bd9Sstevel@tonic-gate test_driver(&errdef, collecttime); 23877c478bd9Sstevel@tonic-gate return (0); 23887c478bd9Sstevel@tonic-gate } 2389