1 /* 2 * Check decoding of move_pages syscall. 3 * 4 * Copyright (c) 2016 Dmitry V. Levin <ldv (at) altlinux.org> 5 * Copyright (c) 2016-2017 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 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 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 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 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 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 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