/* * Check decoding of mbind syscall. * * Copyright (c) 2016-2019 Dmitry V. Levin * All rights reserved. * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "tests.h" #include "scno.h" #ifdef __NR_mbind # include # include static const char *errstr; static long k_mbind(const unsigned long start, const unsigned long len, const unsigned long mode, const unsigned long nmask, const unsigned long maxnode, const unsigned int flags) { const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL; const kernel_ulong_t arg1 = start; const kernel_ulong_t arg2 = len; const kernel_ulong_t arg3 = mode; const kernel_ulong_t arg4 = nmask; const kernel_ulong_t arg5 = maxnode; const kernel_ulong_t arg6 = fill | flags; const long rc = syscall(__NR_mbind, arg1, arg2, arg3, arg4, arg5, arg6); errstr = sprintrc(rc); return rc; } # if XLAT_RAW # define out_str raw # define flags_str "0xffffffff" # elif XLAT_VERBOSE # define out_str verbose # define flags_str "0xffffffff /* MPOL_MF_STRICT|MPOL_MF_MOVE" \ "|MPOL_MF_MOVE_ALL|0xfffffff8 */" # else # define out_str abbrev # define flags_str "MPOL_MF_STRICT|MPOL_MF_MOVE|MPOL_MF_MOVE_ALL|0xfffffff8" # endif static struct { unsigned long val; const char *raw; const char *verbose; const char *abbrev; } mpol_modes[] = { { ARG_STR(0), "0 /* MPOL_DEFAULT */", "MPOL_DEFAULT" }, { ARG_STR(0x1), "0x1 /* MPOL_PREFERRED */", "MPOL_PREFERRED" }, { ARG_STR(0x2), "0x2 /* MPOL_BIND */", "MPOL_BIND" }, { ARG_STR(0x3), "0x3 /* MPOL_INTERLEAVE */", "MPOL_INTERLEAVE" }, { ARG_STR(0x4), "0x4 /* MPOL_LOCAL */", "MPOL_LOCAL" }, { ARG_STR(0x8000), "0x8000 /* MPOL_DEFAULT|MPOL_F_STATIC_NODES */", "MPOL_DEFAULT|MPOL_F_STATIC_NODES" }, { ARG_STR(0x4001), "0x4001 /* MPOL_PREFERRED|MPOL_F_RELATIVE_NODES */", "MPOL_PREFERRED|MPOL_F_RELATIVE_NODES" }, { ARG_STR(0xc002), "0xc002 /* MPOL_BIND|MPOL_F_STATIC_NODES|MPOL_F_RELATIVE_NODES */", "MPOL_BIND|MPOL_F_STATIC_NODES|MPOL_F_RELATIVE_NODES" }, { ARG_STR(0x5), "0x5 /* MPOL_??? */", "0x5 /* MPOL_??? */" }, { ARG_STR(0xffff3fff), "0xffff3fff /* MPOL_??? */", "0xffff3fff /* MPOL_??? */" }, { ARG_STR(0xffffffff), "0xffffffff /* MPOL_F_STATIC_NODES|MPOL_F_RELATIVE_NODES|0xffff3fff */", "MPOL_F_STATIC_NODES|MPOL_F_RELATIVE_NODES|0xffff3fff" }, # if SIZEOF_LONG > 4 { 0xffffffff00000000UL, "0xffffffff00000000", "0xffffffff00000000 /* MPOL_??? */", "0xffffffff00000000 /* MPOL_??? */" }, { 0xffffffffffff3fffUL, "0xffffffffffff3fff", "0xffffffffffff3fff /* MPOL_??? */", "0xffffffffffff3fff /* MPOL_??? */" }, { -1UL, "0xffffffffffffffff", "0xffffffffffffffff /* MPOL_F_STATIC_NODES|MPOL_F_RELATIVE_NODES" "|0xffffffffffff3fff */", "MPOL_F_STATIC_NODES|MPOL_F_RELATIVE_NODES|0xffffffffffff3fff" }, # endif }; int main(void) { const unsigned long size = get_page_size(); unsigned long *const addr = tail_alloc(size); const unsigned long start = (unsigned long) 0xfffffff1fffffff2ULL; const unsigned long len = (unsigned long) 0xfffffff4fffffff4ULL; const unsigned long nodemask = (unsigned long) 0xfffffff5fffffff6ULL; const unsigned long maxnode = (unsigned long) 0xfffffff7fffffff8ULL; if (k_mbind((unsigned long) addr, size, mpol_modes[0].val, 0, 0, 0)) perror_msg_and_skip("mbind"); printf("mbind(%p, %lu, %s, NULL, 0, 0) = 0\n", addr, size, mpol_modes[0].out_str); for (unsigned int i = 0; i < ARRAY_SIZE(mpol_modes); ++i) { if (i) { k_mbind((unsigned long) addr, size, mpol_modes[i].val, 0, 0, 0); printf("mbind(%p, %lu, %s, NULL, 0, 0) = %s\n", addr, size, mpol_modes[i].out_str, errstr); } k_mbind(start, len, mpol_modes[i].val, nodemask, maxnode, -1U); printf("mbind(%#lx, %lu, %s, %#lx, %lu, %s) = %s\n", start, len, mpol_modes[i].out_str, nodemask, maxnode, flags_str, errstr); } puts("+++ exited with 0 +++"); return 0; } #else SKIP_MAIN_UNDEFINED("__NR_mbind") #endif