18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/compiler.h>
38c2ecf20Sopenharmony_ci#include <linux/kernel.h>
48c2ecf20Sopenharmony_ci#include "tests.h"
58c2ecf20Sopenharmony_ci#include "map.h"
68c2ecf20Sopenharmony_ci#include "maps.h"
78c2ecf20Sopenharmony_ci#include "dso.h"
88c2ecf20Sopenharmony_ci#include "debug.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_cistruct map_def {
118c2ecf20Sopenharmony_ci	const char *name;
128c2ecf20Sopenharmony_ci	u64 start;
138c2ecf20Sopenharmony_ci	u64 end;
148c2ecf20Sopenharmony_ci};
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistatic int check_maps(struct map_def *merged, unsigned int size, struct maps *maps)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	struct map *map;
198c2ecf20Sopenharmony_ci	unsigned int i = 0;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	maps__for_each_entry(maps, map) {
228c2ecf20Sopenharmony_ci		if (i > 0)
238c2ecf20Sopenharmony_ci			TEST_ASSERT_VAL("less maps expected", (map && i < size) || (!map && i == size));
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci		TEST_ASSERT_VAL("wrong map start",  map->start == merged[i].start);
268c2ecf20Sopenharmony_ci		TEST_ASSERT_VAL("wrong map end",    map->end == merged[i].end);
278c2ecf20Sopenharmony_ci		TEST_ASSERT_VAL("wrong map name",  !strcmp(map->dso->name, merged[i].name));
288c2ecf20Sopenharmony_ci		TEST_ASSERT_VAL("wrong map refcnt", refcount_read(&map->refcnt) == 1);
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci		i++;
318c2ecf20Sopenharmony_ci	}
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	return TEST_OK;
348c2ecf20Sopenharmony_ci}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ciint test__maps__merge_in(struct test *t __maybe_unused, int subtest __maybe_unused)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	struct maps maps;
398c2ecf20Sopenharmony_ci	unsigned int i;
408c2ecf20Sopenharmony_ci	struct map_def bpf_progs[] = {
418c2ecf20Sopenharmony_ci		{ "bpf_prog_1", 200, 300 },
428c2ecf20Sopenharmony_ci		{ "bpf_prog_2", 500, 600 },
438c2ecf20Sopenharmony_ci		{ "bpf_prog_3", 800, 900 },
448c2ecf20Sopenharmony_ci	};
458c2ecf20Sopenharmony_ci	struct map_def merged12[] = {
468c2ecf20Sopenharmony_ci		{ "kcore1",     100,  200 },
478c2ecf20Sopenharmony_ci		{ "bpf_prog_1", 200,  300 },
488c2ecf20Sopenharmony_ci		{ "kcore1",     300,  500 },
498c2ecf20Sopenharmony_ci		{ "bpf_prog_2", 500,  600 },
508c2ecf20Sopenharmony_ci		{ "kcore1",     600,  800 },
518c2ecf20Sopenharmony_ci		{ "bpf_prog_3", 800,  900 },
528c2ecf20Sopenharmony_ci		{ "kcore1",     900, 1000 },
538c2ecf20Sopenharmony_ci	};
548c2ecf20Sopenharmony_ci	struct map_def merged3[] = {
558c2ecf20Sopenharmony_ci		{ "kcore1",      100,  200 },
568c2ecf20Sopenharmony_ci		{ "bpf_prog_1",  200,  300 },
578c2ecf20Sopenharmony_ci		{ "kcore1",      300,  500 },
588c2ecf20Sopenharmony_ci		{ "bpf_prog_2",  500,  600 },
598c2ecf20Sopenharmony_ci		{ "kcore1",      600,  800 },
608c2ecf20Sopenharmony_ci		{ "bpf_prog_3",  800,  900 },
618c2ecf20Sopenharmony_ci		{ "kcore1",      900, 1000 },
628c2ecf20Sopenharmony_ci		{ "kcore3",     1000, 1100 },
638c2ecf20Sopenharmony_ci	};
648c2ecf20Sopenharmony_ci	struct map *map_kcore1, *map_kcore2, *map_kcore3;
658c2ecf20Sopenharmony_ci	int ret;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	maps__init(&maps, NULL);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(bpf_progs); i++) {
708c2ecf20Sopenharmony_ci		struct map *map;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci		map = dso__new_map(bpf_progs[i].name);
738c2ecf20Sopenharmony_ci		TEST_ASSERT_VAL("failed to create map", map);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci		map->start = bpf_progs[i].start;
768c2ecf20Sopenharmony_ci		map->end   = bpf_progs[i].end;
778c2ecf20Sopenharmony_ci		maps__insert(&maps, map);
788c2ecf20Sopenharmony_ci		map__put(map);
798c2ecf20Sopenharmony_ci	}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	map_kcore1 = dso__new_map("kcore1");
828c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to create map", map_kcore1);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	map_kcore2 = dso__new_map("kcore2");
858c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to create map", map_kcore2);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	map_kcore3 = dso__new_map("kcore3");
888c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to create map", map_kcore3);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	/* kcore1 map overlaps over all bpf maps */
918c2ecf20Sopenharmony_ci	map_kcore1->start = 100;
928c2ecf20Sopenharmony_ci	map_kcore1->end   = 1000;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	/* kcore2 map hides behind bpf_prog_2 */
958c2ecf20Sopenharmony_ci	map_kcore2->start = 550;
968c2ecf20Sopenharmony_ci	map_kcore2->end   = 570;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	/* kcore3 map hides behind bpf_prog_3, kcore1 and adds new map */
998c2ecf20Sopenharmony_ci	map_kcore3->start = 880;
1008c2ecf20Sopenharmony_ci	map_kcore3->end   = 1100;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	ret = maps__merge_in(&maps, map_kcore1);
1038c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to merge map", !ret);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	ret = check_maps(merged12, ARRAY_SIZE(merged12), &maps);
1068c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("merge check failed", !ret);
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	ret = maps__merge_in(&maps, map_kcore2);
1098c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to merge map", !ret);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	ret = check_maps(merged12, ARRAY_SIZE(merged12), &maps);
1128c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("merge check failed", !ret);
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	ret = maps__merge_in(&maps, map_kcore3);
1158c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("failed to merge map", !ret);
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	ret = check_maps(merged3, ARRAY_SIZE(merged3), &maps);
1188c2ecf20Sopenharmony_ci	TEST_ASSERT_VAL("merge check failed", !ret);
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	maps__exit(&maps);
1218c2ecf20Sopenharmony_ci	return TEST_OK;
1228c2ecf20Sopenharmony_ci}
123