qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] target_mmap and host vs target page sizes.
@ 2007-09-30  1:18 Edgar E. Iglesias
  2007-09-30  7:27 ` Blue Swirl
  0 siblings, 1 reply; 7+ messages in thread
From: Edgar E. Iglesias @ 2007-09-30  1:18 UTC (permalink / raw)
  To: qemu-devel

Hello,

I have cleaned up the mmap patch that corrects the alignment for un-fixed mappings when the target page-size is larger than the hosts.

The error was found and the patch tested with the CRIS target port (not yet contributed) on a x86 host running GCC's c-torture tests for CRIS. Without the patch, randomly every other test case fails to load.

I tried the sparc64-linux-user target but it fails to run any of my programs both with and without the change. Similarly, the m68k-linux-user target also fails but it at least manages to load and start executing before hitting an illegal insn. For the m68k I could verify that it also randomly fails to load programs. With the patch, it always manages to load the elf files at least. Additionally I tested the mips target after changing the page size to 8K, it also randomly fails to load programs but works fine with the patch (thanks for suggesting this test Thiemo).

If you see any issues with the change or if you feel I need to test something else, I'll be happy to fix or do that. Otherwise, I'd appreciate it if this went in.

Thanks
-- 
Edgar E. Iglesias
Axis Communications AB

Index: mmap.c
===================================================================
RCS file: /sources/qemu/qemu/linux-user/mmap.c,v
retrieving revision 1.15
diff -u -p -r1.15 mmap.c
--- mmap.c	27 Sep 2007 04:10:43 -0000	1.15
+++ mmap.c	30 Sep 2007 01:06:46 -0000
@@ -209,30 +209,45 @@ long target_mmap(target_ulong start, tar
             last_start += HOST_PAGE_ALIGN(len);
         }
 #endif
-        if (0 && qemu_host_page_size != qemu_real_host_page_size) {
-            /* NOTE: this code is only for debugging with '-p' option */
-            /* ??? Can also occur when TARGET_PAGE_SIZE > host page size.  */
-            /* reserve a memory area */
-            /* ??? This needs fixing for remapping.  */
-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);
-            if (real_start == -1)
-                return real_start;
-            real_end = real_start + host_len;
-            start = HOST_PAGE_ALIGN(real_start);
-            end = start + HOST_PAGE_ALIGN(len);
-            if (start > real_start)
-                munmap((void *)g2h(real_start), start - real_start);
-            if (end < real_end)
-                munmap((void *)g2h(end), real_end - end);
-            /* use it as a fixed mapping */
-            flags |= MAP_FIXED;
+        host_offset = offset & qemu_host_page_mask;
+        host_len = len + offset - host_offset;
+
+        if (qemu_host_page_size > qemu_real_host_page_size) {
+	    /*
+	     * The guest expects to see mmapped areas aligned to it's pagesize.
+	     * If the hosts real page size is smaller than the guests, we need 
+	     * to fixup the maps. It is done by allocating a larger area, 
+	     * displacing the map (if needed) and finally choping off the spare
+	     * room at the edges.
+	     */
+
+	    /* 
+	     * We assume qemu_host_page_size is always the same as 
+	     * TARGET_PAGE_SIZE, see exec.c. qemu_real_host_page_size is the
+	     * hosts real page size. 
+	     */
+            target_ulong host_end;
+
+            host_len = HOST_PAGE_ALIGN(host_len + qemu_host_page_size
+                                       - qemu_real_host_page_size); 
+            host_start = (long)mmap(real_start ? g2h(real_start) : NULL,
+                                    host_len, prot, flags, fd, host_offset);
+            if (host_start == -1)
+                return host_start;
+            host_end = host_start + host_len;
+
+            /* Find start and end, aligned to the targets pagesize with-in the
+               large mmaped area.  */
+            start = TARGET_PAGE_ALIGN(host_start);
+            end = start + TARGET_PAGE_ALIGN(len);
+            /* Chop off the leftovers, if any.  */
+            if (start > host_start)
+                munmap((void *)g2h(host_start), start - host_start);
+            if (end < host_end)
+                munmap((void *)g2h(end), host_end - end);
+	    goto the_end1;
         } else {
             /* if not fixed, no need to do anything */
-            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);
             if (host_start == -1)

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

end of thread, other threads:[~2007-09-30 16:20 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-30  1:18 [Qemu-devel] target_mmap and host vs target page sizes Edgar E. Iglesias
2007-09-30  7:27 ` Blue Swirl
2007-09-30  9:53   ` Edgar E. Iglesias
2007-09-30 11:47     ` Edgar E. Iglesias
2007-09-30 15:45       ` Blue Swirl
2007-09-30 16:05         ` Edgar E. Iglesias
2007-09-30 16:20           ` Blue Swirl

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).