Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mkregtable.c
Go to the documentation of this file.
1 /* utility to create the register check tables
2  * this includes inlined list.h safe for userspace.
3  *
4  * Copyright 2009 Jerome Glisse
5  * Copyright 2009 Red Hat Inc.
6  *
7  * Authors:
8  * Jerome Glisse
9  * Dave Airlie
10  */
11 
12 #include <sys/types.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <regex.h>
17 #include <libgen.h>
18 
19 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
20 
27 #define container_of(ptr, type, member) ({ \
28  const typeof(((type *)0)->member)*__mptr = (ptr); \
29  (type *)((char *)__mptr - offsetof(type, member)); })
30 
31 /*
32  * Simple doubly linked list implementation.
33  *
34  * Some of the internal functions ("__xxx") are useful when
35  * manipulating whole lists rather than single entries, as
36  * sometimes we already know the next/prev entries and we can
37  * generate better code by using them directly rather than
38  * using the generic single-entry routines.
39  */
40 
41 struct list_head {
42  struct list_head *next, *prev;
43 };
44 
45 #define LIST_HEAD_INIT(name) { &(name), &(name) }
46 
47 #define LIST_HEAD(name) \
48  struct list_head name = LIST_HEAD_INIT(name)
49 
50 static inline void INIT_LIST_HEAD(struct list_head *list)
51 {
52  list->next = list;
53  list->prev = list;
54 }
55 
56 /*
57  * Insert a new entry between two known consecutive entries.
58  *
59  * This is only for internal list manipulation where we know
60  * the prev/next entries already!
61  */
62 #ifndef CONFIG_DEBUG_LIST
63 static inline void __list_add(struct list_head *new,
64  struct list_head *prev, struct list_head *next)
65 {
66  next->prev = new;
67  new->next = next;
68  new->prev = prev;
69  prev->next = new;
70 }
71 #else
72 extern void __list_add(struct list_head *new,
73  struct list_head *prev, struct list_head *next);
74 #endif
75 
84 static inline void list_add(struct list_head *new, struct list_head *head)
85 {
86  __list_add(new, head, head->next);
87 }
88 
97 static inline void list_add_tail(struct list_head *new, struct list_head *head)
98 {
99  __list_add(new, head->prev, head);
100 }
101 
102 /*
103  * Delete a list entry by making the prev/next entries
104  * point to each other.
105  *
106  * This is only for internal list manipulation where we know
107  * the prev/next entries already!
108  */
109 static inline void __list_del(struct list_head *prev, struct list_head *next)
110 {
111  next->prev = prev;
112  prev->next = next;
113 }
114 
121 #ifndef CONFIG_DEBUG_LIST
122 static inline void list_del(struct list_head *entry)
123 {
124  __list_del(entry->prev, entry->next);
125  entry->next = (void *)0xDEADBEEF;
126  entry->prev = (void *)0xBEEFDEAD;
127 }
128 #else
129 extern void list_del(struct list_head *entry);
130 #endif
131 
139 static inline void list_replace(struct list_head *old, struct list_head *new)
140 {
141  new->next = old->next;
142  new->next->prev = new;
143  new->prev = old->prev;
144  new->prev->next = new;
145 }
146 
147 static inline void list_replace_init(struct list_head *old,
148  struct list_head *new)
149 {
150  list_replace(old, new);
151  INIT_LIST_HEAD(old);
152 }
153 
158 static inline void list_del_init(struct list_head *entry)
159 {
160  __list_del(entry->prev, entry->next);
161  INIT_LIST_HEAD(entry);
162 }
163 
169 static inline void list_move(struct list_head *list, struct list_head *head)
170 {
171  __list_del(list->prev, list->next);
172  list_add(list, head);
173 }
174 
180 static inline void list_move_tail(struct list_head *list,
181  struct list_head *head)
182 {
183  __list_del(list->prev, list->next);
184  list_add_tail(list, head);
185 }
186 
192 static inline int list_is_last(const struct list_head *list,
193  const struct list_head *head)
194 {
195  return list->next == head;
196 }
197 
202 static inline int list_empty(const struct list_head *head)
203 {
204  return head->next == head;
205 }
206 
220 static inline int list_empty_careful(const struct list_head *head)
221 {
222  struct list_head *next = head->next;
223  return (next == head) && (next == head->prev);
224 }
225 
230 static inline int list_is_singular(const struct list_head *head)
231 {
232  return !list_empty(head) && (head->next == head->prev);
233 }
234 
235 static inline void __list_cut_position(struct list_head *list,
236  struct list_head *head,
237  struct list_head *entry)
238 {
239  struct list_head *new_first = entry->next;
240  list->next = head->next;
241  list->next->prev = list;
242  list->prev = entry;
243  entry->next = list;
244  head->next = new_first;
245  new_first->prev = head;
246 }
247 
262 static inline void list_cut_position(struct list_head *list,
263  struct list_head *head,
264  struct list_head *entry)
265 {
266  if (list_empty(head))
267  return;
268  if (list_is_singular(head) && (head->next != entry && head != entry))
269  return;
270  if (entry == head)
271  INIT_LIST_HEAD(list);
272  else
273  __list_cut_position(list, head, entry);
274 }
275 
276 static inline void __list_splice(const struct list_head *list,
277  struct list_head *prev, struct list_head *next)
278 {
279  struct list_head *first = list->next;
280  struct list_head *last = list->prev;
281 
282  first->prev = prev;
283  prev->next = first;
284 
285  last->next = next;
286  next->prev = last;
287 }
288 
294 static inline void list_splice(const struct list_head *list,
295  struct list_head *head)
296 {
297  if (!list_empty(list))
298  __list_splice(list, head, head->next);
299 }
300 
306 static inline void list_splice_tail(struct list_head *list,
307  struct list_head *head)
308 {
309  if (!list_empty(list))
310  __list_splice(list, head->prev, head);
311 }
312 
320 static inline void list_splice_init(struct list_head *list,
321  struct list_head *head)
322 {
323  if (!list_empty(list)) {
324  __list_splice(list, head, head->next);
325  INIT_LIST_HEAD(list);
326  }
327 }
328 
337 static inline void list_splice_tail_init(struct list_head *list,
338  struct list_head *head)
339 {
340  if (!list_empty(list)) {
341  __list_splice(list, head->prev, head);
342  INIT_LIST_HEAD(list);
343  }
344 }
345 
352 #define list_entry(ptr, type, member) \
353  container_of(ptr, type, member)
354 
363 #define list_first_entry(ptr, type, member) \
364  list_entry((ptr)->next, type, member)
365 
371 #define list_for_each(pos, head) \
372  for (pos = (head)->next; prefetch(pos->next), pos != (head); \
373  pos = pos->next)
374 
385 #define __list_for_each(pos, head) \
386  for (pos = (head)->next; pos != (head); pos = pos->next)
387 
393 #define list_for_each_prev(pos, head) \
394  for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
395  pos = pos->prev)
396 
403 #define list_for_each_safe(pos, n, head) \
404  for (pos = (head)->next, n = pos->next; pos != (head); \
405  pos = n, n = pos->next)
406 
413 #define list_for_each_prev_safe(pos, n, head) \
414  for (pos = (head)->prev, n = pos->prev; \
415  prefetch(pos->prev), pos != (head); \
416  pos = n, n = pos->prev)
417 
424 #define list_for_each_entry(pos, head, member) \
425  for (pos = list_entry((head)->next, typeof(*pos), member); \
426  &pos->member != (head); \
427  pos = list_entry(pos->member.next, typeof(*pos), member))
428 
435 #define list_for_each_entry_reverse(pos, head, member) \
436  for (pos = list_entry((head)->prev, typeof(*pos), member); \
437  prefetch(pos->member.prev), &pos->member != (head); \
438  pos = list_entry(pos->member.prev, typeof(*pos), member))
439 
448 #define list_prepare_entry(pos, head, member) \
449  ((pos) ? : list_entry(head, typeof(*pos), member))
450 
460 #define list_for_each_entry_continue(pos, head, member) \
461  for (pos = list_entry(pos->member.next, typeof(*pos), member); \
462  prefetch(pos->member.next), &pos->member != (head); \
463  pos = list_entry(pos->member.next, typeof(*pos), member))
464 
474 #define list_for_each_entry_continue_reverse(pos, head, member) \
475  for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
476  prefetch(pos->member.prev), &pos->member != (head); \
477  pos = list_entry(pos->member.prev, typeof(*pos), member))
478 
487 #define list_for_each_entry_from(pos, head, member) \
488  for (; prefetch(pos->member.next), &pos->member != (head); \
489  pos = list_entry(pos->member.next, typeof(*pos), member))
490 
498 #define list_for_each_entry_safe(pos, n, head, member) \
499  for (pos = list_entry((head)->next, typeof(*pos), member), \
500  n = list_entry(pos->member.next, typeof(*pos), member); \
501  &pos->member != (head); \
502  pos = n, n = list_entry(n->member.next, typeof(*n), member))
503 
514 #define list_for_each_entry_safe_continue(pos, n, head, member) \
515  for (pos = list_entry(pos->member.next, typeof(*pos), member), \
516  n = list_entry(pos->member.next, typeof(*pos), member); \
517  &pos->member != (head); \
518  pos = n, n = list_entry(n->member.next, typeof(*n), member))
519 
530 #define list_for_each_entry_safe_from(pos, n, head, member) \
531  for (n = list_entry(pos->member.next, typeof(*pos), member); \
532  &pos->member != (head); \
533  pos = n, n = list_entry(n->member.next, typeof(*n), member))
534 
545 #define list_for_each_entry_safe_reverse(pos, n, head, member) \
546  for (pos = list_entry((head)->prev, typeof(*pos), member), \
547  n = list_entry(pos->member.prev, typeof(*pos), member); \
548  &pos->member != (head); \
549  pos = n, n = list_entry(n->member.prev, typeof(*n), member))
550 
551 struct offset {
552  struct list_head list;
553  unsigned offset;
554 };
555 
556 struct table {
558  unsigned offset_max;
559  unsigned nentry;
560  unsigned *table;
561  char *gpu_prefix;
562 };
563 
564 static struct offset *offset_new(unsigned o)
565 {
566  struct offset *offset;
567 
568  offset = (struct offset *)malloc(sizeof(struct offset));
569  if (offset) {
570  INIT_LIST_HEAD(&offset->list);
571  offset->offset = o;
572  }
573  return offset;
574 }
575 
576 static void table_offset_add(struct table *t, struct offset *offset)
577 {
578  list_add_tail(&offset->list, &t->offsets);
579 }
580 
581 static void table_init(struct table *t)
582 {
583  INIT_LIST_HEAD(&t->offsets);
584  t->offset_max = 0;
585  t->nentry = 0;
586  t->table = NULL;
587 }
588 
589 static void table_print(struct table *t)
590 {
591  unsigned nlloop, i, j, n, c, id;
592 
593  nlloop = (t->nentry + 3) / 4;
594  c = t->nentry;
595  printf("static const unsigned %s_reg_safe_bm[%d] = {\n", t->gpu_prefix,
596  t->nentry);
597  for (i = 0, id = 0; i < nlloop; i++) {
598  n = 4;
599  if (n > c)
600  n = c;
601  c -= n;
602  for (j = 0; j < n; j++) {
603  if (j == 0)
604  printf("\t");
605  else
606  printf(" ");
607  printf("0x%08X,", t->table[id++]);
608  }
609  printf("\n");
610  }
611  printf("};\n");
612 }
613 
614 static int table_build(struct table *t)
615 {
616  struct offset *offset;
617  unsigned i, m;
618 
619  t->nentry = ((t->offset_max >> 2) + 31) / 32;
620  t->table = (unsigned *)malloc(sizeof(unsigned) * t->nentry);
621  if (t->table == NULL)
622  return -1;
623  memset(t->table, 0xff, sizeof(unsigned) * t->nentry);
624  list_for_each_entry(offset, &t->offsets, list) {
625  i = (offset->offset >> 2) / 32;
626  m = (offset->offset >> 2) & 31;
627  m = 1 << m;
628  t->table[i] ^= m;
629  }
630  return 0;
631 }
632 
633 static char gpu_name[10];
634 static int parser_auth(struct table *t, const char *filename)
635 {
636  FILE *file;
637  regex_t mask_rex;
638  regmatch_t match[4];
639  char buf[1024];
640  size_t end;
641  int len;
642  int done = 0;
643  int r;
644  unsigned o;
645  struct offset *offset;
646  char last_reg_s[10];
647  int last_reg;
648 
649  if (regcomp
650  (&mask_rex, "(0x[0-9a-fA-F]*) *([_a-zA-Z0-9]*)", REG_EXTENDED)) {
651  fprintf(stderr, "Failed to compile regular expression\n");
652  return -1;
653  }
654  file = fopen(filename, "r");
655  if (file == NULL) {
656  fprintf(stderr, "Failed to open: %s\n", filename);
657  return -1;
658  }
659  fseek(file, 0, SEEK_END);
660  end = ftell(file);
661  fseek(file, 0, SEEK_SET);
662 
663  /* get header */
664  if (fgets(buf, 1024, file) == NULL) {
665  fclose(file);
666  return -1;
667  }
668 
669  /* first line will contain the last register
670  * and gpu name */
671  sscanf(buf, "%s %s", gpu_name, last_reg_s);
672  t->gpu_prefix = gpu_name;
673  last_reg = strtol(last_reg_s, NULL, 16);
674 
675  do {
676  if (fgets(buf, 1024, file) == NULL) {
677  fclose(file);
678  return -1;
679  }
680  len = strlen(buf);
681  if (ftell(file) == end)
682  done = 1;
683  if (len) {
684  r = regexec(&mask_rex, buf, 4, match, 0);
685  if (r == REG_NOMATCH) {
686  } else if (r) {
687  fprintf(stderr,
688  "Error matching regular expression %d in %s\n",
689  r, filename);
690  fclose(file);
691  return -1;
692  } else {
693  buf[match[0].rm_eo] = 0;
694  buf[match[1].rm_eo] = 0;
695  buf[match[2].rm_eo] = 0;
696  o = strtol(&buf[match[1].rm_so], NULL, 16);
697  offset = offset_new(o);
698  table_offset_add(t, offset);
699  if (o > t->offset_max)
700  t->offset_max = o;
701  }
702  }
703  } while (!done);
704  fclose(file);
705  if (t->offset_max < last_reg)
706  t->offset_max = last_reg;
707  return table_build(t);
708 }
709 
710 int main(int argc, char *argv[])
711 {
712  struct table t;
713 
714  if (argc != 2) {
715  fprintf(stderr, "Usage: %s <authfile>\n", argv[0]);
716  exit(1);
717  }
718  table_init(&t);
719  if (parser_auth(&t, argv[1])) {
720  fprintf(stderr, "Failed to parse file %s\n", argv[1]);
721  return -1;
722  }
723  table_print(&t);
724  return 0;
725 }