[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] Rewrite mmap_find_vma() to work fine on 64-bit host
From: |
Kirill A. Shutemov |
Subject: |
[Qemu-devel] [PATCH] Rewrite mmap_find_vma() to work fine on 64-bit hosts with 32-bit targets |
Date: |
Wed, 3 Dec 2008 13:29:42 +0200 |
qemu's page table can be incomple if /proc/self/maps is unavailable or
host allocating a memory with mmap(), so we can't use it to find free
memory area.
New version mmap_find_vma() uses mmap() without MAP_FIXED to find free
memory.
Signed-off-by: Kirill A. Shutemov <address@hidden>
---
linux-user/mmap.c | 81 ++++++++++++++++++++++++++++------------------------
1 files changed, 44 insertions(+), 37 deletions(-)
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index d5f22b8..d96917d 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -255,52 +255,59 @@ static abi_ulong mmap_next_start = 0x40000000;
unsigned long last_brk;
-/* find a free memory area of size 'size'. The search starts at
- 'start'. If 'start' == 0, then a default start address is used.
- Return -1 if error.
-*/
-/* page_init() marks pages used by the host as reserved to be sure not
- to use them. */
-static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
+/*
+ * Find and reserve a free memory area of size 'size'. The search
+ * starts at 'start'.
+ * 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 addr, addr1, addr_start;
- int prot;
- unsigned long new_brk;
-
- new_brk = (unsigned long)sbrk(0);
- if (last_brk && last_brk < new_brk && last_brk == (target_ulong)last_brk) {
- /* This is a hack to catch the host allocating memory with brk().
- If it uses mmap then we loose.
- FIXME: We really want to avoid the host allocating memory in
- the first place, and maybe leave some slack to avoid switching
- to mmap. */
- page_set_flags(last_brk & TARGET_PAGE_MASK,
- TARGET_PAGE_ALIGN(new_brk),
- PAGE_RESERVED);
- }
- last_brk = new_brk;
+ void *ptr;
+ abi_ulong addr;
size = HOST_PAGE_ALIGN(size);
- start = start & qemu_host_page_mask;
+ start &= qemu_host_page_mask;
+
+ /* If 'start' == 0, then a default start address is used. */
+ if (start == 0)
+ start = mmap_next_start;
+
addr = start;
- if (addr == 0)
- addr = mmap_next_start;
- addr_start = addr;
+
for(;;) {
- prot = 0;
- for(addr1 = addr; addr1 < (addr + size); addr1 += TARGET_PAGE_SIZE) {
- prot |= page_get_flags(addr1);
- }
- if (prot == 0)
+ /*
+ * Reserve needed memory area to avoid a race.
+ * It should be discarded using:
+ * - mmap() with MAP_FIXED flag
+ * - mremap() with MREMAP_FIXED flag
+ * - shmat() with SHM_REMAP flag
+ */
+ ptr = mmap((void *)(unsigned long)addr, size, PROT_NONE,
+ MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
+
+ /* ENOMEM, if host address space has no memory */
+ if (ptr == MAP_FAILED)
+ return (abi_ulong)-1;
+
+ /* If address fits target address space we've found what we need */
+ if ((unsigned long)ptr + size - 1 <= (abi_ulong)-1)
break;
+
+ /* Unmap and try again with new page */
+ munmap(ptr, size);
addr += qemu_host_page_size;
- /* we found nothing */
- if (addr == addr_start)
+
+ /* ENOMEM if we check whole of target address space */
+ if (addr == start)
return (abi_ulong)-1;
}
- if (start == 0)
- mmap_next_start = addr + size;
- return addr;
+
+ /* Update default start address */
+ if (start == mmap_next_start)
+ mmap_next_start = (unsigned long)ptr + size;
+
+ return h2g(ptr);
}
/* NOTE: all the constants are the HOST ones */
--
1.6.0.2.GIT
- [Qemu-devel] [PATCH] Introduce --enable-binfmt-misc configure option, Kirill A. Shutemov, 2008/12/03
- [Qemu-devel] [PATCH] Fix fstatat64()/newfstatat() syscall implementation, Kirill A. Shutemov, 2008/12/03
- [Qemu-devel] [PATCH] Move abi_* typedefs into qemu-types.h, Kirill A. Shutemov, 2008/12/03
- [Qemu-devel] [PATCH] linux-user: Safety belt for h2g, Kirill A. Shutemov, 2008/12/03
- [Qemu-devel] [PATCH] linux-user: Introduce h2g_valid, Kirill A. Shutemov, 2008/12/03
- [Qemu-devel] [PATCH] linux-user: Fix h2g usage in page_find_alloc, Kirill A. Shutemov, 2008/12/03
- [Qemu-devel] [PATCH] Rewrite mmap_find_vma() to work fine on 64-bit hosts with 32-bit targets,
Kirill A. Shutemov <=
- [Qemu-devel] [PATCH] mmap: add check if requested memory area fits target address space, Kirill A. Shutemov, 2008/12/03
- [Qemu-devel] [PATCH] mremap(): handle MREMAP_FIXED and MREMAP_MAYMOVE correctly, Kirill A. Shutemov, 2008/12/03
- [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling, Kirill A. Shutemov, 2008/12/03
- [Qemu-devel] [PATCH] Implement sem* syscalls, Kirill A. Shutemov, 2008/12/03
- [Qemu-devel] [PATCH] Fix and cleanup IPCOP_shm* ipc calls handling, Kirill A. Shutemov, 2008/12/03
- [Qemu-devel] [PATCH] Implement shm* syscalls, Kirill A. Shutemov, 2008/12/03
- [Qemu-devel] [PATCH] shmat(): use mmap_find_vma to find free memory area, Kirill A. Shutemov, 2008/12/03
- Re: [Qemu-devel] [PATCH] mremap(): handle MREMAP_FIXED and MREMAP_MAYMOVE correctly, Edgar E. Iglesias, 2008/12/06
- Re: [Qemu-devel] [PATCH] mremap(): handle MREMAP_FIXED and MREMAP_MAYMOVE correctly, Kirill A. Shutemov, 2008/12/06
- Re: [Qemu-devel] [PATCH] mremap(): handle MREMAP_FIXED and MREMAP_MAYMOVE correctly, Aurelien Jarno, 2008/12/08