1 /* 2 * mmap support for qemu 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 #include "qemu/osdep.h" 20 #include "trace.h" 21 #include "exec/log.h" 22 #include "qemu.h" 23 #include "user-internals.h" 24 #include "user-mmap.h" 25 26 static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER; 27 static __thread int mmap_lock_count; 28 29 void mmap_lock(void) 30 { 31 if (mmap_lock_count++ == 0) { 32 pthread_mutex_lock(&mmap_mutex); 33 } 34 } 35 36 void mmap_unlock(void) 37 { 38 if (--mmap_lock_count == 0) { 39 pthread_mutex_unlock(&mmap_mutex); 40 } 41 } 42 43 bool have_mmap_lock(void) 44 { 45 return mmap_lock_count > 0 ? true : false; 46 } 47 48 /* Grab lock to make sure things are in a consistent state after fork(). */ 49 void mmap_fork_start(void) 50 { 51 if (mmap_lock_count) 52 abort(); 53 pthread_mutex_lock(&mmap_mutex); 54 } 55 56 void mmap_fork_end(int child) 57 { 58 if (child) 59 pthread_mutex_init(&mmap_mutex, NULL); 60 else 61 pthread_mutex_unlock(&mmap_mutex); 62 } 63 64 /* 65 * Validate target prot bitmask. 66 * Return the prot bitmask for the host in *HOST_PROT. 67 * Return 0 if the target prot bitmask is invalid, otherwise 68 * the internal qemu page_flags (which will include PAGE_VALID). 69 */ 70 static int validate_prot_to_pageflags(int *host_prot, int prot) 71 { 72 int valid = PROT_READ | PROT_WRITE | PROT_EXEC | TARGET_PROT_SEM; 73 int page_flags = (prot & PAGE_BITS) | PAGE_VALID; 74 75 /* 76 * For the host, we need not pass anything except read/write/exec. 77 * While PROT_SEM is allowed by all hosts, it is also ignored, so 78 * don't bother transforming guest bit to host bit. Any other 79 * target-specific prot bits will not be understood by the host 80 * and will need to be encoded into page_flags for qemu emulation. 81 * 82 * Pages that are executable by the guest will never be executed 83 * by the host, but the host will need to be able to read them. 84 */ 85 *host_prot = (prot & (PROT_READ | PROT_WRITE)) 86 | (prot & PROT_EXEC ? PROT_READ : 0); 87 88 #ifdef TARGET_AARCH64 89 { 90 ARMCPU *cpu = ARM_CPU(thread_cpu); 91 92 /* 93 * The PROT_BTI bit is only accepted if the cpu supports the feature. 94 * Since this is the unusual case, don't bother checking unless 95 * the bit has been requested. If set and valid, record the bit 96 * within QEMU's page_flags. 97 */ 98 if ((prot & TARGET_PROT_BTI) && cpu_isar_feature(aa64_bti, cpu)) { 99 valid |= TARGET_PROT_BTI; 100 page_flags |= PAGE_BTI; 101 } 102 /* Similarly for the PROT_MTE bit. */ 103 if ((prot & TARGET_PROT_MTE) && cpu_isar_feature(aa64_mte, cpu)) { 104 valid |= TARGET_PROT_MTE; 105 page_flags |= PAGE_MTE; 106 } 107 } 108 #endif 109 110 return prot & ~valid ? 0 : page_flags; 111 } 112 113 /* NOTE: all the constants are the HOST ones, but addresses are target. */ 114 int target_mprotect(abi_ulong start, abi_ulong len, int target_prot) 115 { 116 abi_ulong end, host_start, host_end, addr; 117 int prot1, ret, page_flags, host_prot; 118 119 trace_target_mprotect(start, len, target_prot); 120 121 if ((start & ~TARGET_PAGE_MASK) != 0) { 122 return -TARGET_EINVAL; 123 } 124 page_flags = validate_prot_to_pageflags(&host_prot, target_prot); 125 if (!page_flags) { 126 return -TARGET_EINVAL; 127 } 128 len = TARGET_PAGE_ALIGN(len); 129 end = start + len; 130 if (!guest_range_valid_untagged(start, len)) { 131 return -TARGET_ENOMEM; 132 } 133 if (len == 0) { 134 return 0; 135 } 136 137 mmap_lock(); 138 host_start = start & qemu_host_page_mask; 139 host_end = HOST_PAGE_ALIGN(end); 140 if (start > host_start) { 141 /* handle host page containing start */ 142 prot1 = host_prot; 143 for (addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) { 144 prot1 |= page_get_flags(addr); 145 } 146 if (host_end == host_start + qemu_host_page_size) { 147 for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { 148 prot1 |= page_get_flags(addr); 149 } 150 end = host_end; 151 } 152 ret = mprotect(g2h_untagged(host_start), qemu_host_page_size, 153 prot1 & PAGE_BITS); 154 if (ret != 0) { 155 goto error; 156 } 157 host_start += qemu_host_page_size; 158 } 159 if (end < host_end) { 160 prot1 = host_prot; 161 for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { 162 prot1 |= page_get_flags(addr); 163 } 164 ret = mprotect(g2h_untagged(host_end - qemu_host_page_size), 165 qemu_host_page_size, prot1 & PAGE_BITS); 166 if (ret != 0) { 167 goto error; 168 } 169 host_end -= qemu_host_page_size; 170 } 171 172 /* handle the pages in the middle */ 173 if (host_start < host_end) { 174 ret = mprotect(g2h_untagged(host_start), 175 host_end - host_start, host_prot); 176 if (ret != 0) { 177 goto error; 178 } 179 } 180 181 page_set_flags(start, start + len, page_flags); 182 tb_invalidate_phys_range(start, start + len); 183 ret = 0; 184 185 error: 186 mmap_unlock(); 187 return ret; 188 } 189 190 /* map an incomplete host page */ 191 static int mmap_frag(abi_ulong real_start, 192 abi_ulong start, abi_ulong end, 193 int prot, int flags, int fd, abi_ulong offset) 194 { 195 abi_ulong real_end, addr; 196 void *host_start; 197 int prot1, prot_new; 198 199 real_end = real_start + qemu_host_page_size; 200 host_start = g2h_untagged(real_start); 201 202 /* get the protection of the target pages outside the mapping */ 203 prot1 = 0; 204 for(addr = real_start; addr < real_end; addr++) { 205 if (addr < start || addr >= end) 206 prot1 |= page_get_flags(addr); 207 } 208 209 if (prot1 == 0) { 210 /* no page was there, so we allocate one */ 211 void *p = mmap(host_start, qemu_host_page_size, prot, 212 flags | MAP_ANONYMOUS, -1, 0); 213 if (p == MAP_FAILED) 214 return -1; 215 prot1 = prot; 216 } 217 prot1 &= PAGE_BITS; 218 219 prot_new = prot | prot1; 220 if (!(flags & MAP_ANONYMOUS)) { 221 /* msync() won't work here, so we return an error if write is 222 possible while it is a shared mapping */ 223 if ((flags & MAP_TYPE) == MAP_SHARED && 224 (prot & PROT_WRITE)) 225 return -1; 226 227 /* adjust protection to be able to read */ 228 if (!(prot1 & PROT_WRITE)) 229 mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE); 230 231 /* read the corresponding file data */ 232 if (pread(fd, g2h_untagged(start), end - start, offset) == -1) 233 return -1; 234 235 /* put final protection */ 236 if (prot_new != (prot1 | PROT_WRITE)) 237 mprotect(host_start, qemu_host_page_size, prot_new); 238 } else { 239 if (prot_new != prot1) { 240 mprotect(host_start, qemu_host_page_size, prot_new); 241 } 242 if (prot_new & PROT_WRITE) { 243 memset(g2h_untagged(start), 0, end - start); 244 } 245 } 246 return 0; 247 } 248 249 #if HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64 250 #ifdef TARGET_AARCH64 251 # define TASK_UNMAPPED_BASE 0x5500000000 252 #else 253 # define TASK_UNMAPPED_BASE (1ul << 38) 254 #endif 255 #else 256 # define TASK_UNMAPPED_BASE 0x40000000 257 #endif 258 abi_ulong mmap_next_start = TASK_UNMAPPED_BASE; 259 260 unsigned long last_brk; 261 262 /* Subroutine of mmap_find_vma, used when we have pre-allocated a chunk 263 of guest address space. */ 264 static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size, 265 abi_ulong align) 266 { 267 abi_ulong addr, end_addr, incr = qemu_host_page_size; 268 int prot; 269 bool looped = false; 270 271 if (size > reserved_va) { 272 return (abi_ulong)-1; 273 } 274 275 /* Note that start and size have already been aligned by mmap_find_vma. */ 276 277 end_addr = start + size; 278 if (start > reserved_va - size) { 279 /* Start at the top of the address space. */ 280 end_addr = ((reserved_va - size) & -align) + size; 281 looped = true; 282 } 283 284 /* Search downward from END_ADDR, checking to see if a page is in use. */ 285 addr = end_addr; 286 while (1) { 287 addr -= incr; 288 if (addr > end_addr) { 289 if (looped) { 290 /* Failure. The entire address space has been searched. */ 291 return (abi_ulong)-1; 292 } 293 /* Re-start at the top of the address space. */ 294 addr = end_addr = ((reserved_va - size) & -align) + size; 295 looped = true; 296 } else { 297 prot = page_get_flags(addr); 298 if (prot) { 299 /* Page in use. Restart below this page. */ 300 addr = end_addr = ((addr - size) & -align) + size; 301 } else if (addr && addr + size == end_addr) { 302 /* Success! All pages between ADDR and END_ADDR are free. */ 303 if (start == mmap_next_start) { 304 mmap_next_start = addr; 305 } 306 return addr; 307 } 308 } 309 } 310 } 311 312 /* 313 * Find and reserve a free memory area of size 'size'. The search 314 * starts at 'start'. 315 * It must be called with mmap_lock() held. 316 * Return -1 if error. 317 */ 318 abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong align) 319 { 320 void *ptr, *prev; 321 abi_ulong addr; 322 int wrapped, repeat; 323 324 align = MAX(align, qemu_host_page_size); 325 326 /* If 'start' == 0, then a default start address is used. */ 327 if (start == 0) { 328 start = mmap_next_start; 329 } else { 330 start &= qemu_host_page_mask; 331 } 332 start = ROUND_UP(start, align); 333 334 size = HOST_PAGE_ALIGN(size); 335 336 if (reserved_va) { 337 return mmap_find_vma_reserved(start, size, align); 338 } 339 340 addr = start; 341 wrapped = repeat = 0; 342 prev = 0; 343 344 for (;; prev = ptr) { 345 /* 346 * Reserve needed memory area to avoid a race. 347 * It should be discarded using: 348 * - mmap() with MAP_FIXED flag 349 * - mremap() with MREMAP_FIXED flag 350 * - shmat() with SHM_REMAP flag 351 */ 352 ptr = mmap(g2h_untagged(addr), size, PROT_NONE, 353 MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); 354 355 /* ENOMEM, if host address space has no memory */ 356 if (ptr == MAP_FAILED) { 357 return (abi_ulong)-1; 358 } 359 360 /* Count the number of sequential returns of the same address. 361 This is used to modify the search algorithm below. */ 362 repeat = (ptr == prev ? repeat + 1 : 0); 363 364 if (h2g_valid(ptr + size - 1)) { 365 addr = h2g(ptr); 366 367 if ((addr & (align - 1)) == 0) { 368 /* Success. */ 369 if (start == mmap_next_start && addr >= TASK_UNMAPPED_BASE) { 370 mmap_next_start = addr + size; 371 } 372 return addr; 373 } 374 375 /* The address is not properly aligned for the target. */ 376 switch (repeat) { 377 case 0: 378 /* Assume the result that the kernel gave us is the 379 first with enough free space, so start again at the 380 next higher target page. */ 381 addr = ROUND_UP(addr, align); 382 break; 383 case 1: 384 /* Sometimes the kernel decides to perform the allocation 385 at the top end of memory instead. */ 386 addr &= -align; 387 break; 388 case 2: 389 /* Start over at low memory. */ 390 addr = 0; 391 break; 392 default: 393 /* Fail. This unaligned block must the last. */ 394 addr = -1; 395 break; 396 } 397 } else { 398 /* Since the result the kernel gave didn't fit, start 399 again at low memory. If any repetition, fail. */ 400 addr = (repeat ? -1 : 0); 401 } 402 403 /* Unmap and try again. */ 404 munmap(ptr, size); 405 406 /* ENOMEM if we checked the whole of the target address space. */ 407 if (addr == (abi_ulong)-1) { 408 return (abi_ulong)-1; 409 } else if (addr == 0) { 410 if (wrapped) { 411 return (abi_ulong)-1; 412 } 413 wrapped = 1; 414 /* Don't actually use 0 when wrapping, instead indicate 415 that we'd truly like an allocation in low memory. */ 416 addr = (mmap_min_addr > TARGET_PAGE_SIZE 417 ? TARGET_PAGE_ALIGN(mmap_min_addr) 418 : TARGET_PAGE_SIZE); 419 } else if (wrapped && addr >= start) { 420 return (abi_ulong)-1; 421 } 422 } 423 } 424 425 /* NOTE: all the constants are the HOST ones */ 426 abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot, 427 int flags, int fd, abi_ulong offset) 428 { 429 abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len; 430 int page_flags, host_prot; 431 432 mmap_lock(); 433 trace_target_mmap(start, len, target_prot, flags, fd, offset); 434 435 if (!len) { 436 errno = EINVAL; 437 goto fail; 438 } 439 440 page_flags = validate_prot_to_pageflags(&host_prot, target_prot); 441 if (!page_flags) { 442 errno = EINVAL; 443 goto fail; 444 } 445 446 /* Also check for overflows... */ 447 len = TARGET_PAGE_ALIGN(len); 448 if (!len) { 449 errno = ENOMEM; 450 goto fail; 451 } 452 453 if (offset & ~TARGET_PAGE_MASK) { 454 errno = EINVAL; 455 goto fail; 456 } 457 458 /* 459 * If we're mapping shared memory, ensure we generate code for parallel 460 * execution and flush old translations. This will work up to the level 461 * supported by the host -- anything that requires EXCP_ATOMIC will not 462 * be atomic with respect to an external process. 463 */ 464 if (flags & MAP_SHARED) { 465 CPUState *cpu = thread_cpu; 466 if (!(cpu->tcg_cflags & CF_PARALLEL)) { 467 cpu->tcg_cflags |= CF_PARALLEL; 468 tb_flush(cpu); 469 } 470 } 471 472 real_start = start & qemu_host_page_mask; 473 host_offset = offset & qemu_host_page_mask; 474 475 /* If the user is asking for the kernel to find a location, do that 476 before we truncate the length for mapping files below. */ 477 if (!(flags & MAP_FIXED)) { 478 host_len = len + offset - host_offset; 479 host_len = HOST_PAGE_ALIGN(host_len); 480 start = mmap_find_vma(real_start, host_len, TARGET_PAGE_SIZE); 481 if (start == (abi_ulong)-1) { 482 errno = ENOMEM; 483 goto fail; 484 } 485 } 486 487 /* When mapping files into a memory area larger than the file, accesses 488 to pages beyond the file size will cause a SIGBUS. 489 490 For example, if mmaping a file of 100 bytes on a host with 4K pages 491 emulating a target with 8K pages, the target expects to be able to 492 access the first 8K. But the host will trap us on any access beyond 493 4K. 494 495 When emulating a target with a larger page-size than the hosts, we 496 may need to truncate file maps at EOF and add extra anonymous pages 497 up to the targets page boundary. */ 498 499 if ((qemu_real_host_page_size() < qemu_host_page_size) && 500 !(flags & MAP_ANONYMOUS)) { 501 struct stat sb; 502 503 if (fstat (fd, &sb) == -1) 504 goto fail; 505 506 /* Are we trying to create a map beyond EOF?. */ 507 if (offset + len > sb.st_size) { 508 /* If so, truncate the file map at eof aligned with 509 the hosts real pagesize. Additional anonymous maps 510 will be created beyond EOF. */ 511 len = REAL_HOST_PAGE_ALIGN(sb.st_size - offset); 512 } 513 } 514 515 if (!(flags & MAP_FIXED)) { 516 unsigned long host_start; 517 void *p; 518 519 host_len = len + offset - host_offset; 520 host_len = HOST_PAGE_ALIGN(host_len); 521 522 /* Note: we prefer to control the mapping address. It is 523 especially important if qemu_host_page_size > 524 qemu_real_host_page_size */ 525 p = mmap(g2h_untagged(start), host_len, host_prot, 526 flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0); 527 if (p == MAP_FAILED) { 528 goto fail; 529 } 530 /* update start so that it points to the file position at 'offset' */ 531 host_start = (unsigned long)p; 532 if (!(flags & MAP_ANONYMOUS)) { 533 p = mmap(g2h_untagged(start), len, host_prot, 534 flags | MAP_FIXED, fd, host_offset); 535 if (p == MAP_FAILED) { 536 munmap(g2h_untagged(start), host_len); 537 goto fail; 538 } 539 host_start += offset - host_offset; 540 } 541 start = h2g(host_start); 542 } else { 543 if (start & ~TARGET_PAGE_MASK) { 544 errno = EINVAL; 545 goto fail; 546 } 547 end = start + len; 548 real_end = HOST_PAGE_ALIGN(end); 549 550 /* 551 * Test if requested memory area fits target address space 552 * It can fail only on 64-bit host with 32-bit target. 553 * On any other target/host host mmap() handles this error correctly. 554 */ 555 if (end < start || !guest_range_valid_untagged(start, len)) { 556 errno = ENOMEM; 557 goto fail; 558 } 559 560 /* worst case: we cannot map the file because the offset is not 561 aligned, so we read it */ 562 if (!(flags & MAP_ANONYMOUS) && 563 (offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) { 564 /* msync() won't work here, so we return an error if write is 565 possible while it is a shared mapping */ 566 if ((flags & MAP_TYPE) == MAP_SHARED && 567 (host_prot & PROT_WRITE)) { 568 errno = EINVAL; 569 goto fail; 570 } 571 retaddr = target_mmap(start, len, target_prot | PROT_WRITE, 572 MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, 573 -1, 0); 574 if (retaddr == -1) 575 goto fail; 576 if (pread(fd, g2h_untagged(start), len, offset) == -1) 577 goto fail; 578 if (!(host_prot & PROT_WRITE)) { 579 ret = target_mprotect(start, len, target_prot); 580 assert(ret == 0); 581 } 582 goto the_end; 583 } 584 585 /* handle the start of the mapping */ 586 if (start > real_start) { 587 if (real_end == real_start + qemu_host_page_size) { 588 /* one single host page */ 589 ret = mmap_frag(real_start, start, end, 590 host_prot, flags, fd, offset); 591 if (ret == -1) 592 goto fail; 593 goto the_end1; 594 } 595 ret = mmap_frag(real_start, start, real_start + qemu_host_page_size, 596 host_prot, flags, fd, offset); 597 if (ret == -1) 598 goto fail; 599 real_start += qemu_host_page_size; 600 } 601 /* handle the end of the mapping */ 602 if (end < real_end) { 603 ret = mmap_frag(real_end - qemu_host_page_size, 604 real_end - qemu_host_page_size, end, 605 host_prot, flags, fd, 606 offset + real_end - qemu_host_page_size - start); 607 if (ret == -1) 608 goto fail; 609 real_end -= qemu_host_page_size; 610 } 611 612 /* map the middle (easier) */ 613 if (real_start < real_end) { 614 void *p; 615 unsigned long offset1; 616 if (flags & MAP_ANONYMOUS) 617 offset1 = 0; 618 else 619 offset1 = offset + real_start - start; 620 p = mmap(g2h_untagged(real_start), real_end - real_start, 621 host_prot, flags, fd, offset1); 622 if (p == MAP_FAILED) 623 goto fail; 624 } 625 } 626 the_end1: 627 if (flags & MAP_ANONYMOUS) { 628 page_flags |= PAGE_ANON; 629 } 630 page_flags |= PAGE_RESET; 631 page_set_flags(start, start + len, page_flags); 632 the_end: 633 trace_target_mmap_complete(start); 634 if (qemu_loglevel_mask(CPU_LOG_PAGE)) { 635 FILE *f = qemu_log_trylock(); 636 if (f) { 637 fprintf(f, "page layout changed following mmap\n"); 638 page_dump(f); 639 qemu_log_unlock(f); 640 } 641 } 642 tb_invalidate_phys_range(start, start + len); 643 mmap_unlock(); 644 return start; 645 fail: 646 mmap_unlock(); 647 return -1; 648 } 649 650 static void mmap_reserve(abi_ulong start, abi_ulong size) 651 { 652 abi_ulong real_start; 653 abi_ulong real_end; 654 abi_ulong addr; 655 abi_ulong end; 656 int prot; 657 658 real_start = start & qemu_host_page_mask; 659 real_end = HOST_PAGE_ALIGN(start + size); 660 end = start + size; 661 if (start > real_start) { 662 /* handle host page containing start */ 663 prot = 0; 664 for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) { 665 prot |= page_get_flags(addr); 666 } 667 if (real_end == real_start + qemu_host_page_size) { 668 for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) { 669 prot |= page_get_flags(addr); 670 } 671 end = real_end; 672 } 673 if (prot != 0) 674 real_start += qemu_host_page_size; 675 } 676 if (end < real_end) { 677 prot = 0; 678 for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) { 679 prot |= page_get_flags(addr); 680 } 681 if (prot != 0) 682 real_end -= qemu_host_page_size; 683 } 684 if (real_start != real_end) { 685 mmap(g2h_untagged(real_start), real_end - real_start, PROT_NONE, 686 MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, 687 -1, 0); 688 } 689 } 690 691 int target_munmap(abi_ulong start, abi_ulong len) 692 { 693 abi_ulong end, real_start, real_end, addr; 694 int prot, ret; 695 696 trace_target_munmap(start, len); 697 698 if (start & ~TARGET_PAGE_MASK) 699 return -TARGET_EINVAL; 700 len = TARGET_PAGE_ALIGN(len); 701 if (len == 0 || !guest_range_valid_untagged(start, len)) { 702 return -TARGET_EINVAL; 703 } 704 705 mmap_lock(); 706 end = start + len; 707 real_start = start & qemu_host_page_mask; 708 real_end = HOST_PAGE_ALIGN(end); 709 710 if (start > real_start) { 711 /* handle host page containing start */ 712 prot = 0; 713 for(addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) { 714 prot |= page_get_flags(addr); 715 } 716 if (real_end == real_start + qemu_host_page_size) { 717 for(addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) { 718 prot |= page_get_flags(addr); 719 } 720 end = real_end; 721 } 722 if (prot != 0) 723 real_start += qemu_host_page_size; 724 } 725 if (end < real_end) { 726 prot = 0; 727 for(addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) { 728 prot |= page_get_flags(addr); 729 } 730 if (prot != 0) 731 real_end -= qemu_host_page_size; 732 } 733 734 ret = 0; 735 /* unmap what we can */ 736 if (real_start < real_end) { 737 if (reserved_va) { 738 mmap_reserve(real_start, real_end - real_start); 739 } else { 740 ret = munmap(g2h_untagged(real_start), real_end - real_start); 741 } 742 } 743 744 if (ret == 0) { 745 page_set_flags(start, start + len, 0); 746 tb_invalidate_phys_range(start, start + len); 747 } 748 mmap_unlock(); 749 return ret; 750 } 751 752 abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, 753 abi_ulong new_size, unsigned long flags, 754 abi_ulong new_addr) 755 { 756 int prot; 757 void *host_addr; 758 759 if (!guest_range_valid_untagged(old_addr, old_size) || 760 ((flags & MREMAP_FIXED) && 761 !guest_range_valid_untagged(new_addr, new_size)) || 762 ((flags & MREMAP_MAYMOVE) == 0 && 763 !guest_range_valid_untagged(old_addr, new_size))) { 764 errno = ENOMEM; 765 return -1; 766 } 767 768 mmap_lock(); 769 770 if (flags & MREMAP_FIXED) { 771 host_addr = mremap(g2h_untagged(old_addr), old_size, new_size, 772 flags, g2h_untagged(new_addr)); 773 774 if (reserved_va && host_addr != MAP_FAILED) { 775 /* If new and old addresses overlap then the above mremap will 776 already have failed with EINVAL. */ 777 mmap_reserve(old_addr, old_size); 778 } 779 } else if (flags & MREMAP_MAYMOVE) { 780 abi_ulong mmap_start; 781 782 mmap_start = mmap_find_vma(0, new_size, TARGET_PAGE_SIZE); 783 784 if (mmap_start == -1) { 785 errno = ENOMEM; 786 host_addr = MAP_FAILED; 787 } else { 788 host_addr = mremap(g2h_untagged(old_addr), old_size, new_size, 789 flags | MREMAP_FIXED, 790 g2h_untagged(mmap_start)); 791 if (reserved_va) { 792 mmap_reserve(old_addr, old_size); 793 } 794 } 795 } else { 796 int prot = 0; 797 if (reserved_va && old_size < new_size) { 798 abi_ulong addr; 799 for (addr = old_addr + old_size; 800 addr < old_addr + new_size; 801 addr++) { 802 prot |= page_get_flags(addr); 803 } 804 } 805 if (prot == 0) { 806 host_addr = mremap(g2h_untagged(old_addr), 807 old_size, new_size, flags); 808 809 if (host_addr != MAP_FAILED) { 810 /* Check if address fits target address space */ 811 if (!guest_range_valid_untagged(h2g(host_addr), new_size)) { 812 /* Revert mremap() changes */ 813 host_addr = mremap(g2h_untagged(old_addr), 814 new_size, old_size, flags); 815 errno = ENOMEM; 816 host_addr = MAP_FAILED; 817 } else if (reserved_va && old_size > new_size) { 818 mmap_reserve(old_addr + old_size, old_size - new_size); 819 } 820 } 821 } else { 822 errno = ENOMEM; 823 host_addr = MAP_FAILED; 824 } 825 } 826 827 if (host_addr == MAP_FAILED) { 828 new_addr = -1; 829 } else { 830 new_addr = h2g(host_addr); 831 prot = page_get_flags(old_addr); 832 page_set_flags(old_addr, old_addr + old_size, 0); 833 page_set_flags(new_addr, new_addr + new_size, 834 prot | PAGE_VALID | PAGE_RESET); 835 } 836 tb_invalidate_phys_range(new_addr, new_addr + new_size); 837 mmap_unlock(); 838 return new_addr; 839 } 840 841 static bool can_passthrough_madv_dontneed(abi_ulong start, abi_ulong end) 842 { 843 ulong addr; 844 845 if ((start | end) & ~qemu_host_page_mask) { 846 return false; 847 } 848 849 for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { 850 if (!(page_get_flags(addr) & PAGE_ANON)) { 851 return false; 852 } 853 } 854 855 return true; 856 } 857 858 abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice) 859 { 860 abi_ulong len, end; 861 int ret = 0; 862 863 if (start & ~TARGET_PAGE_MASK) { 864 return -TARGET_EINVAL; 865 } 866 len = TARGET_PAGE_ALIGN(len_in); 867 868 if (len_in && !len) { 869 return -TARGET_EINVAL; 870 } 871 872 end = start + len; 873 if (end < start) { 874 return -TARGET_EINVAL; 875 } 876 877 if (end == start) { 878 return 0; 879 } 880 881 if (!guest_range_valid_untagged(start, len)) { 882 return -TARGET_EINVAL; 883 } 884 885 /* 886 * A straight passthrough may not be safe because qemu sometimes turns 887 * private file-backed mappings into anonymous mappings. 888 * 889 * This is a hint, so ignoring and returning success is ok. 890 * 891 * This breaks MADV_DONTNEED, completely implementing which is quite 892 * complicated. However, there is one low-hanging fruit: host-page-aligned 893 * anonymous mappings. In this case passthrough is safe, so do it. 894 */ 895 mmap_lock(); 896 if (advice == MADV_DONTNEED && 897 can_passthrough_madv_dontneed(start, end)) { 898 ret = get_errno(madvise(g2h_untagged(start), len, MADV_DONTNEED)); 899 if (ret == 0) { 900 page_reset_target_data(start, start + len); 901 } 902 } 903 mmap_unlock(); 904 905 return ret; 906 } 907