1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2020 Petr Vorel <pvorel@suse.cz> 4f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2009-2020 5f08c3bdfSopenharmony_ci * Copyright (c) Crackerjack Project, 2007-2008, Hitachi, Ltd 6f08c3bdfSopenharmony_ci * 7f08c3bdfSopenharmony_ci * Authors: 8f08c3bdfSopenharmony_ci * Takahiro Yasui <takahiro.yasui.mp@hitachi.com> 9f08c3bdfSopenharmony_ci * Yumiko Sugita <yumiko.sugita.yf@hitachi.com> 10f08c3bdfSopenharmony_ci * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp> 11f08c3bdfSopenharmony_ci * Manas Kumar Nayak <maknayak@in.ibm.com> (original port to the legacy API) 12f08c3bdfSopenharmony_ci */ 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci/*\ 15f08c3bdfSopenharmony_ci * [Description] 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci * Verify that get_mempolicy() returns a proper return value and errno for various cases. 18f08c3bdfSopenharmony_ci */ 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci#include "config.h" 21f08c3bdfSopenharmony_ci#include "tst_test.h" 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_ci#ifdef HAVE_NUMA_V2 24f08c3bdfSopenharmony_ci#include <numa.h> 25f08c3bdfSopenharmony_ci#include <numaif.h> 26f08c3bdfSopenharmony_ci#include <errno.h> 27f08c3bdfSopenharmony_ci#include "tst_numa.h" 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_ci#define MEM_LENGTH (4 * 1024 * 1024) 30f08c3bdfSopenharmony_ci#define PAGES_ALLOCATED 16u 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci#define POLICY_DESC(x) .policy = x, .desc = "policy: "#x 33f08c3bdfSopenharmony_ci#define POLICY_DESC_NO_TARGET(x) .policy = x, .desc = "policy: "#x", no target" 34f08c3bdfSopenharmony_ci#define POLICY_DESC_FLAGS(x, y) .policy = x, .flags = y, .desc = "policy: "#x", flags: "#y 35f08c3bdfSopenharmony_ci#define POLICY_DESC_FLAGS_NO_TARGET(x, y) .policy = x, .flags = y, .desc = "policy: "#x", flags: "#y", no target" 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_cistatic struct tst_nodemap *node; 38f08c3bdfSopenharmony_cistatic struct bitmask *nodemask, *getnodemask, *empty_nodemask; 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_cistruct test_case { 41f08c3bdfSopenharmony_ci int policy; 42f08c3bdfSopenharmony_ci const char *desc; 43f08c3bdfSopenharmony_ci unsigned int flags; 44f08c3bdfSopenharmony_ci char *addr; 45f08c3bdfSopenharmony_ci int (*pre_test)(struct test_case *tc); 46f08c3bdfSopenharmony_ci int (*alloc)(struct test_case *tc); 47f08c3bdfSopenharmony_ci struct bitmask **exp_nodemask; 48f08c3bdfSopenharmony_ci}; 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_cistatic int test_set_mempolicy_default(struct test_case *tc); 51f08c3bdfSopenharmony_cistatic int test_set_mempolicy_none(struct test_case *tc); 52f08c3bdfSopenharmony_cistatic int test_mbind_none(struct test_case *tc); 53f08c3bdfSopenharmony_cistatic int test_mbind_default(struct test_case *tc); 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_cistatic struct test_case tcase[] = { 56f08c3bdfSopenharmony_ci { 57f08c3bdfSopenharmony_ci POLICY_DESC_NO_TARGET(MPOL_DEFAULT), 58f08c3bdfSopenharmony_ci .alloc = test_set_mempolicy_none, 59f08c3bdfSopenharmony_ci .exp_nodemask = &nodemask, 60f08c3bdfSopenharmony_ci }, 61f08c3bdfSopenharmony_ci { 62f08c3bdfSopenharmony_ci POLICY_DESC(MPOL_BIND), 63f08c3bdfSopenharmony_ci .alloc = test_set_mempolicy_default, 64f08c3bdfSopenharmony_ci .exp_nodemask = &nodemask, 65f08c3bdfSopenharmony_ci }, 66f08c3bdfSopenharmony_ci { 67f08c3bdfSopenharmony_ci POLICY_DESC(MPOL_INTERLEAVE), 68f08c3bdfSopenharmony_ci .alloc = test_set_mempolicy_default, 69f08c3bdfSopenharmony_ci .exp_nodemask = &nodemask, 70f08c3bdfSopenharmony_ci }, 71f08c3bdfSopenharmony_ci { 72f08c3bdfSopenharmony_ci POLICY_DESC_NO_TARGET(MPOL_PREFERRED), 73f08c3bdfSopenharmony_ci .alloc = test_set_mempolicy_none, 74f08c3bdfSopenharmony_ci .exp_nodemask = &nodemask, 75f08c3bdfSopenharmony_ci }, 76f08c3bdfSopenharmony_ci { 77f08c3bdfSopenharmony_ci POLICY_DESC(MPOL_PREFERRED), 78f08c3bdfSopenharmony_ci .alloc = test_set_mempolicy_default, 79f08c3bdfSopenharmony_ci .exp_nodemask = &nodemask, 80f08c3bdfSopenharmony_ci }, 81f08c3bdfSopenharmony_ci { 82f08c3bdfSopenharmony_ci POLICY_DESC_FLAGS_NO_TARGET(MPOL_DEFAULT, MPOL_F_ADDR), 83f08c3bdfSopenharmony_ci .pre_test = test_mbind_none, 84f08c3bdfSopenharmony_ci .alloc = test_set_mempolicy_none, 85f08c3bdfSopenharmony_ci .exp_nodemask = &empty_nodemask, 86f08c3bdfSopenharmony_ci }, 87f08c3bdfSopenharmony_ci { 88f08c3bdfSopenharmony_ci POLICY_DESC_FLAGS(MPOL_BIND, MPOL_F_ADDR), 89f08c3bdfSopenharmony_ci .pre_test = test_mbind_default, 90f08c3bdfSopenharmony_ci .exp_nodemask = &nodemask, 91f08c3bdfSopenharmony_ci }, 92f08c3bdfSopenharmony_ci { 93f08c3bdfSopenharmony_ci POLICY_DESC_FLAGS(MPOL_INTERLEAVE, MPOL_F_ADDR), 94f08c3bdfSopenharmony_ci .pre_test = test_mbind_default, 95f08c3bdfSopenharmony_ci .alloc = test_set_mempolicy_default, 96f08c3bdfSopenharmony_ci .exp_nodemask = &nodemask, 97f08c3bdfSopenharmony_ci }, 98f08c3bdfSopenharmony_ci { 99f08c3bdfSopenharmony_ci POLICY_DESC_FLAGS_NO_TARGET(MPOL_PREFERRED, MPOL_F_ADDR), 100f08c3bdfSopenharmony_ci .pre_test = test_mbind_none, 101f08c3bdfSopenharmony_ci .alloc = test_set_mempolicy_none, 102f08c3bdfSopenharmony_ci .exp_nodemask = &empty_nodemask, 103f08c3bdfSopenharmony_ci }, 104f08c3bdfSopenharmony_ci { 105f08c3bdfSopenharmony_ci POLICY_DESC_FLAGS(MPOL_PREFERRED, MPOL_F_ADDR), 106f08c3bdfSopenharmony_ci .pre_test = test_mbind_default, 107f08c3bdfSopenharmony_ci .alloc = test_set_mempolicy_default, 108f08c3bdfSopenharmony_ci .exp_nodemask = &nodemask, 109f08c3bdfSopenharmony_ci }, 110f08c3bdfSopenharmony_ci}; 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_cistatic int test_set_mempolicy_default(struct test_case *tc) 113f08c3bdfSopenharmony_ci{ 114f08c3bdfSopenharmony_ci TEST(set_mempolicy(tc->policy, nodemask->maskp, nodemask->size)); 115f08c3bdfSopenharmony_ci return TST_RET; 116f08c3bdfSopenharmony_ci} 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_cistatic int test_set_mempolicy_none(struct test_case *tc) 119f08c3bdfSopenharmony_ci{ 120f08c3bdfSopenharmony_ci TEST(set_mempolicy(tc->policy, NULL, 0)); 121f08c3bdfSopenharmony_ci return TST_RET; 122f08c3bdfSopenharmony_ci} 123f08c3bdfSopenharmony_ci 124f08c3bdfSopenharmony_cistatic int test_mbind(struct test_case *tc, unsigned long *maskp, unsigned long size) 125f08c3bdfSopenharmony_ci{ 126f08c3bdfSopenharmony_ci tc->addr = SAFE_MMAP(NULL, MEM_LENGTH, PROT_READ | PROT_WRITE, 127f08c3bdfSopenharmony_ci MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci TEST(mbind(tc->addr, MEM_LENGTH, tc->policy, maskp, size, 0)); 130f08c3bdfSopenharmony_ci return TST_RET; 131f08c3bdfSopenharmony_ci} 132f08c3bdfSopenharmony_ci 133f08c3bdfSopenharmony_cistatic int test_mbind_none(struct test_case *tc) 134f08c3bdfSopenharmony_ci{ 135f08c3bdfSopenharmony_ci return test_mbind(tc, NULL, 0); 136f08c3bdfSopenharmony_ci} 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_cistatic int test_mbind_default(struct test_case *tc) 139f08c3bdfSopenharmony_ci{ 140f08c3bdfSopenharmony_ci return test_mbind(tc, nodemask->maskp, nodemask->size); 141f08c3bdfSopenharmony_ci} 142f08c3bdfSopenharmony_ci 143f08c3bdfSopenharmony_cistatic void setup(void) 144f08c3bdfSopenharmony_ci{ 145f08c3bdfSopenharmony_ci unsigned int i; 146f08c3bdfSopenharmony_ci 147f08c3bdfSopenharmony_ci node = tst_get_nodemap(TST_NUMA_MEM, PAGES_ALLOCATED * getpagesize() / 1024); 148f08c3bdfSopenharmony_ci if (node->cnt < 1) 149f08c3bdfSopenharmony_ci tst_brk(TCONF, "test requires at least one NUMA memory node"); 150f08c3bdfSopenharmony_ci 151f08c3bdfSopenharmony_ci nodemask = numa_allocate_nodemask(); 152f08c3bdfSopenharmony_ci empty_nodemask = numa_allocate_nodemask(); 153f08c3bdfSopenharmony_ci getnodemask = numa_allocate_nodemask(); 154f08c3bdfSopenharmony_ci numa_bitmask_setbit(nodemask, node->map[0]); 155f08c3bdfSopenharmony_ci 156f08c3bdfSopenharmony_ci for (i = 0; i < ARRAY_SIZE(tcase); i++) { 157f08c3bdfSopenharmony_ci struct test_case *tc = &tcase[i]; 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci if (tc->pre_test && tc->pre_test(tc)) 160f08c3bdfSopenharmony_ci tst_brk(TFAIL | TERRNO, "test #%d: mbind() failed", i+1); 161f08c3bdfSopenharmony_ci 162f08c3bdfSopenharmony_ci if (tc->alloc && tc->alloc(tc)) 163f08c3bdfSopenharmony_ci tst_brk(TFAIL | TERRNO, "test #%d: set_mempolicy() failed", i+1); 164f08c3bdfSopenharmony_ci } 165f08c3bdfSopenharmony_ci} 166f08c3bdfSopenharmony_ci 167f08c3bdfSopenharmony_cistatic void cleanup(void) 168f08c3bdfSopenharmony_ci{ 169f08c3bdfSopenharmony_ci unsigned int i; 170f08c3bdfSopenharmony_ci 171f08c3bdfSopenharmony_ci for (i = 0; i < ARRAY_SIZE(tcase); i++) { 172f08c3bdfSopenharmony_ci struct test_case *tc = &tcase[i]; 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ci if (tc->pre_test) 175f08c3bdfSopenharmony_ci SAFE_MUNMAP(tc->addr, MEM_LENGTH); 176f08c3bdfSopenharmony_ci } 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_ci numa_free_nodemask(nodemask); 179f08c3bdfSopenharmony_ci numa_free_nodemask(getnodemask); 180f08c3bdfSopenharmony_ci tst_nodemap_free(node); 181f08c3bdfSopenharmony_ci} 182f08c3bdfSopenharmony_ci 183f08c3bdfSopenharmony_cistatic void do_test(unsigned int i) 184f08c3bdfSopenharmony_ci{ 185f08c3bdfSopenharmony_ci struct test_case *tc = &tcase[i]; 186f08c3bdfSopenharmony_ci int policy; 187f08c3bdfSopenharmony_ci 188f08c3bdfSopenharmony_ci tst_res(TINFO, "test #%d: %s", i+1, tc->desc); 189f08c3bdfSopenharmony_ci 190f08c3bdfSopenharmony_ci TST_EXP_PASS(get_mempolicy(&policy, getnodemask->maskp, getnodemask->size, 191f08c3bdfSopenharmony_ci tc->addr, tc->flags), "%s", tc->desc); 192f08c3bdfSopenharmony_ci 193f08c3bdfSopenharmony_ci struct bitmask *exp_mask = *(tc->exp_nodemask); 194f08c3bdfSopenharmony_ci 195f08c3bdfSopenharmony_ci if (!numa_bitmask_equal(exp_mask, getnodemask)) { 196f08c3bdfSopenharmony_ci tst_res(TFAIL, "masks are not equal"); 197f08c3bdfSopenharmony_ci tst_res_hexd(TINFO, exp_mask->maskp, 198f08c3bdfSopenharmony_ci exp_mask->size / 8, "expected:"); 199f08c3bdfSopenharmony_ci tst_res_hexd(TINFO, getnodemask->maskp, 200f08c3bdfSopenharmony_ci getnodemask->size / 8, "returned:"); 201f08c3bdfSopenharmony_ci } 202f08c3bdfSopenharmony_ci} 203f08c3bdfSopenharmony_ci 204f08c3bdfSopenharmony_cistatic struct tst_test test = { 205f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcase), 206f08c3bdfSopenharmony_ci .test = do_test, 207f08c3bdfSopenharmony_ci .setup = setup, 208f08c3bdfSopenharmony_ci .cleanup = cleanup, 209f08c3bdfSopenharmony_ci}; 210f08c3bdfSopenharmony_ci 211f08c3bdfSopenharmony_ci#else 212f08c3bdfSopenharmony_ciTST_TEST_TCONF(NUMA_ERROR_MSG); 213f08c3bdfSopenharmony_ci#endif /* HAVE_NUMA_V2 */ 214