diff mbox

[2/7] QEMU does not currently support host pages that are larger than guest pages, likely due to glibc using fixed mmap requests.

Message ID 1841580212.1359461.1466295316691.JavaMail.zimbra@raptorengineeringinc.com
State New
Headers show

Commit Message

Timothy Pearson June 19, 2016, 12:15 a.m. UTC
Attempting to use host pages larger than the guest leads to
alignment errors during ELF load in the best case, and an
initialization failure inside NPTL in the worst case, causing
all fork() requests inside the guest to fail.

Warn when thread space cannot be set up, and suggest reducing
host page size if applicable.

Signed-off-by: Timothy Pearson <tpearson@raptorengineering.com>
---
 linux-user/syscall.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

Comments

Eric Blake June 20, 2016, 4:39 p.m. UTC | #1
On 06/18/2016 06:15 PM, Timothy Pearson wrote:
> Attempting to use host pages larger than the guest leads to
> alignment errors during ELF load in the best case, and an
> initialization failure inside NPTL in the worst case, causing
> all fork() requests inside the guest to fail.

Long subject line.  Try to keep subject lines in the form:

topic: short description

with at most 65 characters (reading 'git shortlog' adds indentation and
commit ids, and you still want the lines to be legible in an 80-column
window).

Improperly threaded; this showed up as its own top-level message instead
of in-reply-to the 0/7 cover letter.
diff mbox

Patch

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1c17b74..2968b57 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5482,8 +5482,13 @@  static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
             /* Wait for the child to initialize.  */
             pthread_cond_wait(&info.cond, &info.mutex);
             ret = info.tid;
-            if (flags & CLONE_PARENT_SETTID)
-                put_user_u32(ret, parent_tidptr);
+            if (flags & CLONE_PARENT_SETTID) {
+                if (put_user_u32(ret, parent_tidptr)) {
+                    fprintf(stderr, "do_fork: put_user_u32() failed, child process state invalid\n");
+                    if (qemu_real_host_page_size > TARGET_PAGE_SIZE)
+                        fprintf(stderr, "do_fork: host page size > target page size; reduce host page size and try again\n");
+                }
+            }
         } else {
             ret = -1;
         }
@@ -5514,10 +5519,20 @@  static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
                (not implemented) or having *_tidptr to point at a shared memory
                mapping.  We can't repeat the spinlock hack used above because
                the child process gets its own copy of the lock.  */
-            if (flags & CLONE_CHILD_SETTID)
-                put_user_u32(gettid(), child_tidptr);
-            if (flags & CLONE_PARENT_SETTID)
-                put_user_u32(gettid(), parent_tidptr);
+            if (flags & CLONE_CHILD_SETTID) {
+                if (put_user_u32(gettid(), child_tidptr)) {
+                    fprintf(stderr, "do_fork: put_user_u32() failed, child process state invalid\n");
+                    if (qemu_real_host_page_size > TARGET_PAGE_SIZE)
+                        fprintf(stderr, "do_fork: host page size > target page size; reduce host page size and try again\n");
+                }
+            }
+            if (flags & CLONE_PARENT_SETTID) {
+                if (put_user_u32(gettid(), parent_tidptr)) {
+                    fprintf(stderr, "do_fork: put_user_u32() failed, child process state invalid\n");
+                    if (qemu_real_host_page_size > TARGET_PAGE_SIZE)
+                        fprintf(stderr, "do_fork: host page size > target page size; reduce host page size and try again\n");
+                }
+            }
             ts = (TaskState *)cpu->opaque;
             if (flags & CLONE_SETTLS)
                 cpu_set_tls (env, newtls);