From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Ib817-0003L1-Tk for qemu-devel@nongnu.org; Fri, 28 Sep 2007 01:03:57 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Ib817-0003K7-4p for qemu-devel@nongnu.org; Fri, 28 Sep 2007 01:03:57 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ib816-0003Je-GY for qemu-devel@nongnu.org; Fri, 28 Sep 2007 01:03:56 -0400 Received: from owa.c2.net ([207.235.78.2] helo=email.c2.net) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Ib816-0007XP-3G for qemu-devel@nongnu.org; Fri, 28 Sep 2007 01:03:56 -0400 From: Thayne Harbaugh Content-Type: multipart/mixed; boundary="=-Ugs0jN1xFJPddFvZVeo3" Date: Thu, 27 Sep 2007 22:56:48 -0600 Message-Id: <1190955408.5128.67.camel@phantasm.home.enterpriseandprosperity.com> Mime-Version: 1.0 Subject: [Qemu-devel] linux-user mmap() for 32-bit guest on 64-bit host Reply-To: thayne@c2.net, qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel --=-Ugs0jN1xFJPddFvZVeo3 Content-Type: text/plain Content-Transfer-Encoding: 7bit I've been using the patch posted by Kirill Shutemov (http://www.mail-archive.com/qemu-devel@nongnu.org/msg10893.html) for forcing mmap() addresses on 64-bit hosts to be 32-bit clean. I just discovered a minor problem with the patch: MAP_32BIT is not a valid flag to mremap() and will cause mremap() to be rejected by the kernel with EINVAL. I've investigated the kernel and it doesn't preserve the flags from the original mmap() call. Essentially do_mremap() in the kernel calls get_unmapped_area() with the only possible flag being MAP_SHARED. The attached patch fixes qemu so that mremap() won't get rejected for having an illegal flag, but it might cause havoc for allocating a >32-bit address. A possible patch for the kernel is also included (and untested). --=-Ugs0jN1xFJPddFvZVeo3 Content-Disposition: attachment; filename=38_mmap_32bit.patch Content-Type: text/x-patch; name=38_mmap_32bit.patch; charset=UTF-8 Content-Transfer-Encoding: 7bit Index: qemu/linux-user/mmap.c =================================================================== --- qemu.orig/linux-user/mmap.c 2007-09-27 10:32:45.000000000 -0600 +++ qemu/linux-user/mmap.c 2007-09-27 22:36:39.000000000 -0600 @@ -27,6 +27,10 @@ #include "qemu.h" +#if !defined(MAP_32BIT) +#define MAP_32BIT 0 +#endif + //#define DEBUG_MMAP /* NOTE: all the constants are the HOST ones, but addresses are target. */ @@ -116,7 +120,7 @@ if (prot1 == 0) { /* no page was there, so we allocate one */ ret = (long)mmap(host_start, qemu_host_page_size, prot, - flags | MAP_ANONYMOUS, -1, 0); + flags | MAP_ANONYMOUS | MAP_32BIT, -1, 0); if (ret == -1) return ret; prot1 = prot; @@ -217,7 +221,8 @@ abort(); host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE; real_start = (long)mmap(g2h(real_start), host_len, PROT_NONE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, + -1, 0); if (real_start == -1) return real_start; real_end = real_start + host_len; @@ -234,7 +239,7 @@ host_offset = offset & qemu_host_page_mask; host_len = len + offset - host_offset; host_start = (long)mmap(real_start ? g2h(real_start) : NULL, - host_len, prot, flags, fd, host_offset); + host_len, prot, flags | MAP_32BIT, fd, host_offset); if (host_start == -1) return host_start; /* update start so that it points to the file position at 'offset' */ @@ -312,7 +317,7 @@ else offset1 = offset + real_start - start; ret = (long)mmap(g2h(real_start), real_end - real_start, - prot, flags, fd, offset1); + prot, flags | MAP_32BIT, fd, offset1); if (ret == -1) return ret; } --=-Ugs0jN1xFJPddFvZVeo3 Content-Disposition: attachment; filename=linux-mremap_map_32bit.patch Content-Type: text/x-patch; name=linux-mremap_map_32bit.patch; charset=UTF-8 Content-Transfer-Encoding: 7bit --- linux-source-2.6.22/mm/mremap.c.orig 2007-09-27 23:02:13.000000000 -0600 +++ linux-source-2.6.22/mm/mremap.c 2007-09-27 23:07:29.000000000 -0600 @@ -23,6 +23,10 @@ #include #include +#ifndef MAP_32BIT +#define MAP_32BIT 0 +#endif + static pmd_t *get_old_pmd(struct mm_struct *mm, unsigned long addr) { pgd_t *pgd; @@ -255,7 +259,7 @@ unsigned long ret = -EINVAL; unsigned long charged = 0; - if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE)) + if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE | MAP_32BIT)) goto out; if (addr & ~PAGE_MASK) @@ -388,6 +392,9 @@ if (vma->vm_flags & VM_MAYSHARE) map_flags |= MAP_SHARED; + if (flags & MAP_32BIT) + map_flags |= MAP_32BIT; + new_addr = get_unmapped_area(vma->vm_file, 0, new_len, vma->vm_pgoff, map_flags); ret = new_addr; --=-Ugs0jN1xFJPddFvZVeo3--