From patchwork Tue Sep 21 16:33:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Axel Rasmussen X-Patchwork-Id: 12508325 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=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL 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 74DDCC433EF for ; Tue, 21 Sep 2021 16:33:29 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id DF5BC6023D for ; Tue, 21 Sep 2021 16:33:28 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org DF5BC6023D Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kvack.org Received: by kanga.kvack.org (Postfix) id 61AEC940011; Tue, 21 Sep 2021 12:33:28 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 5CA44940007; Tue, 21 Sep 2021 12:33:28 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 49286940011; Tue, 21 Sep 2021 12:33:28 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0038.hostedemail.com [216.40.44.38]) by kanga.kvack.org (Postfix) with ESMTP id 3C350940007 for ; Tue, 21 Sep 2021 12:33:28 -0400 (EDT) Received: from smtpin13.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id EA8768249980 for ; Tue, 21 Sep 2021 16:33:27 +0000 (UTC) X-FDA: 78612126054.13.BC6B91E Received: from mail-qv1-f74.google.com (mail-qv1-f74.google.com [209.85.219.74]) by imf09.hostedemail.com (Postfix) with ESMTP id 9B5FA300010B for ; Tue, 21 Sep 2021 16:33:27 +0000 (UTC) Received: by mail-qv1-f74.google.com with SMTP id z8-20020a056214040800b00380dea65c01so24910785qvx.4 for ; Tue, 21 Sep 2021 09:33:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:message-id:mime-version:subject:from:to:cc; bh=eRBohQvfWYLfYtUzm95CYLT/7wrohS6aURHgvBsCQbc=; b=RT/CTVw0IjX1ywZHTy43dO2Ttl+CVT/8ZEQ8b9W9XXrTSLQo1C8YFjBrPAye30XWl5 zE4QVhIbnPzr0qXErl8f9V32ji66+eUDjcX5TbsA8De5jJ3cyh7MZP8S9aQKL3+UND28 uaINQRDjmYll7b9dcxHimpJV1b9bL7pZ6h8Du0csdbDQeXIew5Clh1ZWvbI7+2B9K6Ah JpCPF8hUcadLZYkHWRcA2TxEMdju0s5EiQ8l4dmpA5AZfkbZuzsJgyN/rOWCwI2w0enh zU6VTl8ljsElsP4FeC65akXy258w7hOpPQME3YxDvQ4IkYU0pgCcQ64NVC7fMQwDvk0Y OPnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=eRBohQvfWYLfYtUzm95CYLT/7wrohS6aURHgvBsCQbc=; b=o/g6MY4tVKYRj/WrXj46Ah/FzQ5BwiOi9HJX/ij4Skn9f5RtapzgthpeOn1MiQdjeB 3CtDbC9mYcRcEAf6KgqnpihzOe53xQoPw8WxMpH5IlBHJE9DlgQepu3ruDyWWGiZ8GYv h2EMVrN+rssBEM1CunezaUx3kxCoT7cHPWMPEON6HtNKAa8YqXqAI+UqoTyfFOfdYf1L 0CYbrzJNLPVjwQ0aqa3JNLIiUhSE7QWrnjtdyiQZ/vrznk2UX2rwXdeAm/FmRXKMda8B mMtz4dUPFTbummIRibRb2wHV0RJkxyP01umbNnXdve+VkZBe9hBTVD3SY4f8Qsh8jzxF inWw== X-Gm-Message-State: AOAM530vMI5W1E3iyMwQfiYVG8QpYn7jlQp7RiHM4kA2GXvqQWObZBpp cXPFiOYf8++KRkZpuoqtxChOQ93eXmI1OkhT2kib X-Google-Smtp-Source: ABdhPJxYT3xrgOkjcmsxGwfgxs89od1eDDVy3/ncgM+iAfoUNxOGOowrVKVe2XEiFGiq+R3QREZKy2khRhYRG1ntWQ2V X-Received: from ajr0.svl.corp.google.com ([2620:15c:2cd:203:ed57:a230:8c3d:64d8]) (user=axelrasmussen job=sendgmr) by 2002:a05:6214:122e:: with SMTP id p14mr32188853qvv.37.1632242006900; Tue, 21 Sep 2021 09:33:26 -0700 (PDT) Date: Tue, 21 Sep 2021 09:33:21 -0700 Message-Id: <20210921163323.944352-1-axelrasmussen@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.33.0.464.g1972c5931b-goog Subject: [PATCH 1/3] userfaultfd/selftests: fix feature support detection From: Axel Rasmussen To: Andrew Morton , Peter Xu , Shuah Khan Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Axel Rasmussen X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: 9B5FA300010B X-Stat-Signature: jfe4xgbtgpz9r4kss3n54oh16m89pt9r Authentication-Results: imf09.hostedemail.com; dkim=pass header.d=google.com header.s=20210112 header.b="RT/CTVw0"; spf=pass (imf09.hostedemail.com: domain of 3VglKYQ0KCKEBYFMSBTNVTTFOHPPHMF.DPNMJOVY-NNLWBDL.PSH@flex--axelrasmussen.bounces.google.com designates 209.85.219.74 as permitted sender) smtp.mailfrom=3VglKYQ0KCKEBYFMSBTNVTTFOHPPHMF.DPNMJOVY-NNLWBDL.PSH@flex--axelrasmussen.bounces.google.com; dmarc=pass (policy=reject) header.from=google.com X-HE-Tag: 1632242007-932303 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Currently, the test decides whether or not to test certain features (e.g., writeprotect support) essentially by examining command-line arguments. For example, if we're testing anonymous memory, then we should test writeprotect support as well (since it generally is supported for anonymous). This is broken, however. Take writeprotect support as an example: sure it's supported for anon, but it also requires that we have CONFIG_HAVE_ARCH_USERFAULTFD_WP. I.e., it is not supported at all on aarch64. So, running the test on such an arch fails: it tries to test writeprotect for anon, but since it isn't *actually* supported, it fails. So, instead of checking command-line arguments to the test, check the features the way the UFFD API intends: when we open a new userfaultfd, pass in the feature(s) this test case would like to try to exercise. The kernel reports back a subset of those features which are actually supported: check these returned flags to see if the features are *actually* supported. (For a couple of cases, where *registration* would fail [with -EINVAL] even though UFFDIO_API reports the feature as supported, we have to check test_type as well as the feature flag.) In some cases, we check immediately after opening the userfaultfd, and if the features are missing, we skip the entire test. In some other cases, we can proceed with "most" of the test, only skipping a few pieces. This lets us remove the global test_uffdio_wp and test_uffdio_minor variables entirely. Signed-off-by: Axel Rasmussen --- tools/testing/selftests/vm/userfaultfd.c | 94 +++++++++++------------- 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c index 10ab56c2484a..2366caf90435 100644 --- a/tools/testing/selftests/vm/userfaultfd.c +++ b/tools/testing/selftests/vm/userfaultfd.c @@ -79,10 +79,6 @@ static int test_type; #define ALARM_INTERVAL_SECS 10 static volatile bool test_uffdio_copy_eexist = true; static volatile bool test_uffdio_zeropage_eexist = true; -/* Whether to test uffd write-protection */ -static bool test_uffdio_wp = false; -/* Whether to test uffd minor faults */ -static bool test_uffdio_minor = false; static bool map_shared; static int shm_fd; @@ -90,6 +86,7 @@ static int huge_fd; static char *huge_fd_off0; static unsigned long long *count_verify; static int uffd = -1; +static uint64_t uffd_features; static int uffd_flags, finished, *pipefd; static char *area_src, *area_src_alias, *area_dst, *area_dst_alias; static char *zeropage; @@ -345,7 +342,7 @@ static struct uffd_test_ops hugetlb_uffd_test_ops = { static struct uffd_test_ops *uffd_test_ops; -static void userfaultfd_open(uint64_t *features) +static void userfaultfd_open(uint64_t features) { struct uffdio_api uffdio_api; @@ -355,14 +352,20 @@ static void userfaultfd_open(uint64_t *features) uffd_flags = fcntl(uffd, F_GETFD, NULL); uffdio_api.api = UFFD_API; - uffdio_api.features = *features; + uffdio_api.features = features; if (ioctl(uffd, UFFDIO_API, &uffdio_api)) err("UFFDIO_API failed.\nPlease make sure to " "run with either root or ptrace capability."); if (uffdio_api.api != UFFD_API) err("UFFDIO_API error: %" PRIu64, (uint64_t)uffdio_api.api); - *features = uffdio_api.features; + uffd_features = uffdio_api.features; +} + +static inline bool uffd_wp_supported(void) +{ + return test_type == TEST_ANON && + (uffd_features & UFFD_FEATURE_PAGEFAULT_FLAG_WP); } static inline void munmap_area(void **area) @@ -397,6 +400,7 @@ static void uffd_test_ctx_clear(void) err("close uffd"); uffd = -1; } + uffd_features = 0; huge_fd_off0 = NULL; munmap_area((void **)&area_src); @@ -405,7 +409,7 @@ static void uffd_test_ctx_clear(void) munmap_area((void **)&area_dst_alias); } -static void uffd_test_ctx_init_ext(uint64_t *features) +static void uffd_test_ctx_init(uint64_t features) { unsigned long nr, cpu; @@ -445,11 +449,6 @@ static void uffd_test_ctx_init_ext(uint64_t *features) err("pipe"); } -static inline void uffd_test_ctx_init(uint64_t features) -{ - uffd_test_ctx_init_ext(&features); -} - static int my_bcmp(char *str1, char *str2, size_t n) { unsigned long i; @@ -587,7 +586,7 @@ static int __copy_page(int ufd, unsigned long offset, bool retry) uffdio_copy.dst = (unsigned long) area_dst + offset; uffdio_copy.src = (unsigned long) area_src + offset; uffdio_copy.len = page_size; - if (test_uffdio_wp) + if (uffd_wp_supported()) uffdio_copy.mode = UFFDIO_COPY_MODE_WP; else uffdio_copy.mode = 0; @@ -778,7 +777,7 @@ static void *background_thread(void *arg) * at least the first half of the pages mapped already which * can be write-protected for testing */ - if (test_uffdio_wp) + if (uffd_wp_supported()) wp_range(uffd, (unsigned long)area_dst + start_nr * page_size, nr_pages_per_cpu * page_size, true); @@ -1062,12 +1061,12 @@ static int userfaultfd_zeropage_test(void) printf("testing UFFDIO_ZEROPAGE: "); fflush(stdout); - uffd_test_ctx_init(0); + uffd_test_ctx_init(UFFD_FEATURE_PAGEFAULT_FLAG_WP); uffdio_register.range.start = (unsigned long) area_dst; uffdio_register.range.len = nr_pages * page_size; uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING; - if (test_uffdio_wp) + if (uffd_wp_supported()) uffdio_register.mode |= UFFDIO_REGISTER_MODE_WP; if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) err("register failure"); @@ -1089,7 +1088,7 @@ static int userfaultfd_events_test(void) struct uffdio_register uffdio_register; unsigned long expected_ioctls; pthread_t uffd_mon; - int err, features; + int err; pid_t pid; char c; struct uffd_stats stats = { 0 }; @@ -1097,16 +1096,15 @@ static int userfaultfd_events_test(void) printf("testing events (fork, remap, remove): "); fflush(stdout); - features = UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP | - UFFD_FEATURE_EVENT_REMOVE; - uffd_test_ctx_init(features); + uffd_test_ctx_init(UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP | + UFFD_FEATURE_EVENT_REMOVE | UFFD_FEATURE_PAGEFAULT_FLAG_WP); fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK); uffdio_register.range.start = (unsigned long) area_dst; uffdio_register.range.len = nr_pages * page_size; uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING; - if (test_uffdio_wp) + if (uffd_wp_supported()) uffdio_register.mode |= UFFDIO_REGISTER_MODE_WP; if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) err("register failure"); @@ -1144,7 +1142,7 @@ static int userfaultfd_sig_test(void) unsigned long expected_ioctls; unsigned long userfaults; pthread_t uffd_mon; - int err, features; + int err; pid_t pid; char c; struct uffd_stats stats = { 0 }; @@ -1152,15 +1150,15 @@ static int userfaultfd_sig_test(void) printf("testing signal delivery: "); fflush(stdout); - features = UFFD_FEATURE_EVENT_FORK|UFFD_FEATURE_SIGBUS; - uffd_test_ctx_init(features); + uffd_test_ctx_init(UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_SIGBUS | + UFFD_FEATURE_PAGEFAULT_FLAG_WP); fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK); uffdio_register.range.start = (unsigned long) area_dst; uffdio_register.range.len = nr_pages * page_size; uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING; - if (test_uffdio_wp) + if (uffd_wp_supported()) uffdio_register.mode |= UFFDIO_REGISTER_MODE_WP; if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) err("register failure"); @@ -1209,25 +1207,23 @@ static int userfaultfd_minor_test(void) void *expected_page; char c; struct uffd_stats stats = { 0 }; - uint64_t req_features, features_out; - - if (!test_uffdio_minor) - return 0; + uint64_t features; printf("testing minor faults: "); fflush(stdout); - if (test_type == TEST_HUGETLB) - req_features = UFFD_FEATURE_MINOR_HUGETLBFS; + if (test_type == TEST_HUGETLB && map_shared) + features = UFFD_FEATURE_MINOR_HUGETLBFS; else if (test_type == TEST_SHMEM) - req_features = UFFD_FEATURE_MINOR_SHMEM; - else - return 1; + features = UFFD_FEATURE_MINOR_SHMEM; + else { + printf("skipping test due to unsupported memory type\n"); + return 0; + } - features_out = req_features; - uffd_test_ctx_init_ext(&features_out); + uffd_test_ctx_init(features); /* If kernel reports required features aren't supported, skip test. */ - if ((features_out & req_features) != req_features) { + if ((uffd_features & features) != features) { printf("skipping test due to lack of feature support\n"); fflush(stdout); return 0; @@ -1349,10 +1345,6 @@ static void userfaultfd_pagemap_test(unsigned int test_pgsize) int pagemap_fd; uint64_t value; - /* Pagemap tests uffd-wp only */ - if (!test_uffdio_wp) - return; - /* Not enough memory to test this page size */ if (test_pgsize > nr_pages * page_size) return; @@ -1361,7 +1353,12 @@ static void userfaultfd_pagemap_test(unsigned int test_pgsize) /* Flush so it doesn't flush twice in parent/child later */ fflush(stdout); - uffd_test_ctx_init(0); + uffd_test_ctx_init(UFFD_FEATURE_PAGEFAULT_FLAG_WP); + /* Pagemap tests uffd-wp only */ + if (!uffd_wp_supported()) { + printf("skipping test due to lack of feature support\n"); + return; + } if (test_pgsize > page_size) { /* This is a thp test */ @@ -1426,7 +1423,7 @@ static int userfaultfd_stress(void) struct uffdio_register uffdio_register; struct uffd_stats uffd_stats[nr_cpus]; - uffd_test_ctx_init(0); + uffd_test_ctx_init(UFFD_FEATURE_PAGEFAULT_FLAG_WP); if (posix_memalign(&area, page_size, page_size)) err("out of memory"); @@ -1464,7 +1461,7 @@ static int userfaultfd_stress(void) uffdio_register.range.start = (unsigned long) area_dst; uffdio_register.range.len = nr_pages * page_size; uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING; - if (test_uffdio_wp) + if (uffd_wp_supported()) uffdio_register.mode |= UFFDIO_REGISTER_MODE_WP; if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) err("register failure"); @@ -1513,7 +1510,7 @@ static int userfaultfd_stress(void) return 1; /* Clear all the write protections if there is any */ - if (test_uffdio_wp) + if (uffd_wp_supported()) wp_range(uffd, (unsigned long)area_dst, nr_pages * page_size, false); @@ -1595,8 +1592,6 @@ static void set_test_type(const char *type) if (!strcmp(type, "anon")) { test_type = TEST_ANON; uffd_test_ops = &anon_uffd_test_ops; - /* Only enable write-protect test for anonymous test */ - test_uffdio_wp = true; } else if (!strcmp(type, "hugetlb")) { test_type = TEST_HUGETLB; uffd_test_ops = &hugetlb_uffd_test_ops; @@ -1604,13 +1599,10 @@ static void set_test_type(const char *type) map_shared = true; test_type = TEST_HUGETLB; uffd_test_ops = &hugetlb_uffd_test_ops; - /* Minor faults require shared hugetlb; only enable here. */ - test_uffdio_minor = true; } else if (!strcmp(type, "shmem")) { map_shared = true; test_type = TEST_SHMEM; uffd_test_ops = &shmem_uffd_test_ops; - test_uffdio_minor = true; } else { err("Unknown test type: %s", type); } From patchwork Tue Sep 21 16:33:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Axel Rasmussen X-Patchwork-Id: 12508327 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=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham 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 2D34FC433FE for ; Tue, 21 Sep 2021 16:33:31 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 9B8FB6115A for ; Tue, 21 Sep 2021 16:33:30 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 9B8FB6115A Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kvack.org Received: by kanga.kvack.org (Postfix) id 30D9D940012; Tue, 21 Sep 2021 12:33:30 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 2BCBA940007; Tue, 21 Sep 2021 12:33:30 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 15E6B940012; Tue, 21 Sep 2021 12:33:30 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0100.hostedemail.com [216.40.44.100]) by kanga.kvack.org (Postfix) with ESMTP id 0540D940007 for ; Tue, 21 Sep 2021 12:33:30 -0400 (EDT) Received: from smtpin33.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id B30A68249980 for ; Tue, 21 Sep 2021 16:33:29 +0000 (UTC) X-FDA: 78612126138.33.C5BCE8E Received: from mail-qk1-f201.google.com (mail-qk1-f201.google.com [209.85.222.201]) by imf20.hostedemail.com (Postfix) with ESMTP id 7163ED0000AB for ; Tue, 21 Sep 2021 16:33:29 +0000 (UTC) Received: by mail-qk1-f201.google.com with SMTP id s18-20020a05620a255200b00433885d4fa7so21397700qko.4 for ; Tue, 21 Sep 2021 09:33:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=NgPoad1ME6wlZVXGi4jGZtPG1kpzd8MCngh0GNGmSTU=; b=OiBXpaE7L7Cg8Vn+IE64i4Bmc0+OP/WPBKzNQewvjrlr6POIZZk+Ky9xhXty8SZ8lP RKxJXIhHc5So/Kp1f68gaaPk7U39WA10s+ztBJQqJfPxLoF0mZBXA7tGzbDhd825rFfR OH+uArjVvTx1MmoJDVDAVESSeAa8gD35aUj6Sr7xwfWGttxUFmpNkbMIg3X/mugBdbu5 aq0ToSOB8bOQFJE0lUjmNAhqmbDtq0DufSUQX6+e99zp5bZVrWrWRLKdKgrU7d1V0SD8 Fme80gZSqKVTyHq2gQoPVM/Twl/7ePPdwGWN9p7x17VmTMfkNdj1lKr16+dl7pSk0FWO eKOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=NgPoad1ME6wlZVXGi4jGZtPG1kpzd8MCngh0GNGmSTU=; b=LuGDeFqgIT/zIOmw5YzjLC+1+GzS5TzNLz1jDko4NMUYZkWEU1Frq249D3wXRg1r9X ac/hl7P8BLMaayO2RH1PFm6SFAgH0onsAKCp+Y6ibs/kmOT1dg/ic2ZRz1iJj6S7+FTF hKOoP+ScZuBeEsWg5noCHtT9mxn0A9kIEmikv86/supuNIpFVB4NBdEcLDs5QHrtmktN GrO33y5W1IPsbU9eNeOmrbv6fAWt9wcUmsjXJuLHcy5NbyggnNpPGqxSpzzU3bhJNatC 3t/uDgFEjrHfq9ANj0qY3J3RUu/gTtRtUSoFyXp91qsxeT0+SceJNuEWgz+EZKE4Euht lRaw== X-Gm-Message-State: AOAM531oowtHouNsVc63kNSs7+07efHdeDfWlz7cOhA/UlVZwar1eR1k 3DqMbM0pMpT9HggvGyX825+33RPWTkJu2/1Gl7+b X-Google-Smtp-Source: ABdhPJzFUqv9WN4LgLUzjGZJ0PdywLcz6io6aPqJZC1htFwB2/tNqKY4+zhvKxW6rLMTqAezbaRHM8hF3wMx62GMdI3q X-Received: from ajr0.svl.corp.google.com ([2620:15c:2cd:203:ed57:a230:8c3d:64d8]) (user=axelrasmussen job=sendgmr) by 2002:ad4:4873:: with SMTP id u19mr32664806qvy.11.1632242008820; Tue, 21 Sep 2021 09:33:28 -0700 (PDT) Date: Tue, 21 Sep 2021 09:33:22 -0700 In-Reply-To: <20210921163323.944352-1-axelrasmussen@google.com> Message-Id: <20210921163323.944352-2-axelrasmussen@google.com> Mime-Version: 1.0 References: <20210921163323.944352-1-axelrasmussen@google.com> X-Mailer: git-send-email 2.33.0.464.g1972c5931b-goog Subject: [PATCH 2/3] userfaultfd/selftests: fix calculation of expected ioctls From: Axel Rasmussen To: Andrew Morton , Peter Xu , Shuah Khan Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Axel Rasmussen X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: 7163ED0000AB X-Stat-Signature: iyni9f13un1g1uj8gmr53dqtyqqh3s8o Authentication-Results: imf20.hostedemail.com; dkim=pass header.d=google.com header.s=20210112 header.b=OiBXpaE7; spf=pass (imf20.hostedemail.com: domain of 3WAlKYQ0KCKMDaHOUDVPXVVHQJRRJOH.FRPOLQXa-PPNYDFN.RUJ@flex--axelrasmussen.bounces.google.com designates 209.85.222.201 as permitted sender) smtp.mailfrom=3WAlKYQ0KCKMDaHOUDVPXVVHQJRRJOH.FRPOLQXa-PPNYDFN.RUJ@flex--axelrasmussen.bounces.google.com; dmarc=pass (policy=reject) header.from=google.com X-HE-Tag: 1632242009-326610 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Currently, the list of expected ioctls is stored in uffd_test_ops. This design comes with the implicit assumption that the set of expected ioctls is a function of the memory type (anon, shmem, or hugetlb). However, this is not the case. For example: - UFFDIO_WRITEPROTECT is supported for anon in general, *but not on aarch64* (which lacks CONFIG_HAVE_ARCH_USERFAULTFD_WP). - UFFDIO_WRITEPROTECT is supported for anon, but only if one registers the region with UFFD_REGISTER_MODE_WP. - We want to test (and expect) UFFDIO_CONTINUE, but only for *shared* hugetlb, not private. So, instead, remove the set of expected ioctls from this structure. Define a new function which can compute the correct set by examining the memory type, the userfaultfd registration mode(s), whether map_shared is set, and what set of features the kernel reports as supported (from UFFDIO_API). In addition to being more correct, this improves code re-use - less boilerplate in each test trying to perform this assertion. Signed-off-by: Axel Rasmussen --- tools/testing/selftests/vm/userfaultfd.c | 103 ++++++++++++----------- 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c index 2366caf90435..aad5211f5012 100644 --- a/tools/testing/selftests/vm/userfaultfd.c +++ b/tools/testing/selftests/vm/userfaultfd.c @@ -304,37 +304,24 @@ static void shmem_alias_mapping(__u64 *start, size_t len, unsigned long offset) } struct uffd_test_ops { - unsigned long expected_ioctls; void (*allocate_area)(void **alloc_area); void (*release_pages)(char *rel_area); void (*alias_mapping)(__u64 *start, size_t len, unsigned long offset); }; -#define SHMEM_EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \ - (1 << _UFFDIO_COPY) | \ - (1 << _UFFDIO_ZEROPAGE)) - -#define ANON_EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \ - (1 << _UFFDIO_COPY) | \ - (1 << _UFFDIO_ZEROPAGE) | \ - (1 << _UFFDIO_WRITEPROTECT)) - static struct uffd_test_ops anon_uffd_test_ops = { - .expected_ioctls = ANON_EXPECTED_IOCTLS, .allocate_area = anon_allocate_area, .release_pages = anon_release_pages, .alias_mapping = noop_alias_mapping, }; static struct uffd_test_ops shmem_uffd_test_ops = { - .expected_ioctls = SHMEM_EXPECTED_IOCTLS, .allocate_area = shmem_allocate_area, .release_pages = shmem_release_pages, .alias_mapping = shmem_alias_mapping, }; static struct uffd_test_ops hugetlb_uffd_test_ops = { - .expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC & ~(1 << _UFFDIO_CONTINUE), .allocate_area = hugetlb_allocate_area, .release_pages = hugetlb_release_pages, .alias_mapping = hugetlb_alias_mapping, @@ -368,6 +355,47 @@ static inline bool uffd_wp_supported(void) (uffd_features & UFFD_FEATURE_PAGEFAULT_FLAG_WP); } +static inline uint64_t uffd_minor_feature(void) +{ + if (test_type == TEST_HUGETLB && map_shared) + return UFFD_FEATURE_MINOR_HUGETLBFS; + else if (test_type == TEST_SHMEM) + return UFFD_FEATURE_MINOR_SHMEM; + else + return 0; +} + +static inline bool uffd_minor_supported(void) +{ + return uffd_features & uffd_minor_feature(); +} + +static unsigned long get_expected_ioctls(uint64_t mode) +{ + unsigned long ioctls = UFFD_API_RANGE_IOCTLS; + + if (test_type == TEST_HUGETLB) + ioctls &= ~(1 << _UFFDIO_ZEROPAGE); + + if (!((mode & UFFDIO_REGISTER_MODE_WP) && uffd_wp_supported())) + ioctls &= ~(1 << _UFFDIO_WRITEPROTECT); + + if (!((mode & UFFDIO_REGISTER_MODE_MINOR) && uffd_minor_supported())) + ioctls &= ~(1 << _UFFDIO_CONTINUE); + + return ioctls; +} + +static inline void assert_expected_ioctls_present(uint64_t mode, uint64_t ioctls) +{ + uint64_t expected = get_expected_ioctls(mode); + uint64_t actual = ioctls & expected; + + if (actual != expected) + err("missing ioctl(s); expected: %"PRIx64" actual: %"PRIx64, + expected, actual); +} + static inline void munmap_area(void **area) { if (*area) @@ -1012,11 +1040,9 @@ static int __uffdio_zeropage(int ufd, unsigned long offset, bool retry) { struct uffdio_zeropage uffdio_zeropage; int ret; - unsigned long has_zeropage; + bool has_zeropage = get_expected_ioctls(0) & (1 << _UFFDIO_ZEROPAGE); __s64 res; - has_zeropage = uffd_test_ops->expected_ioctls & (1 << _UFFDIO_ZEROPAGE); - if (offset >= nr_pages * page_size) err("unexpected offset %lu", offset); uffdio_zeropage.range.start = (unsigned long) area_dst + offset; @@ -1056,7 +1082,6 @@ static int uffdio_zeropage(int ufd, unsigned long offset) static int userfaultfd_zeropage_test(void) { struct uffdio_register uffdio_register; - unsigned long expected_ioctls; printf("testing UFFDIO_ZEROPAGE: "); fflush(stdout); @@ -1071,9 +1096,8 @@ static int userfaultfd_zeropage_test(void) if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) err("register failure"); - expected_ioctls = uffd_test_ops->expected_ioctls; - if ((uffdio_register.ioctls & expected_ioctls) != expected_ioctls) - err("unexpected missing ioctl for anon memory"); + assert_expected_ioctls_present( + uffdio_register.mode, uffdio_register.ioctls); if (uffdio_zeropage(uffd, 0)) if (my_bcmp(area_dst, zeropage, page_size)) @@ -1086,7 +1110,6 @@ static int userfaultfd_zeropage_test(void) static int userfaultfd_events_test(void) { struct uffdio_register uffdio_register; - unsigned long expected_ioctls; pthread_t uffd_mon; int err; pid_t pid; @@ -1109,9 +1132,8 @@ static int userfaultfd_events_test(void) if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) err("register failure"); - expected_ioctls = uffd_test_ops->expected_ioctls; - if ((uffdio_register.ioctls & expected_ioctls) != expected_ioctls) - err("unexpected missing ioctl for anon memory"); + assert_expected_ioctls_present( + uffdio_register.mode, uffdio_register.ioctls); if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &stats)) err("uffd_poll_thread create"); @@ -1139,7 +1161,6 @@ static int userfaultfd_events_test(void) static int userfaultfd_sig_test(void) { struct uffdio_register uffdio_register; - unsigned long expected_ioctls; unsigned long userfaults; pthread_t uffd_mon; int err; @@ -1163,9 +1184,8 @@ static int userfaultfd_sig_test(void) if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) err("register failure"); - expected_ioctls = uffd_test_ops->expected_ioctls; - if ((uffdio_register.ioctls & expected_ioctls) != expected_ioctls) - err("unexpected missing ioctl for anon memory"); + assert_expected_ioctls_present( + uffdio_register.mode, uffdio_register.ioctls); if (faulting_process(1)) err("faulting process failed"); @@ -1200,30 +1220,25 @@ static int userfaultfd_sig_test(void) static int userfaultfd_minor_test(void) { struct uffdio_register uffdio_register; - unsigned long expected_ioctls; unsigned long p; pthread_t uffd_mon; uint8_t expected_byte; void *expected_page; char c; struct uffd_stats stats = { 0 }; - uint64_t features; + uint64_t features = uffd_minor_feature(); printf("testing minor faults: "); fflush(stdout); - if (test_type == TEST_HUGETLB && map_shared) - features = UFFD_FEATURE_MINOR_HUGETLBFS; - else if (test_type == TEST_SHMEM) - features = UFFD_FEATURE_MINOR_SHMEM; - else { + if (!features) { printf("skipping test due to unsupported memory type\n"); + fflush(stdout); return 0; } uffd_test_ctx_init(features); - /* If kernel reports required features aren't supported, skip test. */ - if ((uffd_features & features) != features) { + if (!uffd_minor_supported()) { printf("skipping test due to lack of feature support\n"); fflush(stdout); return 0; @@ -1235,10 +1250,8 @@ static int userfaultfd_minor_test(void) if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) err("register failure"); - expected_ioctls = uffd_test_ops->expected_ioctls; - expected_ioctls |= 1 << _UFFDIO_CONTINUE; - if ((uffdio_register.ioctls & expected_ioctls) != expected_ioctls) - err("unexpected missing ioctl(s)"); + assert_expected_ioctls_present( + uffdio_register.mode, uffdio_register.ioctls); /* * After registering with UFFD, populate the non-UFFD-registered side of @@ -1436,8 +1449,6 @@ static int userfaultfd_stress(void) pthread_attr_setstacksize(&attr, 16*1024*1024); while (bounces--) { - unsigned long expected_ioctls; - printf("bounces: %d, mode:", bounces); if (bounces & BOUNCE_RANDOM) printf(" rnd"); @@ -1465,10 +1476,8 @@ static int userfaultfd_stress(void) uffdio_register.mode |= UFFDIO_REGISTER_MODE_WP; if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) err("register failure"); - expected_ioctls = uffd_test_ops->expected_ioctls; - if ((uffdio_register.ioctls & expected_ioctls) != - expected_ioctls) - err("unexpected missing ioctl for anon memory"); + assert_expected_ioctls_present( + uffdio_register.mode, uffdio_register.ioctls); if (area_dst_alias) { uffdio_register.range.start = (unsigned long) From patchwork Tue Sep 21 16:33:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Axel Rasmussen X-Patchwork-Id: 12508329 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=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham 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 53A1AC4332F for ; Tue, 21 Sep 2021 16:33:33 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id F354C60F6D for ; Tue, 21 Sep 2021 16:33:32 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org F354C60F6D Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kvack.org Received: by kanga.kvack.org (Postfix) id 929D7940013; Tue, 21 Sep 2021 12:33:32 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 8D6F0940007; Tue, 21 Sep 2021 12:33:32 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 7C671940013; Tue, 21 Sep 2021 12:33:32 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0199.hostedemail.com [216.40.44.199]) by kanga.kvack.org (Postfix) with ESMTP id 6DC1F940007 for ; Tue, 21 Sep 2021 12:33:32 -0400 (EDT) Received: from smtpin04.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id 2547B1812ED86 for ; Tue, 21 Sep 2021 16:33:32 +0000 (UTC) X-FDA: 78612126264.04.3753197 Received: from mail-qk1-f201.google.com (mail-qk1-f201.google.com [209.85.222.201]) by imf13.hostedemail.com (Postfix) with ESMTP id E6C9A10DFED1 for ; Tue, 21 Sep 2021 16:33:31 +0000 (UTC) Received: by mail-qk1-f201.google.com with SMTP id h10-20020a05620a284a00b003d30e8c8cb5so180945306qkp.11 for ; Tue, 21 Sep 2021 09:33:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=XXlfpcBmbRno5SA+gst6Gevlk7ltg9389UQ9dhNVCvA=; b=Wf+QnXwZGfTR93ea68ZPKzFik9oK5cF0gl/6r7BXDTKkCEkNlT5puLNHR76CLQ4TxS sqnivS0sK15CMFeU/ykdAnnhQlLBTCOEwfM3X+Sc1uvAZ3q2dU+XX2CTC6tqtw/qpobw jEpk3zQXOidiuHrp/6oAP/MWm+Ybq220aML/CuZnSDiuYveXKux6S17aaiLnikWbL+QL k+qzoGVvrmTGw0A2trsphU4lw0U4aTCe3vkkP2ZuPFRvH5Eg6dTZcXR2p3I8D0o3GQAN wmv53dN1fi7EhnyFpRlW+rbaFzAB2o8DOg/NIAJK4uDK/coDPCIvKWAdo9GuKq7tFxG7 uVsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=XXlfpcBmbRno5SA+gst6Gevlk7ltg9389UQ9dhNVCvA=; b=vSd5+hMmr6on1nKciNqwnPF/VRffF+Jnn8LxGdvGxApLOO21AaTiw2kE63ccLaa141 p1TnvMQV5s0q/WPtja3dRnKHjFBMFzXa903Y6kjCrwDPKxXx62P7mpFOlQlaERDHyM1K 2zV+qe5LwTRFMJNjl1Lb6HSZ12NezonX9oiTMCm6XGlYgiimJUKGrlDuwOsoXR66qbD2 4vpgpFjZhBbSK7KlfjhJ7IR42CX0Vynn2pgFQFYIPbFI3N+boPx5CkMYKiivCfcYhA+3 vHfY8wC3IOo+/8UkqyxELYDvx+qLTCX4Z3SM4GbSCE1/FY3nBaqSMSoJfv6AfAOBdoVJ 3juA== X-Gm-Message-State: AOAM532j8dHeDM12tmz5zuiBJeKvaaSGD/ayEnfURUd5D9iSqTIb48EG 2AKwZqUvE6c62wRUOvYlRi/VjB4nUHAuiwfvJATb X-Google-Smtp-Source: ABdhPJwgz8JIJfqh2iJ8cYLJJQmL1F5G7QJHu8shYN6bVP9STb44sPjeNHitaFyPqxCJcvfDRzpn0Hr1vzMSdjOiXvAJ X-Received: from ajr0.svl.corp.google.com ([2620:15c:2cd:203:ed57:a230:8c3d:64d8]) (user=axelrasmussen job=sendgmr) by 2002:a05:6902:124e:: with SMTP id t14mr39259664ybu.106.1632242011222; Tue, 21 Sep 2021 09:33:31 -0700 (PDT) Date: Tue, 21 Sep 2021 09:33:23 -0700 In-Reply-To: <20210921163323.944352-1-axelrasmussen@google.com> Message-Id: <20210921163323.944352-3-axelrasmussen@google.com> Mime-Version: 1.0 References: <20210921163323.944352-1-axelrasmussen@google.com> X-Mailer: git-send-email 2.33.0.464.g1972c5931b-goog Subject: [PATCH 3/3] userfaultfd/selftests: don't rely on GNU extensions for random numbers From: Axel Rasmussen To: Andrew Morton , Peter Xu , Shuah Khan Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Axel Rasmussen X-Rspamd-Server: rspam01 X-Rspamd-Queue-Id: E6C9A10DFED1 Authentication-Results: imf13.hostedemail.com; dkim=pass header.d=google.com header.s=20210112 header.b=Wf+QnXwZ; dmarc=pass (policy=reject) header.from=google.com; spf=pass (imf13.hostedemail.com: domain of 3WwlKYQ0KCKYGdKRXGYSaYYKTMUUMRK.IUSROTad-SSQbGIQ.UXM@flex--axelrasmussen.bounces.google.com designates 209.85.222.201 as permitted sender) smtp.mailfrom=3WwlKYQ0KCKYGdKRXGYSaYYKTMUUMRK.IUSROTad-SSQbGIQ.UXM@flex--axelrasmussen.bounces.google.com X-Stat-Signature: 7qdihganz176u539fdjsb85qz1br37yh X-HE-Tag: 1632242011-568897 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000007, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Two arguments for doing this: First, and maybe most importantly, the resulting code is significantly shorter / simpler. Then, we avoid using GNU libc extensions. Why does this matter? It makes testing userfaultfd with the selftest easier e.g. on distros which use something other than glibc (e.g., Alpine, which uses musl); basically, it makes the test more portable. Signed-off-by: Axel Rasmussen Reviewed-by: Peter Xu --- tools/testing/selftests/vm/userfaultfd.c | 26 ++++-------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c index aad5211f5012..9d9f60e71524 100644 --- a/tools/testing/selftests/vm/userfaultfd.c +++ b/tools/testing/selftests/vm/userfaultfd.c @@ -57,6 +57,7 @@ #include #include #include +#include #include "../kselftest.h" @@ -528,22 +529,10 @@ static void continue_range(int ufd, __u64 start, __u64 len) static void *locking_thread(void *arg) { unsigned long cpu = (unsigned long) arg; - struct random_data rand; unsigned long page_nr = *(&(page_nr)); /* uninitialized warning */ - int32_t rand_nr; unsigned long long count; - char randstate[64]; - unsigned int seed; - if (bounces & BOUNCE_RANDOM) { - seed = (unsigned int) time(NULL) - bounces; - if (!(bounces & BOUNCE_RACINGFAULTS)) - seed += cpu; - bzero(&rand, sizeof(rand)); - bzero(&randstate, sizeof(randstate)); - if (initstate_r(seed, randstate, sizeof(randstate), &rand)) - err("initstate_r failed"); - } else { + if (!(bounces & BOUNCE_RANDOM)) { page_nr = -bounces; if (!(bounces & BOUNCE_RACINGFAULTS)) page_nr += cpu * nr_pages_per_cpu; @@ -551,15 +540,8 @@ static void *locking_thread(void *arg) while (!finished) { if (bounces & BOUNCE_RANDOM) { - if (random_r(&rand, &rand_nr)) - err("random_r failed"); - page_nr = rand_nr; - if (sizeof(page_nr) > sizeof(rand_nr)) { - if (random_r(&rand, &rand_nr)) - err("random_r failed"); - page_nr |= (((unsigned long) rand_nr) << 16) << - 16; - } + if (getrandom(&page_nr, sizeof(page_nr), 0) != sizeof(page_nr)) + err("getrandom failed"); } else page_nr += 1; page_nr %= nr_pages;