1 /*
2 * Copyright (c) 2003-2007 Ulrich Drepper <drepper@redhat.com>
3 * Copyright (c) 2005-2016 Dmitry V. Levin <ldv@strace.io>
4 * Copyright (c) 2016-2022 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: LGPL-2.1-or-later
8 */
9
10 #include "defs.h"
11
12 static bool
13 print_node(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
14 {
15 if (elem_size < sizeof(kernel_ulong_t)) {
16 unsigned int val = *(unsigned int *) elem_buf;
17 PRINT_VAL_0X(val);
18 } else {
19 kernel_ulong_t val = *(kernel_ulong_t *) elem_buf;
20 PRINT_VAL_0X(val);
21 }
22
23 return true;
24 }
25
26 static void
27 print_nodemask(struct tcb *const tcp, const kernel_ulong_t addr,
28 const kernel_ulong_t maxnodes)
29 {
30 const unsigned int bits_per_long = 8 * current_wordsize;
31 const kernel_ulong_t nmemb =
32 (maxnodes + bits_per_long - 2) / bits_per_long;
33
34 if (nmemb < maxnodes / bits_per_long ||
35 (maxnodes && !nmemb)) {
36 printaddr(addr);
37 return;
38 }
39
40 kernel_ulong_t buf;
41 print_array(tcp, addr, nmemb, &buf, current_wordsize,
42 tfetch_mem, print_node, 0);
43 }
44
45 SYS_FUNC(migrate_pages)
46 {
47 /* pid */
48 printpid(tcp, tcp->u_arg[0], PT_TGID);
49 tprint_arg_next();
50
51 /* maxnode */
52 PRINT_VAL_U(tcp->u_arg[1]);
53 tprint_arg_next();
54
55 /* old_nodes */
56 print_nodemask(tcp, tcp->u_arg[2], tcp->u_arg[1]);
57 tprint_arg_next();
58
59 /* new_nodes */
60 print_nodemask(tcp, tcp->u_arg[3], tcp->u_arg[1]);
61
62 return RVAL_DECODED;
63 }
64
65 #include "xlat/mpol_modes.h"
66 #include "xlat/mpol_mode_flags.h"
67 #include "xlat/mbind_flags.h"
68
69 static void
70 print_mode(struct tcb *const tcp, const kernel_ulong_t mode_arg)
71 {
72 const kernel_ulong_t flags_mask = MPOL_F_STATIC_NODES |
73 MPOL_F_RELATIVE_NODES |
74 MPOL_F_NUMA_BALANCING;
75 const kernel_ulong_t mode = mode_arg & ~flags_mask;
76 const unsigned int flags = mode_arg & flags_mask;
77
78 if (!flags) {
79 printxval64(mpol_modes, mode, "MPOL_???");
80 return;
81 }
82
83 const char *mode_str = xlookup(mpol_modes, mode);
84 if (!mode_str) {
85 printflags64(mpol_mode_flags, mode_arg, "MPOL_???");
86 return;
87 }
88
89 if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV)
90 PRINT_VAL_X(mode_arg);
91
92 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
93 return;
94
95 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
96 tprint_comment_begin();
97
98 tprint_flags_begin();
99 tprints_string(mode_str);
100 tprint_flags_or();
101 printflags_ex(flags, NULL, XLAT_STYLE_ABBREV, mpol_mode_flags, NULL);
102 tprint_flags_end();
103
104 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
105 tprint_comment_end();
106 }
107
108 SYS_FUNC(mbind)
109 {
110 /* addr */
111 printaddr(tcp->u_arg[0]);
112 tprint_arg_next();
113
114 /* len */
115 PRINT_VAL_U(tcp->u_arg[1]);
116 tprint_arg_next();
117
118 /* mode */
119 print_mode(tcp, tcp->u_arg[2]);
120 tprint_arg_next();
121
122 /* nodemask */
123 print_nodemask(tcp, tcp->u_arg[3], tcp->u_arg[4]);
124 tprint_arg_next();
125
126 /* maxnode */
127 PRINT_VAL_U(tcp->u_arg[4]);
128 tprint_arg_next();
129
130 /* flags */
131 printflags(mbind_flags, tcp->u_arg[5], "MPOL_???");
132
133 return RVAL_DECODED;
134 }
135
136 SYS_FUNC(set_mempolicy)
137 {
138 /* mode */
139 print_mode(tcp, (unsigned int) tcp->u_arg[0]);
140 tprint_arg_next();
141
142 /* nodemask */
143 print_nodemask(tcp, tcp->u_arg[1], tcp->u_arg[2]);
144 tprint_arg_next();
145
146 /* maxnode */
147 PRINT_VAL_U(tcp->u_arg[2]);
148
149 return RVAL_DECODED;
150 }
151
152 #include "xlat/get_mempolicy_flags.h"
153
154 SYS_FUNC(get_mempolicy)
155 {
156 if (exiting(tcp)) {
157 /* mode */
158 int pol;
159 if (!umove_or_printaddr(tcp, tcp->u_arg[0], &pol)) {
160 tprint_indirect_begin();
161 printxval(mpol_modes, pol, "MPOL_???");
162 tprint_indirect_end();
163 }
164 tprint_arg_next();
165
166 /* nodemask */
167 print_nodemask(tcp, tcp->u_arg[1], tcp->u_arg[2]);
168 tprint_arg_next();
169
170 /* maxnode */
171 PRINT_VAL_U(tcp->u_arg[2]);
172 tprint_arg_next();
173
174 /* addr */
175 printaddr(tcp->u_arg[3]);
176 tprint_arg_next();
177
178 /* flags */
179 printflags64(get_mempolicy_flags, tcp->u_arg[4], "MPOL_???");
180 }
181 return 0;
182 }
183
184 SYS_FUNC(set_mempolicy_home_node)
185 {
186 /* start */
187 printaddr(tcp->u_arg[0]);
188 tprint_arg_next();
189
190 /* len */
191 PRINT_VAL_U(tcp->u_arg[1]);
192 tprint_arg_next();
193
194 /* home_node */
195 PRINT_VAL_U(tcp->u_arg[2]);
196 tprint_arg_next();
197
198 /* flags */
199 PRINT_VAL_X(tcp->u_arg[3]);
200
201 return RVAL_DECODED;
202 }
203
204 #include "xlat/move_pages_flags.h"
205
206 static bool
207 print_addr(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
208 {
209 kernel_ulong_t addr;
210
211 if (elem_size < sizeof(addr)) {
212 addr = *(unsigned int *) elem_buf;
213 } else {
214 addr = *(kernel_ulong_t *) elem_buf;
215 }
216
217 printaddr(addr);
218
219 return true;
220 }
221
222 static bool
223 print_status(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
224 {
225 const int status = *(int *) elem_buf;
226
227 print_err(status, true);
228
229 return true;
230 }
231
232 SYS_FUNC(move_pages)
233 {
234 const kernel_ulong_t npages = tcp->u_arg[1];
235 kernel_ulong_t buf;
236
237 if (entering(tcp)) {
238 /* pid */
239 printpid(tcp, tcp->u_arg[0], PT_TGID);
240 tprint_arg_next();
241
242 /* count */
243 PRINT_VAL_U(npages);
244 tprint_arg_next();
245
246 /* pages */
247 print_array(tcp, tcp->u_arg[2], npages, &buf, current_wordsize,
248 tfetch_mem, print_addr, 0);
249 tprint_arg_next();
250
251 /* nodes */
252 print_array(tcp, tcp->u_arg[3], npages, &buf, sizeof(int),
253 tfetch_mem, print_int_array_member, 0);
254 tprint_arg_next();
255 } else {
256 /* status */
257 print_array(tcp, tcp->u_arg[4], npages, &buf, sizeof(int),
258 tfetch_mem, print_status, 0);
259 tprint_arg_next();
260
261 /* flags */
262 printflags(move_pages_flags, tcp->u_arg[5], "MPOL_???");
263 }
264 return 0;
265 }