From 0b985d2b11df9b34bbc8ebb300b2ec493d7dc5b8 Mon Sep 17 00:00:00 2001 From: Loic Dachary Date: Tue, 25 Nov 2014 10:39:21 +0100 Subject: [PATCH] arch: fix neon feature detection The fread function returns the number of elements read, not the number of bytes. Introduced by 1cef8339f7a2a503327c20c014e696c91d36281e , after giant. Add tests for protection against similar regressions. http://tracker.ceph.com/issues/10185 Fixes: #10185 Signed-off-by: Loic Dachary --- src/arch/neon.c | 2 +- src/test/test_arch.cc | 88 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 81 insertions(+), 9 deletions(-) diff --git a/src/arch/neon.c b/src/arch/neon.c index 8baadedcc8d4b..6dad7e6e13eb9 100644 --- a/src/arch/neon.c +++ b/src/arch/neon.c @@ -22,7 +22,7 @@ static unsigned long get_auxval(unsigned long type) if (f) { ElfW(auxv_t) entry; while ((read = fread(&entry, sizeof(entry), 1, f)) > 0) { - if (read != sizeof(entry)) + if (read != 1) break; if (entry.a_type == type) { result = entry.a_un.a_val; diff --git a/src/test/test_arch.cc b/src/test/test_arch.cc index 7b7ffe42f67e6..3b0cd8267f228 100644 --- a/src/test/test_arch.cc +++ b/src/test/test_arch.cc @@ -1,20 +1,92 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph distributed storage system + * + * Copyright (C) 2014 Red Hat + * + * Author: Loic Dachary + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + */ #include -#include -#include #include "arch/probe.h" #include "arch/intel.h" #include "arch/neon.h" +#include "global/global_init.h" +#include "common/ceph_argparse.h" +#include "global/global_context.h" +#include "gtest/gtest.h" + +#define FLAGS_SIZE 4096 + +TEST(Arch, all) +{ + ceph_arch_probe(); + EXPECT_TRUE(ceph_arch_probed); + +#if (__arm__ || __aarch64__ || __x86_64__) && __linux__ + char flags[FLAGS_SIZE]; + FILE *f = popen("grep '^\\(flags\\|Features\\)[ ]*:' " + "/proc/cpuinfo | head -1", "r"); + if(f == NULL || fgets(flags, FLAGS_SIZE - 1, f) == NULL) { + // silently do nothing if /proc/cpuinfo does exist, is not + // readable or does not contain the expected information + if (f) + pclose(f); + return; + } + pclose(f); + flags[strlen(flags) - 1] = ' '; + + int expected; + + expected = strstr(flags, " neon ") ? 1 : 0; + EXPECT_EQ(expected, ceph_arch_neon); + + expected = strstr(flags, " pclmulqdq ") ? 1 : 0; + EXPECT_EQ(expected, ceph_arch_intel_pclmul); + + expected = strstr(flags, " sse4_2 ") ? 1 : 0; + EXPECT_EQ(expected, ceph_arch_intel_sse42); + + expected = strstr(flags, " sse4_1 ") ? 1 : 0; + EXPECT_EQ(expected, ceph_arch_intel_sse41); + + expected = (strstr(flags, " sse3 ") || strstr(flags, " ssse3 ")) ? 1 : 0; + EXPECT_EQ(expected, ceph_arch_intel_sse3); + + expected = strstr(flags, " ssse3 ") ? 1 : 0; + EXPECT_EQ(expected, ceph_arch_intel_ssse3); + + expected = strstr(flags, " sse2 ") ? 1 : 0; + EXPECT_EQ(expected, ceph_arch_intel_sse2); +#endif +} int main(int argc, char **argv) { - ceph_arch_probe(); - assert(ceph_arch_probed); + vector args; + argv_to_vec(argc, (const char **)argv, args); - printf("ceph_arch_intel_sse42 = %d\n", ceph_arch_intel_sse42); - printf("ceph_arch_intel_sse2 = %d\n", ceph_arch_intel_sse2); - printf("ceph_arch_neon = %d\n", ceph_arch_neon); + global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0); + common_init_finish(g_ceph_context); - return 0; + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } + + +/* + * Local Variables: + * compile-command: "cd .. ; make -j4 && + * make unittest_arch && + * valgrind --tool=memcheck ./unittest_arch --gtest_filter=*.*" + * End: + */ -- 2.39.5