From patchwork Mon Jun 24 06:36:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vivek Kasireddy X-Patchwork-Id: 13709050 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5EBF7C2BD05 for ; Mon, 24 Jun 2024 07:05:53 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 818376B03BA; Mon, 24 Jun 2024 03:05:35 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 7C7CD6B03BD; Mon, 24 Jun 2024 03:05:35 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5F3EF6B03BF; Mon, 24 Jun 2024 03:05:35 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 3E67C6B03BA for ; Mon, 24 Jun 2024 03:05:35 -0400 (EDT) Received: from smtpin25.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 07002A0BAB for ; Mon, 24 Jun 2024 07:05:35 +0000 (UTC) X-FDA: 82264896630.25.1C9E9CD Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) by imf22.hostedemail.com (Postfix) with ESMTP id CB28EC0006 for ; Mon, 24 Jun 2024 07:05:32 +0000 (UTC) Authentication-Results: imf22.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=khYv0OU3; spf=pass (imf22.hostedemail.com: domain of vivek.kasireddy@intel.com designates 198.175.65.21 as permitted sender) smtp.mailfrom=vivek.kasireddy@intel.com; dmarc=pass (policy=none) header.from=intel.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1719212719; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=K6deuOdligGOWcs/cUpiN5v80J3yBU/FgM9oryyRYQU=; b=gRfs0nWQO1f1QnMwVU688x3QFdOMg0Us6n6V12iwepjfjLn2OedvZkL8Z1/QeojjYSzEu5 VQy9QA0FGo3R6TJh9knQolWk+PThZjKvbmRARLesHUv09L1/bdFOxkKRMbfH+PnO5mcqsr 89ZtKQoDxZrwaCbRfpnZxOKqoqfNf2M= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1719212719; a=rsa-sha256; cv=none; b=EykEycloZ0W31p2V5pJOAQ03Z7jl0s4oEY8D0MH7AqG+GPlwcLPaxisMTPr7ME4WCvGm+P kJ5SH39HLWjyfalLYTSmuRzDXWggPTLMGUuag/wT0FsVRzI32tVVqpOtGl3yQFARly5LWF 6zUxd57Sft+lTvynDbsRt1iGqVprTLo= ARC-Authentication-Results: i=1; imf22.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=khYv0OU3; spf=pass (imf22.hostedemail.com: domain of vivek.kasireddy@intel.com designates 198.175.65.21 as permitted sender) smtp.mailfrom=vivek.kasireddy@intel.com; dmarc=pass (policy=none) header.from=intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1719212733; x=1750748733; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=mwX/Ut3liG+2eL4EiqMYYCOWpRlKdeioXbS3wyxFBs0=; b=khYv0OU38bKhLgqFon0SnMxTYSYBvWQR7IXLqm/9OGgth8lblWvPBKom ihyqagG3kEc8Fp/mxHJJr4+idcq42OiXjJLAbS4l1XQ2h18sM7iwNtitQ KfGSEqxo9qSyH+8NYSZRK/GG5eR8ONlAjuBBLzGxQRenioGoPFymr5AWY 6IjChN0fQNkHirksLx+pQzvkYEVxUbVedt8rZoN1vqKHumEqNUssxHoU3 QL4WMGfqgl4XEfWonsly/g6ai+CLSHnoomFmUpLFwoMr7grDtCH5yePbD o/NuMX9H88GQ2l7989OPkslpVrp0SNSLnCReKVKze4I/6Y9UQmTWGOVdU w==; X-CSE-ConnectionGUID: U4ysVL6wSpKVfpXXQSVzEQ== X-CSE-MsgGUID: icpR+AziSvK7xn7qKXSqRg== X-IronPort-AV: E=McAfee;i="6700,10204,11112"; a="16134987" X-IronPort-AV: E=Sophos;i="6.08,261,1712646000"; d="scan'208";a="16134987" Received: from orviesa002.jf.intel.com ([10.64.159.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jun 2024 00:05:27 -0700 X-CSE-ConnectionGUID: r8OaYolhSbGcZ+TgCa9tdA== X-CSE-MsgGUID: WyAqrCRFRzW+3jfsoMu6/A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,261,1712646000"; d="scan'208";a="73955893" Received: from vkasired-desk2.fm.intel.com ([10.105.128.132]) by orviesa002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jun 2024 00:05:26 -0700 From: Vivek Kasireddy To: dri-devel@lists.freedesktop.org, linux-mm@kvack.org Cc: Vivek Kasireddy , Shuah Khan , David Hildenbrand , Daniel Vetter , Hugh Dickins , Peter Xu , Jason Gunthorpe , Gerd Hoffmann , Dongwon Kim , Junxiao Chang , linux-kselftest@vger.kernel.org, Mike Kravetz , Dave Airlie Subject: [PATCH v16 9/9] selftests/udmabuf: Add tests to verify data after page migration Date: Sun, 23 Jun 2024 23:36:17 -0700 Message-ID: <20240624063952.1572359-10-vivek.kasireddy@intel.com> X-Mailer: git-send-email 2.45.1 In-Reply-To: <20240624063952.1572359-1-vivek.kasireddy@intel.com> References: <20240624063952.1572359-1-vivek.kasireddy@intel.com> MIME-Version: 1.0 X-Stat-Signature: w39npiukr79qwgzognucfg4rmnocmwhr X-Rspamd-Queue-Id: CB28EC0006 X-Rspam-User: X-Rspamd-Server: rspam08 X-HE-Tag: 1719212732-485582 X-HE-Meta: U2FsdGVkX18W6uWeObxUwXzxtxnWq/sOYZUyyEbCycVoYg01uq1B2VLItB0qED/Dsv6Lw2zVVYUSgs70ezXds7Y0kc3VA7mXlhrOvg1K2qzBQ9UEEaD8AjCmCP4SjxojGJg5e2y8eQcC0Q+s+5YmAjuZQk2Hov6RX+3UN0MxLvxpXirE4dlFLKJn5XvSkBDu01g2cscqO0USFpf0yQcuKoYxCODR7Vhh+bnMBSZXEIv6TwhHvTdWIg15Y5gErYBVFiJVNhCuwssDiawWN03sGCkBb1utlvEicziTipb24qnDO7nijJLh9Mi9FDIbWL2SBaMi4s8WrtF266gtsSTLM8VsJa5sU8Q8ur2vJNMlMKYSHofPFuA0XwSMBYIfPQikJSrhq11fIAV7jPbMyxicZkx72mP9rXeNoxvX47eSA6RTl86e0PxTfxAwUR7e6lJTReGzX87ot2dw88tRhxva4JmgKHpxVgSNPUNLrXhotE5XE3qDkgLQhnwZPakzGkKhL9xfb/kFgwDSXGxgGrKW5IjPXR8H2CTqPq89vuJZ2Sc9xHkXF75k4y45WqJFJLHvIoQQhrPRk1ocMQa6w9Wi6dHYvlDLl6S/6TW++xNe3KSINqH4dS4q3xc6ymaATyP9vuuwsv23HuwTEa8HwMxL7SHERmE2Do45ehtBl9CmP4FdZV/F4jjXi2sH1GXbOFnsBS1tmdfa54lcEHv2fpPETvXBFcsbudIQVzCERpJUA2C6iGw0Ofpl/mGmKKfvlWYMwdpLnsvMMVH8iC30IsHBvpYhynllBamnA+uwCqZWkqYPB+wNv6ohyYlqds/YI8431qWjem4HK2vY1aC5iFNfBq/Mig8Iz+VXMLEFNqJN4gSYWwWz0zNHdp24KBKU7024Bym2uG4/wy9cWwo0wmGVz1V5Yag1lJ0efrwgZXRrkuUNBVbohEUM7KJOyvQ2O/3uqTFZ3GG4E5kCYDbaHXx SYS4wvM8 Vfe2k6vfRIllpqsRAMxWv0VVihAIV3iR0FjoMd4OkDqvmEKJl7T9fVnF5qejef8uCb0lgz1kltWTIlJGurOEYZ2/jHGi8IYKgJSWW+76y4KJgc+xlq6PkTfTp76B5z/xk8wnUPJD8jtRIzGiJGZCG9ZLGPehhnbb7aYWziy7ALXA1z5fsn6MWMDySFkYFpRv0MyfOdJrDykrYUQZ4LHd2Dgd3dLuQZsJdbuCGdbMW6gIaMAGlctp4dir/Ts/qLRX6XJxbwC2ZwNLvoSwdsrF4rGgXXZJeON4EH7/xJ0ZxiU10t7To694qz0L4SkWNTrZu/91ipnfjLjguVncJKik69QHZa9Szo9v7FDMIN54Genw2WLPtsOakYnYw31U2+xvYlKoeldEqTdmUCzA= 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: List-Subscribe: List-Unsubscribe: Since the memfd pages associated with a udmabuf may be migrated as part of udmabuf create, we need to verify the data coherency after successful migration. The new tests added in this patch try to do just that using 4k sized pages and also 2 MB sized huge pages for the memfd. Successful completion of the tests would mean that there is no disconnect between the memfd pages and the ones associated with a udmabuf. And, these tests can also be augmented in the future to test newer udmabuf features (such as handling memfd hole punch). The idea for these tests comes from a patch by Mike Kravetz here: https://lists.freedesktop.org/archives/dri-devel/2023-June/410623.html v1->v2: (suggestions from Shuah) - Use ksft_* functions to print and capture results of tests - Use appropriate KSFT_* status codes for exit() - Add Mike Kravetz's suggested-by tag Cc: Shuah Khan Cc: David Hildenbrand Cc: Daniel Vetter Cc: Hugh Dickins Cc: Peter Xu Cc: Jason Gunthorpe Cc: Gerd Hoffmann Cc: Dongwon Kim Cc: Junxiao Chang Cc: linux-kselftest@vger.kernel.org Suggested-by: Mike Kravetz Acked-by: Dave Airlie Acked-by: Gerd Hoffmann Signed-off-by: Vivek Kasireddy --- .../selftests/drivers/dma-buf/udmabuf.c | 214 +++++++++++++++--- 1 file changed, 183 insertions(+), 31 deletions(-) diff --git a/tools/testing/selftests/drivers/dma-buf/udmabuf.c b/tools/testing/selftests/drivers/dma-buf/udmabuf.c index c812080e304e..6062723a172e 100644 --- a/tools/testing/selftests/drivers/dma-buf/udmabuf.c +++ b/tools/testing/selftests/drivers/dma-buf/udmabuf.c @@ -9,52 +9,162 @@ #include #include #include +#include #include #include +#include #include #include +#include "../../kselftest.h" #define TEST_PREFIX "drivers/dma-buf/udmabuf" #define NUM_PAGES 4 +#define NUM_ENTRIES 4 +#define MEMFD_SIZE 1024 /* in pages */ -static int memfd_create(const char *name, unsigned int flags) +static unsigned int page_size; + +static int create_memfd_with_seals(off64_t size, bool hpage) +{ + int memfd, ret; + unsigned int flags = MFD_ALLOW_SEALING; + + if (hpage) + flags |= MFD_HUGETLB; + + memfd = memfd_create("udmabuf-test", flags); + if (memfd < 0) { + ksft_print_msg("%s: [skip,no-memfd]\n", TEST_PREFIX); + exit(KSFT_SKIP); + } + + ret = fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK); + if (ret < 0) { + ksft_print_msg("%s: [skip,fcntl-add-seals]\n", TEST_PREFIX); + exit(KSFT_SKIP); + } + + ret = ftruncate(memfd, size); + if (ret == -1) { + ksft_print_msg("%s: [FAIL,memfd-truncate]\n", TEST_PREFIX); + exit(KSFT_FAIL); + } + + return memfd; +} + +static int create_udmabuf_list(int devfd, int memfd, off64_t memfd_size) +{ + struct udmabuf_create_list *list; + int ubuf_fd, i; + + list = malloc(sizeof(struct udmabuf_create_list) + + sizeof(struct udmabuf_create_item) * NUM_ENTRIES); + if (!list) { + ksft_print_msg("%s: [FAIL, udmabuf-malloc]\n", TEST_PREFIX); + exit(KSFT_FAIL); + } + + for (i = 0; i < NUM_ENTRIES; i++) { + list->list[i].memfd = memfd; + list->list[i].offset = i * (memfd_size / NUM_ENTRIES); + list->list[i].size = getpagesize() * NUM_PAGES; + } + + list->count = NUM_ENTRIES; + list->flags = UDMABUF_FLAGS_CLOEXEC; + ubuf_fd = ioctl(devfd, UDMABUF_CREATE_LIST, list); + free(list); + if (ubuf_fd < 0) { + ksft_print_msg("%s: [FAIL, udmabuf-create]\n", TEST_PREFIX); + exit(KSFT_FAIL); + } + + return ubuf_fd; +} + +static void write_to_memfd(void *addr, off64_t size, char chr) +{ + int i; + + for (i = 0; i < size / page_size; i++) { + *((char *)addr + (i * page_size)) = chr; + } +} + +static void *mmap_fd(int fd, off64_t size) { - return syscall(__NR_memfd_create, name, flags); + void *addr; + + addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + ksft_print_msg("%s: ubuf_fd mmap fail\n", TEST_PREFIX); + exit(KSFT_FAIL); + } + + return addr; +} + +static int compare_chunks(void *addr1, void *addr2, off64_t memfd_size) +{ + off64_t off; + int i = 0, j, k = 0, ret = 0; + char char1, char2; + + while (i < NUM_ENTRIES) { + off = i * (memfd_size / NUM_ENTRIES); + for (j = 0; j < NUM_PAGES; j++, k++) { + char1 = *((char *)addr1 + off + (j * getpagesize())); + char2 = *((char *)addr2 + (k * getpagesize())); + if (char1 != char2) { + ret = -1; + goto err; + } + } + i++; + } +err: + munmap(addr1, memfd_size); + munmap(addr2, NUM_ENTRIES * NUM_PAGES * getpagesize()); + return ret; } int main(int argc, char *argv[]) { struct udmabuf_create create; int devfd, memfd, buf, ret; - off_t size; - void *mem; + off64_t size; + void *addr1, *addr2; + + ksft_print_header(); + ksft_set_plan(6); devfd = open("/dev/udmabuf", O_RDWR); if (devfd < 0) { - printf("%s: [skip,no-udmabuf: Unable to access DMA buffer device file]\n", - TEST_PREFIX); - exit(77); + ksft_print_msg( + "%s: [skip,no-udmabuf: Unable to access DMA buffer device file]\n", + TEST_PREFIX); + exit(KSFT_SKIP); } memfd = memfd_create("udmabuf-test", MFD_ALLOW_SEALING); if (memfd < 0) { - printf("%s: [skip,no-memfd]\n", TEST_PREFIX); - exit(77); + ksft_print_msg("%s: [skip,no-memfd]\n", TEST_PREFIX); + exit(KSFT_SKIP); } ret = fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK); if (ret < 0) { - printf("%s: [skip,fcntl-add-seals]\n", TEST_PREFIX); - exit(77); + ksft_print_msg("%s: [skip,fcntl-add-seals]\n", TEST_PREFIX); + exit(KSFT_SKIP); } - size = getpagesize() * NUM_PAGES; ret = ftruncate(memfd, size); if (ret == -1) { - printf("%s: [FAIL,memfd-truncate]\n", TEST_PREFIX); - exit(1); + ksft_print_msg("%s: [FAIL,memfd-truncate]\n", TEST_PREFIX); + exit(KSFT_FAIL); } memset(&create, 0, sizeof(create)); @@ -64,44 +174,86 @@ int main(int argc, char *argv[]) create.offset = getpagesize()/2; create.size = getpagesize(); buf = ioctl(devfd, UDMABUF_CREATE, &create); - if (buf >= 0) { - printf("%s: [FAIL,test-1]\n", TEST_PREFIX); - exit(1); - } + if (buf >= 0) + ksft_test_result_fail("%s: [FAIL,test-1]\n", TEST_PREFIX); + else + ksft_test_result_pass("%s: [PASS,test-1]\n", TEST_PREFIX); /* should fail (size not multiple of page) */ create.memfd = memfd; create.offset = 0; create.size = getpagesize()/2; buf = ioctl(devfd, UDMABUF_CREATE, &create); - if (buf >= 0) { - printf("%s: [FAIL,test-2]\n", TEST_PREFIX); - exit(1); - } + if (buf >= 0) + ksft_test_result_fail("%s: [FAIL,test-2]\n", TEST_PREFIX); + else + ksft_test_result_pass("%s: [PASS,test-2]\n", TEST_PREFIX); /* should fail (not memfd) */ create.memfd = 0; /* stdin */ create.offset = 0; create.size = size; buf = ioctl(devfd, UDMABUF_CREATE, &create); - if (buf >= 0) { - printf("%s: [FAIL,test-3]\n", TEST_PREFIX); - exit(1); - } + if (buf >= 0) + ksft_test_result_fail("%s: [FAIL,test-3]\n", TEST_PREFIX); + else + ksft_test_result_pass("%s: [PASS,test-3]\n", TEST_PREFIX); /* should work */ + page_size = getpagesize(); + addr1 = mmap_fd(memfd, size); + write_to_memfd(addr1, size, 'a'); create.memfd = memfd; create.offset = 0; create.size = size; buf = ioctl(devfd, UDMABUF_CREATE, &create); - if (buf < 0) { - printf("%s: [FAIL,test-4]\n", TEST_PREFIX); - exit(1); - } + if (buf < 0) + ksft_test_result_fail("%s: [FAIL,test-4]\n", TEST_PREFIX); + else + ksft_test_result_pass("%s: [PASS,test-4]\n", TEST_PREFIX); + + munmap(addr1, size); + close(buf); + close(memfd); + + /* should work (migration of 4k size pages)*/ + size = MEMFD_SIZE * page_size; + memfd = create_memfd_with_seals(size, false); + addr1 = mmap_fd(memfd, size); + write_to_memfd(addr1, size, 'a'); + buf = create_udmabuf_list(devfd, memfd, size); + addr2 = mmap_fd(buf, NUM_PAGES * NUM_ENTRIES * getpagesize()); + write_to_memfd(addr1, size, 'b'); + ret = compare_chunks(addr1, addr2, size); + if (ret < 0) + ksft_test_result_fail("%s: [FAIL,test-5]\n", TEST_PREFIX); + else + ksft_test_result_pass("%s: [PASS,test-5]\n", TEST_PREFIX); + + close(buf); + close(memfd); + + /* should work (migration of 2MB size huge pages)*/ + page_size = getpagesize() * 512; /* 2 MB */ + size = MEMFD_SIZE * page_size; + memfd = create_memfd_with_seals(size, true); + addr1 = mmap_fd(memfd, size); + write_to_memfd(addr1, size, 'a'); + buf = create_udmabuf_list(devfd, memfd, size); + addr2 = mmap_fd(buf, NUM_PAGES * NUM_ENTRIES * getpagesize()); + write_to_memfd(addr1, size, 'b'); + ret = compare_chunks(addr1, addr2, size); + if (ret < 0) + ksft_test_result_fail("%s: [FAIL,test-6]\n", TEST_PREFIX); + else + ksft_test_result_pass("%s: [PASS,test-6]\n", TEST_PREFIX); - fprintf(stderr, "%s: ok\n", TEST_PREFIX); close(buf); close(memfd); close(devfd); + + ksft_print_msg("%s: ok\n", TEST_PREFIX); + ksft_print_cnts(); + return 0; }