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