summaryrefslogtreecommitdiff
path: root/tests/mbind.c
blob: 321defb9339e4032bdb1f479d45f7fe06efe3ead (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
 * Check decoding of mbind syscall.
 *
 * Copyright (c) 2016-2019 Dmitry V. Levin <ldv@altlinux.org>
 * All rights reserved.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "tests.h"
#include "scno.h"

#ifdef __NR_mbind

# include <stdio.h>
# include <unistd.h>

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