From patchwork Mon Aug 10 13:52:55 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Jan-Simon_M=C3=B6ller?= X-Patchwork-Id: 31079 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by bilbo.ozlabs.org (Postfix) with ESMTPS id 3CDADB6EDE for ; Mon, 10 Aug 2009 23:55:50 +1000 (EST) Received: from localhost ([127.0.0.1]:33651 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MaVLm-0005fq-VI for incoming@patchwork.ozlabs.org; Mon, 10 Aug 2009 09:55:47 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MaVJN-0004OS-UV for qemu-devel@nongnu.org; Mon, 10 Aug 2009 09:53:18 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MaVJH-0004Nd-Ex for qemu-devel@nongnu.org; Mon, 10 Aug 2009 09:53:16 -0400 Received: from [199.232.76.173] (port=54895 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MaVJH-0004NX-6X for qemu-devel@nongnu.org; Mon, 10 Aug 2009 09:53:11 -0400 Received: from mail.gmx.net ([213.165.64.20]:33041) by monty-python.gnu.org with smtp (Exim 4.60) (envelope-from ) id 1MaVJG-0004Xu-Ck for qemu-devel@nongnu.org; Mon, 10 Aug 2009 09:53:10 -0400 Received: (qmail invoked by alias); 10 Aug 2009 13:53:08 -0000 Received: from ip180156.wh.uni-hannover.de (EHLO ip180156.wh.uni-hannover.de) [130.75.180.156] by mail.gmx.net (mp048) with SMTP; 10 Aug 2009 15:53:08 +0200 X-Authenticated: #7313500 X-Provags-ID: V01U2FsdGVkX1/t4hEN8yXtHthMlxJ5bKO9aEyaXRbjatbivuFbJZ 7nZ67KD3jHRtKB From: "Jan-Simon =?utf-8?q?M=C3=B6ller?=" To: "Kirill A. Shutemov" Subject: Re: [Qemu-devel] qemu-arm fails on test-mmap - take #2 Date: Mon, 10 Aug 2009 15:52:55 +0200 User-Agent: KMail/1.9.9 References: <200908100145.52476.dl9pf@gmx.de> In-Reply-To: MIME-Version: 1.0 Message-Id: <200908101552.55755.dl9pf@gmx.de> X-Y-GMX-Trusted: 0 X-FuHaFi: 0.55 X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 3) Cc: riku.voipio@iki.fi, qemu-devel@nongnu.org X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Am Montag 10 August 2009 08:33:38 schrieb Kirill A. Shutemov: > > Now my question is: how is the data of the already blocked pages > > processed/aquired ? It seems to me that the pages get "lost" somewhere. > > Current mmap() implementation requires /proc to obtain all mappings. > > I have alternative implementation of mmap_find_vma() which doesn't > require /proc: > > http://www.archivum.info/qemu-devel@nongnu.org/2008-10/01118/%5BQemu-devel% >5D_%5BPATCH,_v2%5D_Rewrite_mmap_find_vma%28%29_to_work_fine_on_64-bit_hosts_ >with_32-bit_targets > > It is probably out of date. This does the trick ! I've attached a version against trunk. @Riku: can we apply this to git ? Acked-by: Jan-Simon Möller Original post: http://www.archivum.info/qemu-devel%40nongnu.org/2008-10/01118/[Qemu-devel]_[PATCH,_v2]_Rewrite_mmap_find_vma()_to_work_fine_on_64-bit_hosts_with_32-bit_targets Attachement: Patch rebased to trunk. Best, Jan-Simon diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 6f300a0..8cec230 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -275,52 +275,59 @@ 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. */ -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 */