summarylogtreecommitdiffstats
path: root/openonload-201606-bug64486-63982-ilog2-no_KALLSYMS_ALL.patch
diff options
context:
space:
mode:
Diffstat (limited to 'openonload-201606-bug64486-63982-ilog2-no_KALLSYMS_ALL.patch')
-rw-r--r--openonload-201606-bug64486-63982-ilog2-no_KALLSYMS_ALL.patch135
1 files changed, 135 insertions, 0 deletions
diff --git a/openonload-201606-bug64486-63982-ilog2-no_KALLSYMS_ALL.patch b/openonload-201606-bug64486-63982-ilog2-no_KALLSYMS_ALL.patch
new file mode 100644
index 000000000000..9015aab27489
--- /dev/null
+++ b/openonload-201606-bug64486-63982-ilog2-no_KALLSYMS_ALL.patch
@@ -0,0 +1,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;
+ }