Messages in this thread Patch in this message | | | From | Matthias Kaehlcke <> | Date | Fri, 15 Mar 2019 13:54:50 -0700 | Subject | [PATCH] lib: Add shared copy of __lshrti3 from libgcc |
| |
The compiler may emit calls to __lshrti3 from the compiler runtime library, which results in undefined references:
arch/x86/kvm/x86.o: In function `mul_u64_u64_shr': include/linux/math64.h:186: undefined reference to `__lshrti3'
Add a copy of the __lshrti3 libgcc routine (from gcc v4.9.2).
Include the function for x86 builds with clang, which is the environment where the above error was observed.
Signed-off-by: Matthias Kaehlcke <mka@chromium.org> --- arch/x86/Kconfig | 1 + include/linux/libgcc.h | 16 ++++++++++++++++ lib/Kconfig | 3 +++ lib/Makefile | 1 + lib/lshrti3.c | 31 +++++++++++++++++++++++++++++++ 5 files changed, 52 insertions(+) create mode 100644 lib/lshrti3.c
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c1f9b3cf437c..a5e0d923845d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -105,6 +105,7 @@ config X86 select GENERIC_IRQ_PROBE select GENERIC_IRQ_RESERVATION_MODE select GENERIC_IRQ_SHOW + select GENERIC_LIB_LSHRTI3 if CC_IS_CLANG select GENERIC_PENDING_IRQ if SMP select GENERIC_SMP_IDLE_THREAD select GENERIC_STRNCPY_FROM_USER diff --git a/include/linux/libgcc.h b/include/linux/libgcc.h index 32e1e0f4b2d0..a71036471838 100644 --- a/include/linux/libgcc.h +++ b/include/linux/libgcc.h @@ -22,15 +22,26 @@ #include <asm/byteorder.h>
typedef int word_type __attribute__ ((mode (__word__))); +typedef int TItype __attribute__ ((mode (TI)));
#ifdef __BIG_ENDIAN struct DWstruct { int high, low; }; + +struct DWstruct128 { + long long high, low; +}; + #elif defined(__LITTLE_ENDIAN) struct DWstruct { int low, high; }; + +struct DWstruct128 { + long long low, high; +}; + #else #error I feel sick. #endif @@ -40,4 +51,9 @@ typedef union { long long ll; } DWunion;
+typedef union { + struct DWstruct128 s; + TItype ll; +} DWunion128; + #endif /* __ASM_LIBGCC_H */ diff --git a/lib/Kconfig b/lib/Kconfig index a9e56539bd11..369e10259ea6 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -624,6 +624,9 @@ config GENERIC_LIB_ASHRDI3 config GENERIC_LIB_LSHRDI3 bool
+config GENERIC_LIB_LSHRTI3 + bool + config GENERIC_LIB_MULDI3 bool
diff --git a/lib/Makefile b/lib/Makefile index 4e066120a0d6..42648411f451 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -277,6 +277,7 @@ obj-$(CONFIG_PARMAN) += parman.o obj-$(CONFIG_GENERIC_LIB_ASHLDI3) += ashldi3.o obj-$(CONFIG_GENERIC_LIB_ASHRDI3) += ashrdi3.o obj-$(CONFIG_GENERIC_LIB_LSHRDI3) += lshrdi3.o +obj-$(CONFIG_GENERIC_LIB_LSHRTI3) += lshrti3.o obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o diff --git a/lib/lshrti3.c b/lib/lshrti3.c new file mode 100644 index 000000000000..2d2123bb3030 --- /dev/null +++ b/lib/lshrti3.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/export.h> +#include <linux/libgcc.h> + +long long __lshrti3(long long u, word_type b) +{ + DWunion128 uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 64 - b; + + if (bm <= 0) { + w.s.high = 0; + w.s.low = (unsigned long long) uu.s.high >> -bm; + } else { + const unsigned long long carries = + (unsigned long long) uu.s.high << bm; + w.s.high = (unsigned long long) uu.s.high >> b; + w.s.low = ((unsigned long long) uu.s.low >> b) | carries; + } + + return w.ll; +} +#ifndef BUILD_VDSO +EXPORT_SYMBOL(__lshrti3); +#endif -- 2.21.0.360.g471c308f928-goog
| |