mem.c revision 15fc6a2add5cc636435b120075d2c27637528b11
1/* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 6 * Copyright (c) 2000 PocketPenguins Inc. Linux for Hitachi SuperH 7 * port by Greg Banks <gbanks@pocketpenguins.com> 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include "defs.h" 34#include <asm/mman.h> 35#include <sys/mman.h> 36#if defined(I386) 37# include <asm/ldt.h> 38# ifdef HAVE_STRUCT_USER_DESC 39# define modify_ldt_ldt_s user_desc 40# endif 41#endif 42 43static unsigned long 44get_pagesize() 45{ 46 static unsigned long pagesize; 47 48 if (!pagesize) 49 pagesize = sysconf(_SC_PAGESIZE); 50 return pagesize; 51} 52 53int 54sys_brk(struct tcb *tcp) 55{ 56 if (entering(tcp)) { 57 tprintf("%#lx", tcp->u_arg[0]); 58 } 59 return RVAL_HEX; 60} 61 62static const struct xlat mmap_prot[] = { 63 { PROT_NONE, "PROT_NONE", }, 64 { PROT_READ, "PROT_READ" }, 65 { PROT_WRITE, "PROT_WRITE" }, 66 { PROT_EXEC, "PROT_EXEC" }, 67#ifdef PROT_SEM 68 { PROT_SEM, "PROT_SEM" }, 69#endif 70#ifdef PROT_GROWSDOWN 71 { PROT_GROWSDOWN,"PROT_GROWSDOWN"}, 72#endif 73#ifdef PROT_GROWSUP 74 { PROT_GROWSUP, "PROT_GROWSUP" }, 75#endif 76#ifdef PROT_SAO 77 { PROT_SAO, "PROT_SAO" }, 78#endif 79 { 0, NULL }, 80}; 81 82static const struct xlat mmap_flags[] = { 83 { MAP_SHARED, "MAP_SHARED" }, 84 { MAP_PRIVATE, "MAP_PRIVATE" }, 85 { MAP_FIXED, "MAP_FIXED" }, 86#ifdef MAP_ANONYMOUS 87 { MAP_ANONYMOUS,"MAP_ANONYMOUS" }, 88#endif 89#ifdef MAP_32BIT 90 { MAP_32BIT, "MAP_32BIT" }, 91#endif 92#ifdef MAP_RENAME 93 { MAP_RENAME, "MAP_RENAME" }, 94#endif 95#ifdef MAP_NORESERVE 96 { MAP_NORESERVE,"MAP_NORESERVE" }, 97#endif 98#ifdef MAP_POPULATE 99 { MAP_POPULATE, "MAP_POPULATE" }, 100#endif 101#ifdef MAP_NONBLOCK 102 { MAP_NONBLOCK, "MAP_NONBLOCK" }, 103#endif 104 /* 105 * XXX - this was introduced in SunOS 4.x to distinguish between 106 * the old pre-4.x "mmap()", which: 107 * 108 * only let you map devices with an "mmap" routine (e.g., 109 * frame buffers) in; 110 * 111 * required you to specify the mapping address; 112 * 113 * returned 0 on success and -1 on failure; 114 * 115 * memory and which, and the 4.x "mmap()" which: 116 * 117 * can map plain files; 118 * 119 * can be asked to pick where to map the file; 120 * 121 * returns the address where it mapped the file on success 122 * and -1 on failure. 123 * 124 * It's not actually used in source code that calls "mmap()"; the 125 * "mmap()" routine adds it for you. 126 * 127 * It'd be nice to come up with some way of eliminating it from 128 * the flags, e.g. reporting calls *without* it as "old_mmap()" 129 * and calls with it as "mmap()". 130 */ 131#ifdef _MAP_NEW 132 { _MAP_NEW, "_MAP_NEW" }, 133#endif 134#ifdef MAP_GROWSDOWN 135 { MAP_GROWSDOWN,"MAP_GROWSDOWN" }, 136#endif 137#ifdef MAP_DENYWRITE 138 { MAP_DENYWRITE,"MAP_DENYWRITE" }, 139#endif 140#ifdef MAP_EXECUTABLE 141 { MAP_EXECUTABLE,"MAP_EXECUTABLE"}, 142#endif 143#ifdef MAP_INHERIT 144 { MAP_INHERIT, "MAP_INHERIT" }, 145#endif 146#ifdef MAP_FILE 147 { MAP_FILE, "MAP_FILE" }, 148#endif 149#ifdef MAP_LOCKED 150 { MAP_LOCKED, "MAP_LOCKED" }, 151#endif 152 /* FreeBSD ones */ 153#if defined(MAP_ANON) && (!defined(MAP_ANONYMOUS) || MAP_ANON != MAP_ANONYMOUS) 154 { MAP_ANON, "MAP_ANON" }, 155#endif 156#ifdef MAP_HASSEMAPHORE 157 { MAP_HASSEMAPHORE,"MAP_HASSEMAPHORE"}, 158#endif 159#ifdef MAP_STACK 160 { MAP_STACK, "MAP_STACK" }, 161#endif 162#if defined MAP_UNINITIALIZED && MAP_UNINITIALIZED > 0 163 { MAP_UNINITIALIZED,"MAP_UNINITIALIZED"}, 164#endif 165#ifdef MAP_NOSYNC 166 { MAP_NOSYNC, "MAP_NOSYNC" }, 167#endif 168#ifdef MAP_NOCORE 169 { MAP_NOCORE, "MAP_NOCORE" }, 170#endif 171 { 0, NULL }, 172}; 173 174static int 175print_mmap(struct tcb *tcp, long *u_arg, unsigned long long offset) 176{ 177 if (entering(tcp)) { 178 /* addr */ 179 if (!u_arg[0]) 180 tprints("NULL, "); 181 else 182 tprintf("%#lx, ", u_arg[0]); 183 /* len */ 184 tprintf("%lu, ", u_arg[1]); 185 /* prot */ 186 printflags(mmap_prot, u_arg[2], "PROT_???"); 187 tprints(", "); 188 /* flags */ 189#ifdef MAP_TYPE 190 printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???"); 191 addflags(mmap_flags, u_arg[3] & ~MAP_TYPE); 192#else 193 printflags(mmap_flags, u_arg[3], "MAP_???"); 194#endif 195 tprints(", "); 196 /* fd */ 197 printfd(tcp, u_arg[4]); 198 /* offset */ 199 tprintf(", %#llx", offset); 200 } 201 return RVAL_HEX; 202} 203 204/* Syscall name<->function correspondence is messed up on many arches. 205 * For example: 206 * i386 has __NR_mmap == 90, and it is "old mmap", and 207 * also it has __NR_mmap2 == 192, which is a "new mmap with page offsets". 208 * But x86_64 has just one __NR_mmap == 9, a "new mmap with byte offsets". 209 * Confused? Me too! 210 */ 211 212/* Params are pointed to by u_arg[0], offset is in bytes */ 213int 214sys_old_mmap(struct tcb *tcp) 215{ 216 long u_arg[6]; 217#if defined(IA64) 218 /* 219 * IA64 processes never call this routine, they only use the 220 * new 'sys_mmap' interface. Only IA32 processes come here. 221 */ 222 int i; 223 unsigned narrow_arg[6]; 224 if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1) 225 return 0; 226 for (i = 0; i < 6; i++) 227 u_arg[i] = (unsigned long) narrow_arg[i]; 228#elif defined(X86_64) 229 /* We are here only in personality 1 (i386) */ 230 int i; 231 unsigned narrow_arg[6]; 232 if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1) 233 return 0; 234 for (i = 0; i < 6; ++i) 235 u_arg[i] = (unsigned long) narrow_arg[i]; 236#else 237 if (umoven(tcp, tcp->u_arg[0], sizeof(u_arg), (char *) u_arg) == -1) 238 return 0; 239#endif 240 return print_mmap(tcp, u_arg, (unsigned long) u_arg[5]); 241} 242 243#if defined(S390) 244/* Params are pointed to by u_arg[0], offset is in pages */ 245int 246sys_old_mmap_pgoff(struct tcb *tcp) 247{ 248 long u_arg[5]; 249 int i; 250 unsigned narrow_arg[6]; 251 unsigned long long offset; 252 if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1) 253 return 0; 254 for (i = 0; i < 5; i++) 255 u_arg[i] = (unsigned long) narrow_arg[i]; 256 offset = narrow_arg[5]; 257 offset *= get_pagesize(); 258 return print_mmap(tcp, u_arg, offset); 259} 260#endif 261 262/* Params are passed directly, offset is in bytes */ 263int 264sys_mmap(struct tcb *tcp) 265{ 266 unsigned long long offset = (unsigned long) tcp->u_arg[5]; 267#if defined(LINUX_MIPSN32) || defined(X32) 268 /* Try test/x32_mmap.c */ 269 offset = tcp->ext_arg[5]; 270#endif 271 /* Example of kernel-side handling of this variety of mmap: 272 * arch/x86/kernel/sys_x86_64.c::SYSCALL_DEFINE6(mmap, ...) calls 273 * sys_mmap_pgoff(..., off >> PAGE_SHIFT); i.e. off is in bytes, 274 * since the above code converts off to pages. 275 */ 276 return print_mmap(tcp, tcp->u_arg, offset); 277} 278 279/* Params are passed directly, offset is in pages */ 280int 281sys_mmap_pgoff(struct tcb *tcp) 282{ 283 /* Try test/mmap_offset_decode.c */ 284 unsigned long long offset; 285 offset = (unsigned long) tcp->u_arg[5]; 286 offset *= get_pagesize(); 287 return print_mmap(tcp, tcp->u_arg, offset); 288} 289 290/* Params are passed directly, offset is in 4k units */ 291int 292sys_mmap_4koff(struct tcb *tcp) 293{ 294 unsigned long long offset; 295 offset = (unsigned long) tcp->u_arg[5]; 296 offset <<= 12; 297 return print_mmap(tcp, tcp->u_arg, offset); 298} 299 300int 301sys_munmap(struct tcb *tcp) 302{ 303 if (entering(tcp)) { 304 tprintf("%#lx, %lu", 305 tcp->u_arg[0], tcp->u_arg[1]); 306 } 307 return 0; 308} 309 310int 311sys_mprotect(struct tcb *tcp) 312{ 313 if (entering(tcp)) { 314 tprintf("%#lx, %lu, ", 315 tcp->u_arg[0], tcp->u_arg[1]); 316 printflags(mmap_prot, tcp->u_arg[2], "PROT_???"); 317 } 318 return 0; 319} 320 321static const struct xlat mremap_flags[] = { 322 { MREMAP_MAYMOVE, "MREMAP_MAYMOVE" }, 323#ifdef MREMAP_FIXED 324 { MREMAP_FIXED, "MREMAP_FIXED" }, 325#endif 326 { 0, NULL } 327}; 328 329int 330sys_mremap(struct tcb *tcp) 331{ 332 if (entering(tcp)) { 333 tprintf("%#lx, %lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1], 334 tcp->u_arg[2]); 335 printflags(mremap_flags, tcp->u_arg[3], "MREMAP_???"); 336#ifdef MREMAP_FIXED 337 if ((tcp->u_arg[3] & (MREMAP_MAYMOVE | MREMAP_FIXED)) == 338 (MREMAP_MAYMOVE | MREMAP_FIXED)) 339 tprintf(", %#lx", tcp->u_arg[4]); 340#endif 341 } 342 return RVAL_HEX; 343} 344 345static const struct xlat madvise_cmds[] = { 346#ifdef MADV_NORMAL 347 { MADV_NORMAL, "MADV_NORMAL" }, 348#endif 349#ifdef MADV_RANDOM 350 { MADV_RANDOM, "MADV_RANDOM" }, 351#endif 352#ifdef MADV_SEQUENTIAL 353 { MADV_SEQUENTIAL, "MADV_SEQUENTIAL" }, 354#endif 355#ifdef MADV_WILLNEED 356 { MADV_WILLNEED, "MADV_WILLNEED" }, 357#endif 358#ifdef MADV_DONTNEED 359 { MADV_DONTNEED, "MADV_DONTNEED" }, 360#endif 361#ifdef MADV_REMOVE 362 { MADV_REMOVE, "MADV_REMOVE" }, 363#endif 364#ifdef MADV_DONTFORK 365 { MADV_DONTFORK, "MADV_DONTFORK" }, 366#endif 367#ifdef MADV_DOFORK 368 { MADV_DOFORK, "MADV_DOFORK" }, 369#endif 370#ifdef MADV_HWPOISON 371 { MADV_HWPOISON, "MADV_HWPOISON" }, 372#endif 373#ifdef MADV_SOFT_OFFLINE 374 { MADV_SOFT_OFFLINE, "MADV_SOFT_OFFLINE" }, 375#endif 376#ifdef MADV_MERGEABLE 377 { MADV_MERGEABLE, "MADV_MERGEABLE" }, 378#endif 379#ifdef MADV_UNMERGEABLE 380 { MADV_UNMERGEABLE, "MADV_UNMERGEABLE" }, 381#endif 382#ifdef MADV_HUGEPAGE 383 { MADV_HUGEPAGE, "MADV_HUGEPAGE" }, 384#endif 385#ifdef MADV_NOHUGEPAGE 386 { MADV_NOHUGEPAGE, "MADV_NOHUGEPAGE" }, 387#endif 388#ifdef MADV_DONTDUMP 389 { MADV_DONTDUMP, "MADV_DONTDUMP" }, 390#endif 391#ifdef MADV_DODUMP 392 { MADV_DODUMP, "MADV_DODUMP" }, 393#endif 394 { 0, NULL }, 395}; 396 397int 398sys_madvise(struct tcb *tcp) 399{ 400 if (entering(tcp)) { 401 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 402 printxval(madvise_cmds, tcp->u_arg[2], "MADV_???"); 403 } 404 return 0; 405} 406 407static const struct xlat mlockall_flags[] = { 408#ifdef MCL_CURRENT 409 { MCL_CURRENT, "MCL_CURRENT" }, 410#endif 411#ifdef MCL_FUTURE 412 { MCL_FUTURE, "MCL_FUTURE" }, 413#endif 414 { 0, NULL} 415}; 416 417int 418sys_mlockall(struct tcb *tcp) 419{ 420 if (entering(tcp)) { 421 printflags(mlockall_flags, tcp->u_arg[0], "MCL_???"); 422 } 423 return 0; 424} 425 426#ifdef MS_ASYNC 427 428static const struct xlat mctl_sync[] = { 429#ifdef MS_SYNC 430 { MS_SYNC, "MS_SYNC" }, 431#endif 432 { MS_ASYNC, "MS_ASYNC" }, 433 { MS_INVALIDATE,"MS_INVALIDATE" }, 434 { 0, NULL }, 435}; 436 437int 438sys_msync(struct tcb *tcp) 439{ 440 if (entering(tcp)) { 441 /* addr */ 442 tprintf("%#lx", tcp->u_arg[0]); 443 /* len */ 444 tprintf(", %lu, ", tcp->u_arg[1]); 445 /* flags */ 446 printflags(mctl_sync, tcp->u_arg[2], "MS_???"); 447 } 448 return 0; 449} 450 451#endif /* MS_ASYNC */ 452 453#ifdef MC_SYNC 454 455static const struct xlat mctl_funcs[] = { 456 { MC_LOCK, "MC_LOCK" }, 457 { MC_LOCKAS, "MC_LOCKAS" }, 458 { MC_SYNC, "MC_SYNC" }, 459 { MC_UNLOCK, "MC_UNLOCK" }, 460 { MC_UNLOCKAS, "MC_UNLOCKAS" }, 461 { 0, NULL }, 462}; 463 464static const struct xlat mctl_lockas[] = { 465 { MCL_CURRENT, "MCL_CURRENT" }, 466 { MCL_FUTURE, "MCL_FUTURE" }, 467 { 0, NULL }, 468}; 469 470int 471sys_mctl(struct tcb *tcp) 472{ 473 int arg, function; 474 475 if (entering(tcp)) { 476 /* addr */ 477 tprintf("%#lx", tcp->u_arg[0]); 478 /* len */ 479 tprintf(", %lu, ", tcp->u_arg[1]); 480 /* function */ 481 function = tcp->u_arg[2]; 482 printflags(mctl_funcs, function, "MC_???"); 483 /* arg */ 484 arg = tcp->u_arg[3]; 485 tprints(", "); 486 switch (function) { 487 case MC_SYNC: 488 printflags(mctl_sync, arg, "MS_???"); 489 break; 490 case MC_LOCKAS: 491 printflags(mctl_lockas, arg, "MCL_???"); 492 break; 493 default: 494 tprintf("%#x", arg); 495 break; 496 } 497 } 498 return 0; 499} 500 501#endif /* MC_SYNC */ 502 503int 504sys_mincore(struct tcb *tcp) 505{ 506 if (entering(tcp)) { 507 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 508 } else { 509 unsigned long i, len; 510 char *vec = NULL; 511 512 len = tcp->u_arg[1]; 513 if (syserror(tcp) || tcp->u_arg[2] == 0 || 514 (vec = malloc(len)) == NULL || 515 umoven(tcp, tcp->u_arg[2], len, vec) < 0) 516 tprintf("%#lx", tcp->u_arg[2]); 517 else { 518 tprints("["); 519 for (i = 0; i < len; i++) { 520 if (abbrev(tcp) && i >= max_strlen) { 521 tprints("..."); 522 break; 523 } 524 tprints((vec[i] & 1) ? "1" : "0"); 525 } 526 tprints("]"); 527 } 528 free(vec); 529 } 530 return 0; 531} 532 533#if defined(ALPHA) || defined(IA64) || defined(SPARC) || defined(SPARC64) 534int 535sys_getpagesize(struct tcb *tcp) 536{ 537 if (exiting(tcp)) 538 return RVAL_HEX; 539 return 0; 540} 541#endif 542 543#if defined(I386) 544void 545print_ldt_entry(struct modify_ldt_ldt_s *ldt_entry) 546{ 547 tprintf("base_addr:%#08lx, " 548 "limit:%d, " 549 "seg_32bit:%d, " 550 "contents:%d, " 551 "read_exec_only:%d, " 552 "limit_in_pages:%d, " 553 "seg_not_present:%d, " 554 "useable:%d}", 555 (long) ldt_entry->base_addr, 556 ldt_entry->limit, 557 ldt_entry->seg_32bit, 558 ldt_entry->contents, 559 ldt_entry->read_exec_only, 560 ldt_entry->limit_in_pages, 561 ldt_entry->seg_not_present, 562 ldt_entry->useable); 563} 564 565int 566sys_modify_ldt(struct tcb *tcp) 567{ 568 if (entering(tcp)) { 569 struct modify_ldt_ldt_s copy; 570 tprintf("%ld", tcp->u_arg[0]); 571 if (tcp->u_arg[1] == 0 572 || tcp->u_arg[2] != sizeof(struct modify_ldt_ldt_s) 573 || umove(tcp, tcp->u_arg[1], ©) == -1) 574 tprintf(", %lx", tcp->u_arg[1]); 575 else { 576 tprintf(", {entry_number:%d, ", copy.entry_number); 577 if (!verbose(tcp)) 578 tprints("...}"); 579 else { 580 print_ldt_entry(©); 581 } 582 } 583 tprintf(", %lu", tcp->u_arg[2]); 584 } 585 return 0; 586} 587 588int 589sys_set_thread_area(struct tcb *tcp) 590{ 591 struct modify_ldt_ldt_s copy; 592 if (entering(tcp)) { 593 if (umove(tcp, tcp->u_arg[0], ©) != -1) { 594 if (copy.entry_number == -1) 595 tprintf("{entry_number:%d -> ", 596 copy.entry_number); 597 else 598 tprints("{entry_number:"); 599 } 600 } else { 601 if (umove(tcp, tcp->u_arg[0], ©) != -1) { 602 tprintf("%d, ", copy.entry_number); 603 if (!verbose(tcp)) 604 tprints("...}"); 605 else { 606 print_ldt_entry(©); 607 } 608 } else { 609 tprintf("%lx", tcp->u_arg[0]); 610 } 611 } 612 return 0; 613 614} 615 616int 617sys_get_thread_area(struct tcb *tcp) 618{ 619 struct modify_ldt_ldt_s copy; 620 if (exiting(tcp)) { 621 if (umove(tcp, tcp->u_arg[0], ©) != -1) { 622 tprintf("{entry_number:%d, ", copy.entry_number); 623 if (!verbose(tcp)) 624 tprints("...}"); 625 else { 626 print_ldt_entry(©); 627 } 628 } else { 629 tprintf("%lx", tcp->u_arg[0]); 630 } 631 } 632 return 0; 633 634} 635#endif /* I386 */ 636 637#if defined(M68K) 638int 639sys_set_thread_area(struct tcb *tcp) 640{ 641 if (entering(tcp)) 642 tprintf("%#lx", tcp->u_arg[0]); 643 return 0; 644 645} 646 647int 648sys_get_thread_area(struct tcb *tcp) 649{ 650 return RVAL_HEX; 651} 652#endif 653 654int 655sys_remap_file_pages(struct tcb *tcp) 656{ 657 if (entering(tcp)) { 658 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 659 printflags(mmap_prot, tcp->u_arg[2], "PROT_???"); 660 tprintf(", %lu, ", tcp->u_arg[3]); 661#ifdef MAP_TYPE 662 printxval(mmap_flags, tcp->u_arg[4] & MAP_TYPE, "MAP_???"); 663 addflags(mmap_flags, tcp->u_arg[4] & ~MAP_TYPE); 664#else 665 printflags(mmap_flags, tcp->u_arg[4], "MAP_???"); 666#endif 667 } 668 return 0; 669} 670 671#define MPOL_DEFAULT 0 672#define MPOL_PREFERRED 1 673#define MPOL_BIND 2 674#define MPOL_INTERLEAVE 3 675 676#define MPOL_F_NODE (1<<0) 677#define MPOL_F_ADDR (1<<1) 678 679#define MPOL_MF_STRICT (1<<0) 680#define MPOL_MF_MOVE (1<<1) 681#define MPOL_MF_MOVE_ALL (1<<2) 682 683static const struct xlat policies[] = { 684 { MPOL_DEFAULT, "MPOL_DEFAULT" }, 685 { MPOL_PREFERRED, "MPOL_PREFERRED" }, 686 { MPOL_BIND, "MPOL_BIND" }, 687 { MPOL_INTERLEAVE, "MPOL_INTERLEAVE" }, 688 { 0, NULL } 689}; 690 691static const struct xlat mbindflags[] = { 692 { MPOL_MF_STRICT, "MPOL_MF_STRICT" }, 693 { MPOL_MF_MOVE, "MPOL_MF_MOVE" }, 694 { MPOL_MF_MOVE_ALL, "MPOL_MF_MOVE_ALL" }, 695 { 0, NULL } 696}; 697 698static const struct xlat mempolicyflags[] = { 699 { MPOL_F_NODE, "MPOL_F_NODE" }, 700 { MPOL_F_ADDR, "MPOL_F_ADDR" }, 701 { 0, NULL } 702}; 703 704static const struct xlat move_pages_flags[] = { 705 { MPOL_MF_MOVE, "MPOL_MF_MOVE" }, 706 { MPOL_MF_MOVE_ALL, "MPOL_MF_MOVE_ALL" }, 707 { 0, NULL } 708}; 709 710static void 711get_nodes(struct tcb *tcp, unsigned long ptr, unsigned long maxnodes, int err) 712{ 713 unsigned long nlongs, size, end; 714 715 nlongs = (maxnodes + 8 * sizeof(long) - 1) / (8 * sizeof(long)); 716 size = nlongs * sizeof(long); 717 end = ptr + size; 718 if (nlongs == 0 || ((err || verbose(tcp)) && (size * 8 == maxnodes) 719 && (end > ptr))) { 720 unsigned long n, cur, abbrev_end; 721 int failed = 0; 722 723 if (abbrev(tcp)) { 724 abbrev_end = ptr + max_strlen * sizeof(long); 725 if (abbrev_end < ptr) 726 abbrev_end = end; 727 } else { 728 abbrev_end = end; 729 } 730 tprints(", {"); 731 for (cur = ptr; cur < end; cur += sizeof(long)) { 732 if (cur > ptr) 733 tprints(", "); 734 if (cur >= abbrev_end) { 735 tprints("..."); 736 break; 737 } 738 if (umoven(tcp, cur, sizeof(n), (char *) &n) < 0) { 739 tprints("?"); 740 failed = 1; 741 break; 742 } 743 tprintf("%#0*lx", (int) sizeof(long) * 2 + 2, n); 744 } 745 tprints("}"); 746 if (failed) 747 tprintf(" %#lx", ptr); 748 } else 749 tprintf(", %#lx", ptr); 750 tprintf(", %lu", maxnodes); 751} 752 753int 754sys_mbind(struct tcb *tcp) 755{ 756 if (entering(tcp)) { 757 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 758 printxval(policies, tcp->u_arg[2], "MPOL_???"); 759 get_nodes(tcp, tcp->u_arg[3], tcp->u_arg[4], 0); 760 tprints(", "); 761 printflags(mbindflags, tcp->u_arg[5], "MPOL_???"); 762 } 763 return 0; 764} 765 766int 767sys_set_mempolicy(struct tcb *tcp) 768{ 769 if (entering(tcp)) { 770 printxval(policies, tcp->u_arg[0], "MPOL_???"); 771 get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], 0); 772 } 773 return 0; 774} 775 776int 777sys_get_mempolicy(struct tcb *tcp) 778{ 779 if (exiting(tcp)) { 780 int pol; 781 if (tcp->u_arg[0] == 0) 782 tprints("NULL"); 783 else if (syserror(tcp) || umove(tcp, tcp->u_arg[0], &pol) < 0) 784 tprintf("%#lx", tcp->u_arg[0]); 785 else 786 printxval(policies, pol, "MPOL_???"); 787 get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], syserror(tcp)); 788 tprintf(", %#lx, ", tcp->u_arg[3]); 789 printflags(mempolicyflags, tcp->u_arg[4], "MPOL_???"); 790 } 791 return 0; 792} 793 794int 795sys_migrate_pages(struct tcb *tcp) 796{ 797 if (entering(tcp)) { 798 tprintf("%ld, ", (long) (pid_t) tcp->u_arg[0]); 799 get_nodes(tcp, tcp->u_arg[2], tcp->u_arg[1], 0); 800 tprints(", "); 801 get_nodes(tcp, tcp->u_arg[3], tcp->u_arg[1], 0); 802 } 803 return 0; 804} 805 806int 807sys_move_pages(struct tcb *tcp) 808{ 809 if (entering(tcp)) { 810 unsigned long npages = tcp->u_arg[1]; 811 tprintf("%ld, %lu, ", tcp->u_arg[0], npages); 812 if (tcp->u_arg[2] == 0) 813 tprints("NULL, "); 814 else { 815 int i; 816 long puser = tcp->u_arg[2]; 817 tprints("{"); 818 for (i = 0; i < npages; ++i) { 819 void *p; 820 if (i > 0) 821 tprints(", "); 822 if (umove(tcp, puser, &p) < 0) { 823 tprints("???"); 824 break; 825 } 826 tprintf("%p", p); 827 puser += sizeof(void *); 828 } 829 tprints("}, "); 830 } 831 if (tcp->u_arg[3] == 0) 832 tprints("NULL, "); 833 else { 834 int i; 835 long nodeuser = tcp->u_arg[3]; 836 tprints("{"); 837 for (i = 0; i < npages; ++i) { 838 int node; 839 if (i > 0) 840 tprints(", "); 841 if (umove(tcp, nodeuser, &node) < 0) { 842 tprints("???"); 843 break; 844 } 845 tprintf("%#x", node); 846 nodeuser += sizeof(int); 847 } 848 tprints("}, "); 849 } 850 } 851 if (exiting(tcp)) { 852 unsigned long npages = tcp->u_arg[1]; 853 if (tcp->u_arg[4] == 0) 854 tprints("NULL, "); 855 else { 856 int i; 857 long statususer = tcp->u_arg[4]; 858 tprints("{"); 859 for (i = 0; i < npages; ++i) { 860 int status; 861 if (i > 0) 862 tprints(", "); 863 if (umove(tcp, statususer, &status) < 0) { 864 tprints("???"); 865 break; 866 } 867 tprintf("%#x", status); 868 statususer += sizeof(int); 869 } 870 tprints("}, "); 871 } 872 printflags(move_pages_flags, tcp->u_arg[5], "MPOL_???"); 873 } 874 return 0; 875} 876 877#if defined(POWERPC) 878int 879sys_subpage_prot(struct tcb *tcp) 880{ 881 if (entering(tcp)) { 882 unsigned long cur, end, abbrev_end, entries; 883 unsigned int entry; 884 885 tprintf("%#lx, %#lx, ", tcp->u_arg[0], tcp->u_arg[1]); 886 entries = tcp->u_arg[1] >> 16; 887 if (!entries || !tcp->u_arg[2]) { 888 tprints("{}"); 889 return 0; 890 } 891 cur = tcp->u_arg[2]; 892 end = cur + (sizeof(int) * entries); 893 if (!verbose(tcp) || end < tcp->u_arg[2]) { 894 tprintf("%#lx", tcp->u_arg[2]); 895 return 0; 896 } 897 if (abbrev(tcp)) { 898 abbrev_end = cur + (sizeof(int) * max_strlen); 899 if (abbrev_end > end) 900 abbrev_end = end; 901 } 902 else 903 abbrev_end = end; 904 tprints("{"); 905 for (; cur < end; cur += sizeof(int)) { 906 if (cur > tcp->u_arg[2]) 907 tprints(", "); 908 if (cur >= abbrev_end) { 909 tprints("..."); 910 break; 911 } 912 if (umove(tcp, cur, &entry) < 0) { 913 tprintf("??? [%#lx]", cur); 914 break; 915 } 916 else 917 tprintf("%#08x", entry); 918 } 919 tprints("}"); 920 } 921 922 return 0; 923} 924#endif 925