From: Zi Yan <ziy@nvidia.com>
To: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: wang lian <lianux.mm@gmail.com>,
Andrew Morton <akpm@linux-foundation.org>,
linux-mm@kvack.org, David Hildenbrand <david@redhat.com>,
Wei Yang <richard.weiyang@gmail.com>,
Christian Brauner <brauner@kernel.org>,
Jann Horn <jannh@google.com>, Kairui Song <ryncsn@gmail.com>,
Liam Howlett <liam.howlett@oracle.com>,
Mark Brown <broonie@kernel.org>, SeongJae Park <sj@kernel.org>,
Shuah Khan <shuah@kernel.org>, Vlastimil Babka <vbabka@suse.cz>,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org
Subject: Re: [PATCH] selftests/mm: fix FORCE_READ to read input value correctly.
Date: Tue, 05 Aug 2025 15:09:54 -0400 [thread overview]
Message-ID: <6E5CCF4D-CB63-4E4C-BEDA-6FE533E0DFCD@nvidia.com> (raw)
In-Reply-To: <7eaa1660-06d3-49b9-ba5e-28df1c35dcd1@lucifer.local>
On 5 Aug 2025, at 15:00, Lorenzo Stoakes wrote:
> On Tue, Aug 05, 2025 at 01:51:40PM -0400, Zi Yan wrote:
>> FORCE_READ() converts input value x to its pointer type then reads from
>> address x. This is wrong. If x is a non-pointer, it would be caught it
>> easily. But all FORCE_READ() callers are trying to read from a pointer and
>> FORCE_READ() basically reads a pointer to a pointer instead of the original
>> typed pointer. Almost no access violation was found, except the one from
>> split_huge_page_test.
>
> Oops, sorry about that! I had incorrectly assumed typeof() decayed the type
> when I wrote the guard-regions test code, and hadn't considered that we
> were casting to (t **) and dereffing that.
>
> And as discussed off-list, if you deref a char array like that, and are at
> the end of an array, that's err... not brilliant :)
>
>>
>> Fix it by implementing a simplified READ_ONCE() instead.
>
> I sort of intended to make this easier for pointers, but the semantics of
> this are actually potentially a bit nicer - it's more like READ_ONCE() and
> you're passing in the value you're actually reading so this is probably
> better.
>
>>
>> Fixes: 3f6bfd4789a0 ("selftests/mm: reuse FORCE_READ to replace "asm volatile("" : "+r" (XXX));"")
>> Signed-off-by: Zi Yan <ziy@nvidia.com>
>
> LGTM, so:
>
> Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
>
> But see nits below.
>
>> ---
>> FORCE_READ() comes from commit 876320d71f51 ("selftests/mm: add self tests for
>> guard page feature"). I will a separate patch to stable tree.
>>
>>
>> tools/testing/selftests/mm/cow.c | 4 ++--
>> tools/testing/selftests/mm/guard-regions.c | 2 +-
>> tools/testing/selftests/mm/hugetlb-madvise.c | 4 +++-
>> tools/testing/selftests/mm/migration.c | 2 +-
>> tools/testing/selftests/mm/pagemap_ioctl.c | 2 +-
>> tools/testing/selftests/mm/split_huge_page_test.c | 7 +++++--
>> tools/testing/selftests/mm/vm_util.h | 2 +-
>> 7 files changed, 14 insertions(+), 9 deletions(-)
>>
>> diff --git a/tools/testing/selftests/mm/cow.c b/tools/testing/selftests/mm/cow.c
>> index d30625c18259..c744c603d688 100644
>> --- a/tools/testing/selftests/mm/cow.c
>> +++ b/tools/testing/selftests/mm/cow.c
>> @@ -1554,8 +1554,8 @@ static void run_with_zeropage(non_anon_test_fn fn, const char *desc)
>> }
>>
>> /* Read from the page to populate the shared zeropage. */
>> - FORCE_READ(mem);
>> - FORCE_READ(smem);
>> + FORCE_READ(*mem);
>> + FORCE_READ(*smem);
>>
>> fn(mem, smem, pagesize);
>> munmap:
>> diff --git a/tools/testing/selftests/mm/guard-regions.c b/tools/testing/selftests/mm/guard-regions.c
>> index b0d42eb04e3a..8dd81c0a4a5a 100644
>> --- a/tools/testing/selftests/mm/guard-regions.c
>> +++ b/tools/testing/selftests/mm/guard-regions.c
>> @@ -145,7 +145,7 @@ static bool try_access_buf(char *ptr, bool write)
>> if (write)
>> *ptr = 'x';
>> else
>> - FORCE_READ(ptr);
>> + FORCE_READ(*ptr);
>> }
>>
>> signal_jump_set = false;
>> diff --git a/tools/testing/selftests/mm/hugetlb-madvise.c b/tools/testing/selftests/mm/hugetlb-madvise.c
>> index 1afe14b9dc0c..c5940c0595be 100644
>> --- a/tools/testing/selftests/mm/hugetlb-madvise.c
>> +++ b/tools/testing/selftests/mm/hugetlb-madvise.c
>> @@ -50,8 +50,10 @@ void read_fault_pages(void *addr, unsigned long nr_pages)
>> unsigned long i;
>>
>> for (i = 0; i < nr_pages; i++) {
>> + unsigned long *addr2 =
>> + ((unsigned long *)(addr + (i * huge_page_size)));
>> /* Prevent the compiler from optimizing out the entire loop: */
>> - FORCE_READ(((unsigned long *)(addr + (i * huge_page_size))));
>> + FORCE_READ(*addr2);
>> }
>> }
>>
>> diff --git a/tools/testing/selftests/mm/migration.c b/tools/testing/selftests/mm/migration.c
>> index c5a73617796a..ea945eebec2f 100644
>> --- a/tools/testing/selftests/mm/migration.c
>> +++ b/tools/testing/selftests/mm/migration.c
>> @@ -110,7 +110,7 @@ void *access_mem(void *ptr)
>> * the memory access actually happens and prevents the compiler
>> * from optimizing away this entire loop.
>> */
>> - FORCE_READ((uint64_t *)ptr);
>> + FORCE_READ(*(uint64_t *)ptr);
>> }
>>
>> return NULL;
>> diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c
>> index 0d4209eef0c3..e6face7c0166 100644
>> --- a/tools/testing/selftests/mm/pagemap_ioctl.c
>> +++ b/tools/testing/selftests/mm/pagemap_ioctl.c
>> @@ -1525,7 +1525,7 @@ void zeropfn_tests(void)
>>
>> ret = madvise(mem, hpage_size, MADV_HUGEPAGE);
>> if (!ret) {
>> - FORCE_READ(mem);
>> + FORCE_READ(*mem);
>>
>> ret = pagemap_ioctl(mem, hpage_size, &vec, 1, 0,
>> 0, PAGE_IS_PFNZERO, 0, 0, PAGE_IS_PFNZERO);
>> diff --git a/tools/testing/selftests/mm/split_huge_page_test.c b/tools/testing/selftests/mm/split_huge_page_test.c
>> index 718daceb5282..3c761228e451 100644
>> --- a/tools/testing/selftests/mm/split_huge_page_test.c
>> +++ b/tools/testing/selftests/mm/split_huge_page_test.c
>> @@ -440,8 +440,11 @@ int create_pagecache_thp_and_fd(const char *testfile, size_t fd_size, int *fd,
>> }
>> madvise(*addr, fd_size, MADV_HUGEPAGE);
>>
>> - for (size_t i = 0; i < fd_size; i++)
>> - FORCE_READ((*addr + i));
>> + for (size_t i = 0; i < fd_size; i++) {
>> + char *addr2 = *addr + i;
>> +
>> + FORCE_READ(*addr2);
>> + }
>>
>> if (!check_huge_file(*addr, fd_size / pmd_pagesize, pmd_pagesize)) {
>> ksft_print_msg("No large pagecache folio generated, please provide a filesystem supporting large folio\n");
>> diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h
>> index c20298ae98ea..b55d1809debc 100644
>> --- a/tools/testing/selftests/mm/vm_util.h
>> +++ b/tools/testing/selftests/mm/vm_util.h
>> @@ -23,7 +23,7 @@
>> * anything with it in order to trigger a read page fault. We therefore must use
>> * volatile to stop the compiler from optimising this away.
>> */
>> -#define FORCE_READ(x) (*(volatile typeof(x) *)x)
>> +#define FORCE_READ(x) (*(const volatile typeof(x) *)&(x))
>
> NIT: but wonder if const is necessary, and also (as discussed off-list
I just used READ_ONCE() code, but it is not necessary.
> again :) will this work with a (void) prefixed, just to a. make it clear
> we're reading but discarding and b. to avoid any possible compiler warning
> on this?
Adding (void) makes no difference, at least from godbolt.
>
> I know for some reason this form doesn't generate one currently (not sure
> why), but we may hit that in future.
Neither gcc nor clang complains without (void). My guess is that volatile
is doing something there.
Best Regards,
Yan, Zi
next prev parent reply other threads:[~2025-08-05 19:10 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-05 17:51 Zi Yan
2025-08-05 18:38 ` Jann Horn
2025-08-05 18:48 ` Zi Yan
2025-08-05 18:56 ` Lorenzo Stoakes
2025-08-05 19:00 ` Lorenzo Stoakes
2025-08-05 19:09 ` Zi Yan [this message]
2025-08-05 19:21 ` Lorenzo Stoakes
2025-08-06 10:34 ` Pedro Falcato
2025-08-06 10:37 ` Lorenzo Stoakes
2025-08-06 1:44 ` wang lian
2025-08-05 21:05 ` David Hildenbrand
2025-08-06 2:07 ` Wei Yang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6E5CCF4D-CB63-4E4C-BEDA-6FE533E0DFCD@nvidia.com \
--to=ziy@nvidia.com \
--cc=akpm@linux-foundation.org \
--cc=brauner@kernel.org \
--cc=broonie@kernel.org \
--cc=david@redhat.com \
--cc=jannh@google.com \
--cc=liam.howlett@oracle.com \
--cc=lianux.mm@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lorenzo.stoakes@oracle.com \
--cc=richard.weiyang@gmail.com \
--cc=ryncsn@gmail.com \
--cc=shuah@kernel.org \
--cc=sj@kernel.org \
--cc=vbabka@suse.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox