1 // SPDX-License-Identifier: GPL-2.0 2 /* utility to create the register check tables 3 * this includes inlined list.h safe for userspace. 4 * 5 * Copyright 2009 Jerome Glisse 6 * Copyright 2009 Red Hat Inc. 7 * 8 * Authors: 9 * Jerome Glisse 10 * Dave Airlie 11 */ 12 13 #include <sys/types.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <stdio.h> 17 #include <regex.h> 18 #include <libgen.h> 19 20 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 21 /** 22 * container_of - cast a member of a structure out to the containing structure 23 * @ptr: the pointer to the member. 24 * @type: the type of the container struct this is embedded in. 25 * @member: the name of the member within the struct. 26 * 27 */ 28 #define container_of(ptr, type, member) ({ \ 29 const typeof(((type *)0)->member)*__mptr = (ptr); \ 30 (type *)((char *)__mptr - offsetof(type, member)); }) 31 32 /* 33 * Simple doubly linked list implementation. 34 * 35 * Some of the internal functions ("__xxx") are useful when 36 * manipulating whole lists rather than single entries, as 37 * sometimes we already know the next/prev entries and we can 38 * generate better code by using them directly rather than 39 * using the generic single-entry routines. 40 */ 41 42 struct list_head { 43 struct list_head *next, *prev; 44 }; 45 46 #define LIST_HEAD_INIT(name) { &(name), &(name) } 47 48 #define LIST_HEAD(name) \ 49 struct list_head name = LIST_HEAD_INIT(name) 50 51 static inline void INIT_LIST_HEAD(struct list_head *list) 52 { 53 list->next = list; 54 list->prev = list; 55 } 56 57 /* 58 * Insert a new entry between two known consecutive entries. 59 * 60 * This is only for internal list manipulation where we know 61 * the prev/next entries already! 62 */ 63 #ifndef CONFIG_DEBUG_LIST 64 static inline void __list_add(struct list_head *new, 65 struct list_head *prev, struct list_head *next) 66 { 67 next->prev = new; 68 new->next = next; 69 new->prev = prev; 70 prev->next = new; 71 } 72 #else 73 extern void __list_add(struct list_head *new, 74 struct list_head *prev, struct list_head *next); 75 #endif 76 77 /** 78 * list_add - add a new entry 79 * @new: new entry to be added 80 * @head: list head to add it after 81 * 82 * Insert a new entry after the specified head. 83 * This is good for implementing stacks. 84 */ 85 static inline void list_add(struct list_head *new, struct list_head *head) 86 { 87 __list_add(new, head, head->next); 88 } 89 90 /** 91 * list_add_tail - add a new entry 92 * @new: new entry to be added 93 * @head: list head to add it before 94 * 95 * Insert a new entry before the specified head. 96 * This is useful for implementing queues. 97 */ 98 static inline void list_add_tail(struct list_head *new, struct list_head *head) 99 { 100 __list_add(new, head->prev, head); 101 } 102 103 /* 104 * Delete a list entry by making the prev/next entries 105 * point to each other. 106 * 107 * This is only for internal list manipulation where we know 108 * the prev/next entries already! 109 */ 110 static inline void __list_del(struct list_head *prev, struct list_head *next) 111 { 112 next->prev = prev; 113 prev->next = next; 114 } 115 116 /** 117 * list_del - deletes entry from list. 118 * @entry: the element to delete from the list. 119 * Note: list_empty() on entry does not return true after this, the entry is 120 * in an undefined state. 121 */ 122 #ifndef CONFIG_DEBUG_LIST 123 static inline void list_del(struct list_head *entry) 124 { 125 __list_del(entry->prev, entry->next); 126 entry->next = (void *)0xDEADBEEF; 127 entry->prev = (void *)0xBEEFDEAD; 128 } 129 #else 130 extern void list_del(struct list_head *entry); 131 #endif 132 133 /** 134 * list_replace - replace old entry by new one 135 * @old : the element to be replaced 136 * @new : the new element to insert 137 * 138 * If @old was empty, it will be overwritten. 139 */ 140 static inline void list_replace(struct list_head *old, struct list_head *new) 141 { 142 new->next = old->next; 143 new->next->prev = new; 144 new->prev = old->prev; 145 new->prev->next = new; 146 } 147 148 static inline void list_replace_init(struct list_head *old, 149 struct list_head *new) 150 { 151 list_replace(old, new); 152 INIT_LIST_HEAD(old); 153 } 154 155 /** 156 * list_del_init - deletes entry from list and reinitialize it. 157 * @entry: the element to delete from the list. 158 */ 159 static inline void list_del_init(struct list_head *entry) 160 { 161 __list_del(entry->prev, entry->next); 162 INIT_LIST_HEAD(entry); 163 } 164 165 /** 166 * list_move - delete from one list and add as another's head 167 * @list: the entry to move 168 * @head: the head that will precede our entry 169 */ 170 static inline void list_move(struct list_head *list, struct list_head *head) 171 { 172 __list_del(list->prev, list->next); 173 list_add(list, head); 174 } 175 176 /** 177 * list_move_tail - delete from one list and add as another's tail 178 * @list: the entry to move 179 * @head: the head that will follow our entry 180 */ 181 static inline void list_move_tail(struct list_head *list, 182 struct list_head *head) 183 { 184 __list_del(list->prev, list->next); 185 list_add_tail(list, head); 186 } 187 188 /** 189 * list_is_last - tests whether @list is the last entry in list @head 190 * @list: the entry to test 191 * @head: the head of the list 192 */ 193 static inline int list_is_last(const struct list_head *list, 194 const struct list_head *head) 195 { 196 return list->next == head; 197 } 198 199 /** 200 * list_empty - tests whether a list is empty 201 * @head: the list to test. 202 */ 203 static inline int list_empty(const struct list_head *head) 204 { 205 return head->next == head; 206 } 207 208 /** 209 * list_empty_careful - tests whether a list is empty and not being modified 210 * @head: the list to test 211 * 212 * Description: 213 * tests whether a list is empty _and_ checks that no other CPU might be 214 * in the process of modifying either member (next or prev) 215 * 216 * NOTE: using list_empty_careful() without synchronization 217 * can only be safe if the only activity that can happen 218 * to the list entry is list_del_init(). Eg. it cannot be used 219 * if another CPU could re-list_add() it. 220 */ 221 static inline int list_empty_careful(const struct list_head *head) 222 { 223 struct list_head *next = head->next; 224 return (next == head) && (next == head->prev); 225 } 226 227 /** 228 * list_is_singular - tests whether a list has just one entry. 229 * @head: the list to test. 230 */ 231 static inline int list_is_singular(const struct list_head *head) 232 { 233 return !list_empty(head) && (head->next == head->prev); 234 } 235 236 static inline void __list_cut_position(struct list_head *list, 237 struct list_head *head, 238 struct list_head *entry) 239 { 240 struct list_head *new_first = entry->next; 241 list->next = head->next; 242 list->next->prev = list; 243 list->prev = entry; 244 entry->next = list; 245 head->next = new_first; 246 new_first->prev = head; 247 } 248 249 /** 250 * list_cut_position - cut a list into two 251 * @list: a new list to add all removed entries 252 * @head: a list with entries 253 * @entry: an entry within head, could be the head itself 254 * and if so we won't cut the list 255 * 256 * This helper moves the initial part of @head, up to and 257 * including @entry, from @head to @list. You should 258 * pass on @entry an element you know is on @head. @list 259 * should be an empty list or a list you do not care about 260 * losing its data. 261 * 262 */ 263 static inline void list_cut_position(struct list_head *list, 264 struct list_head *head, 265 struct list_head *entry) 266 { 267 if (list_empty(head)) 268 return; 269 if (list_is_singular(head) && (head->next != entry && head != entry)) 270 return; 271 if (entry == head) 272 INIT_LIST_HEAD(list); 273 else 274 __list_cut_position(list, head, entry); 275 } 276 277 static inline void __list_splice(const struct list_head *list, 278 struct list_head *prev, struct list_head *next) 279 { 280 struct list_head *first = list->next; 281 struct list_head *last = list->prev; 282 283 first->prev = prev; 284 prev->next = first; 285 286 last->next = next; 287 next->prev = last; 288 } 289 290 /** 291 * list_splice - join two lists, this is designed for stacks 292 * @list: the new list to add. 293 * @head: the place to add it in the first list. 294 */ 295 static inline void list_splice(const struct list_head *list, 296 struct list_head *head) 297 { 298 if (!list_empty(list)) 299 __list_splice(list, head, head->next); 300 } 301 302 /** 303 * list_splice_tail - join two lists, each list being a queue 304 * @list: the new list to add. 305 * @head: the place to add it in the first list. 306 */ 307 static inline void list_splice_tail(struct list_head *list, 308 struct list_head *head) 309 { 310 if (!list_empty(list)) 311 __list_splice(list, head->prev, head); 312 } 313 314 /** 315 * list_splice_init - join two lists and reinitialise the emptied list. 316 * @list: the new list to add. 317 * @head: the place to add it in the first list. 318 * 319 * The list at @list is reinitialised 320 */ 321 static inline void list_splice_init(struct list_head *list, 322 struct list_head *head) 323 { 324 if (!list_empty(list)) { 325 __list_splice(list, head, head->next); 326 INIT_LIST_HEAD(list); 327 } 328 } 329 330 /** 331 * list_splice_tail_init - join two lists and reinitialise the emptied list 332 * @list: the new list to add. 333 * @head: the place to add it in the first list. 334 * 335 * Each of the lists is a queue. 336 * The list at @list is reinitialised 337 */ 338 static inline void list_splice_tail_init(struct list_head *list, 339 struct list_head *head) 340 { 341 if (!list_empty(list)) { 342 __list_splice(list, head->prev, head); 343 INIT_LIST_HEAD(list); 344 } 345 } 346 347 /** 348 * list_entry - get the struct for this entry 349 * @ptr: the &struct list_head pointer. 350 * @type: the type of the struct this is embedded in. 351 * @member: the name of the list_head within the struct. 352 */ 353 #define list_entry(ptr, type, member) \ 354 container_of(ptr, type, member) 355 356 /** 357 * list_first_entry - get the first element from a list 358 * @ptr: the list head to take the element from. 359 * @type: the type of the struct this is embedded in. 360 * @member: the name of the list_head within the struct. 361 * 362 * Note, that list is expected to be not empty. 363 */ 364 #define list_first_entry(ptr, type, member) \ 365 list_entry((ptr)->next, type, member) 366 367 /** 368 * list_for_each - iterate over a list 369 * @pos: the &struct list_head to use as a loop cursor. 370 * @head: the head for your list. 371 */ 372 #define list_for_each(pos, head) \ 373 for (pos = (head)->next; prefetch(pos->next), pos != (head); \ 374 pos = pos->next) 375 376 /** 377 * list_for_each_prev - iterate over a list backwards 378 * @pos: the &struct list_head to use as a loop cursor. 379 * @head: the head for your list. 380 */ 381 #define list_for_each_prev(pos, head) \ 382 for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \ 383 pos = pos->prev) 384 385 /** 386 * list_for_each_safe - iterate over a list safe against removal of list entry 387 * @pos: the &struct list_head to use as a loop cursor. 388 * @n: another &struct list_head to use as temporary storage 389 * @head: the head for your list. 390 */ 391 #define list_for_each_safe(pos, n, head) \ 392 for (pos = (head)->next, n = pos->next; pos != (head); \ 393 pos = n, n = pos->next) 394 395 /** 396 * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry 397 * @pos: the &struct list_head to use as a loop cursor. 398 * @n: another &struct list_head to use as temporary storage 399 * @head: the head for your list. 400 */ 401 #define list_for_each_prev_safe(pos, n, head) \ 402 for (pos = (head)->prev, n = pos->prev; \ 403 prefetch(pos->prev), pos != (head); \ 404 pos = n, n = pos->prev) 405 406 /** 407 * list_for_each_entry - iterate over list of given type 408 * @pos: the type * to use as a loop cursor. 409 * @head: the head for your list. 410 * @member: the name of the list_head within the struct. 411 */ 412 #define list_for_each_entry(pos, head, member) \ 413 for (pos = list_entry((head)->next, typeof(*pos), member); \ 414 &pos->member != (head); \ 415 pos = list_entry(pos->member.next, typeof(*pos), member)) 416 417 /** 418 * list_for_each_entry_reverse - iterate backwards over list of given type. 419 * @pos: the type * to use as a loop cursor. 420 * @head: the head for your list. 421 * @member: the name of the list_head within the struct. 422 */ 423 #define list_for_each_entry_reverse(pos, head, member) \ 424 for (pos = list_entry((head)->prev, typeof(*pos), member); \ 425 prefetch(pos->member.prev), &pos->member != (head); \ 426 pos = list_entry(pos->member.prev, typeof(*pos), member)) 427 428 /** 429 * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() 430 * @pos: the type * to use as a start point 431 * @head: the head of the list 432 * @member: the name of the list_head within the struct. 433 * 434 * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). 435 */ 436 #define list_prepare_entry(pos, head, member) \ 437 ((pos) ? : list_entry(head, typeof(*pos), member)) 438 439 /** 440 * list_for_each_entry_continue - continue iteration over list of given type 441 * @pos: the type * to use as a loop cursor. 442 * @head: the head for your list. 443 * @member: the name of the list_head within the struct. 444 * 445 * Continue to iterate over list of given type, continuing after 446 * the current position. 447 */ 448 #define list_for_each_entry_continue(pos, head, member) \ 449 for (pos = list_entry(pos->member.next, typeof(*pos), member); \ 450 prefetch(pos->member.next), &pos->member != (head); \ 451 pos = list_entry(pos->member.next, typeof(*pos), member)) 452 453 /** 454 * list_for_each_entry_continue_reverse - iterate backwards from the given point 455 * @pos: the type * to use as a loop cursor. 456 * @head: the head for your list. 457 * @member: the name of the list_head within the struct. 458 * 459 * Start to iterate over list of given type backwards, continuing after 460 * the current position. 461 */ 462 #define list_for_each_entry_continue_reverse(pos, head, member) \ 463 for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ 464 prefetch(pos->member.prev), &pos->member != (head); \ 465 pos = list_entry(pos->member.prev, typeof(*pos), member)) 466 467 /** 468 * list_for_each_entry_from - iterate over list of given type from the current point 469 * @pos: the type * to use as a loop cursor. 470 * @head: the head for your list. 471 * @member: the name of the list_head within the struct. 472 * 473 * Iterate over list of given type, continuing from current position. 474 */ 475 #define list_for_each_entry_from(pos, head, member) \ 476 for (; prefetch(pos->member.next), &pos->member != (head); \ 477 pos = list_entry(pos->member.next, typeof(*pos), member)) 478 479 /** 480 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry 481 * @pos: the type * to use as a loop cursor. 482 * @n: another type * to use as temporary storage 483 * @head: the head for your list. 484 * @member: the name of the list_head within the struct. 485 */ 486 #define list_for_each_entry_safe(pos, n, head, member) \ 487 for (pos = list_entry((head)->next, typeof(*pos), member), \ 488 n = list_entry(pos->member.next, typeof(*pos), member); \ 489 &pos->member != (head); \ 490 pos = n, n = list_entry(n->member.next, typeof(*n), member)) 491 492 /** 493 * list_for_each_entry_safe_continue 494 * @pos: the type * to use as a loop cursor. 495 * @n: another type * to use as temporary storage 496 * @head: the head for your list. 497 * @member: the name of the list_head within the struct. 498 * 499 * Iterate over list of given type, continuing after current point, 500 * safe against removal of list entry. 501 */ 502 #define list_for_each_entry_safe_continue(pos, n, head, member) \ 503 for (pos = list_entry(pos->member.next, typeof(*pos), member), \ 504 n = list_entry(pos->member.next, typeof(*pos), member); \ 505 &pos->member != (head); \ 506 pos = n, n = list_entry(n->member.next, typeof(*n), member)) 507 508 /** 509 * list_for_each_entry_safe_from 510 * @pos: the type * to use as a loop cursor. 511 * @n: another type * to use as temporary storage 512 * @head: the head for your list. 513 * @member: the name of the list_head within the struct. 514 * 515 * Iterate over list of given type from current point, safe against 516 * removal of list entry. 517 */ 518 #define list_for_each_entry_safe_from(pos, n, head, member) \ 519 for (n = list_entry(pos->member.next, typeof(*pos), member); \ 520 &pos->member != (head); \ 521 pos = n, n = list_entry(n->member.next, typeof(*n), member)) 522 523 /** 524 * list_for_each_entry_safe_reverse 525 * @pos: the type * to use as a loop cursor. 526 * @n: another type * to use as temporary storage 527 * @head: the head for your list. 528 * @member: the name of the list_head within the struct. 529 * 530 * Iterate backwards over list of given type, safe against removal 531 * of list entry. 532 */ 533 #define list_for_each_entry_safe_reverse(pos, n, head, member) \ 534 for (pos = list_entry((head)->prev, typeof(*pos), member), \ 535 n = list_entry(pos->member.prev, typeof(*pos), member); \ 536 &pos->member != (head); \ 537 pos = n, n = list_entry(n->member.prev, typeof(*n), member)) 538 539 struct offset { 540 struct list_head list; 541 unsigned offset; 542 }; 543 544 struct table { 545 struct list_head offsets; 546 unsigned offset_max; 547 unsigned nentry; 548 unsigned *table; 549 char *gpu_prefix; 550 }; 551 552 static struct offset *offset_new(unsigned o) 553 { 554 struct offset *offset; 555 556 offset = (struct offset *)malloc(sizeof(struct offset)); 557 if (offset) { 558 INIT_LIST_HEAD(&offset->list); 559 offset->offset = o; 560 } 561 return offset; 562 } 563 564 static void table_offset_add(struct table *t, struct offset *offset) 565 { 566 list_add_tail(&offset->list, &t->offsets); 567 } 568 569 static void table_init(struct table *t) 570 { 571 INIT_LIST_HEAD(&t->offsets); 572 t->offset_max = 0; 573 t->nentry = 0; 574 t->table = NULL; 575 } 576 577 static void table_print(struct table *t) 578 { 579 unsigned nlloop, i, j, n, c, id; 580 581 nlloop = (t->nentry + 3) / 4; 582 c = t->nentry; 583 printf("static const unsigned %s_reg_safe_bm[%d] = {\n", t->gpu_prefix, 584 t->nentry); 585 for (i = 0, id = 0; i < nlloop; i++) { 586 n = 4; 587 if (n > c) 588 n = c; 589 c -= n; 590 for (j = 0; j < n; j++) { 591 if (j == 0) 592 printf("\t"); 593 else 594 printf(" "); 595 printf("0x%08X,", t->table[id++]); 596 } 597 printf("\n"); 598 } 599 printf("};\n"); 600 } 601 602 static int table_build(struct table *t) 603 { 604 struct offset *offset; 605 unsigned i, m; 606 607 t->nentry = ((t->offset_max >> 2) + 31) / 32; 608 t->table = (unsigned *)malloc(sizeof(unsigned) * t->nentry); 609 if (t->table == NULL) 610 return -1; 611 memset(t->table, 0xff, sizeof(unsigned) * t->nentry); 612 list_for_each_entry(offset, &t->offsets, list) { 613 i = (offset->offset >> 2) / 32; 614 m = (offset->offset >> 2) & 31; 615 m = 1 << m; 616 t->table[i] ^= m; 617 } 618 return 0; 619 } 620 621 static char gpu_name[10]; 622 static int parser_auth(struct table *t, const char *filename) 623 { 624 FILE *file; 625 regex_t mask_rex; 626 regmatch_t match[4]; 627 char buf[1024]; 628 size_t end; 629 int len; 630 int done = 0; 631 int r; 632 unsigned o; 633 struct offset *offset; 634 char last_reg_s[10]; 635 int last_reg; 636 637 if (regcomp 638 (&mask_rex, "(0x[0-9a-fA-F]*) *([_a-zA-Z0-9]*)", REG_EXTENDED)) { 639 fprintf(stderr, "Failed to compile regular expression\n"); 640 return -1; 641 } 642 file = fopen(filename, "r"); 643 if (file == NULL) { 644 fprintf(stderr, "Failed to open: %s\n", filename); 645 return -1; 646 } 647 fseek(file, 0, SEEK_END); 648 end = ftell(file); 649 fseek(file, 0, SEEK_SET); 650 651 /* get header */ 652 if (fgets(buf, 1024, file) == NULL) { 653 fclose(file); 654 return -1; 655 } 656 657 /* first line will contain the last register 658 * and gpu name */ 659 sscanf(buf, "%9s %9s", gpu_name, last_reg_s); 660 t->gpu_prefix = gpu_name; 661 last_reg = strtol(last_reg_s, NULL, 16); 662 663 do { 664 if (fgets(buf, 1024, file) == NULL) { 665 fclose(file); 666 return -1; 667 } 668 len = strlen(buf); 669 if (ftell(file) == end) 670 done = 1; 671 if (len) { 672 r = regexec(&mask_rex, buf, 4, match, 0); 673 if (r == REG_NOMATCH) { 674 } else if (r) { 675 fprintf(stderr, 676 "Error matching regular expression %d in %s\n", 677 r, filename); 678 fclose(file); 679 return -1; 680 } else { 681 buf[match[0].rm_eo] = 0; 682 buf[match[1].rm_eo] = 0; 683 buf[match[2].rm_eo] = 0; 684 o = strtol(&buf[match[1].rm_so], NULL, 16); 685 offset = offset_new(o); 686 table_offset_add(t, offset); 687 if (o > t->offset_max) 688 t->offset_max = o; 689 } 690 } 691 } while (!done); 692 fclose(file); 693 if (t->offset_max < last_reg) 694 t->offset_max = last_reg; 695 return table_build(t); 696 } 697 698 int main(int argc, char *argv[]) 699 { 700 struct table t; 701 702 if (argc != 2) { 703 fprintf(stderr, "Usage: %s <authfile>\n", argv[0]); 704 exit(1); 705 } 706 table_init(&t); 707 if (parser_auth(&t, argv[1])) { 708 fprintf(stderr, "Failed to parse file %s\n", argv[1]); 709 return -1; 710 } 711 table_print(&t); 712 return 0; 713 } 714