qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [6510] Partialy fix mmap at EOF for large pagesize targets in user-mode.
@ 2009-02-03 23:06 Edgar E. Iglesias
  2009-02-04 20:17 ` Lionel Landwerlin
  0 siblings, 1 reply; 2+ messages in thread
From: Edgar E. Iglesias @ 2009-02-03 23:06 UTC (permalink / raw)
  To: qemu-devel

Revision: 6510
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6510
Author:   edgar_igl
Date:     2009-02-03 23:06:34 +0000 (Tue, 03 Feb 2009)

Log Message:
-----------
Partialy fix mmap at EOF for large pagesize targets in user-mode.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>

Modified Paths:
--------------
    trunk/linux-user/mmap.c

Modified: trunk/linux-user/mmap.c
===================================================================
--- trunk/linux-user/mmap.c	2009-02-03 22:45:00 UTC (rev 6509)
+++ trunk/linux-user/mmap.c	2009-02-03 23:06:34 UTC (rev 6510)
@@ -24,6 +24,8 @@
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/mman.h>
 #include <linux/mman.h>
 #include <linux/unistd.h>
@@ -366,6 +368,36 @@
         goto the_end;
     real_start = start & qemu_host_page_mask;
 
+    /* When mapping files into a memory area larger than the file, accesses
+       to pages beyond the file size will cause a SIGBUS. 
+
+       For example, if mmaping a file of 100 bytes on a host with 4K pages
+       emulating a target with 8K pages, the target expects to be able to
+       access the first 8K. But the host will trap us on any access beyond
+       4K.  
+
+       When emulating a target with a larger page-size than the hosts, we
+       may need to truncate file maps at EOF and add extra anonymous pages
+       up to the targets page boundary.  */
+
+    if ((qemu_real_host_page_size < TARGET_PAGE_SIZE)
+        && !(flags & MAP_ANONYMOUS)) {
+       struct stat sb;
+
+       if (fstat (fd, &sb) == -1)
+           goto fail;
+
+       /* Are we trying to create a map beyond EOF?.  */
+       if (offset + len > sb.st_size) {
+           /* If so, truncate the file map at eof aligned with 
+              the hosts real pagesize. Additional anonymous maps
+              will be created beyond EOF.  */
+           len = (sb.st_size - offset);
+           len += qemu_real_host_page_size - 1;
+           len &= ~(qemu_real_host_page_size - 1);
+       }
+    }
+
     if (!(flags & MAP_FIXED)) {
         abi_ulong mmap_start;
         void *p;
@@ -381,13 +413,16 @@
            especially important if qemu_host_page_size >
            qemu_real_host_page_size */
         p = mmap(g2h(mmap_start),
-                 host_len, prot, flags | MAP_FIXED, fd, host_offset);
+                 host_len, prot, flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
         if (p == MAP_FAILED)
             goto fail;
         /* update start so that it points to the file position at 'offset' */
         host_start = (unsigned long)p;
-        if (!(flags & MAP_ANONYMOUS))
+        if (!(flags & MAP_ANONYMOUS)) {
+            p = mmap(g2h(mmap_start), len, prot, 
+                     flags | MAP_FIXED, fd, host_offset);
             host_start += offset - host_offset;
+        }
         start = h2g(host_start);
     } else {
         int flg;

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Qemu-devel] [6510] Partialy fix mmap at EOF for large pagesize targets in user-mode.
  2009-02-03 23:06 [Qemu-devel] [6510] Partialy fix mmap at EOF for large pagesize targets in user-mode Edgar E. Iglesias
@ 2009-02-04 20:17 ` Lionel Landwerlin
  0 siblings, 0 replies; 2+ messages in thread
From: Lionel Landwerlin @ 2009-02-04 20:17 UTC (permalink / raw)
  To: qemu-devel

Le mardi 03 février 2009 à 23:06 +0000, Edgar E. Iglesias a écrit :
> Revision: 6510
>           http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6510
> Author:   edgar_igl
> Date:     2009-02-03 23:06:34 +0000 (Tue, 03 Feb 2009)
> 
> Log Message:
> -----------
> Partialy fix mmap at EOF for large pagesize targets in user-mode.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> 
> Modified Paths:
> --------------
>     trunk/linux-user/mmap.c
> 
> Modified: trunk/linux-user/mmap.c
> ===================================================================
> --- trunk/linux-user/mmap.c	2009-02-03 22:45:00 UTC (rev 6509)
> +++ trunk/linux-user/mmap.c	2009-02-03 23:06:34 UTC (rev 6510)
> @@ -24,6 +24,8 @@
>  #include <string.h>
>  #include <unistd.h>
>  #include <errno.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
>  #include <sys/mman.h>
>  #include <linux/mman.h>
>  #include <linux/unistd.h>
> @@ -366,6 +368,36 @@
>          goto the_end;
>      real_start = start & qemu_host_page_mask;
>  
> +    /* When mapping files into a memory area larger than the file, accesses
> +       to pages beyond the file size will cause a SIGBUS. 
> +
> +       For example, if mmaping a file of 100 bytes on a host with 4K pages
> +       emulating a target with 8K pages, the target expects to be able to
> +       access the first 8K. But the host will trap us on any access beyond
> +       4K.  
> +
> +       When emulating a target with a larger page-size than the hosts, we
> +       may need to truncate file maps at EOF and add extra anonymous pages
> +       up to the targets page boundary.  */
> +
> +    if ((qemu_real_host_page_size < TARGET_PAGE_SIZE)
> +        && !(flags & MAP_ANONYMOUS)) {
> +       struct stat sb;
> +
> +       if (fstat (fd, &sb) == -1)
> +           goto fail;
> +
> +       /* Are we trying to create a map beyond EOF?.  */
> +       if (offset + len > sb.st_size) {
> +           /* If so, truncate the file map at eof aligned with 
> +              the hosts real pagesize. Additional anonymous maps
> +              will be created beyond EOF.  */
> +           len = (sb.st_size - offset);
> +           len += qemu_real_host_page_size - 1;
> +           len &= ~(qemu_real_host_page_size - 1);
> +       }
> +    }
> +
>      if (!(flags & MAP_FIXED)) {
>          abi_ulong mmap_start;
>          void *p;
> @@ -381,13 +413,16 @@
>             especially important if qemu_host_page_size >
>             qemu_real_host_page_size */
>          p = mmap(g2h(mmap_start),
> -                 host_len, prot, flags | MAP_FIXED, fd, host_offset);
> +                 host_len, prot, flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
>          if (p == MAP_FAILED)
>              goto fail;
>          /* update start so that it points to the file position at 'offset' */
>          host_start = (unsigned long)p;
> -        if (!(flags & MAP_ANONYMOUS))
> +        if (!(flags & MAP_ANONYMOUS)) {
> +            p = mmap(g2h(mmap_start), len, prot, 
> +                     flags | MAP_FIXED, fd, host_offset);
>              host_start += offset - host_offset;
> +        }
>          start = h2g(host_start);
>      } else {
>          int flg;
> 

We also need to check when mmap_start pointer is inside the code
generation buffer.

-- 
Lione Landwerlin                                         

O p e n W i d e                    14, rue Gaillon 75002 Paris

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-02-04 20:17 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-03 23:06 [Qemu-devel] [6510] Partialy fix mmap at EOF for large pagesize targets in user-mode Edgar E. Iglesias
2009-02-04 20:17 ` Lionel Landwerlin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).