summarylogtreecommitdiffstats
path: root/openonload-201606-bug64486-63982-ilog2-no_KALLSYMS_ALL.patch
blob: 9015aab27489aa3f4155ad7e7d7deeefdabc150f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
diff -ur openonload-201606/src/driver/linux_onload/x86_linux_trampoline.c openonload-201606_patched/src/driver/linux_onload/x86_linux_trampoline.c
--- openonload-201606/src/driver/linux_onload/x86_linux_trampoline.c	2016-06-30 11:42:18.000000000 +0100
+++ openonload-201606_patched/src/driver/linux_onload/x86_linux_trampoline.c	2016-08-15 16:24:49.526866000 +0100
@@ -290,19 +290,22 @@
  */
 static void **find_syscall_table(void)
 {
-  unsigned long *idtbase = NULL;
-  unsigned char *p, *end, idt[6];
+  unsigned char *p = NULL;
+  unsigned char *end;
   void **result = NULL;
 
 #ifdef ERFM_HAVE_NEW_KALLSYMS
   /* Linux-4.4 & 4.5: */
-  idtbase = efrm_find_ksym("do_syscall_32_irqs_on");
+  p = efrm_find_ksym("do_syscall_32_irqs_on");
   /* Linux-4.6: */
-  if( idtbase == NULL )
-    idtbase = efrm_find_ksym("do_int80_syscall_32");
+  if( p == NULL )
+    p = efrm_find_ksym("do_int80_syscall_32");
 #endif
 
-  if( idtbase == NULL ) {
+  if( p == NULL ) {
+    unsigned long *idtbase;
+    unsigned char idt[6];
+
     __asm__("sidt %0" : "=m"(idt));
     idtbase = (unsigned long *)(idt[2] | (idt[3] << 8) | (idt[4] << 16)
                                 | (idt[5] << 24));
@@ -311,9 +314,6 @@
     p = (unsigned char *)((idtbase[0x80*2] & 0xffff)
                           | (idtbase[0x80*2+1] & 0xffff0000));
   }
-  else {
-    p = (void *)idtbase;
-  }
   TRAMP_DEBUG("int 0x80 entry point at %p", p);
   end = p + 1024 - 7;
   while (p < end) {
@@ -366,30 +366,45 @@
 static void **find_ia32_syscall_table(void)
 {
   unsigned long result = 0;
-  unsigned char *p, *pend;
-  unsigned int *idtbase;
-  unsigned char idt[10];
+  unsigned char *p = NULL;
+  unsigned char *pend;
 
 #ifdef ERFM_HAVE_NEW_KALLSYMS
-  void *addr;
-
+#if 0
+  /* It works with CONFIG_KALLSYMS_ALL=y only. */
   /* Linux>=4.2: ia32_sys_call_table is not a local variable any more, so
-   * we can use kallsyms to find it. */
+   * we can use kallsyms to find it if CONFIG_KALLSYMS_ALL=y. */
+  void *addr;
   addr = efrm_find_ksym("ia32_sys_call_table");
   if( addr != NULL )
     return addr;
 #endif
 
-  /* linux<4.4: ia32_sys_call_table is an internal variable in
-   * linux/arch/x86/entry/entry_64_compat.S, and we can parse this asm
-   * code. */
-  __asm__("sidt %0" : "=m"(idt));
-  idtbase = *(unsigned int **)(&idt[2]);
-  TRAMP_DEBUG("idt base=%p, entry 0x80=%08x,%08x,%08x", idtbase,
-              idtbase[0x80*4], idtbase[0x80*4+1], idtbase[0x80*4+2]);
-  result = (idtbase[0x80*4] & 0xffff) | (idtbase[0x80*4+1] & 0xffff0000)
-           | ((unsigned long)idtbase[0x80*4+2] << 32);
-  p = (unsigned char *)result;
+  /* Linux-4.4 & 4.5: do_syscall_32_irqs_off is a function, so it does not
+   * require CONFIG_KALLSYMS_ALL=y. */
+  p = efrm_find_ksym("do_syscall_32_irqs_off");
+  /* Linux-4.6: */
+  if( p == NULL )
+    p = efrm_find_ksym("do_int80_syscall_32");
+#endif
+
+  if( p == NULL ) {
+    /* linux<4.4: get ia32_sys_call_table variable from asm code at
+     * linux/arch/x86/entry/entry_64_compat.S. */
+    unsigned int *idtbase;
+    unsigned char idt[10];
+
+    __asm__("sidt %0" : "=m"(idt));
+    idtbase = *(unsigned int **)(&idt[2]);
+    TRAMP_DEBUG("idt base=%p, entry 0x80=%08x,%08x,%08x", idtbase,
+                idtbase[0x80*4], idtbase[0x80*4+1], idtbase[0x80*4+2]);
+    result = (idtbase[0x80*4] & 0xffff) | (idtbase[0x80*4+1] & 0xffff0000)
+             | ((unsigned long)idtbase[0x80*4+2] << 32);
+    p = (unsigned char *)result;
+  }
+  else {
+    result = (unsigned long)p;
+  }
   TRAMP_DEBUG("int 0x80 entry point at %p", p);
   pend = p + 1024 - 7;
   while (p < pend) {
diff -ur openonload-201606/src/include/onload/version.h openonload-201606_patched/src/include/onload/version.h
--- openonload-201606/src/include/onload/version.h	2016-06-30 11:42:26.000000000 +0100
+++ openonload-201606_patched/src/include/onload/version.h	2016-08-15 16:28:05.299169000 +0100
@@ -29,7 +29,7 @@
 
 
 #ifndef ONLOAD_VERSION
-# define ONLOAD_VERSION "201606"
+# define ONLOAD_VERSION "201606-p63982-p64486"
 #endif
 
 #define ONLOAD_PRODUCT "OpenOnload"
diff -ur openonload-201606/src/lib/efrm/vi_resource_alloc.c openonload-201606_patched/src/lib/efrm/vi_resource_alloc.c
--- openonload-201606/src/lib/efrm/vi_resource_alloc.c	2016-06-30 11:42:13.000000000 +0100
+++ openonload-201606_patched/src/lib/efrm/vi_resource_alloc.c	2016-08-15 16:27:44.743189000 +0100
@@ -1432,6 +1432,15 @@
 
 	qso->q_len_entries = n_q_entries;
 	qso->q_len_bytes = efrm_vi_q_bytes(virs, q_type, n_q_entries);
+
+	/* This value should always be positive, but if we don't check for this
+	 * explicitly, some compilers will assume that undefined logarithms
+	 * can be taken in get_order() and will generate code that won't link.
+	 * See bug63982. */
+	EFRM_ASSERT(qso->q_len_bytes > 0);
+	if (qso->q_len_bytes <= 0)
+		return -EINVAL;
+
 	qso->q_len_page_order = get_order(qso->q_len_bytes);
 	return 0;
 }