1 /* 2 * os-posix-lib.c 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * Copyright (c) 2010 Red Hat, Inc. 6 * 7 * QEMU library functions on POSIX which are shared between QEMU and 8 * the QEMU tools. 9 * 10 * Permission is hereby granted, free of charge, to any person obtaining a copy 11 * of this software and associated documentation files (the "Software"), to deal 12 * in the Software without restriction, including without limitation the rights 13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 * copies of the Software, and to permit persons to whom the Software is 15 * furnished to do so, subject to the following conditions: 16 * 17 * The above copyright notice and this permission notice shall be included in 18 * all copies or substantial portions of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 * THE SOFTWARE. 27 */ 28 29 #include "qemu/osdep.h" 30 #include <termios.h> 31 32 #include <glib/gprintf.h> 33 34 #include "sysemu/sysemu.h" 35 #include "trace.h" 36 #include "qapi/error.h" 37 #include "qemu/error-report.h" 38 #include "qemu/madvise.h" 39 #include "qemu/sockets.h" 40 #include "qemu/thread.h" 41 #include <libgen.h> 42 #include "qemu/cutils.h" 43 #include "qemu/units.h" 44 #include "qemu/thread-context.h" 45 46 #ifdef CONFIG_LINUX 47 #include <sys/syscall.h> 48 #endif 49 50 #ifdef __FreeBSD__ 51 #include <sys/thr.h> 52 #include <sys/user.h> 53 #include <libutil.h> 54 #endif 55 56 #ifdef __NetBSD__ 57 #include <lwp.h> 58 #endif 59 60 #include "qemu/mmap-alloc.h" 61 62 #define MAX_MEM_PREALLOC_THREAD_COUNT 16 63 64 struct MemsetThread; 65 66 typedef struct MemsetContext { 67 bool all_threads_created; 68 bool any_thread_failed; 69 struct MemsetThread *threads; 70 int num_threads; 71 } MemsetContext; 72 73 struct MemsetThread { 74 char *addr; 75 size_t numpages; 76 size_t hpagesize; 77 QemuThread pgthread; 78 sigjmp_buf env; 79 MemsetContext *context; 80 }; 81 typedef struct MemsetThread MemsetThread; 82 83 /* used by sigbus_handler() */ 84 static MemsetContext *sigbus_memset_context; 85 struct sigaction sigbus_oldact; 86 static QemuMutex sigbus_mutex; 87 88 static QemuMutex page_mutex; 89 static QemuCond page_cond; 90 91 int qemu_get_thread_id(void) 92 { 93 #if defined(__linux__) 94 return syscall(SYS_gettid); 95 #elif defined(__FreeBSD__) 96 /* thread id is up to INT_MAX */ 97 long tid; 98 thr_self(&tid); 99 return (int)tid; 100 #elif defined(__NetBSD__) 101 return _lwp_self(); 102 #elif defined(__OpenBSD__) 103 return getthrid(); 104 #else 105 return getpid(); 106 #endif 107 } 108 109 int qemu_daemon(int nochdir, int noclose) 110 { 111 return daemon(nochdir, noclose); 112 } 113 114 bool qemu_write_pidfile(const char *path, Error **errp) 115 { 116 int fd; 117 char pidstr[32]; 118 119 while (1) { 120 struct stat a, b; 121 struct flock lock = { 122 .l_type = F_WRLCK, 123 .l_whence = SEEK_SET, 124 .l_len = 0, 125 }; 126 127 fd = qemu_create(path, O_WRONLY, S_IRUSR | S_IWUSR, errp); 128 if (fd == -1) { 129 return false; 130 } 131 132 if (fstat(fd, &b) < 0) { 133 error_setg_errno(errp, errno, "Cannot stat file"); 134 goto fail_close; 135 } 136 137 if (fcntl(fd, F_SETLK, &lock)) { 138 error_setg_errno(errp, errno, "Cannot lock pid file"); 139 goto fail_close; 140 } 141 142 /* 143 * Now make sure the path we locked is the same one that now 144 * exists on the filesystem. 145 */ 146 if (stat(path, &a) < 0) { 147 /* 148 * PID file disappeared, someone else must be racing with 149 * us, so try again. 150 */ 151 close(fd); 152 continue; 153 } 154 155 if (a.st_ino == b.st_ino) { 156 break; 157 } 158 159 /* 160 * PID file was recreated, someone else must be racing with 161 * us, so try again. 162 */ 163 close(fd); 164 } 165 166 if (ftruncate(fd, 0) < 0) { 167 error_setg_errno(errp, errno, "Failed to truncate pid file"); 168 goto fail_unlink; 169 } 170 171 snprintf(pidstr, sizeof(pidstr), FMT_pid "\n", getpid()); 172 if (qemu_write_full(fd, pidstr, strlen(pidstr)) != strlen(pidstr)) { 173 error_setg(errp, "Failed to write pid file"); 174 goto fail_unlink; 175 } 176 177 return true; 178 179 fail_unlink: 180 unlink(path); 181 fail_close: 182 close(fd); 183 return false; 184 } 185 186 /* alloc shared memory pages */ 187 void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment, bool shared, 188 bool noreserve) 189 { 190 const uint32_t qemu_map_flags = (shared ? QEMU_MAP_SHARED : 0) | 191 (noreserve ? QEMU_MAP_NORESERVE : 0); 192 size_t align = QEMU_VMALLOC_ALIGN; 193 void *ptr = qemu_ram_mmap(-1, size, align, qemu_map_flags, 0); 194 195 if (ptr == MAP_FAILED) { 196 return NULL; 197 } 198 199 if (alignment) { 200 *alignment = align; 201 } 202 203 trace_qemu_anon_ram_alloc(size, ptr); 204 return ptr; 205 } 206 207 void qemu_anon_ram_free(void *ptr, size_t size) 208 { 209 trace_qemu_anon_ram_free(ptr, size); 210 qemu_ram_munmap(-1, ptr, size); 211 } 212 213 void qemu_socket_set_block(int fd) 214 { 215 g_unix_set_fd_nonblocking(fd, false, NULL); 216 } 217 218 int qemu_socket_try_set_nonblock(int fd) 219 { 220 return g_unix_set_fd_nonblocking(fd, true, NULL) ? 0 : -errno; 221 } 222 223 void qemu_socket_set_nonblock(int fd) 224 { 225 int f; 226 f = qemu_socket_try_set_nonblock(fd); 227 assert(f == 0); 228 } 229 230 int socket_set_fast_reuse(int fd) 231 { 232 int val = 1, ret; 233 234 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 235 (const char *)&val, sizeof(val)); 236 237 assert(ret == 0); 238 239 return ret; 240 } 241 242 void qemu_set_cloexec(int fd) 243 { 244 int f; 245 f = fcntl(fd, F_GETFD); 246 assert(f != -1); 247 f = fcntl(fd, F_SETFD, f | FD_CLOEXEC); 248 assert(f != -1); 249 } 250 251 int qemu_socketpair(int domain, int type, int protocol, int sv[2]) 252 { 253 int ret; 254 255 #ifdef SOCK_CLOEXEC 256 ret = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv); 257 if (ret != -1 || errno != EINVAL) { 258 return ret; 259 } 260 #endif 261 ret = socketpair(domain, type, protocol, sv);; 262 if (ret == 0) { 263 qemu_set_cloexec(sv[0]); 264 qemu_set_cloexec(sv[1]); 265 } 266 267 return ret; 268 } 269 270 char * 271 qemu_get_local_state_dir(void) 272 { 273 return get_relocated_path(CONFIG_QEMU_LOCALSTATEDIR); 274 } 275 276 void qemu_set_tty_echo(int fd, bool echo) 277 { 278 struct termios tty; 279 280 tcgetattr(fd, &tty); 281 282 if (echo) { 283 tty.c_lflag |= ECHO | ECHONL | ICANON | IEXTEN; 284 } else { 285 tty.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN); 286 } 287 288 tcsetattr(fd, TCSANOW, &tty); 289 } 290 291 #ifdef CONFIG_LINUX 292 static void sigbus_handler(int signal, siginfo_t *siginfo, void *ctx) 293 #else /* CONFIG_LINUX */ 294 static void sigbus_handler(int signal) 295 #endif /* CONFIG_LINUX */ 296 { 297 int i; 298 299 if (sigbus_memset_context) { 300 for (i = 0; i < sigbus_memset_context->num_threads; i++) { 301 MemsetThread *thread = &sigbus_memset_context->threads[i]; 302 303 if (qemu_thread_is_self(&thread->pgthread)) { 304 siglongjmp(thread->env, 1); 305 } 306 } 307 } 308 309 #ifdef CONFIG_LINUX 310 /* 311 * We assume that the MCE SIGBUS handler could have been registered. We 312 * should never receive BUS_MCEERR_AO on any of our threads, but only on 313 * the main thread registered for PR_MCE_KILL_EARLY. Further, we should not 314 * receive BUS_MCEERR_AR triggered by action of other threads on one of 315 * our threads. So, no need to check for unrelated SIGBUS when seeing one 316 * for our threads. 317 * 318 * We will forward to the MCE handler, which will either handle the SIGBUS 319 * or reinstall the default SIGBUS handler and reraise the SIGBUS. The 320 * default SIGBUS handler will crash the process, so we don't care. 321 */ 322 if (sigbus_oldact.sa_flags & SA_SIGINFO) { 323 sigbus_oldact.sa_sigaction(signal, siginfo, ctx); 324 return; 325 } 326 #endif /* CONFIG_LINUX */ 327 warn_report("qemu_prealloc_mem: unrelated SIGBUS detected and ignored"); 328 } 329 330 static void *do_touch_pages(void *arg) 331 { 332 MemsetThread *memset_args = (MemsetThread *)arg; 333 sigset_t set, oldset; 334 int ret = 0; 335 336 /* 337 * On Linux, the page faults from the loop below can cause mmap_sem 338 * contention with allocation of the thread stacks. Do not start 339 * clearing until all threads have been created. 340 */ 341 qemu_mutex_lock(&page_mutex); 342 while (!memset_args->context->all_threads_created) { 343 qemu_cond_wait(&page_cond, &page_mutex); 344 } 345 qemu_mutex_unlock(&page_mutex); 346 347 /* unblock SIGBUS */ 348 sigemptyset(&set); 349 sigaddset(&set, SIGBUS); 350 pthread_sigmask(SIG_UNBLOCK, &set, &oldset); 351 352 if (sigsetjmp(memset_args->env, 1)) { 353 ret = -EFAULT; 354 } else { 355 char *addr = memset_args->addr; 356 size_t numpages = memset_args->numpages; 357 size_t hpagesize = memset_args->hpagesize; 358 size_t i; 359 for (i = 0; i < numpages; i++) { 360 /* 361 * Read & write back the same value, so we don't 362 * corrupt existing user/app data that might be 363 * stored. 364 * 365 * 'volatile' to stop compiler optimizing this away 366 * to a no-op 367 */ 368 *(volatile char *)addr = *addr; 369 addr += hpagesize; 370 } 371 } 372 pthread_sigmask(SIG_SETMASK, &oldset, NULL); 373 return (void *)(uintptr_t)ret; 374 } 375 376 static void *do_madv_populate_write_pages(void *arg) 377 { 378 MemsetThread *memset_args = (MemsetThread *)arg; 379 const size_t size = memset_args->numpages * memset_args->hpagesize; 380 char * const addr = memset_args->addr; 381 int ret = 0; 382 383 /* See do_touch_pages(). */ 384 qemu_mutex_lock(&page_mutex); 385 while (!memset_args->context->all_threads_created) { 386 qemu_cond_wait(&page_cond, &page_mutex); 387 } 388 qemu_mutex_unlock(&page_mutex); 389 390 if (size && qemu_madvise(addr, size, QEMU_MADV_POPULATE_WRITE)) { 391 ret = -errno; 392 } 393 return (void *)(uintptr_t)ret; 394 } 395 396 static inline int get_memset_num_threads(size_t hpagesize, size_t numpages, 397 int max_threads) 398 { 399 long host_procs = sysconf(_SC_NPROCESSORS_ONLN); 400 int ret = 1; 401 402 if (host_procs > 0) { 403 ret = MIN(MIN(host_procs, MAX_MEM_PREALLOC_THREAD_COUNT), max_threads); 404 } 405 406 /* Especially with gigantic pages, don't create more threads than pages. */ 407 ret = MIN(ret, numpages); 408 /* Don't start threads to prealloc comparatively little memory. */ 409 ret = MIN(ret, MAX(1, hpagesize * numpages / (64 * MiB))); 410 411 /* In case sysconf() fails, we fall back to single threaded */ 412 return ret; 413 } 414 415 static int touch_all_pages(char *area, size_t hpagesize, size_t numpages, 416 int max_threads, ThreadContext *tc, 417 bool use_madv_populate_write) 418 { 419 static gsize initialized = 0; 420 MemsetContext context = { 421 .num_threads = get_memset_num_threads(hpagesize, numpages, max_threads), 422 }; 423 size_t numpages_per_thread, leftover; 424 void *(*touch_fn)(void *); 425 int ret = 0, i = 0; 426 char *addr = area; 427 428 if (g_once_init_enter(&initialized)) { 429 qemu_mutex_init(&page_mutex); 430 qemu_cond_init(&page_cond); 431 g_once_init_leave(&initialized, 1); 432 } 433 434 if (use_madv_populate_write) { 435 /* Avoid creating a single thread for MADV_POPULATE_WRITE */ 436 if (context.num_threads == 1) { 437 if (qemu_madvise(area, hpagesize * numpages, 438 QEMU_MADV_POPULATE_WRITE)) { 439 return -errno; 440 } 441 return 0; 442 } 443 touch_fn = do_madv_populate_write_pages; 444 } else { 445 touch_fn = do_touch_pages; 446 } 447 448 context.threads = g_new0(MemsetThread, context.num_threads); 449 numpages_per_thread = numpages / context.num_threads; 450 leftover = numpages % context.num_threads; 451 for (i = 0; i < context.num_threads; i++) { 452 context.threads[i].addr = addr; 453 context.threads[i].numpages = numpages_per_thread + (i < leftover); 454 context.threads[i].hpagesize = hpagesize; 455 context.threads[i].context = &context; 456 if (tc) { 457 thread_context_create_thread(tc, &context.threads[i].pgthread, 458 "touch_pages", 459 touch_fn, &context.threads[i], 460 QEMU_THREAD_JOINABLE); 461 } else { 462 qemu_thread_create(&context.threads[i].pgthread, "touch_pages", 463 touch_fn, &context.threads[i], 464 QEMU_THREAD_JOINABLE); 465 } 466 addr += context.threads[i].numpages * hpagesize; 467 } 468 469 if (!use_madv_populate_write) { 470 sigbus_memset_context = &context; 471 } 472 473 qemu_mutex_lock(&page_mutex); 474 context.all_threads_created = true; 475 qemu_cond_broadcast(&page_cond); 476 qemu_mutex_unlock(&page_mutex); 477 478 for (i = 0; i < context.num_threads; i++) { 479 int tmp = (uintptr_t)qemu_thread_join(&context.threads[i].pgthread); 480 481 if (tmp) { 482 ret = tmp; 483 } 484 } 485 486 if (!use_madv_populate_write) { 487 sigbus_memset_context = NULL; 488 } 489 g_free(context.threads); 490 491 return ret; 492 } 493 494 static bool madv_populate_write_possible(char *area, size_t pagesize) 495 { 496 return !qemu_madvise(area, pagesize, QEMU_MADV_POPULATE_WRITE) || 497 errno != EINVAL; 498 } 499 500 void qemu_prealloc_mem(int fd, char *area, size_t sz, int max_threads, 501 ThreadContext *tc, Error **errp) 502 { 503 static gsize initialized; 504 int ret; 505 size_t hpagesize = qemu_fd_getpagesize(fd); 506 size_t numpages = DIV_ROUND_UP(sz, hpagesize); 507 bool use_madv_populate_write; 508 struct sigaction act; 509 510 /* 511 * Sense on every invocation, as MADV_POPULATE_WRITE cannot be used for 512 * some special mappings, such as mapping /dev/mem. 513 */ 514 use_madv_populate_write = madv_populate_write_possible(area, hpagesize); 515 516 if (!use_madv_populate_write) { 517 if (g_once_init_enter(&initialized)) { 518 qemu_mutex_init(&sigbus_mutex); 519 g_once_init_leave(&initialized, 1); 520 } 521 522 qemu_mutex_lock(&sigbus_mutex); 523 memset(&act, 0, sizeof(act)); 524 #ifdef CONFIG_LINUX 525 act.sa_sigaction = &sigbus_handler; 526 act.sa_flags = SA_SIGINFO; 527 #else /* CONFIG_LINUX */ 528 act.sa_handler = &sigbus_handler; 529 act.sa_flags = 0; 530 #endif /* CONFIG_LINUX */ 531 532 ret = sigaction(SIGBUS, &act, &sigbus_oldact); 533 if (ret) { 534 qemu_mutex_unlock(&sigbus_mutex); 535 error_setg_errno(errp, errno, 536 "qemu_prealloc_mem: failed to install signal handler"); 537 return; 538 } 539 } 540 541 /* touch pages simultaneously */ 542 ret = touch_all_pages(area, hpagesize, numpages, max_threads, tc, 543 use_madv_populate_write); 544 if (ret) { 545 error_setg_errno(errp, -ret, 546 "qemu_prealloc_mem: preallocating memory failed"); 547 } 548 549 if (!use_madv_populate_write) { 550 ret = sigaction(SIGBUS, &sigbus_oldact, NULL); 551 if (ret) { 552 /* Terminate QEMU since it can't recover from error */ 553 perror("qemu_prealloc_mem: failed to reinstall signal handler"); 554 exit(1); 555 } 556 qemu_mutex_unlock(&sigbus_mutex); 557 } 558 } 559 560 char *qemu_get_pid_name(pid_t pid) 561 { 562 char *name = NULL; 563 564 #if defined(__FreeBSD__) 565 /* BSDs don't have /proc, but they provide a nice substitute */ 566 struct kinfo_proc *proc = kinfo_getproc(pid); 567 568 if (proc) { 569 name = g_strdup(proc->ki_comm); 570 free(proc); 571 } 572 #else 573 /* Assume a system with reasonable procfs */ 574 char *pid_path; 575 size_t len; 576 577 pid_path = g_strdup_printf("/proc/%d/cmdline", pid); 578 g_file_get_contents(pid_path, &name, &len, NULL); 579 g_free(pid_path); 580 #endif 581 582 return name; 583 } 584 585 586 void *qemu_alloc_stack(size_t *sz) 587 { 588 void *ptr, *guardpage; 589 int flags; 590 #ifdef CONFIG_DEBUG_STACK_USAGE 591 void *ptr2; 592 #endif 593 size_t pagesz = qemu_real_host_page_size(); 594 #ifdef _SC_THREAD_STACK_MIN 595 /* avoid stacks smaller than _SC_THREAD_STACK_MIN */ 596 long min_stack_sz = sysconf(_SC_THREAD_STACK_MIN); 597 *sz = MAX(MAX(min_stack_sz, 0), *sz); 598 #endif 599 /* adjust stack size to a multiple of the page size */ 600 *sz = ROUND_UP(*sz, pagesz); 601 /* allocate one extra page for the guard page */ 602 *sz += pagesz; 603 604 flags = MAP_PRIVATE | MAP_ANONYMOUS; 605 #if defined(MAP_STACK) && defined(__OpenBSD__) 606 /* Only enable MAP_STACK on OpenBSD. Other OS's such as 607 * Linux/FreeBSD/NetBSD have a flag with the same name 608 * but have differing functionality. OpenBSD will SEGV 609 * if it spots execution with a stack pointer pointing 610 * at memory that was not allocated with MAP_STACK. 611 */ 612 flags |= MAP_STACK; 613 #endif 614 615 ptr = mmap(NULL, *sz, PROT_READ | PROT_WRITE, flags, -1, 0); 616 if (ptr == MAP_FAILED) { 617 perror("failed to allocate memory for stack"); 618 abort(); 619 } 620 621 #if defined(HOST_IA64) 622 /* separate register stack */ 623 guardpage = ptr + (((*sz - pagesz) / 2) & ~pagesz); 624 #elif defined(HOST_HPPA) 625 /* stack grows up */ 626 guardpage = ptr + *sz - pagesz; 627 #else 628 /* stack grows down */ 629 guardpage = ptr; 630 #endif 631 if (mprotect(guardpage, pagesz, PROT_NONE) != 0) { 632 perror("failed to set up stack guard page"); 633 abort(); 634 } 635 636 #ifdef CONFIG_DEBUG_STACK_USAGE 637 for (ptr2 = ptr + pagesz; ptr2 < ptr + *sz; ptr2 += sizeof(uint32_t)) { 638 *(uint32_t *)ptr2 = 0xdeadbeaf; 639 } 640 #endif 641 642 return ptr; 643 } 644 645 #ifdef CONFIG_DEBUG_STACK_USAGE 646 static __thread unsigned int max_stack_usage; 647 #endif 648 649 void qemu_free_stack(void *stack, size_t sz) 650 { 651 #ifdef CONFIG_DEBUG_STACK_USAGE 652 unsigned int usage; 653 void *ptr; 654 655 for (ptr = stack + qemu_real_host_page_size(); ptr < stack + sz; 656 ptr += sizeof(uint32_t)) { 657 if (*(uint32_t *)ptr != 0xdeadbeaf) { 658 break; 659 } 660 } 661 usage = sz - (uintptr_t) (ptr - stack); 662 if (usage > max_stack_usage) { 663 error_report("thread %d max stack usage increased from %u to %u", 664 qemu_get_thread_id(), max_stack_usage, usage); 665 max_stack_usage = usage; 666 } 667 #endif 668 669 munmap(stack, sz); 670 } 671 672 /* 673 * Disable CFI checks. 674 * We are going to call a signal handler directly. Such handler may or may not 675 * have been defined in our binary, so there's no guarantee that the pointer 676 * used to set the handler is a cfi-valid pointer. Since the handlers are 677 * stored in kernel memory, changing the handler to an attacker-defined 678 * function requires being able to call a sigaction() syscall, 679 * which is not as easy as overwriting a pointer in memory. 680 */ 681 QEMU_DISABLE_CFI 682 void sigaction_invoke(struct sigaction *action, 683 struct qemu_signalfd_siginfo *info) 684 { 685 siginfo_t si = {}; 686 si.si_signo = info->ssi_signo; 687 si.si_errno = info->ssi_errno; 688 si.si_code = info->ssi_code; 689 690 /* Convert the minimal set of fields defined by POSIX. 691 * Positive si_code values are reserved for kernel-generated 692 * signals, where the valid siginfo fields are determined by 693 * the signal number. But according to POSIX, it is unspecified 694 * whether SI_USER and SI_QUEUE have values less than or equal to 695 * zero. 696 */ 697 if (info->ssi_code == SI_USER || info->ssi_code == SI_QUEUE || 698 info->ssi_code <= 0) { 699 /* SIGTERM, etc. */ 700 si.si_pid = info->ssi_pid; 701 si.si_uid = info->ssi_uid; 702 } else if (info->ssi_signo == SIGILL || info->ssi_signo == SIGFPE || 703 info->ssi_signo == SIGSEGV || info->ssi_signo == SIGBUS) { 704 si.si_addr = (void *)(uintptr_t)info->ssi_addr; 705 } else if (info->ssi_signo == SIGCHLD) { 706 si.si_pid = info->ssi_pid; 707 si.si_status = info->ssi_status; 708 si.si_uid = info->ssi_uid; 709 } 710 action->sa_sigaction(info->ssi_signo, &si, NULL); 711 } 712 713 size_t qemu_get_host_physmem(void) 714 { 715 #ifdef _SC_PHYS_PAGES 716 long pages = sysconf(_SC_PHYS_PAGES); 717 if (pages > 0) { 718 if (pages > SIZE_MAX / qemu_real_host_page_size()) { 719 return SIZE_MAX; 720 } else { 721 return pages * qemu_real_host_page_size(); 722 } 723 } 724 #endif 725 return 0; 726 } 727 728 int qemu_msync(void *addr, size_t length, int fd) 729 { 730 size_t align_mask = ~(qemu_real_host_page_size() - 1); 731 732 /** 733 * There are no strict reqs as per the length of mapping 734 * to be synced. Still the length needs to follow the address 735 * alignment changes. Additionally - round the size to the multiple 736 * of PAGE_SIZE 737 */ 738 length += ((uintptr_t)addr & (qemu_real_host_page_size() - 1)); 739 length = (length + ~align_mask) & align_mask; 740 741 addr = (void *)((uintptr_t)addr & align_mask); 742 743 return msync(addr, length, MS_SYNC); 744 } 745