From patchwork Mon Oct 26 11:49:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincenzo Frascino X-Patchwork-Id: 11856927 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF54EC4363A for ; Mon, 26 Oct 2020 11:52:01 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6D44A22263 for ; Mon, 26 Oct 2020 11:52:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="NGyC+QU1" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6D44A22263 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=l8DTT0XLxgJ9vbG8Q6GMFKOpDZNTGuSgmMXaLrRy8Ws=; b=NGyC+QU1y2OVcJcIW5XbD7dvD spR3G81GRMOUvotE8LePtq4tqFcVHQzuxlBW93/Afi53TF0lD+2kGr0uxkj+VvCffOYf4FveIg4eM yexNNj43SJAgX2hep1P8PhR2Fbv4RTcqVr0qjXwUtLV1JtDIGvuu1aT8k21BhBCyIU5SOxnI6LE+d hTVoTUFBf7e6SU0QguEjc0ZgAEGxrGcqcuxNSavjoJQ6IxbhKxsDH3Iey3kYC3xpJelJDazyMWnkX MeSTnMjp+En88y0JpT6a7VkcR56iZ56hELxOtArKgUtDJlwLyivc/Wo+Er7euRAdIErHQ527wpe3P 4XQKwuSsQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kX11F-0006tt-4G; Mon, 26 Oct 2020 11:50:33 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kX10y-0006pG-10 for linux-arm-kernel@lists.infradead.org; Mon, 26 Oct 2020 11:50:17 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 5E46B1474; Mon, 26 Oct 2020 04:50:15 -0700 (PDT) Received: from e119884-lin.cambridge.arm.com (e119884-lin.cambridge.arm.com [10.1.196.72]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 286993F719; Mon, 26 Oct 2020 04:50:14 -0700 (PDT) From: Vincenzo Frascino To: linux-arch@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v4 5/5] kselftest: Extend vdso correctness test to clock_gettime64 Date: Mon, 26 Oct 2020 11:49:45 +0000 Message-Id: <20201026114945.48532-6-vincenzo.frascino@arm.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201026114945.48532-1-vincenzo.frascino@arm.com> References: <20201026114945.48532-1-vincenzo.frascino@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201026_075016_228344_6A820EB9 X-CRM114-Status: GOOD ( 21.04 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Gleixner , Vincenzo Frascino , Shuah Khan , Arnd Bergmann , Andy Lutomirski Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org With the release of Linux 5.1 has been added a new syscall, clock_gettime64, that provided a 64 bit time value for a specified clock_ID to make the kernel Y2038 safe on 32 bit architectures. Extend the vdso correctness test to cover the newly exposed vdso function. Cc: Shuah Khan Signed-off-by: Vincenzo Frascino --- tools/testing/selftests/vDSO/vdso_config.h | 4 +- .../selftests/vDSO/vdso_test_correctness.c | 115 +++++++++++++++++- 2 files changed, 115 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/vDSO/vdso_config.h b/tools/testing/selftests/vDSO/vdso_config.h index eeb725df6045..6a6fe8d4ff55 100644 --- a/tools/testing/selftests/vDSO/vdso_config.h +++ b/tools/testing/selftests/vDSO/vdso_config.h @@ -66,12 +66,13 @@ static const char *versions[6] = { "LINUX_4.15", }; -static const char *names[2][5] = { +static const char *names[2][6] = { { "__kernel_gettimeofday", "__kernel_clock_gettime", "__kernel_time", "__kernel_clock_getres", + "__kernel_getcpu", #if defined(VDSO_32BIT) "__kernel_clock_gettime64", #endif @@ -81,6 +82,7 @@ static const char *names[2][5] = { "__vdso_clock_gettime", "__vdso_time", "__vdso_clock_getres", + "__vdso_getcpu", #if defined(VDSO_32BIT) "__vdso_clock_gettime64", #endif diff --git a/tools/testing/selftests/vDSO/vdso_test_correctness.c b/tools/testing/selftests/vDSO/vdso_test_correctness.c index 42052db0f870..5029ef9b228c 100644 --- a/tools/testing/selftests/vDSO/vdso_test_correctness.c +++ b/tools/testing/selftests/vDSO/vdso_test_correctness.c @@ -19,6 +19,10 @@ #include #include +#include "vdso_config.h" + +static const char **name; + #ifndef SYS_getcpu # ifdef __x86_64__ # define SYS_getcpu 309 @@ -27,6 +31,17 @@ # endif #endif +#ifndef __NR_clock_gettime64 +#define __NR_clock_gettime64 403 +#endif + +#ifndef __kernel_timespec +struct __kernel_timespec { + long long tv_sec; + long long tv_nsec; +}; +#endif + /* max length of lines in /proc/self/maps - anything longer is skipped here */ #define MAPS_LINE_LEN 128 @@ -36,6 +51,10 @@ typedef int (*vgettime_t)(clockid_t, struct timespec *); vgettime_t vdso_clock_gettime; +typedef int (*vgettime64_t)(clockid_t, struct __kernel_timespec *); + +vgettime64_t vdso_clock_gettime64; + typedef long (*vgtod_t)(struct timeval *tv, struct timezone *tz); vgtod_t vdso_gettimeofday; @@ -99,17 +118,23 @@ static void fill_function_pointers() return; } - vdso_getcpu = (getcpu_t)dlsym(vdso, "__vdso_getcpu"); + vdso_getcpu = (getcpu_t)dlsym(vdso, name[4]); if (!vdso_getcpu) printf("Warning: failed to find getcpu in vDSO\n"); vgetcpu = (getcpu_t) vsyscall_getcpu(); - vdso_clock_gettime = (vgettime_t)dlsym(vdso, "__vdso_clock_gettime"); + vdso_clock_gettime = (vgettime_t)dlsym(vdso, name[1]); if (!vdso_clock_gettime) printf("Warning: failed to find clock_gettime in vDSO\n"); - vdso_gettimeofday = (vgtod_t)dlsym(vdso, "__vdso_gettimeofday"); +#if defined(VDSO_32BIT) + vdso_clock_gettime64 = (vgettime64_t)dlsym(vdso, name[5]); + if (!vdso_clock_gettime64) + printf("Warning: failed to find clock_gettime64 in vDSO\n"); +#endif + + vdso_gettimeofday = (vgtod_t)dlsym(vdso, name[0]); if (!vdso_gettimeofday) printf("Warning: failed to find gettimeofday in vDSO\n"); @@ -126,6 +151,11 @@ static inline int sys_clock_gettime(clockid_t id, struct timespec *ts) return syscall(__NR_clock_gettime, id, ts); } +static inline int sys_clock_gettime64(clockid_t id, struct __kernel_timespec *ts) +{ + return syscall(__NR_clock_gettime64, id, ts); +} + static inline int sys_gettimeofday(struct timeval *tv, struct timezone *tz) { return syscall(__NR_gettimeofday, tv, tz); @@ -191,6 +221,15 @@ static bool ts_leq(const struct timespec *a, const struct timespec *b) return a->tv_nsec <= b->tv_nsec; } +static bool ts64_leq(const struct __kernel_timespec *a, + const struct __kernel_timespec *b) +{ + if (a->tv_sec != b->tv_sec) + return a->tv_sec < b->tv_sec; + else + return a->tv_nsec <= b->tv_nsec; +} + static bool tv_leq(const struct timeval *a, const struct timeval *b) { if (a->tv_sec != b->tv_sec) @@ -254,7 +293,10 @@ static void test_one_clock_gettime(int clock, const char *name) if (!ts_leq(&start, &vdso) || !ts_leq(&vdso, &end)) { printf("[FAIL]\tTimes are out of sequence\n"); nerrs++; + return; } + + printf("[OK]\tTest Passed.\n"); } static void test_clock_gettime(void) @@ -275,6 +317,70 @@ static void test_clock_gettime(void) test_one_clock_gettime(INT_MAX, "invalid"); } +static void test_one_clock_gettime64(int clock, const char *name) +{ + struct __kernel_timespec start, vdso, end; + int vdso_ret, end_ret; + + printf("[RUN]\tTesting clock_gettime64 for clock %s (%d)...\n", name, clock); + + if (sys_clock_gettime64(clock, &start) < 0) { + if (errno == EINVAL) { + vdso_ret = vdso_clock_gettime64(clock, &vdso); + if (vdso_ret == -EINVAL) { + printf("[OK]\tNo such clock.\n"); + } else { + printf("[FAIL]\tNo such clock, but __vdso_clock_gettime64 returned %d\n", vdso_ret); + nerrs++; + } + } else { + printf("[WARN]\t clock_gettime64(%d) syscall returned error %d\n", clock, errno); + } + return; + } + + vdso_ret = vdso_clock_gettime64(clock, &vdso); + end_ret = sys_clock_gettime64(clock, &end); + + if (vdso_ret != 0 || end_ret != 0) { + printf("[FAIL]\tvDSO returned %d, syscall errno=%d\n", + vdso_ret, errno); + nerrs++; + return; + } + + printf("\t%llu.%09ld %llu.%09ld %llu.%09ld\n", + (unsigned long long)start.tv_sec, start.tv_nsec, + (unsigned long long)vdso.tv_sec, vdso.tv_nsec, + (unsigned long long)end.tv_sec, end.tv_nsec); + + if (!ts64_leq(&start, &vdso) || !ts64_leq(&vdso, &end)) { + printf("[FAIL]\tTimes are out of sequence\n"); + nerrs++; + return; + } + + printf("[OK]\tTest Passed.\n"); +} + +static void test_clock_gettime64(void) +{ + if (!vdso_clock_gettime64) { + printf("[SKIP]\tNo vDSO, so skipping clock_gettime64() tests\n"); + return; + } + + for (int clock = 0; clock < sizeof(clocknames) / sizeof(clocknames[0]); + clock++) { + test_one_clock_gettime64(clock, clocknames[clock]); + } + + /* Also test some invalid clock ids */ + test_one_clock_gettime64(-1, "invalid"); + test_one_clock_gettime64(INT_MIN, "invalid"); + test_one_clock_gettime64(INT_MAX, "invalid"); +} + static void test_gettimeofday(void) { struct timeval start, vdso, end; @@ -327,9 +433,12 @@ static void test_gettimeofday(void) int main(int argc, char **argv) { + name = (const char **)&names[VDSO_NAMES]; + fill_function_pointers(); test_clock_gettime(); + test_clock_gettime64(); test_gettimeofday(); /*