From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MbVT8-0006Rh-N5 for qemu-devel@nongnu.org; Thu, 13 Aug 2009 04:15:30 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MbVT7-0006Qn-7m for qemu-devel@nongnu.org; Thu, 13 Aug 2009 04:15:29 -0400 Received: from [199.232.76.173] (port=41768 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MbVT7-0006Qk-4X for qemu-devel@nongnu.org; Thu, 13 Aug 2009 04:15:29 -0400 Received: from dd21438.kasserver.com ([85.13.141.110]:56994) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MbVT6-0003OO-Bb for qemu-devel@nongnu.org; Thu, 13 Aug 2009 04:15:28 -0400 Message-ID: <4A83CB9C.4050408@opensuse.org> Date: Thu, 13 Aug 2009 10:15:24 +0200 From: Martin Mohring MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------050501090906030000020208" Subject: [Qemu-devel] [PATCH 1/1] Rewrite mmap_find_vma() to work fine on 64-bit hosts with 32-bit targets List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: "Kirill A. Shutemov" , Riku Voipio , Aurelien Jarno This is a multi-part message in MIME format. --------------050501090906030000020208 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Hi, quite some time ago this patch had been sent by Kirill to the QEMU ml. At that time, the patch was rejected. Now we found out why the current user mode memory allocator sometimes fails: - Kernel Bug linux/fs/proc/task_mmu.c (fixed after 2.6.27) http://bugzilla.kernel.org/attachment.cgi?id=17219 - use of proc file system to find memory mappings => bad idea So I please apply the attached patch from Kirill to qemu to fix this longstanding bug, because it causes all older linux distros (using kernel 2.6.26 or older) to fail the QEMU memory allocator in user mode. Cheers, Martin --------------050501090906030000020208 Content-Type: text/x-patch; name="0019-Rewrite-mmap_find_vma-to-work-fine-on-64-bit-hosts.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename*0="0019-Rewrite-mmap_find_vma-to-work-fine-on-64-bit-hosts.patc"; filename*1="h" >>From c77c088e30c44fc8677d7d95cb2180d8dfb43b1c Mon Sep 17 00:00:00 2001 From: Kirill A. Shutemov Date: Wed, 17 Jun 2009 15:14:43 +0200 Subject: [PATCH 19/33] Rewrite mmap_find_vma() to work fine on 64-bit hosts with 32-bit targets From: Kirill A. Shutemov 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. From: Kirill A. Shutemov Signed-off-by: Kirill A. Shutemov Signed-off-by: Riku Voipio --- linux-user/mmap.c | 79 +++++++++++++++++++++++++++++------------------------ 1 files changed, 43 insertions(+), 36 deletions(-) diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 9ca8f6f..8d94783 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -277,52 +277,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. */ +/* + * 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); } #define SNDRV_PCM_MMAP_OFFSET_STATUS 0x80000000 -- 1.6.2.1 --------------050501090906030000020208--