diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2019-05-24 12:47:49 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2019-05-24 12:47:49 +0100 |
| commit | a7b21f6762a2d6ec08106d8a7ccb11829914523f (patch) | |
| tree | 7d74340fae502fa6a9d6e5218275d766e50274b9 /linux-user/mmap.c | |
| parent | 40575757e1ef9fa8e34c2320fb56a7dffd92efcc (diff) | |
| parent | 5f992db605e2c9ed0c8816c2b0f68b9bc8698f1b (diff) | |
| download | focaccia-qemu-a7b21f6762a2d6ec08106d8a7ccb11829914523f.tar.gz focaccia-qemu-a7b21f6762a2d6ec08106d8a7ccb11829914523f.zip | |
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-4.1-pull-request' into staging
Add /proc/hardware and /proc/cpuinfo, update SIOCXXX ioctls, fix shmat emulation, add nanoseconds in stat, init field fp_abi on mips # gpg: Signature made Fri 24 May 2019 12:24:36 BST # gpg: using RSA key F30C38BD3F2FBE3C # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full] # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier2/tags/linux-user-for-4.1-pull-request: linux-user: Pass through nanosecond timestamp components for stat syscalls linux-user: Align mmap_find_vma to host page size linux-user: Fix shmat emulation by honoring host SHMLBA linux-user: Sanitize interp_info and, for mips only, init field fp_abi linux-user: Add support for SIOC<G|S>IFPFLAGS ioctls for all targets linux-user: Add support for SIOCSPGRP ioctl for all targets linux-user: Fix support for SIOCATMARK and SIOCGPGRP ioctls for xtensa linux-user: add pseudo /proc/hardware for m68k linux-user: add pseudo /proc/cpuinfo for sparc Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user/mmap.c')
| -rw-r--r-- | linux-user/mmap.c | 72 |
1 files changed, 39 insertions, 33 deletions
diff --git a/linux-user/mmap.c b/linux-user/mmap.c index e0249efe4f..af41339d57 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -202,49 +202,52 @@ unsigned long last_brk; /* Subroutine of mmap_find_vma, used when we have pre-allocated a chunk of guest address space. */ -static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size) +static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size, + abi_ulong align) { - abi_ulong addr; - abi_ulong end_addr; + abi_ulong addr, end_addr, incr = qemu_host_page_size; int prot; - int looped = 0; + bool looped = false; if (size > reserved_va) { return (abi_ulong)-1; } - size = HOST_PAGE_ALIGN(size); + /* Note that start and size have already been aligned by mmap_find_vma. */ + end_addr = start + size; - if (end_addr > reserved_va) { - end_addr = reserved_va; + if (start > reserved_va - size) { + /* Start at the top of the address space. */ + end_addr = ((reserved_va - size) & -align) + size; + looped = true; } - addr = end_addr - qemu_host_page_size; + /* Search downward from END_ADDR, checking to see if a page is in use. */ + addr = end_addr; while (1) { + addr -= incr; if (addr > end_addr) { if (looped) { + /* Failure. The entire address space has been searched. */ return (abi_ulong)-1; } - end_addr = reserved_va; - addr = end_addr - qemu_host_page_size; - looped = 1; - continue; - } - prot = page_get_flags(addr); - if (prot) { - end_addr = addr; - } - if (addr && addr + size == end_addr) { - break; + /* Re-start at the top of the address space. */ + addr = end_addr = ((reserved_va - size) & -align) + size; + looped = true; + } else { + prot = page_get_flags(addr); + if (prot) { + /* Page in use. Restart below this page. */ + addr = end_addr = ((addr - size) & -align) + size; + } else if (addr && addr + size == end_addr) { + /* Success! All pages between ADDR and END_ADDR are free. */ + if (start == mmap_next_start) { + mmap_next_start = addr; + } + return addr; + } } - addr -= qemu_host_page_size; } - - if (start == mmap_next_start) { - mmap_next_start = addr; - } - - return addr; } /* @@ -253,23 +256,26 @@ static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size) * It must be called with mmap_lock() held. * Return -1 if error. */ -abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size) +abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong align) { void *ptr, *prev; abi_ulong addr; int wrapped, repeat; + align = MAX(align, qemu_host_page_size); + /* If 'start' == 0, then a default start address is used. */ if (start == 0) { start = mmap_next_start; } else { start &= qemu_host_page_mask; } + start = ROUND_UP(start, align); size = HOST_PAGE_ALIGN(size); if (reserved_va) { - return mmap_find_vma_reserved(start, size); + return mmap_find_vma_reserved(start, size, align); } addr = start; @@ -299,7 +305,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size) if (h2g_valid(ptr + size - 1)) { addr = h2g(ptr); - if ((addr & ~TARGET_PAGE_MASK) == 0) { + if ((addr & (align - 1)) == 0) { /* Success. */ if (start == mmap_next_start && addr >= TASK_UNMAPPED_BASE) { mmap_next_start = addr + size; @@ -313,12 +319,12 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size) /* Assume the result that the kernel gave us is the first with enough free space, so start again at the next higher target page. */ - addr = TARGET_PAGE_ALIGN(addr); + addr = ROUND_UP(addr, align); break; case 1: /* Sometimes the kernel decides to perform the allocation at the top end of memory instead. */ - addr &= TARGET_PAGE_MASK; + addr &= -align; break; case 2: /* Start over at low memory. */ @@ -416,7 +422,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, if (!(flags & MAP_FIXED)) { host_len = len + offset - host_offset; host_len = HOST_PAGE_ALIGN(host_len); - start = mmap_find_vma(real_start, host_len); + start = mmap_find_vma(real_start, host_len, TARGET_PAGE_SIZE); if (start == (abi_ulong)-1) { errno = ENOMEM; goto fail; @@ -710,7 +716,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, } else if (flags & MREMAP_MAYMOVE) { abi_ulong mmap_start; - mmap_start = mmap_find_vma(0, new_size); + mmap_start = mmap_find_vma(0, new_size, TARGET_PAGE_SIZE); if (mmap_start == -1) { errno = ENOMEM; |