From patchwork Fri Sep 6 03:07:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Huang, Ying" X-Patchwork-Id: 13793169 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 980C7CE7AA6 for ; Fri, 6 Sep 2024 03:09:33 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 2DA3F6B0096; Thu, 5 Sep 2024 23:09:33 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 262C86B0098; Thu, 5 Sep 2024 23:09:33 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 0DACC6B0099; Thu, 5 Sep 2024 23:09:33 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id E31BA6B0096 for ; Thu, 5 Sep 2024 23:09:32 -0400 (EDT) Received: from smtpin04.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 954751C5194 for ; Fri, 6 Sep 2024 03:09:32 +0000 (UTC) X-FDA: 82532832984.04.5C9B625 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) by imf21.hostedemail.com (Postfix) with ESMTP id 5ED0D1C0008 for ; Fri, 6 Sep 2024 03:09:30 +0000 (UTC) Authentication-Results: imf21.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=AEEnVWIM; dmarc=pass (policy=none) header.from=intel.com; spf=pass (imf21.hostedemail.com: domain of ying.huang@intel.com designates 198.175.65.15 as permitted sender) smtp.mailfrom=ying.huang@intel.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1725592098; a=rsa-sha256; cv=none; b=SkPRLLUm48SYv7PVazWIKlaRlNOwgproU/IGAT+jFifZy1YqsDQP+8HAU6xyje4bwPPIWT 2+EfG6oFDd5dP/5NfCuoncTpgW9/MEsTXH51tCnOQwehUn6bVfChTSYmJk4zjp/bsysZFe UH0cvJKQZ1FZPqDhoK3dVIE2B5HIrjk= ARC-Authentication-Results: i=1; imf21.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=AEEnVWIM; dmarc=pass (policy=none) header.from=intel.com; spf=pass (imf21.hostedemail.com: domain of ying.huang@intel.com designates 198.175.65.15 as permitted sender) smtp.mailfrom=ying.huang@intel.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1725592098; 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=3wQRUy3r1S8VBsOIXEbVAGjehdR3c56i1MbhTZZrqC0=; b=2sWrt1Zfa72BiSRqDJW6bIs9k3yPTvBB9BCE81FigGlrbsNQ4Aq1b/VTqGucWkROpaNPcg 0dBxqn49q9WHqeh+By98cfcdO0pnBOmJ6kUdGAMw/OMv1DGnAkqNk3YKv2EO7k5EBzK/xY OvFqdi5Ne4xrwL+Lj90NKWrOoSy7RpQ= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1725592170; x=1757128170; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=PSFihkZgLasjDkyToU3y/y2OCLAaD/A4Hx/YphgS1CM=; b=AEEnVWIMPpnKFei5Scmnq1d3zHfG3iUZ2AMO92t0DOy5CDhZtLspIJ4S XOPF3y3yRzK67PvEaMRm3vyhsK3wCXDG9zXJKcYR7Um/JF6uZduK8F/MD 4/gz/JQZzk9/9KBFd2hT7oohUlG/yezRTfxTp3udBlfAOevsLV6a9tJv5 3jwu+Qf4+Ym3HHgMX4zmlsvoKkQ6tKSP2cX3T0D0viEP01kx1rXEPqCES gLVW/iuan3S4cEceZqMiyV3we39eGD1TpSuuqm1AGWbsAjw23KiOZw3e7 9dLdubMmhzxJZTGMPUk+D5UaxGNBHGxt2IDLf0OsANrz6Se/MfdBd8Lkm g==; X-CSE-ConnectionGUID: MKJW16GSROSo4mR0JHR/FA== X-CSE-MsgGUID: tFFRlOAfQ0mUHCuD4XsH4g== X-IronPort-AV: E=McAfee;i="6700,10204,11186"; a="28089489" X-IronPort-AV: E=Sophos;i="6.10,206,1719903600"; d="scan'208";a="28089489" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Sep 2024 20:09:30 -0700 X-CSE-ConnectionGUID: x+ooRBcEQECl/064bwq7yg== X-CSE-MsgGUID: 64nkZDu+REefnITy+IXeiw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.10,206,1719903600"; d="scan'208";a="66364412" Received: from unknown (HELO yhuang6-mobl2.ccr.corp.intel.com) ([10.245.242.189]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Sep 2024 20:09:26 -0700 From: Huang Ying To: Andrew Morton Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, linux-cxl@vger.kernel.org, Huang Ying , Dan Williams , David Hildenbrand , Davidlohr Bueso , Jonathan Cameron , Dave Jiang , Alison Schofield , Vishal Verma , Ira Weiny , Alistair Popple , Andy Shevchenko , Bjorn Helgaas , Baoquan He Subject: [PATCH -v3 3/3] resource, kunit: Add test case for region_intersects() Date: Fri, 6 Sep 2024 11:07:13 +0800 Message-Id: <20240906030713.204292-4-ying.huang@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240906030713.204292-1-ying.huang@intel.com> References: <20240906030713.204292-1-ying.huang@intel.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: 5ED0D1C0008 X-Rspam-User: X-Rspamd-Server: rspam05 X-Stat-Signature: gkw6x3xzmrjffyz8tgzzmodf5aqoqf4o X-HE-Tag: 1725592170-992735 X-HE-Meta: U2FsdGVkX18W9wcxTr08HuLTHsme5NvPney/c1glbFsxDZMoTEhw8XmnjJlaMuCAdO3DxYhDJvFyIa4Hy85yzmNbeZlGL6mQLV6JcRdF/eu2Dct63yP68XGoRCjiRmRZJCGexpBbpJM+UqxukxV438SNUWfODodKUp/GxCp/nTBm4+7HkhlbRtDmn2lj6iqgEpwVxoiw9BUgUS4/SaEf2eJ10912QDtd42EfawTRwNPMGrYPIkQOC+s8OnSiR7KBgWK3zrD2nxfG5ZefqFmDhldy/SO9VLCJS53pQWSPodpABIy5o/naute/ZnQsi5v9nLfcGXRwd1v6I1+Px3sC37yAsQXQwr9G5St4pAseVTU0o+gRHsXnMZSxxKiWb0CKDNIfLBb5c2qYlSVaPxm8wFeeE0eV1Bv21qXI6ipS5It6IjGmvSnX1R8xRajJBqqa3InUXHDc8QOs6EJpI7ynqARwqYM0b0325fSuYi2X744SL/w8ncXfR/pOBpQ4wGQ1LQUhaH4JYrVJaxFU5PkwzrGAVYTQggPbmzvXp2MacchTIE6MaCByXP94I/hCxzOBedqySDbiHVAkAMJimvLWZxJmMPeZohpTNxpCna3l3fRK5eH6/9xp/nfTKwxKyYW1mobYJrEqVno2jsYeo1j2yhOi7I5ErysHt3Ln1xXN2F/gBkivr4OpLbL+Z6ksOicvVG7zMkuxDiEvKAastmFLwM/nieSUc9pgP8VBPajtlvR7o//3yE2qPCs+k75oRYWAyhlA5txnzS+9JllRtdCpZE0j0qXdxE2cQhPqQwrb1XE8lVLzBqdPtpIVzzJlmMXtjrU3soGCdlEB5DYJrbybMf+oG1q0r/dd9wtjMY7M6Bmd7cCN4xY7QaZt2KtyCHAQMc2wxaL3NkekesvoCx/n8F2DL0gYhDEgEiaJzu93nDiaI4zmyfUKvskr6wQq/enzXmA3kIMAD+vvHvzmyrh y/GkmUeK DTnecf2a1OboL3oy7ntxF5w8km9PqL7+ZEaN2zh+HUff+k1Utr9QAF0hUh8aO2MdyHCGpQHjHYhaRpmPO2I6auEWJC3FqobTnKFEvjHI0lFsCtkEvpiIi0MNkhU6dlV4xQBvI0yoHBIy8Kz0lV6WFLDLIJJQRq0JmU2SIYK3NH98zW4tQFzuw+/hXWpxwf/MC2Zk2KaH+FfRIr/sthbQuakmRgUi7Sxn9fFWFv6ZhLNgLK7/voiEYpA4GvOlJn27diWNHTTnjpVTyW3RD0naX4/Wo0ibnv5x1A2b0x5j9Rw8fF6/008Xdlw8L19uX+dPdokHnQe8vremRn7fxRE6NkS5pgCjEB52DV33AzrKpaXMjELfyjZYdZot/T6MHKehatj/J 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: region_intersects() is important because it's used for /dev/mem permission checking. To avoid possible bug of region_intersects() in the future, a kunit test case for region_intersects() is added. Signed-off-by: "Huang, Ying" Cc: Dan Williams Cc: David Hildenbrand Cc: Davidlohr Bueso Cc: Jonathan Cameron Cc: Dave Jiang Cc: Alison Schofield Cc: Vishal Verma Cc: Ira Weiny Cc: Alistair Popple Cc: Andy Shevchenko Cc: Bjorn Helgaas Cc: Baoquan He --- kernel/resource.c | 20 ++++-- kernel/resource_kunit.c | 143 ++++++++++++++++++++++++++++++++++++++++ lib/Kconfig.debug | 1 + 3 files changed, 158 insertions(+), 6 deletions(-) diff --git a/kernel/resource.c b/kernel/resource.c index 035ef16c1a66..e6d222fb0f84 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -1860,7 +1860,17 @@ EXPORT_SYMBOL(resource_list_free); #ifdef CONFIG_GET_FREE_REGION #define GFR_DESCENDING (1UL << 0) #define GFR_REQUEST_REGION (1UL << 1) -#define GFR_DEFAULT_ALIGN (1UL << PA_SECTION_SHIFT) +#ifdef PA_SECTION_SHIFT +#define GFR_DEFAULT_ALIGN (1UL << PA_SECTION_SHIFT) +#else +#define GFR_DEFAULT_ALIGN PAGE_SIZE +#endif + +#ifdef MAX_PHYSMEM_BITS +#define MAX_PHYS_ADDR ((1ULL << MAX_PHYSMEM_BITS) - 1) +#else +#define MAX_PHYS_ADDR (-1ULL) +#endif static resource_size_t gfr_start(struct resource *base, resource_size_t size, resource_size_t align, unsigned long flags) @@ -1868,8 +1878,7 @@ static resource_size_t gfr_start(struct resource *base, resource_size_t size, if (flags & GFR_DESCENDING) { resource_size_t end; - end = min_t(resource_size_t, base->end, - (1ULL << MAX_PHYSMEM_BITS) - 1); + end = min_t(resource_size_t, base->end, MAX_PHYS_ADDR); return end - size + 1; } @@ -1886,8 +1895,7 @@ static bool gfr_continue(struct resource *base, resource_size_t addr, * @size did not wrap 0. */ return addr > addr - size && - addr <= min_t(resource_size_t, base->end, - (1ULL << MAX_PHYSMEM_BITS) - 1); + addr <= min_t(resource_size_t, base->end, MAX_PHYS_ADDR); } static resource_size_t gfr_next(resource_size_t addr, resource_size_t size, @@ -2048,7 +2056,7 @@ struct resource *alloc_free_mem_region(struct resource *base, return get_free_mem_region(NULL, base, size, align, name, IORES_DESC_NONE, flags); } -EXPORT_SYMBOL_NS_GPL(alloc_free_mem_region, CXL); +EXPORT_SYMBOL_GPL(alloc_free_mem_region); #endif /* CONFIG_GET_FREE_REGION */ static int __init strict_iomem(char *str) diff --git a/kernel/resource_kunit.c b/kernel/resource_kunit.c index 0e509985a44a..42d2d8d20f5d 100644 --- a/kernel/resource_kunit.c +++ b/kernel/resource_kunit.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #define R0_START 0x0000 #define R0_END 0xffff @@ -137,9 +139,150 @@ static void resource_test_intersection(struct kunit *test) } while (++i < ARRAY_SIZE(results_for_intersection)); } +/* + * The test resource tree for region_intersects() test: + * + * BASE-BASE+1M-1 : Test System RAM 0 + * # hole 0 (BASE+1M-BASE+2M) + * BASE+2M-BASE+3M-1 : Test CXL Window 0 + * BASE+3M-BASE+4M-1 : Test System RAM 1 + * BASE+4M-BASE+7M-1 : Test CXL Window 1 + * BASE+4M-BASE+5M-1 : Test System RAM 2 + * BASE+4M+128K-BASE+4M+256K-1: Test Code + * BASE+5M-BASE+6M-1 : Test System RAM 3 + */ +#define RES_TEST_RAM0_OFFSET 0 +#define RES_TEST_RAM0_SIZE SZ_1M +#define RES_TEST_HOLE0_OFFSET (RES_TEST_RAM0_OFFSET + RES_TEST_RAM0_SIZE) +#define RES_TEST_HOLE0_SIZE SZ_1M +#define RES_TEST_WIN0_OFFSET (RES_TEST_HOLE0_OFFSET + RES_TEST_HOLE0_SIZE) +#define RES_TEST_WIN0_SIZE SZ_1M +#define RES_TEST_RAM1_OFFSET (RES_TEST_WIN0_OFFSET + RES_TEST_WIN0_SIZE) +#define RES_TEST_RAM1_SIZE SZ_1M +#define RES_TEST_WIN1_OFFSET (RES_TEST_RAM1_OFFSET + RES_TEST_RAM1_SIZE) +#define RES_TEST_WIN1_SIZE (SZ_1M * 3) +#define RES_TEST_RAM2_OFFSET RES_TEST_WIN1_OFFSET +#define RES_TEST_RAM2_SIZE SZ_1M +#define RES_TEST_CODE_OFFSET (RES_TEST_RAM2_OFFSET + SZ_128K) +#define RES_TEST_CODE_SIZE SZ_128K +#define RES_TEST_RAM3_OFFSET (RES_TEST_RAM2_OFFSET + RES_TEST_RAM2_SIZE) +#define RES_TEST_RAM3_SIZE SZ_1M +#define RES_TEST_TOTAL_SIZE ((RES_TEST_WIN1_OFFSET + RES_TEST_WIN1_SIZE)) + +static void remove_free_resource(void *ctx) +{ + struct resource *res = (struct resource *)ctx; + + remove_resource(res); + kfree(res); +} + +static void resource_test_request_region(struct kunit *test, struct resource *parent, + resource_size_t start, resource_size_t size, + const char *name, unsigned long flags) +{ + struct resource *res; + + res = __request_region(parent, start, size, name, flags); + KUNIT_ASSERT_NOT_NULL(test, res); + kunit_add_action_or_reset(test, remove_free_resource, res); +} + +static void resource_test_insert_resource(struct kunit *test, struct resource *parent, + resource_size_t start, resource_size_t size, + const char *name, unsigned long flags) +{ + struct resource *res; + + res = kzalloc(sizeof(*res), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, res); + + res->name = name; + res->start = start; + res->end = start + size - 1; + res->flags = flags; + if (insert_resource(parent, res)) { + kfree(res); + KUNIT_FAIL_AND_ABORT(test, "Fail to insert resource %pR\n", res); + } + + kunit_add_action_or_reset(test, remove_free_resource, res); +} + +static void resource_test_region_intersects(struct kunit *test) +{ + unsigned long flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; + struct resource *parent; + resource_size_t start; + + /* Find an iomem_resource hole to hold test resources */ + parent = alloc_free_mem_region(&iomem_resource, RES_TEST_TOTAL_SIZE, SZ_1M, + "test resources"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); + start = parent->start; + kunit_add_action_or_reset(test, remove_free_resource, parent); + + resource_test_request_region(test, parent, start + RES_TEST_RAM0_OFFSET, + RES_TEST_RAM0_SIZE, "Test System RAM 0", flags); + resource_test_insert_resource(test, parent, start + RES_TEST_WIN0_OFFSET, + RES_TEST_WIN0_SIZE, "Test CXL Window 0", + IORESOURCE_MEM); + resource_test_request_region(test, parent, start + RES_TEST_RAM1_OFFSET, + RES_TEST_RAM1_SIZE, "Test System RAM 1", flags); + resource_test_insert_resource(test, parent, start + RES_TEST_WIN1_OFFSET, + RES_TEST_WIN1_SIZE, "Test CXL Window 1", + IORESOURCE_MEM); + resource_test_request_region(test, parent, start + RES_TEST_RAM2_OFFSET, + RES_TEST_RAM2_SIZE, "Test System RAM 2", flags); + resource_test_insert_resource(test, parent, start + RES_TEST_CODE_OFFSET, + RES_TEST_CODE_SIZE, "Test Code", flags); + resource_test_request_region(test, parent, start + RES_TEST_RAM3_OFFSET, + RES_TEST_RAM3_SIZE, "Test System RAM 3", flags); + kunit_release_action(test, remove_free_resource, parent); + + KUNIT_EXPECT_EQ(test, REGION_INTERSECTS, + region_intersects(start + RES_TEST_RAM0_OFFSET, PAGE_SIZE, + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)); + KUNIT_EXPECT_EQ(test, REGION_INTERSECTS, + region_intersects(start + RES_TEST_RAM0_OFFSET + + RES_TEST_RAM0_SIZE - PAGE_SIZE, 2 * PAGE_SIZE, + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)); + KUNIT_EXPECT_EQ(test, REGION_DISJOINT, + region_intersects(start + RES_TEST_HOLE0_OFFSET, PAGE_SIZE, + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)); + KUNIT_EXPECT_EQ(test, REGION_DISJOINT, + region_intersects(start + RES_TEST_HOLE0_OFFSET + + RES_TEST_HOLE0_SIZE - PAGE_SIZE, 2 * PAGE_SIZE, + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)); + KUNIT_EXPECT_EQ(test, REGION_MIXED, + region_intersects(start + RES_TEST_WIN0_OFFSET + + RES_TEST_WIN0_SIZE - PAGE_SIZE, 2 * PAGE_SIZE, + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)); + KUNIT_EXPECT_EQ(test, REGION_INTERSECTS, + region_intersects(start + RES_TEST_RAM1_OFFSET + + RES_TEST_RAM1_SIZE - PAGE_SIZE, 2 * PAGE_SIZE, + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)); + KUNIT_EXPECT_EQ(test, REGION_INTERSECTS, + region_intersects(start + RES_TEST_RAM2_OFFSET + + RES_TEST_RAM2_SIZE - PAGE_SIZE, 2 * PAGE_SIZE, + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)); + KUNIT_EXPECT_EQ(test, REGION_INTERSECTS, + region_intersects(start + RES_TEST_CODE_OFFSET, PAGE_SIZE, + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)); + KUNIT_EXPECT_EQ(test, REGION_INTERSECTS, + region_intersects(start + RES_TEST_RAM2_OFFSET, + RES_TEST_RAM2_SIZE + PAGE_SIZE, + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)); + KUNIT_EXPECT_EQ(test, REGION_MIXED, + region_intersects(start + RES_TEST_RAM3_OFFSET, + RES_TEST_RAM3_SIZE + PAGE_SIZE, + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)); +} + static struct kunit_case resource_test_cases[] = { KUNIT_CASE(resource_test_union), KUNIT_CASE(resource_test_intersection), + KUNIT_CASE(resource_test_region_intersects), {} }; diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index a30c03a66172..383453cbf4af 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2616,6 +2616,7 @@ config RESOURCE_KUNIT_TEST tristate "KUnit test for resource API" if !KUNIT_ALL_TESTS depends on KUNIT default KUNIT_ALL_TESTS + select GET_FREE_REGION help This builds the resource API unit test. Tests the logic of API provided by resource.c and ioport.h.