diff options
| author | Jay Vosburgh <jay.vosburgh@canonical.com> | 2014-11-14 14:05:06 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-11-14 16:36:25 -0500 |
| commit | a77f9c5dcdf8480a93332792c336fa2bf9d31229 (patch) | |
| tree | 003964de0cc772f361d254385406fa75f3fcbff2 /lib | |
| parent | 8cd4313aa775537f724486d5b7503b4d46c9f012 (diff) | |
Revert "fast_hash: avoid indirect function calls"
This reverts commit e5a2c899957659cd1a9f789bc462f9c0b35f5150.
Commit e5a2c899 introduced an alternative_call, arch_fast_hash2,
that selects between __jhash2 and __intel_crc4_2_hash based on the
X86_FEATURE_XMM4_2.
Unfortunately, the alternative_call system does not appear to be
suitable for use with C functions, as register usage is not handled
properly for the called functions. The __jhash2 function in particular
clobbers registers that are not preserved when called via
alternative_call, resulting in a panic for direct callers of
arch_fast_hash2 on older CPUs lacking sse4_2. It is possible that
__intel_crc4_2_hash works merely by chance because it uses fewer
registers.
This commit was suggested as the source of the problem by Jesse
Gross <jesse@nicira.com>.
Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile | 2 | ||||
| -rw-r--r-- | lib/hash.c | 39 |
2 files changed, 40 insertions, 1 deletions
diff --git a/lib/Makefile b/lib/Makefile index 04e53dd16070..7512dc978f18 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
| @@ -26,7 +26,7 @@ obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ | |||
| 26 | bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ | 26 | bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ |
| 27 | gcd.o lcm.o list_sort.o uuid.o flex_array.o iovec.o clz_ctz.o \ | 27 | gcd.o lcm.o list_sort.o uuid.o flex_array.o iovec.o clz_ctz.o \ |
| 28 | bsearch.o find_last_bit.o find_next_bit.o llist.o memweight.o kfifo.o \ | 28 | bsearch.o find_last_bit.o find_next_bit.o llist.o memweight.o kfifo.o \ |
| 29 | percpu-refcount.o percpu_ida.o rhashtable.o | 29 | percpu-refcount.o percpu_ida.o hash.o rhashtable.o |
| 30 | obj-y += string_helpers.o | 30 | obj-y += string_helpers.o |
| 31 | obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o | 31 | obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o |
| 32 | obj-y += kstrtox.o | 32 | obj-y += kstrtox.o |
diff --git a/lib/hash.c b/lib/hash.c new file mode 100644 index 000000000000..fea973f4bd57 --- /dev/null +++ b/lib/hash.c | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | /* General purpose hashing library | ||
| 2 | * | ||
| 3 | * That's a start of a kernel hashing library, which can be extended | ||
| 4 | * with further algorithms in future. arch_fast_hash{2,}() will | ||
| 5 | * eventually resolve to an architecture optimized implementation. | ||
| 6 | * | ||
| 7 | * Copyright 2013 Francesco Fusco <ffusco@redhat.com> | ||
| 8 | * Copyright 2013 Daniel Borkmann <dborkman@redhat.com> | ||
| 9 | * Copyright 2013 Thomas Graf <tgraf@redhat.com> | ||
| 10 | * Licensed under the GNU General Public License, version 2.0 (GPLv2) | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/jhash.h> | ||
| 14 | #include <linux/hash.h> | ||
| 15 | #include <linux/cache.h> | ||
| 16 | |||
| 17 | static struct fast_hash_ops arch_hash_ops __read_mostly = { | ||
| 18 | .hash = jhash, | ||
| 19 | .hash2 = jhash2, | ||
| 20 | }; | ||
| 21 | |||
| 22 | u32 arch_fast_hash(const void *data, u32 len, u32 seed) | ||
| 23 | { | ||
| 24 | return arch_hash_ops.hash(data, len, seed); | ||
| 25 | } | ||
| 26 | EXPORT_SYMBOL_GPL(arch_fast_hash); | ||
| 27 | |||
| 28 | u32 arch_fast_hash2(const u32 *data, u32 len, u32 seed) | ||
| 29 | { | ||
| 30 | return arch_hash_ops.hash2(data, len, seed); | ||
| 31 | } | ||
| 32 | EXPORT_SYMBOL_GPL(arch_fast_hash2); | ||
| 33 | |||
| 34 | static int __init hashlib_init(void) | ||
| 35 | { | ||
| 36 | setup_arch_fast_hash(&arch_hash_ops); | ||
| 37 | return 0; | ||
| 38 | } | ||
| 39 | early_initcall(hashlib_init); | ||
