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 14:32:18.640463000 +0100 @@ -367,29 +367,42 @@ { unsigned long result = 0; unsigned char *p, *pend; - unsigned int *idtbase; + unsigned int *idtbase = NULL; unsigned char idt[10]; #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. */ + idtbase = efrm_find_ksym("do_syscall_32_irqs_off"); + /* Linux-4.6: */ + if( idtbase == NULL ) + idtbase = efrm_find_ksym("do_int80_syscall_32"); +#endif + + if( idtbase == NULL ) { + /* linux<4.4: get ia32_sys_call_table variable from asm code at + * linux/arch/x86/entry/entry_64_compat.S. */ + __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 { + p = (void *)idtbase; + } 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-08-15 14:47:01.461718000 +0100 +++ openonload-201606_patched/src/include/onload/version.h 2016-08-15 14:47:23.538636000 +0100 @@ -29,7 +29,7 @@ #ifndef ONLOAD_VERSION -# define ONLOAD_VERSION "201606" +# define ONLOAD_VERSION "201606-p64486_63982" #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 14:32:28.140994000 +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; }