1 /*
2 * Check decoding of move_pages syscall.
3 *
4 * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
5 * Copyright (c) 2016-2018 The strace developers.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "tests.h"
32 #include <asm/unistd.h>
33
34 #ifdef __NR_move_pages
35
36 # include <errno.h>
37 # include <stdio.h>
38 # include <unistd.h>
39
40 # define MAX_STRLEN 3
41
42 static void
print_page_array(const void ** const pages,const unsigned long count,const unsigned int offset)43 print_page_array(const void **const pages,
44 const unsigned long count,
45 const unsigned int offset)
46 {
47 if (!count) {
48 printf("%s", pages ? "[]" : "NULL");
49 return;
50 }
51 if (count <= offset) {
52 printf("%p", pages);
53 return;
54 }
55 printf("[");
56 unsigned long i;
57 for (i = 0; i < count; ++i) {
58 if (i)
59 printf(", ");
60 if (i + offset < count) {
61 if (i >= MAX_STRLEN) {
62 printf("...");
63 break;
64 }
65 } else {
66 printf("... /* %p */", pages + i);
67 break;
68 }
69 const void *const addr = pages[i];
70 if (addr)
71 printf("%p", addr);
72 else
73 printf("NULL");
74 }
75 printf("]");
76 }
77
78 static void
print_node_array(const int * const nodes,const unsigned long count,const unsigned int offset)79 print_node_array(const int *const nodes,
80 const unsigned long count,
81 const unsigned int offset)
82 {
83 if (!count) {
84 printf("%s", nodes ? "[]" : "NULL");
85 return;
86 }
87 if (count <= offset) {
88 printf("%p", nodes);
89 return;
90 }
91 printf("[");
92 unsigned long i;
93 for (i = 0; i < count; ++i) {
94 if (i)
95 printf(", ");
96 if (i + offset < count) {
97 if (i >= MAX_STRLEN) {
98 printf("...");
99 break;
100 }
101 } else {
102 printf("... /* %p */", nodes + i);
103 break;
104 }
105 printf("%d", nodes[i]);
106 }
107 printf("]");
108 }
109
110 static void
print_status_array(const int * const status,const unsigned long count)111 print_status_array(const int *const status, const unsigned long count)
112 {
113 if (!count) {
114 printf("%s", status ? "[]" : "NULL");
115 return;
116 }
117 printf("[");
118 unsigned long i;
119 for (i = 0; i < count; ++i) {
120 if (i)
121 printf(", ");
122 if (i >= MAX_STRLEN) {
123 printf("...");
124 break;
125 }
126 if (status[i] >= 0) {
127 printf("%d", status[i]);
128 } else {
129 errno = -status[i];
130 printf("-%s", errno2name());
131 }
132 }
133 printf("]");
134 }
135
136 static void
print_stat_pages(const unsigned long pid,const unsigned long count,const void ** const pages,int * const status)137 print_stat_pages(const unsigned long pid, const unsigned long count,
138 const void **const pages, int *const status)
139 {
140 const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL;
141
142 long rc = syscall(__NR_move_pages,
143 pid, count, pages, NULL, status, flags);
144 const char *errstr = sprintrc(rc);
145 printf("move_pages(%d, %lu, ", (int) pid, count);
146 print_page_array(pages, count, 0);
147 printf(", NULL, ");
148 if (rc) {
149 if (count)
150 printf("%p", status);
151 else
152 printf("[]");
153 } else {
154 print_status_array(status, count);
155 }
156 printf(", MPOL_MF_MOVE) = %s\n", errstr);
157 }
158
159 static void
print_move_pages(const unsigned long pid,unsigned long count,const unsigned int offset,const void ** const pages,int * const nodes,int * const status)160 print_move_pages(const unsigned long pid,
161 unsigned long count,
162 const unsigned int offset,
163 const void **const pages,
164 int *const nodes,
165 int *const status)
166 {
167 const unsigned long flags = (unsigned long) 0xfacefeed00000004ULL;
168 count += offset;
169
170 long rc = syscall(__NR_move_pages,
171 pid, count, pages, nodes, status, flags);
172 const char *errstr = sprintrc(rc);
173 printf("move_pages(%d, %lu, ", (int) pid, count);
174 print_page_array(pages, count, offset);
175 printf(", ");
176 print_node_array(nodes, count, offset);
177 printf(", ");
178 if (count)
179 printf("%p", status);
180 else
181 printf("[]");
182 printf(", MPOL_MF_MOVE_ALL) = %s\n", errstr);
183 }
184
185 int
main(void)186 main(void)
187 {
188 const unsigned long pid =
189 (unsigned long) 0xfacefeed00000000ULL | getpid();
190 unsigned long count = 1;
191 const unsigned page_size = get_page_size();
192 const void *const page = tail_alloc(page_size);
193 const void *const efault = page + page_size;
194 TAIL_ALLOC_OBJECT_VAR_PTR(const void *, pages);
195 TAIL_ALLOC_OBJECT_VAR_PTR(int, nodes);
196 TAIL_ALLOC_OBJECT_VAR_PTR(int, status);
197
198 print_stat_pages(pid, 0, pages, status);
199 print_move_pages(pid, 0, 0, pages, nodes, status);
200 print_move_pages(pid, 0, 1, pages + 1, nodes + 1, status + 1);
201
202 *pages = page;
203 print_stat_pages(pid, count, pages, status);
204 *nodes = 0xdeadbee1;
205 print_move_pages(pid, count, 0, pages, nodes, status);
206 print_move_pages(pid, count, 1, pages, nodes, status);
207
208 ++count;
209 --status;
210 *(--pages) = efault;
211 print_stat_pages(pid, count, pages, status);
212 *(--nodes) = 0xdeadbee2;
213 print_move_pages(pid, count, 0, pages, nodes, status);
214 print_move_pages(pid, count, 1, pages, nodes, status);
215
216 ++count;
217 --status;
218 *(--pages) = nodes;
219 print_stat_pages(pid, count, pages, status);
220 *(--nodes) = 0xdeadbee3;
221 print_move_pages(pid, count, 0, pages, nodes, status);
222 print_move_pages(pid, count, 1, pages, nodes, status);
223
224 ++count;
225 --status;
226 *(--pages) = status;
227 print_stat_pages(pid, count, pages, status);
228 *(--nodes) = 0xdeadbee4;
229 print_move_pages(pid, count, 0, pages, nodes, status);
230 print_move_pages(pid, count, 1, pages, nodes, status);
231
232 puts("+++ exited with 0 +++");
233 return 0;
234 }
235
236 #else
237
238 SKIP_MAIN_UNDEFINED("__NR_move_pages")
239
240 #endif
241