Add a test that reserved-memory nodes above ram_top are skipped without an error, and that the part of a node crossing ram_top which lies below it is still reserved.
Enable LMB_LIMIT_DMA_BELOW_RAM_TOP on sandbox so that the test runs. The sandbox RAM ends at ram_top, so nothing is reserved above it outside the test. Signed-off-by: David Lechner <[email protected]> --- lib/Kconfig | 1 + test/boot/image_fdt.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/lib/Kconfig b/lib/Kconfig index 021a82d4709..96d3da335d2 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1372,6 +1372,7 @@ config LMB_LIMIT_DMA_BELOW_RAM_TOP bool depends on LMB default y if ARCH_BCM283X || ARCH_MVEBU || ARCH_ROCKCHIP || STARFIVE_JH7110 + default y if SANDBOX help Some architectures can not DMA above ram_top boundary, which is after 4 GiB or 32-bit boundary too. Limit the diff --git a/test/boot/image_fdt.c b/test/boot/image_fdt.c index 5417689a683..13d2f83983c 100644 --- a/test/boot/image_fdt.c +++ b/test/boot/image_fdt.c @@ -6,11 +6,14 @@ #include <config.h> #include <fdt_support.h> +#include <fdtdec.h> #include <image.h> #include <lmb.h> #include <malloc.h> #include <asm/global_data.h> +#include <linux/libfdt.h> +#include <linux/sizes.h> #include <test/test.h> #include <test/ut.h> @@ -81,3 +84,75 @@ free_blob: return ret; } IMAGE_FDT_TEST(test_boot_fdt_add_mem_rsv_regions, UTF_CONSOLE); + +/** + * test_boot_fdt_rsv_above_ram_top - Make sure dt reservations above ram_top + * are handled quietly + * @uts: Test state + * + * With LMB_LIMIT_DMA_BELOW_RAM_TOP, LMB reserves the memory above ram_top + * itself. A reservation above ram_top must then be skipped without an error, + * and a reservation that crosses ram_top must still reserve its part below + * ram_top. + */ +static int test_boot_fdt_rsv_above_ram_top(struct unit_test_state *uts) +{ + phys_addr_t ram_top = gd->ram_base + gd->ram_size / 2; + phys_addr_t old_ram_top = gd->ram_top; + phys_size_t size = gd->ram_base + gd->ram_size - ram_top; + struct fdt_memory above = { + .start = ram_top + SZ_4K, + .end = ram_top + 2 * SZ_4K - 1, + }; + struct fdt_memory across = { + .start = ram_top - SZ_4K, + .end = ram_top + SZ_4K - 1, + }; + phys_addr_t addr = ram_top; + int nomap_start, nomap_end, nomap_above, noov_above; + struct lmb store; + void *blob; + int ret; + + if (!IS_ENABLED(CONFIG_LMB_LIMIT_DMA_BELOW_RAM_TOP)) + return -EAGAIN; + + blob = malloc(SZ_4K); + ut_assertnonnull(blob); + ut_assertok(fdt_create_empty_tree(blob, SZ_4K)); + ut_assertok(fdtdec_add_reserved_memory(blob, "above", &above, NULL, 0, + NULL, + FDTDEC_RESERVED_MEMORY_NO_MAP)); + ut_assertok(fdtdec_add_reserved_memory(blob, "across", &across, NULL, + 0, NULL, + FDTDEC_RESERVED_MEMORY_NO_MAP)); + + /* Set up LMB as lmb_add_memory() does for a lower ram_top */ + ut_assertok(lmb_push(&store)); + ut_assertok(lmb_add(gd->ram_base, gd->ram_size)); + ut_assertok(lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &addr, size, + LMB_NOOVERWRITE)); + gd->ram_top = ram_top; + + boot_fdt_add_mem_rsv_regions(blob); + ret = ut_check_console_end(uts); + nomap_start = lmb_is_reserved_flags(across.start, LMB_NOMAP); + nomap_end = lmb_is_reserved_flags(ram_top - 1, LMB_NOMAP); + nomap_above = lmb_is_reserved_flags(ram_top, LMB_NOMAP); + noov_above = lmb_is_reserved_flags(ram_top, LMB_NOOVERWRITE); + + gd->ram_top = old_ram_top; + lmb_pop(&store); + free(blob); + + ut_assertok(ret); + /* The part of the region below ram_top is reserved up to ram_top */ + ut_asserteq(1, nomap_start); + ut_asserteq(1, nomap_end); + /* The reservation of LMB above ram_top is left alone */ + ut_asserteq(0, nomap_above); + ut_asserteq(1, noov_above); + + return 0; +} +IMAGE_FDT_TEST(test_boot_fdt_rsv_above_ram_top, UTF_CONSOLE); -- 2.53.0
