From nobody Mon Feb 9 14:32:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 70C3AC77B73 for ; Wed, 31 May 2023 22:09:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230523AbjEaWJD (ORCPT ); Wed, 31 May 2023 18:09:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60304 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230418AbjEaWIs (ORCPT ); Wed, 31 May 2023 18:08:48 -0400 Received: from mail-qt1-x835.google.com (mail-qt1-x835.google.com [IPv6:2607:f8b0:4864:20::835]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C89B712F for ; Wed, 31 May 2023 15:08:24 -0700 (PDT) Received: by mail-qt1-x835.google.com with SMTP id d75a77b69052e-3f6b2f1a04bso68296591cf.3 for ; Wed, 31 May 2023 15:08:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=joelfernandes.org; s=google; t=1685570903; x=1688162903; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=SGzgxSyjCn8pa3p9gX1cUENGQh2HTVaDIrajDjGHrWE=; b=qJbeR3XeX0dyQ9w7zcHDC41lKw4DZl+B5m5ma1wY70zRgQql4bUjPrC4gMymasqXTK BM3QFGwkJEfYqGrUUz8QS6vJaOIG8X1W6MInIXdLQA50Nx8lnRPaUJqzQu+w7PsHFbIi L4d4GNIFwmhD3BECzPNdaa0JfvVlVcgox0QHY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685570903; x=1688162903; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=SGzgxSyjCn8pa3p9gX1cUENGQh2HTVaDIrajDjGHrWE=; b=Q9ZX8Zy0pqUTNgEw2iNeAys2MRhQD/OuPiBjmFKM9hT/MbcserCBMRTkfLur2xinSJ 7wNxRTU8DmWTfYQiUHMjZiVRHdEWTjNKqvBb8rTxKZ9q9svRd/mY5/zMThEMlNBWL1gE E4NojgP3qPWpcQ5CH5ivdfNUcLmA2cnOUfCQjkP8G9hYOFyXpfDXhmNwm4LUnqywjQPM ZcfwaBURg3SLD/xU23fHaOVNrmBw+OLTfI5tXPnhmrmyKzFN1Q6luFKhm9ByicD5l9ia x9M6IJvEmnjDL1TF1zeP5CBf6LSmh9iq7O5B+OTOzHvF2jYhp7ci+U2uCuMIxhLBZ9Oh XaJQ== X-Gm-Message-State: AC+VfDyNHDnVhB6YaoBpMi3qht6AUwAVUsahc+8t1Rcv2ZDQj71dnO3w fNfW0UrxQ8xJjF+uD4D3LxJiOisnAIQiFRhMHY8= X-Google-Smtp-Source: ACHHUZ6+jFrqsN+RgvwHjevLZQaiKw86Y9ByO7H4nf0Ur0uc0THRQNYH80hkrr7ME5DDE/rEaaF0gw== X-Received: by 2002:ac8:7fc6:0:b0:3ef:25ad:27fb with SMTP id b6-20020ac87fc6000000b003ef25ad27fbmr6757537qtk.30.1685570903640; Wed, 31 May 2023 15:08:23 -0700 (PDT) Received: from joelboxx.c.googlers.com.com (129.239.188.35.bc.googleusercontent.com. [35.188.239.129]) by smtp.gmail.com with ESMTPSA id f2-20020ac87f02000000b003f6b0f4126fsm6666172qtk.8.2023.05.31.15.08.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 May 2023 15:08:22 -0700 (PDT) From: "Joel Fernandes (Google)" To: linux-kernel@vger.kernel.org Cc: "Joel Fernandes (Google)" , linux-kselftest@vger.kernel.org, linux-mm@kvack.org, Shuah Khan , Vlastimil Babka , Michal Hocko , Linus Torvalds , Lorenzo Stoakes , Kirill A Shutemov , "Liam R. Howlett" , "Paul E. McKenney" , Suren Baghdasaryan , Kalesh Singh , Lokesh Gidra , Vineeth Pillai Subject: [PATCH v4 7/7] selftests: mm: Add a test for moving from an offset from start of mapping Date: Wed, 31 May 2023 22:08:07 +0000 Message-ID: <20230531220807.2048037-8-joel@joelfernandes.org> X-Mailer: git-send-email 2.41.0.rc2.161.g9c6817b8e7-goog In-Reply-To: <20230531220807.2048037-1-joel@joelfernandes.org> References: <20230531220807.2048037-1-joel@joelfernandes.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" It is possible that the aligned address falls on no existing mapping, however that does not mean that we can just align it down to that. This test verifies that the "vma->vm_start !=3D addr_to_align" check in can_align_down() prevents disastrous results if aligning down when source and dest are mutually aligned within a PMD but the source/dest addresses requested are not at the beginning of the respective mapping containing these addresses. Signed-off-by: Joel Fernandes (Google) --- tools/testing/selftests/mm/mremap_test.c | 189 ++++++++++++++++------- 1 file changed, 134 insertions(+), 55 deletions(-) diff --git a/tools/testing/selftests/mm/mremap_test.c b/tools/testing/selft= ests/mm/mremap_test.c index f45d1abedc9c..c71ac8306c89 100644 --- a/tools/testing/selftests/mm/mremap_test.c +++ b/tools/testing/selftests/mm/mremap_test.c @@ -24,6 +24,7 @@ =20 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) #define SIZE_MB(m) ((size_t)m * (1024 * 1024)) +#define SIZE_KB(k) ((size_t)k * 1024) =20 struct config { unsigned long long src_alignment; @@ -148,6 +149,60 @@ static bool is_range_mapped(FILE *maps_fp, void *start= , void *end) return success; } =20 +/* + * Returns the start address of the mapping on success, else returns + * NULL on failure. + */ +static void *get_source_mapping(struct config c) +{ + unsigned long long addr =3D 0ULL; + void *src_addr =3D NULL; + unsigned long long mmap_min_addr; + + mmap_min_addr =3D get_mmap_min_addr(); + /* + * For some tests, we need to not have any mappings below the + * source mapping. Add some headroom to mmap_min_addr for this. + */ + mmap_min_addr +=3D 10 * _4MB; + +retry: + addr +=3D c.src_alignment; + if (addr < mmap_min_addr) + goto retry; + + src_addr =3D mmap((void *) addr, c.region_size, PROT_READ | PROT_WRITE, + MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_SHARED, + -1, 0); + if (src_addr =3D=3D MAP_FAILED) { + if (errno =3D=3D EPERM || errno =3D=3D EEXIST) + goto retry; + goto error; + } + /* + * Check that the address is aligned to the specified alignment. + * Addresses which have alignments that are multiples of that + * specified are not considered valid. For instance, 1GB address is + * 2MB-aligned, however it will not be considered valid for a + * requested alignment of 2MB. This is done to reduce coincidental + * alignment in the tests. + */ + if (((unsigned long long) src_addr & (c.src_alignment - 1)) || + !((unsigned long long) src_addr & c.src_alignment)) { + munmap(src_addr, c.region_size); + goto retry; + } + + if (!src_addr) + goto error; + + return src_addr; +error: + ksft_print_msg("Failed to map source region: %s\n", + strerror(errno)); + return NULL; +} + /* * This test validates that merge is called when expanding a mapping. * Mapping containing three pages is created, middle page is unmapped @@ -300,60 +355,6 @@ static void mremap_move_within_range(char pattern_seed) ksft_test_result_fail("%s\n", test_name); } =20 -/* - * Returns the start address of the mapping on success, else returns - * NULL on failure. - */ -static void *get_source_mapping(struct config c) -{ - unsigned long long addr =3D 0ULL; - void *src_addr =3D NULL; - unsigned long long mmap_min_addr; - - mmap_min_addr =3D get_mmap_min_addr(); - /* - * For some tests, we need to not have any mappings below the - * source mapping. Add some headroom to mmap_min_addr for this. - */ - mmap_min_addr +=3D 10 * _4MB; - -retry: - addr +=3D c.src_alignment; - if (addr < mmap_min_addr) - goto retry; - - src_addr =3D mmap((void *) addr, c.region_size, PROT_READ | PROT_WRITE, - MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_SHARED, - -1, 0); - if (src_addr =3D=3D MAP_FAILED) { - if (errno =3D=3D EPERM || errno =3D=3D EEXIST) - goto retry; - goto error; - } - /* - * Check that the address is aligned to the specified alignment. - * Addresses which have alignments that are multiples of that - * specified are not considered valid. For instance, 1GB address is - * 2MB-aligned, however it will not be considered valid for a - * requested alignment of 2MB. This is done to reduce coincidental - * alignment in the tests. - */ - if (((unsigned long long) src_addr & (c.src_alignment - 1)) || - !((unsigned long long) src_addr & c.src_alignment)) { - munmap(src_addr, c.region_size); - goto retry; - } - - if (!src_addr) - goto error; - - return src_addr; -error: - ksft_print_msg("Failed to map source region: %s\n", - strerror(errno)); - return NULL; -} - /* Returns the time taken for the remap on success else returns -1. */ static long long remap_region(struct config c, unsigned int threshold_mb, char pattern_seed) @@ -487,6 +488,83 @@ static long long remap_region(struct config c, unsigne= d int threshold_mb, return ret; } =20 +/* + * Verify that an mremap aligning down does not destroy + * the beginning of the mapping just because the aligned + * down address landed on a mapping that maybe does not exist. + */ +static void mremap_move_1mb_from_start(char pattern_seed) +{ + char *test_name =3D "mremap move 1mb from start at 2MB+256KB aligned src"; + void *src =3D NULL, *dest =3D NULL; + int i, success =3D 1; + + /* Config to reuse get_source_mapping() to do an aligned mmap. */ + struct config c =3D { + .src_alignment =3D SIZE_MB(1) + SIZE_KB(256), + .region_size =3D SIZE_MB(6) + }; + + src =3D get_source_mapping(c); + if (!src) { + success =3D 0; + goto out; + } + + c.src_alignment =3D SIZE_MB(1) + SIZE_KB(256); + dest =3D get_source_mapping(c); + if (!dest) { + success =3D 0; + goto out; + } + + /* Set byte pattern for source block. */ + srand(pattern_seed); + for (i =3D 0; i < SIZE_MB(2); i++) { + ((char *)src)[i] =3D (char) rand(); + } + + /* + * Unmap the beginning of dest so that the aligned address + * falls on no mapping. + */ + munmap(dest, SIZE_MB(1)); + + void *new_ptr =3D mremap(src + SIZE_MB(1), SIZE_MB(1), SIZE_MB(1), + MREMAP_MAYMOVE | MREMAP_FIXED, dest + SIZE_MB(1)); + if (new_ptr =3D=3D MAP_FAILED) { + perror("mremap"); + success =3D 0; + goto out; + } + + /* Verify byte pattern after remapping */ + srand(pattern_seed); + for (i =3D 0; i < SIZE_MB(1); i++) { + char c =3D (char) rand(); + + if (((char *)src)[i] !=3D c) { + ksft_print_msg("Data at src at %d got corrupted due to unrelated mremap= \n", + i); + ksft_print_msg("Expected: %#x\t Got: %#x\n", c & 0xff, + ((char *) src)[i] & 0xff); + success =3D 0; + } + } + +out: + if (src && munmap(src, c.region_size) =3D=3D -1) + perror("munmap src"); + + if (dest && munmap(dest, c.region_size) =3D=3D -1) + perror("munmap dest"); + + if (success) + ksft_test_result_pass("%s\n", test_name); + else + ksft_test_result_fail("%s\n", test_name); +} + static void run_mremap_test_case(struct test test_case, int *failures, unsigned int threshold_mb, unsigned int pattern_seed) @@ -565,7 +643,7 @@ int main(int argc, char **argv) unsigned int threshold_mb =3D VALIDATION_DEFAULT_THRESHOLD; unsigned int pattern_seed; int num_expand_tests =3D 2; - int num_misc_tests =3D 1; + int num_misc_tests =3D 2; struct test test_cases[MAX_TEST] =3D {}; struct test perf_test_cases[MAX_PERF_TEST]; int page_size; @@ -666,6 +744,7 @@ int main(int argc, char **argv) fclose(maps_fp); =20 mremap_move_within_range(pattern_seed); + mremap_move_1mb_from_start(pattern_seed); =20 if (run_perf_tests) { ksft_print_msg("\n%s\n", --=20 2.41.0.rc2.161.g9c6817b8e7-goog