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