[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] linux-user: Correct mapping of last page for file m
From: |
Edgar E. Iglesias |
Subject: |
[Qemu-devel] [PATCH] linux-user: Correct mapping of last page for file mmaps. |
Date: |
Thu, 29 Jan 2009 00:03:54 +0100 |
User-agent: |
Mutt/1.5.16 (2007-06-09) |
Hello
I've had this patch in the CRIS tree for a while. Without it, CRIS
linux-user is quite unstable in particular when emulating dynamically
linked programs.
/* 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. */
Does anyone have ideas on better ways to solve this issue?
Or objections to the patch?
Thanks
Handle last page for file mmaps when the hosts page size is smaller than
the emulated page size.
Signed-off-by: Edgar E. Iglesias <address@hidden>
Index: linux-user/mmap.c
===================================================================
--- linux-user/mmap.c (revision 6469)
+++ linux-user/mmap.c (working copy)
@@ -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;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] linux-user: Correct mapping of last page for file mmaps.,
Edgar E. Iglesias <=