From nobody Fri Sep 25 17:42:21 2026 Received: from out-zbxj-a67.jellyfish.systems (out-zbxj-a67.jellyfish.systems [198.54.127.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B6814825B6 for ; Wed, 9 Sep 2026 23:55:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.54.127.67 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788998153; cv=none; b=krbXDLL5YXIC0+pltBeGFIED7bAU6xKsp90DDMg5GVDjlzgOT1RwKEAtAmWT9qo/4YP/fKJlj/71q1jA5k3ctfgSmp/2mTWXxUfgICuFgviQZYjb2mi25KhgR/JWh32AL9pRe8tl+8W7TYVSWA9Iknyiy17wsrhaMw2UoUDQdHw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788998153; c=relaxed/simple; bh=5qk7BOw2pJ5DRi/y2Ft6dCgao63lL/TCifogQvFY3E4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CvL7du81B+Syg4nTFi2ArRJpJ2AH5w/kHQQkJbxxpt7m6GHGscJI0Ms01rkR/hcsb6cSz57oF+qJ8ooUFZuu+ofEgBbYWh+rxIsNnH8WLyksMzfgVQn+MltXir+fJbxtinE9Z9h3JY24D7cuEKROzZ2ipvZ6TdXyBoLJ+LmtSzs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=tychen.cc; spf=pass smtp.mailfrom=tychen.cc; dkim=pass (2048-bit key) header.d=tychen.cc header.i=@tychen.cc header.b=EPVxsCbz; arc=none smtp.client-ip=198.54.127.67 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=tychen.cc Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tychen.cc Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tychen.cc header.i=@tychen.cc header.b="EPVxsCbz" Received: from 192.168.5.7 (unknown [23.142.132.69]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mail.spacemail.com (Postfix) with ESMTPSA id 4hgHkC2CxVz2x99; Wed, 09 Sep 2026 23:55:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tychen.cc; s=spacemail; t=1788998133; bh=1z3Z8gwjIPEJ7RUurdh1RsBPbnoHaInN21ppueWrqqM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EPVxsCbz1LPCAxLcZgiOsedsqzRRSGjZ6JPsEEA3TU9opRqGOLKW1p4c0+eucT89d NItqVcuK+XOGakvFLMit+6z1tLJ/W3cmGARIC08kiOws+MBQ+zGpPOc/eVf/WVIHaP RPkEsj/tYWB0ooWque7FrnfbaXXq62hOQTxko82e/IGb7/uFrjK/AGzZLJP6kY3BQk ixVsilravnf4s+bNp9usLKRTuv84plip8G8S9uYuyLWJ5YdUYGJR6dFMDt4Qt5t899 9PY2un3xwUcOUENCndcyt0aXFdpkdyN7VUtxv1dNdidS3egif2+IRBKW+lgpjmQXvL p3gsrs4zGGfMA== From: Tianyi Chen To: Mike Rapoport Cc: akpm@linux-foundation.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, hi@tychen.cc Subject: [PATCH v3 1/2] memblock tests: model the low allocation limit within dummy memory Date: Thu, 10 Sep 2026 07:55:28 +0800 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Envelope-From: hi@tychen.cc Content-Type: text/plain; charset="utf-8" The simulator represents physical addresses using the address of its allocated buffer. That buffer can lie above the default ARCH_LOW_ADDRESS_LIMIT, preventing meaningful memblock_alloc_low() tests. Use the architecture override in asm/dma.h to place the limit halfway through the memory registered by setup_memblock(). Resolve the limit after allocating the buffer, leaving registered memory on both sides. Assisted-by: LLM Signed-off-by: Tianyi Chen --- tools/testing/memblock/asm/dma.h | 6 ++++++ tools/testing/memblock/tests/common.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/tools/testing/memblock/asm/dma.h b/tools/testing/memblock/asm/= dma.h index 13ff8e5d22ef..6607408dcf25 100644 --- a/tools/testing/memblock/asm/dma.h +++ b/tools/testing/memblock/asm/dma.h @@ -2,4 +2,10 @@ #ifndef _TOOLS_DMA_H #define _TOOLS_DMA_H =20 +#include + +phys_addr_t dummy_physical_memory_low_limit(void); + +#define ARCH_LOW_ADDRESS_LIMIT dummy_physical_memory_low_limit() + #endif diff --git a/tools/testing/memblock/tests/common.c b/tools/testing/memblock= /tests/common.c index 3250c8e5124b..ac032610a56e 100644 --- a/tools/testing/memblock/tests/common.c +++ b/tools/testing/memblock/tests/common.c @@ -118,6 +118,12 @@ phys_addr_t dummy_physical_memory_base(void) return (phys_addr_t)memory_block.base; } =20 +phys_addr_t dummy_physical_memory_low_limit(void) +{ + /* The low limit is halfway through memory registered by setup_memblock()= . */ + return dummy_physical_memory_base() + MEM_SIZE / 2; +} + static void usage(const char *prog) { BUILD_BUG_ON(ARRAY_SIZE(help_opts) !=3D ARRAY_SIZE(long_opts) - 1); --=20 2.55.0 From nobody Fri Sep 25 17:42:21 2026 Received: from out-2uec-a106.jellyfish.systems (out-2uec-a106.jellyfish.systems [63.250.43.106]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DE1F927703 for ; Thu, 10 Sep 2026 00:01:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=63.250.43.106 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788998469; cv=none; b=Kyfv5faKqKiJx0EC6JaeBOBGiRTVvJlgwi7SxJTohIs3Aow9yd704H4fbLrQiixHcmeIQNa8R2i0CcHMunLj7c2YM4rAzNzT4FmCplVoIbYgaFALEBqFXW2aYKwWDApEJm7cNu7WKGoevKtREcxZlDrnuTzMYSmYeFsFwJNJGGE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788998469; c=relaxed/simple; bh=SX+bMZ0aI4X8SyepNmkC/cEyz+B2CQ3mjUz4PL0X4Gg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sfWsrKDroBxyzzOPRZgb88AEzspDby9gsbQwfvQuVXiEvrGX+9ifz5psx+F3c+Gt9pyK5TTvbCadYYlNwrguKbkQIosLeWoob9siE0Tz34CSbPOu+Lrb3PQ7WCq66V3aFd55PhQ/gElmyxffeR6cXw3TPweKCkGj8GGGsc2bsBo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=tychen.cc; spf=pass smtp.mailfrom=tychen.cc; dkim=pass (2048-bit key) header.d=tychen.cc header.i=@tychen.cc header.b=PRwKdnpQ; arc=none smtp.client-ip=63.250.43.106 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=tychen.cc Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tychen.cc Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tychen.cc header.i=@tychen.cc header.b="PRwKdnpQ" Received: from 192.168.5.7 (unknown [23.142.132.69]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mail.spacemail.com (Postfix) with ESMTPSA id 4hgHkJ4BJqz8sWx; Wed, 09 Sep 2026 23:55:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tychen.cc; s=spacemail; t=1788998139; bh=gqlhQP7/rcLpP1L94OJdJPvDYnSuPnzWrOMZcm1+ctk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PRwKdnpQCuj0IQlh8gj0eKl/m+Que9hj8iaNZSqqYUjrOnMMubtS4vz6X0U7E3SEl hXwT4TyghX12pxYDv59MvDg7afpBenbENFnvcN5ZGC7OZ558ZU6tS2+YxZtMik+e4J DEupObNhAO9WG2ynZE8X3Vfto9wRhXyR+GTZG7iFpUf5ulUKXI/7ogQwJe9PQA9e2o 5bMn+z8fdautAj13feG2mz9d22B3FKoZtD0oquAPr5ZSTQsTzdL+Y+6NcRy8BNvwtf eyKKqeTmc6n28mIBWYV73rDWFlf+MoH7DHodYKdD39IAWRmuKd5zOaopqD8MdEw5hM JFZcRmHaw4fKA== From: Tianyi Chen To: Mike Rapoport Cc: akpm@linux-foundation.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, hi@tychen.cc Subject: [PATCH v3 2/2] memblock tests: cover allocations below the low address limit Date: Thu, 10 Sep 2026 07:55:33 +0800 Message-ID: <142ab1025fd1e4b5dcd2a1591b964626ebce9d23.1788997523.git.hi@tychen.cc> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Envelope-From: hi@tychen.cc Content-Type: text/plain; charset="utf-8" Add memblock_alloc_low() coverage using the simulator's low address limit. Exercise aligned allocation, an allocation whose last byte is immediately below the limit, an alignment constraint that prevents fitting below it, and fully reserved low memory with high memory still available. Run each case with bottom-up and top-down allocation. Check zeroing and reserved-region accounting as well as returned addresses. Verify that an unrestricted allocation can use the free high memory after the low allocation fails. Document the simulated limit and remove the completed TODO. Assisted-by: LLM Signed-off-by: Tianyi Chen --- tools/testing/memblock/Makefile | 3 +- tools/testing/memblock/README | 12 +- tools/testing/memblock/TODO | 5 - tools/testing/memblock/main.c | 2 + tools/testing/memblock/tests/alloc_low_api.c | 148 +++++++++++++++++++ tools/testing/memblock/tests/alloc_low_api.h | 9 ++ 6 files changed, 166 insertions(+), 13 deletions(-) delete mode 100644 tools/testing/memblock/TODO create mode 100644 tools/testing/memblock/tests/alloc_low_api.c create mode 100644 tools/testing/memblock/tests/alloc_low_api.h diff --git a/tools/testing/memblock/Makefile b/tools/testing/memblock/Makef= ile index d80982ccdc20..20524fcbe3c7 100644 --- a/tools/testing/memblock/Makefile +++ b/tools/testing/memblock/Makefile @@ -7,7 +7,8 @@ CFLAGS +=3D -I. -I../../include -Wall -O2 -fsanitize=3Daddr= ess \ LDFLAGS +=3D -fsanitize=3Daddress -fsanitize=3Dundefined TARGETS =3D main TEST_OFILES =3D tests/alloc_nid_api.o tests/alloc_helpers_api.o tests/allo= c_api.o \ - tests/basic_api.o tests/common.o tests/alloc_exact_nid_api.o + tests/basic_api.o tests/common.o tests/alloc_exact_nid_api.o \ + tests/alloc_low_api.o DEP_OFILES =3D memblock.o lib/slab.o mmzone.o slab.o cmdline.o OFILES =3D main.o $(DEP_OFILES) $(TEST_OFILES) EXTR_SRC =3D ../../../mm/memblock.c diff --git a/tools/testing/memblock/README b/tools/testing/memblock/README index b435f48d8a70..4ea293209548 100644 --- a/tools/testing/memblock/README +++ b/tools/testing/memblock/README @@ -67,13 +67,13 @@ memblock |-- tests | |-- alloc_api.(c|h) -- memblock_alloc tests | |-- alloc_helpers_api.(c|h) -- memblock_alloc_from tests +| |-- alloc_low_api.(c|h) -- memblock_alloc_low tests | |-- alloc_nid_api.(c|h) -- memblock_alloc_try_nid tests | |-- basic_api.(c|h) -- memblock_add/memblock_reserve/... tests | |-- common.(c|h) -- helper functions for resetting membloc= k; |-- main.c --------------. dummy physical memory definition |-- Makefile `- test runner |-- README -|-- TODO |-- .gitignore =20 Simulating physical memory @@ -101,12 +101,10 @@ There's no need to explicitly free the dummy memory f= rom memblock via memblock_free() call. The entry will be erased by reset_memblock_regions(), called at the beginning of each test. =20 -Known issues -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D - -1. Tests for memblock_alloc_low() can't be easily implemented. The functio= n uses - ARCH_LOW_ADDRESS_LIMIT marco, which can't be changed to point at the low - memory of the memory_block. +The simulator defines ARCH_LOW_ADDRESS_LIMIT in asm/dma.h using the midpoi= nt +of the MEM_SIZE range registered by setup_memblock(). This leaves register= ed +memory both below and above the limit. The limit is the first address an +allocation must not use; an allocation's base plus its size may equal the = limit. =20 References =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D diff --git a/tools/testing/memblock/TODO b/tools/testing/memblock/TODO deleted file mode 100644 index c13ad0dae776..000000000000 --- a/tools/testing/memblock/TODO +++ /dev/null @@ -1,5 +0,0 @@ -TODO -=3D=3D=3D=3D=3D - -1. Add tests for memblock_alloc_low() once the simulator can model - ARCH_LOW_ADDRESS_LIMIT against the low memory in memory_block diff --git a/tools/testing/memblock/main.c b/tools/testing/memblock/main.c index 278f9dec5008..9a96e178551b 100644 --- a/tools/testing/memblock/main.c +++ b/tools/testing/memblock/main.c @@ -4,6 +4,7 @@ #include "tests/alloc_helpers_api.h" #include "tests/alloc_nid_api.h" #include "tests/alloc_exact_nid_api.h" +#include "tests/alloc_low_api.h" #include "tests/common.h" =20 int main(int argc, char **argv) @@ -12,6 +13,7 @@ int main(int argc, char **argv) memblock_basic_checks(); memblock_alloc_checks(); memblock_alloc_helpers_checks(); + memblock_alloc_low_checks(); memblock_alloc_nid_checks(); memblock_alloc_exact_nid_checks(); =20 diff --git a/tools/testing/memblock/tests/alloc_low_api.c b/tools/testing/m= emblock/tests/alloc_low_api.c new file mode 100644 index 000000000000..a117431f1f71 --- /dev/null +++ b/tools/testing/memblock/tests/alloc_low_api.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include "alloc_low_api.h" +#include + +/* Allocate at the first or last aligned address below the low limit. */ +static int alloc_low_simple_check(void) +{ + struct memblock_region *rgn =3D &memblock.reserved.regions[0]; + phys_addr_t size =3D SZ_64; + phys_addr_t expected; + void *allocated_ptr; + + PREFIX_PUSH(); + setup_memblock(); + + /* Simulated physical RAM is not necessarily SMP_CACHE_BYTES aligned. */ + if (memblock_bottom_up()) + expected =3D ALIGN(memblock_start_of_DRAM(), SMP_CACHE_BYTES); + else + expected =3D ALIGN_DOWN(ARCH_LOW_ADDRESS_LIMIT - size, + SMP_CACHE_BYTES); + + allocated_ptr =3D memblock_alloc_low(size, SMP_CACHE_BYTES); + + ASSERT_NE(allocated_ptr, NULL); + ASSERT_EQ((phys_addr_t)(uintptr_t)allocated_ptr, expected); + ASSERT_MEM_EQ(allocated_ptr, 0, size); + ASSERT_EQ(rgn->base, expected); + ASSERT_EQ(rgn->size, size); + ASSERT_LE(region_end(rgn), ARCH_LOW_ADDRESS_LIMIT); + ASSERT_EQ(memblock.reserved.cnt, 1); + ASSERT_EQ(memblock.reserved.total_size, size); + + test_pass_pop(); + return 0; +} + +/* The last byte of the allocation is immediately below the low limit. */ +static int alloc_low_exact_limit_check(void) +{ + phys_addr_t limit =3D ARCH_LOW_ADDRESS_LIMIT; + phys_addr_t base =3D ALIGN_DOWN(limit - SZ_64, SMP_CACHE_BYTES); + phys_addr_t size =3D limit - base; + void *allocated_ptr; + + PREFIX_PUSH(); + setup_memblock(); + ASSERT_EQ(memblock_remove(memblock_start_of_DRAM(), + base - memblock_start_of_DRAM()), 0); + + allocated_ptr =3D memblock_alloc_low(size, SMP_CACHE_BYTES); + + ASSERT_NE(allocated_ptr, NULL); + ASSERT_EQ((phys_addr_t)(uintptr_t)allocated_ptr, base); + ASSERT_MEM_EQ(allocated_ptr, 0, size); + ASSERT_EQ(memblock.reserved.regions[0].base, base); + ASSERT_EQ(region_end(&memblock.reserved.regions[0]), limit); + ASSERT_EQ(memblock.reserved.cnt, 1); + ASSERT_EQ(memblock.reserved.total_size, size); + + test_pass_pop(); + return 0; +} + +/* + * There are size bytes below the limit, but aligning the start makes the + * allocation cross it. Memory above the limit must not satisfy the reques= t. + */ +static int alloc_low_alignment_crosses_limit_check(void) +{ + phys_addr_t limit =3D ARCH_LOW_ADDRESS_LIMIT; + phys_addr_t base =3D ALIGN_DOWN(limit, SMP_CACHE_BYTES) - 1; + phys_addr_t size =3D limit - base; + void *allocated_ptr; + + PREFIX_PUSH(); + setup_memblock(); + ASSERT_EQ(memblock_remove(memblock_start_of_DRAM(), + base - memblock_start_of_DRAM()), 0); + + allocated_ptr =3D memblock_alloc_low(size, SMP_CACHE_BYTES); + + ASSERT_EQ(allocated_ptr, NULL); + ASSERT_EQ(memblock.reserved.cnt, 0); + ASSERT_EQ(memblock.reserved.total_size, 0); + ASSERT_MEM_EQ((void *)(uintptr_t)base, 1, memblock_end_of_DRAM() - base); + + test_pass_pop(); + return 0; +} + +/* Allocation must fail after reserving all low memory, with high memory f= ree. */ +static int alloc_low_reserved_check(void) +{ + phys_addr_t limit =3D ARCH_LOW_ADDRESS_LIMIT; + phys_addr_t base =3D dummy_physical_memory_base(); + phys_addr_t size =3D SZ_64; + void *allocated_ptr; + + PREFIX_PUSH(); + setup_memblock(); + ASSERT_EQ(memblock_reserve(base, limit - base), 0); + + allocated_ptr =3D memblock_alloc_low(size, SMP_CACHE_BYTES); + + ASSERT_EQ(allocated_ptr, NULL); + ASSERT_EQ(memblock.reserved.cnt, 1); + ASSERT_EQ(memblock.reserved.regions[0].base, base); + ASSERT_EQ(memblock.reserved.regions[0].size, limit - base); + ASSERT_EQ(memblock.reserved.total_size, limit - base); + ASSERT_MEM_EQ((void *)(uintptr_t)base, 1, MEM_SIZE); + + allocated_ptr =3D memblock_alloc(size, SMP_CACHE_BYTES); + ASSERT_NE(allocated_ptr, NULL); + ASSERT_LE(limit, (phys_addr_t)(uintptr_t)allocated_ptr); + ASSERT_MEM_EQ(allocated_ptr, 0, size); + + test_pass_pop(); + return 0; +} + +static int alloc_low_checks(void) +{ + alloc_low_simple_check(); + alloc_low_exact_limit_check(); + alloc_low_alignment_crosses_limit_check(); + alloc_low_reserved_check(); + + return 0; +} + +int memblock_alloc_low_checks(void) +{ + prefix_reset(); + prefix_push("memblock_alloc_low"); + test_print("Running memblock_alloc_low tests...\n"); + + reset_memblock_attributes(); + dummy_physical_memory_init(); + + run_top_down(alloc_low_checks); + run_bottom_up(alloc_low_checks); + + dummy_physical_memory_cleanup(); + prefix_pop(); + + return 0; +} diff --git a/tools/testing/memblock/tests/alloc_low_api.h b/tools/testing/m= emblock/tests/alloc_low_api.h new file mode 100644 index 000000000000..2e3cbe336f5d --- /dev/null +++ b/tools/testing/memblock/tests/alloc_low_api.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _MEMBLOCK_ALLOC_LOW_H +#define _MEMBLOCK_ALLOC_LOW_H + +#include "common.h" + +int memblock_alloc_low_checks(void); + +#endif --=20 2.55.0