-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
memblock tests: Add memblock_alloc_from tests for top down
Add checks for memblock_alloc_from for default allocation direction. The tested scenarios are: - Not enough space to allocate memory at the minimal address - Minimal address parameter is smaller than the start address of the available memory - Minimal address is too close to the available memory Add simple memblock_alloc_from test that can be used to test both allocation directions (minimal address is aligned or misaligned). Signed-off-by: Karolina Drobnik <karolinadrobnik@gmail.com> Signed-off-by: Mike Rapoport <rppt@linux.ibm.com> Link: https://lore.kernel.org/r/3dd645f437975fd393010b95b8faa85d2b86490a.1646055639.git.karolinadrobnik@gmail.com
- Loading branch information
Karolina Drobnik
authored and
Mike Rapoport
committed
Mar 9, 2022
1 parent
0237ee2
commit 16567b5
Showing
4 changed files
with
239 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,13 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
#include "tests/basic_api.h" | ||
#include "tests/alloc_api.h" | ||
#include "tests/alloc_helpers_api.h" | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
memblock_basic_checks(); | ||
memblock_alloc_checks(); | ||
memblock_alloc_helpers_checks(); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
#include "alloc_helpers_api.h" | ||
|
||
/* | ||
* A simple test that tries to allocate a memory region above a specified, | ||
* aligned address: | ||
* | ||
* + | ||
* | +-----------+ | | ||
* | | rgn | | | ||
* +----------+-----------+---------+ | ||
* ^ | ||
* | | ||
* Aligned min_addr | ||
* | ||
* Expect to allocate a cleared region at the minimal memory address. | ||
*/ | ||
static int alloc_from_simple_generic_check(void) | ||
{ | ||
struct memblock_region *rgn = &memblock.reserved.regions[0]; | ||
void *allocated_ptr = NULL; | ||
char *b; | ||
|
||
phys_addr_t size = SZ_16; | ||
phys_addr_t min_addr; | ||
|
||
setup_memblock(); | ||
|
||
min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES; | ||
|
||
allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr); | ||
b = (char *)allocated_ptr; | ||
|
||
assert(allocated_ptr); | ||
assert(*b == 0); | ||
|
||
assert(rgn->size == size); | ||
assert(rgn->base == min_addr); | ||
|
||
assert(memblock.reserved.cnt == 1); | ||
assert(memblock.reserved.total_size == size); | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
* A test that tries to allocate a memory region above a certain address. | ||
* The minimal address here is not aligned: | ||
* | ||
* + + | ||
* | + +---------+ | | ||
* | | | rgn | | | ||
* +------+------+---------+------------+ | ||
* ^ ^------. | ||
* | | | ||
* min_addr Aligned address | ||
* boundary | ||
* | ||
* Expect to allocate a cleared region at the closest aligned memory address. | ||
*/ | ||
static int alloc_from_misaligned_generic_check(void) | ||
{ | ||
struct memblock_region *rgn = &memblock.reserved.regions[0]; | ||
void *allocated_ptr = NULL; | ||
char *b; | ||
|
||
phys_addr_t size = SZ_32; | ||
phys_addr_t min_addr; | ||
|
||
setup_memblock(); | ||
|
||
/* A misaligned address */ | ||
min_addr = memblock_end_of_DRAM() - (SMP_CACHE_BYTES * 2 - 1); | ||
|
||
allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr); | ||
b = (char *)allocated_ptr; | ||
|
||
assert(allocated_ptr); | ||
assert(*b == 0); | ||
|
||
assert(rgn->size == size); | ||
assert(rgn->base == memblock_end_of_DRAM() - SMP_CACHE_BYTES); | ||
|
||
assert(memblock.reserved.cnt == 1); | ||
assert(memblock.reserved.total_size == size); | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
* A test that tries to allocate a memory region above an address that is too | ||
* close to the end of the memory: | ||
* | ||
* + + | ||
* | +--------+---+ | | ||
* | | rgn + | | | ||
* +-----------+--------+---+------+ | ||
* ^ ^ | ||
* | | | ||
* | min_addr | ||
* | | ||
* Aligned address | ||
* boundary | ||
* | ||
* Expect to prioritize granting memory over satisfying the minimal address | ||
* requirement. | ||
*/ | ||
static int alloc_from_top_down_high_addr_check(void) | ||
{ | ||
struct memblock_region *rgn = &memblock.reserved.regions[0]; | ||
void *allocated_ptr = NULL; | ||
|
||
phys_addr_t size = SZ_32; | ||
phys_addr_t min_addr; | ||
|
||
setup_memblock(); | ||
|
||
/* The address is too close to the end of the memory */ | ||
min_addr = memblock_end_of_DRAM() - SZ_16; | ||
|
||
allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr); | ||
|
||
assert(allocated_ptr); | ||
assert(rgn->size == size); | ||
assert(rgn->base == memblock_end_of_DRAM() - SMP_CACHE_BYTES); | ||
|
||
assert(memblock.reserved.cnt == 1); | ||
assert(memblock.reserved.total_size == size); | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
* A test that tries to allocate a memory region when there is no space | ||
* available above the minimal address above a certain address: | ||
* | ||
* + | ||
* | +---------+-------------| | ||
* | | rgn | | | ||
* +--------+---------+-------------+ | ||
* ^ | ||
* | | ||
* min_addr | ||
* | ||
* Expect to prioritize granting memory over satisfying the minimal address | ||
* requirement and to allocate next to the previously reserved region. The | ||
* regions get merged into one. | ||
*/ | ||
static int alloc_from_top_down_no_space_above_check(void) | ||
{ | ||
struct memblock_region *rgn = &memblock.reserved.regions[0]; | ||
void *allocated_ptr = NULL; | ||
|
||
phys_addr_t r1_size = SZ_64; | ||
phys_addr_t r2_size = SZ_2; | ||
phys_addr_t total_size = r1_size + r2_size; | ||
phys_addr_t min_addr; | ||
|
||
setup_memblock(); | ||
|
||
min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES * 2; | ||
|
||
/* No space above this address */ | ||
memblock_reserve(min_addr, r2_size); | ||
|
||
allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr); | ||
|
||
assert(allocated_ptr); | ||
assert(rgn->base == min_addr - r1_size); | ||
assert(rgn->size == total_size); | ||
|
||
assert(memblock.reserved.cnt == 1); | ||
assert(memblock.reserved.total_size == total_size); | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
* A test that tries to allocate a memory region with a minimal address below | ||
* the start address of the available memory. As the allocation is top-down, | ||
* first reserve a region that will force allocation near the start. | ||
* Expect successful allocation and merge of both regions. | ||
*/ | ||
static int alloc_from_top_down_min_addr_cap_check(void) | ||
{ | ||
struct memblock_region *rgn = &memblock.reserved.regions[0]; | ||
void *allocated_ptr = NULL; | ||
|
||
phys_addr_t r1_size = SZ_64; | ||
phys_addr_t min_addr; | ||
phys_addr_t start_addr; | ||
|
||
setup_memblock(); | ||
|
||
start_addr = (phys_addr_t)memblock_start_of_DRAM(); | ||
min_addr = start_addr - SMP_CACHE_BYTES * 3; | ||
|
||
memblock_reserve(start_addr + r1_size, MEM_SIZE - r1_size); | ||
|
||
allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr); | ||
|
||
assert(allocated_ptr); | ||
assert(rgn->base == start_addr); | ||
assert(rgn->size == MEM_SIZE); | ||
|
||
assert(memblock.reserved.cnt == 1); | ||
assert(memblock.reserved.total_size == MEM_SIZE); | ||
|
||
return 0; | ||
} | ||
|
||
int memblock_alloc_helpers_checks(void) | ||
{ | ||
reset_memblock_attributes(); | ||
dummy_physical_memory_init(); | ||
|
||
alloc_from_simple_generic_check(); | ||
alloc_from_misaligned_generic_check(); | ||
alloc_from_top_down_high_addr_check(); | ||
alloc_from_top_down_min_addr_cap_check(); | ||
alloc_from_top_down_no_space_above_check(); | ||
|
||
dummy_physical_memory_cleanup(); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-or-later */ | ||
#ifndef _MEMBLOCK_ALLOC_HELPERS_H | ||
#define _MEMBLOCK_ALLOC_HELPERS_H | ||
|
||
#include "common.h" | ||
|
||
int memblock_alloc_helpers_checks(void); | ||
|
||
#endif |