qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] another 64/32 mmap() bug


From: Vince Weaver
Subject: Re: [Qemu-devel] another 64/32 mmap() bug
Date: Sun, 28 Sep 2008 15:11:20 -0400 (EDT)

Hello

So I've tracked down this problem. The linux-user mmap() code does not check to see if an allocation crosses the 2^32 barrier, which is a problem for emulating 32-bit code on a 64-bit machine.

The attached patch is a hack that fixes this problem, and also the related mremap() problem. These definitely aren't meant to be committed. Hoepfully someone who understands the linux-user mmap() code better than I do can take a look at things.

With the patch though, I can finally run correctly all 48 of Spec2k on sparc32-linux-user on x86_64, and I can run all but 5 of Spec2k6.

Patch below, hoepfully pine doesn't mess it up this time.

Vince

Index: linux-user/mmap.c
===================================================================
--- linux-user/mmap.c   (revision 5321)
+++ linux-user/mmap.c   (working copy)
@@ -353,16 +353,27 @@
         host_offset = offset & qemu_host_page_mask;
         host_len = len + offset - host_offset;
         host_len = HOST_PAGE_ALIGN(host_len);
+try_again:
         mmap_start = mmap_find_vma(real_start, host_len);
         if (mmap_start == (abi_ulong)-1) {
             errno = ENOMEM;
             goto fail;
         }
+
+#if TARGET_ABI_BITS == 32 + /* vmw */
+        if ( (long)g2h(mmap_start)+host_len > 0xffff0000) {
+          printf("WARNING! Host len too high: 0x%x + 
0x%x\n",mmap_start,host_len);
+          goto try_again;
+        }
+#endif +
         /* Note: we prefer to control the mapping address. It is
            especially important if qemu_host_page_size >
-           qemu_real_host_page_size */
+           qemu_real_host_page_size */
         p = mmap(g2h(mmap_start),
                  host_len, prot, flags | MAP_FIXED, fd, host_offset);
+
         if (p == MAP_FAILED)
             goto fail;
         /* update start so that it points to the file position at 'offset' */
@@ -538,6 +549,25 @@
     mmap_lock();
     /* XXX: use 5 args syscall */
     host_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags);
+#if TARGET_ABI_BITS == 32
+    if (host_addr > 0xffffffff) {
+       void *temp_addr;
+ + temp_addr = mmap(NULL,new_size,
+                       
PROT_READ|PROT_WRITE,MAP_ANONYMOUS|MAP_PRIVATE|MAP_32BIT, 0, 0);
+       memcpy(temp_addr,(void *)host_addr,old_size);
+ munmap((void *)host_addr,new_size); + host_addr=(long)temp_addr;
+
+ + if (host_addr > 0xffffffff) { + + printf("ERROR! mremap() returned 64-bit value on 32-bit target!\n\n"); + exit(-1); + }
+    }
+#endif +
     if (host_addr == -1) {
         new_addr = -1;
     } else {




reply via email to

[Prev in Thread] Current Thread [Next in Thread]