1 /*
2 * Check decoding of set_mempolicy syscall.
3 *
4 * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2016-2022 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include "scno.h"
13
14 #include <stdio.h>
15 #include <string.h>
16 #include <unistd.h>
17
18 #define MAX_STRLEN 3
19 #define NLONGS(n) ((n + 8 * sizeof(long) - 2) \
20 / (8 * sizeof(long)))
21
22 static const char *errstr;
23
24 static long
25 k_set_mempolicy(const unsigned int mode,
26 const void *const nmask,
27 const unsigned long maxnode)
28 {
29 const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL;
30 const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL;
31 const kernel_ulong_t arg1 = fill | mode;
32 const kernel_ulong_t arg2 = (unsigned long) nmask;
33 const kernel_ulong_t arg3 = maxnode;
34 const long rc = syscall(__NR_set_mempolicy,
35 arg1, arg2, arg3, bad, bad, bad);
36 errstr = sprintrc(rc);
37 return rc;
38 }
39
40 #if XLAT_RAW
41 # define out_str raw
42 #elif XLAT_VERBOSE
43 # define out_str verbose
44 #else
45 # define out_str abbrev
46 #endif
47
48 static struct {
49 unsigned int val;
50 const char *raw;
51 const char *verbose;
52 const char *abbrev;
53 } mpol_modes[] = {
54 { ARG_STR(0),
55 "0 /* MPOL_DEFAULT */",
56 "MPOL_DEFAULT" },
57 { ARG_STR(0x1),
58 "0x1 /* MPOL_PREFERRED */",
59 "MPOL_PREFERRED" },
60 { ARG_STR(0x2),
61 "0x2 /* MPOL_BIND */",
62 "MPOL_BIND" },
63 { ARG_STR(0x3),
64 "0x3 /* MPOL_INTERLEAVE */",
65 "MPOL_INTERLEAVE" },
66 { ARG_STR(0x4),
67 "0x4 /* MPOL_LOCAL */",
68 "MPOL_LOCAL" },
69 { ARG_STR(0x5),
70 "0x5 /* MPOL_PREFERRED_MANY */",
71 "MPOL_PREFERRED_MANY" },
72 { ARG_STR(0x8000),
73 "0x8000 /* MPOL_DEFAULT|MPOL_F_STATIC_NODES */",
74 "MPOL_DEFAULT|MPOL_F_STATIC_NODES" },
75 { ARG_STR(0x4001),
76 "0x4001 /* MPOL_PREFERRED|MPOL_F_RELATIVE_NODES */",
77 "MPOL_PREFERRED|MPOL_F_RELATIVE_NODES" },
78 { ARG_STR(0x2002),
79 "0x2002 /* MPOL_BIND|MPOL_F_NUMA_BALANCING */",
80 "MPOL_BIND|MPOL_F_NUMA_BALANCING" },
81 { ARG_STR(0xe003),
82 "0xe003 /* MPOL_INTERLEAVE|MPOL_F_STATIC_NODES|MPOL_F_RELATIVE_NODES"
83 "|MPOL_F_NUMA_BALANCING */",
84 "MPOL_INTERLEAVE|MPOL_F_STATIC_NODES|MPOL_F_RELATIVE_NODES"
85 "|MPOL_F_NUMA_BALANCING" },
86 { ARG_STR(0x6),
87 "0x6 /* MPOL_??? */",
88 "0x6 /* MPOL_??? */" },
89 { ARG_STR(0xffff1fff),
90 "0xffff1fff /* MPOL_??? */",
91 "0xffff1fff /* MPOL_??? */" },
92 { ARG_STR(0xffffffff),
93 "0xffffffff /* MPOL_F_STATIC_NODES|MPOL_F_RELATIVE_NODES"
94 "|MPOL_F_NUMA_BALANCING|0xffff1fff */",
95 "MPOL_F_STATIC_NODES|MPOL_F_RELATIVE_NODES|MPOL_F_NUMA_BALANCING|0xffff1fff" }
96 };
97
98 static void
99 print_nodes(const unsigned long maxnode, unsigned int offset)
100 {
101 unsigned int nlongs = NLONGS(maxnode);
102 if (nlongs <= offset)
103 nlongs = 0;
104 else
105 nlongs -= offset;
106 const unsigned int size = nlongs * sizeof(long);
107 unsigned long *const nodemask =
108 tail_alloc(size ? size : (offset ? 1 : 0));
109 memset(nodemask, 0, size);
110
111 k_set_mempolicy(mpol_modes[0].val, nodemask, maxnode);
112
113 printf("set_mempolicy(%s, ", mpol_modes[0].out_str);
114
115 if (nlongs) {
116 putc('[', stdout);
117 for (unsigned int i = 0; i < nlongs + offset; ++i) {
118 if (i)
119 fputs(", ", stdout);
120 if (i < nlongs) {
121 if (i >= MAX_STRLEN) {
122 fputs("...", stdout);
123 break;
124 }
125 printf("%#0*lx", (int) sizeof(long) * 2,
126 nodemask[i]);
127 } else {
128 printf("... /* %p */", nodemask + i);
129 break;
130 }
131 }
132 putc(']', stdout);
133 } else {
134 if (maxnode)
135 printf("%p", nodemask);
136 else
137 printf("[]");
138 }
139
140 printf(", %lu) = %s\n", maxnode, errstr);
141 }
142
143 static void
144 test_offset(const unsigned int offset)
145 {
146 unsigned long maxnode = get_page_size() * 8;
147
148 print_nodes(maxnode, offset);
149 print_nodes(maxnode + 1, offset);
150 print_nodes(maxnode + 2, offset);
151
152 maxnode = sizeof(long) * 8;
153 print_nodes(0, offset);
154 print_nodes(1, offset);
155 print_nodes(2, offset);
156 print_nodes(maxnode - 1, offset);
157 print_nodes(maxnode , offset);
158 print_nodes(maxnode + 1, offset);
159 print_nodes(maxnode + 2, offset);
160 print_nodes(maxnode * 2 - 1, offset);
161 print_nodes(maxnode * 2 , offset);
162 print_nodes(maxnode * 2 + 1, offset);
163 print_nodes(maxnode * 2 + 2, offset);
164 print_nodes(maxnode * 3 - 1, offset);
165 print_nodes(maxnode * 3 , offset);
166 print_nodes(maxnode * 3 + 1, offset);
167 print_nodes(maxnode * 3 + 2, offset);
168 print_nodes(maxnode * 4 + 2, offset);
169 }
170
171 int
172 main(void)
173 {
174 if (k_set_mempolicy(mpol_modes[0].val, 0, 0))
175 perror_msg_and_skip("set_mempolicy");
176 printf("set_mempolicy(%s, NULL, 0) = 0\n", mpol_modes[0].out_str);
177
178 const unsigned long *nodemask = (void *) 0xfacefeedfffffffeULL;
179 const unsigned long maxnode = (unsigned long) 0xcafef00ddeadbeefULL;
180
181 for (unsigned int i = 0; i < ARRAY_SIZE(mpol_modes); ++i) {
182 if (i) {
183 k_set_mempolicy(mpol_modes[i].val, 0, 0);
184 printf("set_mempolicy(%s, NULL, 0) = %s\n",
185 mpol_modes[i].out_str, errstr);
186 }
187
188 k_set_mempolicy(mpol_modes[i].val, nodemask, maxnode);
189 printf("set_mempolicy(%s, %p, %lu) = %s\n",
190 mpol_modes[i].out_str, nodemask, maxnode, errstr);
191 }
192
193 test_offset(0);
194 test_offset(1);
195
196 puts("+++ exited with 0 +++");
197 return 0;
198 }