mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
memblock: extend test coverage
* add tests that trigger reallocation of memblock structures from memblock itself via memblock_double_array() * add tests for memblock_alloc_exact_nid_raw() that verify that requested node and memory range constraints are respected. -----BEGIN PGP SIGNATURE----- iQFMBAABCAA2FiEEeOVYVaWZL5900a/pOQOGJssO/ZEFAmOYL14YHG1pa2UucmFw b3BvcnRAZ21haWwuY29tAAoJEDkDhibLDv2RZdcH/2AE447oXzVO2lzOgkqQH1EX xJdaa7hu00h2Euzv2lgcOHroHGXDP8wYjUV2cEyNZMP0WOMiO8i6rwIKmrzWufcm R+ZoKPQV/Nc+7rIycpW455yLxcgsVIpUILK2BQEkDCGYugSHKb7IYdcA9KDJwtmR xIG9j8nsuwWJtmtAuQqNOBmsc5FzKNYFa/RtDiJoMFmQNK3UqB8G8VCASdP0DYvH 7MXPcyRmlwpmOsKoNKi2/wQBsiag8/PLgcZv5vYg+E6no1tMG6u7pgDS12Sn6ZvA I8gThJ8HNAo0d1O2SnbkicMx2CqrPFSub3QXaEFjCZF5mdBcirxHc/VBKj50TXU= =iXEA -----END PGP SIGNATURE----- Merge tag 'memblock-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock Pull memblock updates from Mike Rapoport: "Extend test coverage: - add tests that trigger reallocation of memblock structures from memblock itself via memblock_double_array() - add tests for memblock_alloc_exact_nid_raw() that verify that requested node and memory range constraints are respected" * tag 'memblock-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock: memblock tests: remove completed TODO item memblock tests: add generic NUMA tests for memblock_alloc_exact_nid_raw memblock tests: add bottom-up NUMA tests for memblock_alloc_exact_nid_raw memblock tests: add top-down NUMA tests for memblock_alloc_exact_nid_raw memblock tests: introduce range tests for memblock_alloc_exact_nid_raw memblock test: Update TODO list memblock test: Add test to memblock_reserve() 129th region memblock test: Add test to memblock_add() 129th region
This commit is contained in:
commit
ad76bf1ff1
10 changed files with 1621 additions and 279 deletions
|
@ -7,7 +7,7 @@ CFLAGS += -I. -I../../include -Wall -O2 -fsanitize=address \
|
||||||
LDFLAGS += -fsanitize=address -fsanitize=undefined
|
LDFLAGS += -fsanitize=address -fsanitize=undefined
|
||||||
TARGETS = main
|
TARGETS = main
|
||||||
TEST_OFILES = tests/alloc_nid_api.o tests/alloc_helpers_api.o tests/alloc_api.o \
|
TEST_OFILES = tests/alloc_nid_api.o tests/alloc_helpers_api.o tests/alloc_api.o \
|
||||||
tests/basic_api.o tests/common.o
|
tests/basic_api.o tests/common.o tests/alloc_exact_nid_api.o
|
||||||
DEP_OFILES = memblock.o lib/slab.o mmzone.o slab.o
|
DEP_OFILES = memblock.o lib/slab.o mmzone.o slab.o
|
||||||
OFILES = main.o $(DEP_OFILES) $(TEST_OFILES)
|
OFILES = main.o $(DEP_OFILES) $(TEST_OFILES)
|
||||||
EXTR_SRC = ../../../mm/memblock.c
|
EXTR_SRC = ../../../mm/memblock.c
|
||||||
|
|
|
@ -1,17 +1,5 @@
|
||||||
TODO
|
TODO
|
||||||
=====
|
=====
|
||||||
|
|
||||||
1. Add tests trying to memblock_add() or memblock_reserve() 129th region.
|
1. Add tests for memblock_alloc_node() to check if the correct NUMA node is set
|
||||||
This will trigger memblock_double_array(), make sure it succeeds.
|
|
||||||
*Important:* These tests require valid memory ranges, use dummy physical
|
|
||||||
memory block from common.c to implement them. It is also very
|
|
||||||
likely that the current MEM_SIZE won't be enough for these
|
|
||||||
test cases. Use realloc to adjust the size accordingly.
|
|
||||||
|
|
||||||
2. Add test cases using this functions (implement them for both directions):
|
|
||||||
+ memblock_alloc_raw()
|
|
||||||
+ memblock_alloc_exact_nid_raw()
|
|
||||||
+ memblock_alloc_try_nid_raw()
|
|
||||||
|
|
||||||
3. Add tests for memblock_alloc_node() to check if the correct NUMA node is set
|
|
||||||
for the new region
|
for the new region
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "tests/alloc_api.h"
|
#include "tests/alloc_api.h"
|
||||||
#include "tests/alloc_helpers_api.h"
|
#include "tests/alloc_helpers_api.h"
|
||||||
#include "tests/alloc_nid_api.h"
|
#include "tests/alloc_nid_api.h"
|
||||||
|
#include "tests/alloc_exact_nid_api.h"
|
||||||
#include "tests/common.h"
|
#include "tests/common.h"
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
|
@ -12,6 +13,7 @@ int main(int argc, char **argv)
|
||||||
memblock_alloc_checks();
|
memblock_alloc_checks();
|
||||||
memblock_alloc_helpers_checks();
|
memblock_alloc_helpers_checks();
|
||||||
memblock_alloc_nid_checks();
|
memblock_alloc_nid_checks();
|
||||||
|
memblock_alloc_exact_nid_checks();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
1113
tools/testing/memblock/tests/alloc_exact_nid_api.c
Normal file
1113
tools/testing/memblock/tests/alloc_exact_nid_api.c
Normal file
File diff suppressed because it is too large
Load diff
25
tools/testing/memblock/tests/alloc_exact_nid_api.h
Normal file
25
tools/testing/memblock/tests/alloc_exact_nid_api.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
#ifndef _MEMBLOCK_ALLOC_EXACT_NID_H
|
||||||
|
#define _MEMBLOCK_ALLOC_EXACT_NID_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int memblock_alloc_exact_nid_checks(void);
|
||||||
|
int __memblock_alloc_exact_nid_numa_checks(void);
|
||||||
|
|
||||||
|
#ifdef CONFIG_NUMA
|
||||||
|
static inline int memblock_alloc_exact_nid_numa_checks(void)
|
||||||
|
{
|
||||||
|
__memblock_alloc_exact_nid_numa_checks();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
static inline int memblock_alloc_exact_nid_numa_checks(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_NUMA */
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -5,6 +5,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
int memblock_alloc_nid_checks(void);
|
int memblock_alloc_nid_checks(void);
|
||||||
|
int memblock_alloc_exact_nid_range_checks(void);
|
||||||
int __memblock_alloc_nid_numa_checks(void);
|
int __memblock_alloc_nid_numa_checks(void);
|
||||||
|
|
||||||
#ifdef CONFIG_NUMA
|
#ifdef CONFIG_NUMA
|
||||||
|
|
|
@ -423,6 +423,98 @@ static int memblock_add_near_max_check(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A test that trying to add the 129th memory block.
|
||||||
|
* Expect to trigger memblock_double_array() to double the
|
||||||
|
* memblock.memory.max, find a new valid memory as
|
||||||
|
* memory.regions.
|
||||||
|
*/
|
||||||
|
static int memblock_add_many_check(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
void *orig_region;
|
||||||
|
struct region r = {
|
||||||
|
.base = SZ_16K,
|
||||||
|
.size = SZ_16K,
|
||||||
|
};
|
||||||
|
phys_addr_t new_memory_regions_size;
|
||||||
|
phys_addr_t base, size = SZ_64;
|
||||||
|
phys_addr_t gap_size = SZ_64;
|
||||||
|
|
||||||
|
PREFIX_PUSH();
|
||||||
|
|
||||||
|
reset_memblock_regions();
|
||||||
|
memblock_allow_resize();
|
||||||
|
|
||||||
|
dummy_physical_memory_init();
|
||||||
|
/*
|
||||||
|
* We allocated enough memory by using dummy_physical_memory_init(), and
|
||||||
|
* split it into small block. First we split a large enough memory block
|
||||||
|
* as the memory region which will be choosed by memblock_double_array().
|
||||||
|
*/
|
||||||
|
base = PAGE_ALIGN(dummy_physical_memory_base());
|
||||||
|
new_memory_regions_size = PAGE_ALIGN(INIT_MEMBLOCK_REGIONS * 2 *
|
||||||
|
sizeof(struct memblock_region));
|
||||||
|
memblock_add(base, new_memory_regions_size);
|
||||||
|
|
||||||
|
/* This is the base of small memory block. */
|
||||||
|
base += new_memory_regions_size + gap_size;
|
||||||
|
|
||||||
|
orig_region = memblock.memory.regions;
|
||||||
|
|
||||||
|
for (i = 0; i < INIT_MEMBLOCK_REGIONS; i++) {
|
||||||
|
/*
|
||||||
|
* Add these small block to fulfill the memblock. We keep a
|
||||||
|
* gap between the nearby memory to avoid being merged.
|
||||||
|
*/
|
||||||
|
memblock_add(base, size);
|
||||||
|
base += size + gap_size;
|
||||||
|
|
||||||
|
ASSERT_EQ(memblock.memory.cnt, i + 2);
|
||||||
|
ASSERT_EQ(memblock.memory.total_size, new_memory_regions_size +
|
||||||
|
(i + 1) * size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At there, memblock_double_array() has been succeed, check if it
|
||||||
|
* update the memory.max.
|
||||||
|
*/
|
||||||
|
ASSERT_EQ(memblock.memory.max, INIT_MEMBLOCK_REGIONS * 2);
|
||||||
|
|
||||||
|
/* memblock_double_array() will reserve the memory it used. Check it. */
|
||||||
|
ASSERT_EQ(memblock.reserved.cnt, 1);
|
||||||
|
ASSERT_EQ(memblock.reserved.total_size, new_memory_regions_size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now memblock_double_array() works fine. Let's check after the
|
||||||
|
* double_array(), the memblock_add() still works as normal.
|
||||||
|
*/
|
||||||
|
memblock_add(r.base, r.size);
|
||||||
|
ASSERT_EQ(memblock.memory.regions[0].base, r.base);
|
||||||
|
ASSERT_EQ(memblock.memory.regions[0].size, r.size);
|
||||||
|
|
||||||
|
ASSERT_EQ(memblock.memory.cnt, INIT_MEMBLOCK_REGIONS + 2);
|
||||||
|
ASSERT_EQ(memblock.memory.total_size, INIT_MEMBLOCK_REGIONS * size +
|
||||||
|
new_memory_regions_size +
|
||||||
|
r.size);
|
||||||
|
ASSERT_EQ(memblock.memory.max, INIT_MEMBLOCK_REGIONS * 2);
|
||||||
|
|
||||||
|
dummy_physical_memory_cleanup();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The current memory.regions is occupying a range of memory that
|
||||||
|
* allocated from dummy_physical_memory_init(). After free the memory,
|
||||||
|
* we must not use it. So restore the origin memory region to make sure
|
||||||
|
* the tests can run as normal and not affected by the double array.
|
||||||
|
*/
|
||||||
|
memblock.memory.regions = orig_region;
|
||||||
|
memblock.memory.cnt = INIT_MEMBLOCK_REGIONS;
|
||||||
|
|
||||||
|
test_pass_pop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int memblock_add_checks(void)
|
static int memblock_add_checks(void)
|
||||||
{
|
{
|
||||||
prefix_reset();
|
prefix_reset();
|
||||||
|
@ -438,6 +530,7 @@ static int memblock_add_checks(void)
|
||||||
memblock_add_twice_check();
|
memblock_add_twice_check();
|
||||||
memblock_add_between_check();
|
memblock_add_between_check();
|
||||||
memblock_add_near_max_check();
|
memblock_add_near_max_check();
|
||||||
|
memblock_add_many_check();
|
||||||
|
|
||||||
prefix_pop();
|
prefix_pop();
|
||||||
|
|
||||||
|
@ -799,6 +892,96 @@ static int memblock_reserve_near_max_check(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A test that trying to reserve the 129th memory block.
|
||||||
|
* Expect to trigger memblock_double_array() to double the
|
||||||
|
* memblock.memory.max, find a new valid memory as
|
||||||
|
* reserved.regions.
|
||||||
|
*/
|
||||||
|
static int memblock_reserve_many_check(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
void *orig_region;
|
||||||
|
struct region r = {
|
||||||
|
.base = SZ_16K,
|
||||||
|
.size = SZ_16K,
|
||||||
|
};
|
||||||
|
phys_addr_t memory_base = SZ_128K;
|
||||||
|
phys_addr_t new_reserved_regions_size;
|
||||||
|
|
||||||
|
PREFIX_PUSH();
|
||||||
|
|
||||||
|
reset_memblock_regions();
|
||||||
|
memblock_allow_resize();
|
||||||
|
|
||||||
|
/* Add a valid memory region used by double_array(). */
|
||||||
|
dummy_physical_memory_init();
|
||||||
|
memblock_add(dummy_physical_memory_base(), MEM_SIZE);
|
||||||
|
|
||||||
|
for (i = 0; i < INIT_MEMBLOCK_REGIONS; i++) {
|
||||||
|
/* Reserve some fakes memory region to fulfill the memblock. */
|
||||||
|
memblock_reserve(memory_base, MEM_SIZE);
|
||||||
|
|
||||||
|
ASSERT_EQ(memblock.reserved.cnt, i + 1);
|
||||||
|
ASSERT_EQ(memblock.reserved.total_size, (i + 1) * MEM_SIZE);
|
||||||
|
|
||||||
|
/* Keep the gap so these memory region will not be merged. */
|
||||||
|
memory_base += MEM_SIZE * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
orig_region = memblock.reserved.regions;
|
||||||
|
|
||||||
|
/* This reserve the 129 memory_region, and makes it double array. */
|
||||||
|
memblock_reserve(memory_base, MEM_SIZE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the memory region size used by the doubled reserved.regions,
|
||||||
|
* and it has been reserved due to it has been used. The size is used to
|
||||||
|
* calculate the total_size that the memblock.reserved have now.
|
||||||
|
*/
|
||||||
|
new_reserved_regions_size = PAGE_ALIGN((INIT_MEMBLOCK_REGIONS * 2) *
|
||||||
|
sizeof(struct memblock_region));
|
||||||
|
/*
|
||||||
|
* The double_array() will find a free memory region as the new
|
||||||
|
* reserved.regions, and the used memory region will be reserved, so
|
||||||
|
* there will be one more region exist in the reserved memblock. And the
|
||||||
|
* one more reserved region's size is new_reserved_regions_size.
|
||||||
|
*/
|
||||||
|
ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 2);
|
||||||
|
ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE +
|
||||||
|
new_reserved_regions_size);
|
||||||
|
ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now memblock_double_array() works fine. Let's check after the
|
||||||
|
* double_array(), the memblock_reserve() still works as normal.
|
||||||
|
*/
|
||||||
|
memblock_reserve(r.base, r.size);
|
||||||
|
ASSERT_EQ(memblock.reserved.regions[0].base, r.base);
|
||||||
|
ASSERT_EQ(memblock.reserved.regions[0].size, r.size);
|
||||||
|
|
||||||
|
ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 3);
|
||||||
|
ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE +
|
||||||
|
new_reserved_regions_size +
|
||||||
|
r.size);
|
||||||
|
ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2);
|
||||||
|
|
||||||
|
dummy_physical_memory_cleanup();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The current reserved.regions is occupying a range of memory that
|
||||||
|
* allocated from dummy_physical_memory_init(). After free the memory,
|
||||||
|
* we must not use it. So restore the origin memory region to make sure
|
||||||
|
* the tests can run as normal and not affected by the double array.
|
||||||
|
*/
|
||||||
|
memblock.reserved.regions = orig_region;
|
||||||
|
memblock.reserved.cnt = INIT_MEMBLOCK_RESERVED_REGIONS;
|
||||||
|
|
||||||
|
test_pass_pop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int memblock_reserve_checks(void)
|
static int memblock_reserve_checks(void)
|
||||||
{
|
{
|
||||||
prefix_reset();
|
prefix_reset();
|
||||||
|
@ -813,6 +996,7 @@ static int memblock_reserve_checks(void)
|
||||||
memblock_reserve_twice_check();
|
memblock_reserve_twice_check();
|
||||||
memblock_reserve_between_check();
|
memblock_reserve_between_check();
|
||||||
memblock_reserve_near_max_check();
|
memblock_reserve_near_max_check();
|
||||||
|
memblock_reserve_many_check();
|
||||||
|
|
||||||
prefix_pop();
|
prefix_pop();
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
#include <linux/memory_hotplug.h>
|
#include <linux/memory_hotplug.h>
|
||||||
#include <linux/build_bug.h>
|
#include <linux/build_bug.h>
|
||||||
|
|
||||||
#define INIT_MEMBLOCK_REGIONS 128
|
|
||||||
#define INIT_MEMBLOCK_RESERVED_REGIONS INIT_MEMBLOCK_REGIONS
|
|
||||||
#define PREFIXES_MAX 15
|
#define PREFIXES_MAX 15
|
||||||
#define DELIM ": "
|
#define DELIM ": "
|
||||||
#define BASIS 10000
|
#define BASIS 10000
|
||||||
|
@ -115,6 +113,11 @@ void dummy_physical_memory_cleanup(void)
|
||||||
free(memory_block.base);
|
free(memory_block.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
phys_addr_t dummy_physical_memory_base(void)
|
||||||
|
{
|
||||||
|
return (phys_addr_t)memory_block.base;
|
||||||
|
}
|
||||||
|
|
||||||
static void usage(const char *prog)
|
static void usage(const char *prog)
|
||||||
{
|
{
|
||||||
BUILD_BUG_ON(ARRAY_SIZE(help_opts) != ARRAY_SIZE(long_opts) - 1);
|
BUILD_BUG_ON(ARRAY_SIZE(help_opts) != ARRAY_SIZE(long_opts) - 1);
|
||||||
|
|
|
@ -10,14 +10,19 @@
|
||||||
#include <linux/printk.h>
|
#include <linux/printk.h>
|
||||||
#include <../selftests/kselftest.h>
|
#include <../selftests/kselftest.h>
|
||||||
|
|
||||||
#define MEM_SIZE SZ_16K
|
#define MEM_SIZE SZ_32K
|
||||||
#define NUMA_NODES 8
|
#define NUMA_NODES 8
|
||||||
|
|
||||||
|
#define INIT_MEMBLOCK_REGIONS 128
|
||||||
|
#define INIT_MEMBLOCK_RESERVED_REGIONS INIT_MEMBLOCK_REGIONS
|
||||||
|
|
||||||
enum test_flags {
|
enum test_flags {
|
||||||
/* No special request. */
|
/* No special request. */
|
||||||
TEST_F_NONE = 0x0,
|
TEST_F_NONE = 0x0,
|
||||||
/* Perform raw allocations (no zeroing of memory). */
|
/* Perform raw allocations (no zeroing of memory). */
|
||||||
TEST_F_RAW = 0x1,
|
TEST_F_RAW = 0x1,
|
||||||
|
/* Perform allocations on the exact node specified. */
|
||||||
|
TEST_F_EXACT = 0x2
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,6 +129,7 @@ void setup_memblock(void);
|
||||||
void setup_numa_memblock(const unsigned int node_fracs[]);
|
void setup_numa_memblock(const unsigned int node_fracs[]);
|
||||||
void dummy_physical_memory_init(void);
|
void dummy_physical_memory_init(void);
|
||||||
void dummy_physical_memory_cleanup(void);
|
void dummy_physical_memory_cleanup(void);
|
||||||
|
phys_addr_t dummy_physical_memory_base(void);
|
||||||
void parse_args(int argc, char **argv);
|
void parse_args(int argc, char **argv);
|
||||||
|
|
||||||
void test_fail(void);
|
void test_fail(void);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue