1 /*
2 * Check decoding of move_pages syscall.
3 *
4 * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2016-2021 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 #include "pidns.h"
14
15 #include <errno.h>
16 #include <stdio.h>
17 #include <unistd.h>
18
19 #define MAX_STRLEN 3
20
21 static void
22 print_page_array(const void **const pages,
23 const unsigned long count,
24 const unsigned int offset)
25 {
26 if (!count) {
27 printf("%s", pages ? "[]" : "NULL");
28 return;
29 }
30 if (count <= offset) {
31 printf("%p", pages);
32 return;
33 }
34 printf("[");
35 for (unsigned long i = 0; i < count; ++i) {
36 if (i)
37 printf(", ");
38 if (i + offset < count) {
39 if (i >= MAX_STRLEN) {
40 printf("...");
41 break;
42 }
43 } else {
44 printf("... /* %p */", pages + i);
45 break;
46 }
47 const void *const addr = pages[i];
48 if (addr)
49 printf("%p", addr);
50 else
51 printf("NULL");
52 }
53 printf("]");
54 }
55
56 static void
57 print_node_array(const int *const nodes,
58 const unsigned long count,
59 const unsigned int offset)
60 {
61 if (!count) {
62 printf("%s", nodes ? "[]" : "NULL");
63 return;
64 }
65 if (count <= offset) {
66 printf("%p", nodes);
67 return;
68 }
69 printf("[");
70 for (unsigned long i = 0; i < count; ++i) {
71 if (i)
72 printf(", ");
73 if (i + offset < count) {
74 if (i >= MAX_STRLEN) {
75 printf("...");
76 break;
77 }
78 } else {
79 printf("... /* %p */", nodes + i);
80 break;
81 }
82 printf("%d", nodes[i]);
83 }
84 printf("]");
85 }
86
87 static void
88 print_status_array(const int *const status, const unsigned long count)
89 {
90 if (!count) {
91 printf("%s", status ? "[]" : "NULL");
92 return;
93 }
94 printf("[");
95 for (unsigned long i = 0; i < count; ++i) {
96 if (i)
97 printf(", ");
98 if (i >= MAX_STRLEN) {
99 printf("...");
100 break;
101 }
102 if (status[i] >= 0) {
103 printf("%d", status[i]);
104 } else {
105 #if !XLAT_RAW
106 errno = -status[i];
107 #endif
108 #if XLAT_RAW
109 printf("%d", status[i]);
110 #elif XLAT_VERBOSE
111 printf("%d /* -%s */", status[i], errno2name());
112 #else
113 printf("-%s", errno2name());
114 #endif
115 }
116 }
117 printf("]");
118 }
119
120 static void
121 print_stat_pages(const unsigned long pid,
122 const char *pid_str,
123 const unsigned long count,
124 const void **const pages,
125 int *const status)
126 {
127 const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL;
128
129 long rc = syscall(__NR_move_pages,
130 pid, count, pages, NULL, status, flags);
131 const char *errstr = sprintrc(rc);
132 pidns_print_leader();
133 printf("move_pages(%d%s, %lu, ", (int) pid, pid_str,
134 count);
135 print_page_array(pages, count, 0);
136 printf(", NULL, ");
137 if (rc) {
138 if (count)
139 printf("%p", status);
140 else
141 printf("[]");
142 } else {
143 print_status_array(status, count);
144 }
145 #if XLAT_RAW
146 printf(", 0x2) = %s\n", errstr);
147 #elif XLAT_VERBOSE
148 printf(", 0x2 /* MPOL_MF_MOVE */) = %s\n", errstr);
149 #else /* XLAT_ABBREV */
150 printf(", MPOL_MF_MOVE) = %s\n", errstr);
151 #endif
152 }
153
154 static void
155 print_move_pages(const unsigned long pid,
156 const char *pid_str,
157 unsigned long count,
158 const unsigned int offset,
159 const void **const pages,
160 int *const nodes,
161 int *const status)
162 {
163 const unsigned long flags = (unsigned long) 0xfacefeed00000004ULL;
164 count += offset;
165
166 long rc = syscall(__NR_move_pages,
167 pid, count, pages, nodes, status, flags);
168 const char *errstr = sprintrc(rc);
169 pidns_print_leader();
170 printf("move_pages(%d%s, %lu, ", (int) pid, pid_str,
171 count);
172 print_page_array(pages, count, offset);
173 printf(", ");
174 print_node_array(nodes, count, offset);
175 printf(", ");
176 if (count)
177 printf("%p", status);
178 else
179 printf("[]");
180 #if XLAT_RAW
181 printf(", 0x4) = %s\n", errstr);
182 #elif XLAT_VERBOSE
183 printf(", 0x4 /* MPOL_MF_MOVE_ALL */) = %s\n", errstr);
184 #else /* XLAT_ABBREV */
185 printf(", MPOL_MF_MOVE_ALL) = %s\n", errstr);
186 #endif
187 }
188
189 int
190 main(void)
191 {
192 PIDNS_TEST_INIT;
193
194 const unsigned long pid =
195 (unsigned long) 0xfacefeed00000000ULL | getpid();
196 const char *pid_str = pidns_pid2str(PT_TGID);
197 unsigned long count = 1;
198 const unsigned page_size = get_page_size();
199 const void *const page = tail_alloc(page_size);
200 const void *const efault = page + page_size;
201 TAIL_ALLOC_OBJECT_VAR_PTR(const void *, pages);
202 TAIL_ALLOC_OBJECT_VAR_PTR(int, nodes);
203 TAIL_ALLOC_OBJECT_VAR_PTR(int, status);
204
205 print_stat_pages(pid, pid_str, 0, pages, status);
206 print_move_pages(pid, pid_str, 0, 0, pages, nodes, status);
207 print_move_pages(pid, pid_str, 0, 1, pages + 1, nodes + 1, status + 1);
208
209 *pages = page;
210 print_stat_pages(pid, pid_str, count, pages, status);
211 *nodes = 0xdeadbee1;
212 print_move_pages(pid, pid_str, count, 0, pages, nodes, status);
213 print_move_pages(pid, pid_str, count, 1, pages, nodes, status);
214
215 ++count;
216 --status;
217 *(--pages) = efault;
218 print_stat_pages(pid, pid_str, count, pages, status);
219 *(--nodes) = 0xdeadbee2;
220 print_move_pages(pid, pid_str, count, 0, pages, nodes, status);
221 print_move_pages(pid, pid_str, count, 1, pages, nodes, status);
222
223 ++count;
224 --status;
225 *(--pages) = nodes;
226 print_stat_pages(pid, pid_str, count, pages, status);
227 *(--nodes) = 0xdeadbee3;
228 print_move_pages(pid, pid_str, count, 0, pages, nodes, status);
229 print_move_pages(pid, pid_str, count, 1, pages, nodes, status);
230
231 ++count;
232 --status;
233 *(--pages) = status;
234 print_stat_pages(pid, pid_str, count, pages, status);
235 *(--nodes) = 0xdeadbee4;
236 print_move_pages(pid, pid_str, count, 0, pages, nodes, status);
237 print_move_pages(pid, pid_str, count, 1, pages, nodes, status);
238
239 pidns_print_leader();
240 puts("+++ exited with 0 +++");
241 return 0;
242 }