1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 #pragma ident "@(#)buf_init.c 1.8 09/05/26 SMI" 23 24 /* 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 /* 30 * Routines for inializing read and write buffers. 31 */ 32 #include <sys/types.h> 33 #include <sys/isa_defs.h> 34 #include <search.h> 35 #include "args.h" 36 #include "diskomizer64mpism.h" 37 #include "buf_init.h" 38 39 static uchar_t seq8(int, int); 40 static uchar_t rseq8(int, int); 41 static uchar_t seq16(int, int); 42 static uchar_t rseq16(int, int); 43 static uchar_t seq32(int, int); 44 static uchar_t rseq32(int, int); 45 static uchar_t seq64(int, int); 46 static uchar_t rseq64(int, int); 47 static uchar_t random_value(int, int); 48 static uchar_t fixed_value_func(int, int); 49 static uchar_t cjtpat_func(int, int); 50 static uchar_t isipat_func(int, int); 51 static uchar_t cjt_and_isi_func(int bufno, int i); 52 static uchar_t userpat_func(int, int); 53 54 static void rbufinit_init(uchar_t *, ulong_t len, const uchar_t * const); 55 static void zero_init(uchar_t *, ulong_t len, const uchar_t * const); 56 static void xor_init(uchar_t *, ulong_t len, const uchar_t * const); 57 static int rinit_init(uint64_t value); 58 static int cinit_init(uint64_t value); 59 static int userpat_init(struct ilist *, int *, int); 60 61 static uint64_t *read_buf_source; 62 63 static struct ilist fixed_value; 64 65 typedef int (*init_init_t)(struct ilist *, int *, int); 66 67 struct write_buf_initializers { 68 const char *name; 69 write_buf_initializer_t func; /* error handleing function */ 70 init_init_t init; 71 int val; 72 }; 73 74 typedef int (*rinit_init_t)(uint64_t); 75 76 struct read_buf_initializers { 77 const char *name; 78 read_buf_initializer_t func; 79 rinit_init_t init; 80 uint64_t val; 81 }; 82 83 struct write_buf_initializers write_buf_initializers[] = { 84 {"ONES", fixed_value_func, load_ilist, ~0}, 85 {"ZEROS", fixed_value_func, load_ilist, 0}, 86 {"SUPPLIED_VALUE", fixed_value_func, NULL, 0}, 87 {"SEQ", seq8, NULL, 0}, /* for compatability */ 88 {"RSEQ", rseq8, NULL, 0}, /* for compatability */ 89 {"SEQ8", seq8, NULL, 0}, 90 {"SREQ8", rseq8, NULL, 0}, 91 {"SEQ16", seq16, NULL, 0}, 92 {"SREQ16", rseq16, NULL, 0}, 93 {"SEQ32", seq32, NULL, 0}, 94 {"SREQ32", rseq32, NULL, 0}, 95 {"SEQ64", seq64, NULL, 0}, 96 {"SREQ64", rseq64, NULL, 0}, 97 {"RANDOM", random_value, NULL, 0}, 98 {"CJTPAT", cjtpat_func, NULL, 0}, 99 {"ISIPAT", isipat_func, NULL, 0}, 100 {"ISI_AND_CJT_PAT", cjt_and_isi_func, NULL, 0}, 101 {"USERPAT", userpat_func, userpat_init, 0} 102 }; 103 104 static size_t nel_write_buf_initializers = ARRAY_LEN(write_buf_initializers); 105 106 struct read_buf_initializers read_buf_initializers[] = { 107 {"DEADBEEF", rbufinit_init, rinit_init, 0xDEADBEEFDEADBEEFULL}, 108 {"DEADBEEF_64", rbufinit_init, rinit_init, 0xDEADBEEFULL}, 109 {"SUPPLIED_VALUE", rbufinit_init, cinit_init, 0ULL}, 110 {"ZERO", zero_init, NULL, 0ULL}, 111 {"ZERO_ONE", rbufinit_init, rinit_init, 0x5555555555555555ULL}, 112 {"ONE_ZERO", rbufinit_init, rinit_init, 0xAAAAAAAAAAAAAAAAULL}, 113 {"XOR", xor_init, NULL, 0ULL}, 114 {"NOP", (read_buf_initializer_t)nop, NULL, 0ULL}, 115 {"NONE", (read_buf_initializer_t)nop, NULL, 0ULL} 116 }; 117 118 static size_t nel_read_buf_initializers = ARRAY_LEN(read_buf_initializers); 119 120 struct { 121 uchar_t *buf; 122 size_t len; 123 } userpat_data; 124 125 /* 126 * Macro to return the correct char to give bigendian data all the time. 127 */ 128 #ifdef _BIG_ENDIAN 129 130 #define RETURN_CHAR(X, I) return (X.c[(I) % sizeof (X)]) 131 132 #elif defined(_LITTLE_ENDIAN) 133 134 #define RETURN_CHAR(X, I) return (X.c[(sizeof (X) - 1) - ((I) % sizeof (X))]) 135 136 #else 137 138 /* This "can't" happen! */ 139 #error "niether _BIG_ENDIAN or _LITTLE_ENDIAN defined" 140 141 #endif 142 143 /* 144 * Seq8(). Returns an 8 bit quantity. Each 145 * of the 8 bit quantinites are set following a standard pattern, which in 146 * its simplest would be just a sequence from 0 to 255. However since the 147 * by initialising from 0 to 250, giving 251 values, we make the combination 148 * of pattern and position of the pattern in a block not repeat for 251 149 * blocks. By then shifting each value by a variable amount between 0 and 4 150 * depending on each block we move the number of blocks before the pattern 151 * posistion pair repeats up to 1255 blocks. 152 * 153 * You end up with 5 blocks of X-Y inclusive: 154 * 155 * 0-250 156 * 1-251 157 * 2-252 158 * 3-253 159 * 4-254 160 * 161 * The final pattern you see in the data is of this form: 162 * 163 * 0-250 164 * 1-251 165 * 2-252 166 * 3-253 167 * 4-254 168 * 0-250 169 * 1-251 170 * 2-252 171 * 3-253 172 * 4-254 173 * 174 * 175 * 251 and 5 are used as 251 is the largest prime less than or equal to 176 * 256 and 5 is the largest prime that when added to to 251 gives less than 256. 177 */ 178 static uchar_t 179 seq8(int bufno, int i) 180 { 181 uchar_t x, y, c; 182 ulong_t len = INDEX_TO_DIOLEN(max_disk_io_len); 183 ulong_t bufoff = (bufno * len) + i; 184 185 x = bufoff % 251; 186 y = (bufoff / 251) % 5; 187 188 c = x + y; 189 return (c); 190 } 191 192 static uchar_t 193 rseq8(int bufno, int i) 194 { 195 return (0xff - seq8(bufno, i)); 196 } 197 /* 198 * the key primes for 16 bit numbers are 13 and 65521. Apart from 199 * that the theory is the same as for the 8 bit numbers. 200 */ 201 static uint16_t 202 seq16gen(int bufno, int i) 203 { 204 uint16_t x, y, s; 205 ulong_t len = INDEX_TO_DIOLEN(max_disk_io_len); 206 ulong_t bufoff = ((bufno * len) + i) / sizeof (uint16_t); 207 208 x = bufoff % 65521; 209 y = (bufoff / 65521) % 13; 210 211 s = x + y; 212 return (s); 213 } 214 215 static uchar_t 216 seq16(int bufno, int i) 217 { 218 union { 219 uchar_t c[sizeof (uint16_t)]; 220 uint16_t s; 221 } u; 222 223 u.s = seq16gen(bufno, i); 224 225 RETURN_CHAR(u, i); 226 } 227 228 static uchar_t 229 rseq16(int bufno, int i) 230 { 231 union { 232 uchar_t c[sizeof (uint16_t)]; 233 uint16_t s; 234 } u; 235 236 u.s = USHRT_MAX - seq16gen(bufno, i); 237 238 RETURN_CHAR(u, i); 239 } 240 241 /* 242 * For 32 bit numbers the primes are: 4294967291 and 3 243 */ 244 static uint32_t 245 seq32gen(int bufno, int i) 246 { 247 uint32_t x, y, s; 248 ulong_t len = INDEX_TO_DIOLEN(max_disk_io_len); 249 ulong_t bufoff = ((bufno * len) + i) / sizeof (uint32_t); 250 251 x = bufoff % 4294967291LL; 252 y = (bufoff / 4294967291LL) % 3; 253 254 s = x + y; 255 return (s); 256 } 257 258 static uchar_t 259 seq32(int bufno, int i) 260 { 261 union { 262 uchar_t c[sizeof (uint32_t)]; 263 uint32_t i; 264 } u; 265 266 u.i = seq32gen(bufno, i); 267 268 RETURN_CHAR(u, i); 269 } 270 271 static uchar_t 272 rseq32(int bufno, int i) 273 { 274 union { 275 uchar_t c[sizeof (uint32_t)]; 276 uint32_t i; 277 } u; 278 279 u.i = UINT_MAX - seq32gen(bufno, i); 280 281 RETURN_CHAR(u, i); 282 } 283 284 /* 285 * For 64 bit numbers we are just not going to repeat so don't 286 * do the prime bit. 287 */ 288 static uint64_t 289 seq64gen(int bufno, int i) 290 { 291 uint64_t len = INDEX_TO_DIOLEN(max_disk_io_len); 292 uint64_t bufoff = ((bufno * len) + i) / sizeof (uint64_t); 293 294 return (bufoff); 295 } 296 297 static uchar_t 298 seq64(int bufno, int i) 299 { 300 union { 301 uchar_t c[sizeof (uint64_t)]; 302 uint64_t l; 303 } u; 304 305 u.l = seq64gen(bufno, i); 306 307 RETURN_CHAR(u, i); 308 } 309 310 static uchar_t 311 rseq64(int bufno, int i) 312 { 313 union { 314 uchar_t c[sizeof (uint64_t)]; 315 uint64_t l; 316 } u; 317 318 u.l = 0xffffffffffffffffULL - seq64gen(bufno, i); 319 320 RETURN_CHAR(u, i); 321 } 322 323 /*ARGSUSED*/ 324 static uchar_t 325 random_value(int bufno, int i) 326 { 327 return ((uchar_t)(lrand48() >> 8)); 328 } 329 330 static uint_t 331 get_fixed_value(int bufno) 332 { 333 if (fixed_value.weightings == NULL) 334 return (fixed_value.vals[bufno % fixed_value.wlen]); 335 else 336 return (fixed_value.vals[fixed_value.weightings[bufno 337 % fixed_value.wlen]]); 338 } 339 340 /* 341 * Users can supply 32 bit fixed values. So this function has to give 342 * them back in the correct way. 343 */ 344 /*ARGSUSED*/ 345 static uchar_t 346 fixed_value_func(int bufno, int i) 347 { 348 union { 349 uchar_t c[sizeof (uint32_t)]; 350 uint32_t i; 351 } u; 352 353 u.i = get_fixed_value(bufno); 354 355 return (u.c[i % sizeof (uint32_t)]); 356 } 357 358 static int 359 wb_key_cmp(const void *k, const void *v) 360 { 361 return (strcasecmp((char *)k, 362 ((struct write_buf_initializers *)v)->name)); 363 } 364 365 write_buf_initializer_t 366 setup_write_buf_initializer(void) 367 { 368 struct write_buf_initializers *r; 369 370 fixed_value = opts.write_buffer_supplied_value; 371 372 r = (struct write_buf_initializers *)lfind( 373 opts.initializer, write_buf_initializers, 374 &nel_write_buf_initializers, 375 sizeof (write_buf_initializers[0]), 376 wb_key_cmp); 377 378 if (r != NULL) { 379 if (r->init != NULL) { 380 if (r->init(&fixed_value, &r->val, 1) == 0) { 381 return (NULL); 382 } 383 } 384 return (r->func); 385 } 386 return (NULL); 387 } 388 389 /*ARGSUSED2*/ 390 static void 391 zero_init(uchar_t *buf, ulong_t len, const uchar_t * const foo) 392 { 393 (void) memset(buf, NULL, len); 394 } 395 /*ARGSUSED2*/ 396 static void 397 deadbeef64_init(uchar_t *buf, ulong_t len, const uchar_t * const foo) 398 { 399 ulong_t i; 400 401 for (i = 0; i < len; i += 64) { 402 uint32_t *ptr; 403 404 /*LINTED*/ 405 ptr = (uint32_t *)(buf + i); 406 *ptr = 0xdeadbeef; 407 } 408 } 409 410 static void 411 uint32_init(uchar_t *buf, ulong_t len, uint32_t value) 412 { 413 ulong_t i; 414 415 for (i = 0; i < len; i += sizeof (uint32_t)) { 416 uint32_t *ptr; 417 418 /*LINTED*/ 419 ptr = (uint32_t *)(buf + i); 420 *ptr = value; 421 } 422 } 423 424 /*ARGSUSED2*/ 425 static void 426 rbufinit_init(uchar_t *buf, ulong_t len, const uchar_t * const foo) 427 { 428 memcpy(buf, read_buf_source, len); 429 } 430 431 static void 432 xor_init(uchar_t *buf, ulong_t len, const uchar_t * const data_written) 433 { 434 ulong_t i; 435 436 for (i = 0; i < len; i += sizeof (uint32_t)) { 437 uint32_t *to; 438 uint32_t *from; 439 440 /*LINTED*/ 441 to = (uint32_t *)(buf + i); 442 /*LINTED*/ 443 from = (uint32_t *)(data_written + i); 444 *to = 0xffffffff ^ *from; 445 } 446 } 447 448 static int 449 rb_key_cmp(const void *k, const void *v) 450 { 451 return (strcasecmp((char *)k, 452 ((struct read_buf_initializers *)v)->name)); 453 } 454 455 read_buf_initializer_t 456 setup_read_buf_initializer(void) 457 { 458 struct read_buf_initializers *r; 459 460 if ((r = (struct read_buf_initializers *)lfind( 461 opts.read_buffer_init, read_buf_initializers, 462 &nel_read_buf_initializers, 463 sizeof (read_buf_initializers[0]), rb_key_cmp)) != NULL) { 464 if (r->init != NULL) { 465 if (r->init(r->val) == 0) { 466 return (NULL); 467 } 468 } 469 return (r->func); 470 } else { 471 return (NULL); 472 } 473 } 474 475 476 static int 477 rinit_init(uint64_t value) 478 { 479 uint64_t *x; 480 int i; 481 int fd; 482 483 if ((fd = open("/dev/zero", O_RDWR)) == -1) 484 return (NULL); 485 486 x = (uint64_t *)mmap(NULL, INDEX_TO_DIOLEN(max_disk_io_len), 487 PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 488 close(fd); 489 if (x == MAP_FAILED) 490 return (NULL); 491 read_buf_source = x; 492 493 for (i = 0; i < INDEX_TO_DIOLEN(max_disk_io_len); 494 i += sizeof (uint64_t)) { 495 *(x++) = value; 496 } 497 498 mprotect((char *)read_buf_source, INDEX_TO_DIOLEN(max_disk_io_len), 499 PROT_READ); 500 501 return (1); 502 } 503 504 static int 505 vinit_init(uint32_t value) 506 { 507 union { 508 uint64_t ll; 509 uint32_t i[sizeof (uint64_t)/sizeof (uint32_t)]; 510 } u; 511 int i; 512 513 for (i = 0; i < ARRAY_LEN(u.i); i++) { 514 u.i[i] = value; 515 } 516 return (rinit_init(u.ll)); 517 } 518 519 static int 520 cinit_init(uint64_t value) 521 { 522 return (vinit_init(opts.read_buffer_supplied_value)); 523 } 524 525 static uchar_t 526 pat_func(int bufno, int i, uchar_t *pat, int plen) 527 { 528 ulong_t len = INDEX_TO_DIOLEN(max_disk_io_len); 529 ulong_t off = ((bufno * len) + i) % plen; 530 531 return (pat[off]); 532 } 533 /* 534 * CJTPAT Payload pattern is: 535 * 167 7E's 536 * 1 74 537 * 1 7E 538 * 1 AB 539 * 51 B5's 540 * 1 5E 541 * 1 4A 542 * 4 7E's 543 * 1 FE 544 */ 545 static uchar_t cjtpat[] = { 546 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 1 */ 547 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 2 */ 548 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 3 */ 549 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 4 */ 550 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 5 */ 551 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 6 */ 552 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 7 */ 553 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 8 */ 554 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 9 */ 555 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 10 */ 556 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 11 */ 557 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 12 */ 558 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 13 */ 559 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 14 */ 560 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 15 */ 561 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, /* 16 */ 562 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x74, 0x7e, 0xab, /* 17 */ 563 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, /* 18 */ 564 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, /* 19 */ 565 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, /* 20 */ 566 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, /* 21 */ 567 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, /* 22 */ 568 0xb5, 0x5e, 0x4A, 0x7e, 0x7e, 0x7e, 0x7e, 0xfe /* 23 */ 569 }; 570 571 static uchar_t 572 cjtpat_func(int bufno, int i) 573 { 574 assert(sizeof (cjtpat) == 228); 575 576 return (pat_func(bufno, i, cjtpat, sizeof (cjtpat))); 577 } 578 579 /* 580 * ISI "Killer" pattern 581 * 582 * 00101101, = 0x2d 583 * 11110100, = 0xf4 584 * 10000010, = 0x82 585 * 11011111, = 0xdf 586 * 01001000, = 0x48 587 */ 588 static uchar_t isipat[] = { 589 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 590 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 591 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 592 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 593 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 594 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 595 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 596 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 0xf4, 0xeb, 597 0xf4, 0x2d, 0xf4, 0x82, 0xdf, 0x48 598 }; 599 600 static uchar_t 601 isipat_func(int bufno, int i) 602 { 603 return (pat_func(bufno, i, isipat, sizeof (isipat))); 604 } 605 606 static int 607 userpat_init(struct ilist *a, int *b, int c) 608 { 609 610 int fd; 611 struct stat buf; 612 613 if ((fd = open(opts.expert_userpat_file, O_RDONLY)) == -1) { 614 return (1); 615 } 616 if (fstat(fd, &buf) == -1) { 617 close(fd); 618 return (1); 619 } 620 621 userpat_data.buf = (uchar_t *)mmap(0, buf.st_size, 622 PROT_READ, MAP_PRIVATE, fd, 0); 623 close(fd); 624 625 if (userpat_data.buf == MAP_FAILED) { 626 return (1); 627 } 628 userpat_data.len = buf.st_size; 629 } 630 631 static uchar_t 632 userpat_func(int bufno, int i) 633 { 634 return (pat_func(bufno, i, userpat_data.buf, userpat_data.len)); 635 } 636 637 static uchar_t 638 cjt_and_isi_func(int bufno, int i) 639 { 640 ulong_t plen = sizeof (isipat) + sizeof (cjtpat); 641 ulong_t len = INDEX_TO_DIOLEN(max_disk_io_len); 642 ulong_t off = ((bufno * len) + i) % plen; 643 644 if (off > sizeof (isipat)) { 645 return (cjtpat[off - sizeof (isipat)]); 646 } else { 647 return (isipat[off]); 648 } 649 } 650