qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH] linux-user sysinfo support & do_sigreturn fix for i


From: François Guimond
Subject: [Qemu-devel] [PATCH] linux-user sysinfo support & do_sigreturn fix for i386-user
Date: Fri, 18 Jun 2004 13:27:37 -0400


Heya folks...

I posted here I think a week or two ago about about deadlocks I had with qemu-i386 hoping one of the qemu developpers would be faster at finding the culprits. Due to lack of feedback I guess my post was simply ignored. Anyway, since then I have successfully found the bug and fixed it, so this post includes the patch for it. Also, in order to get the software I was attempting to run working, I had to implement the sysinfo syscall (previously 'unimplemented') so I figured I'd share that patch here too.

First is the fix to signal handling. When I paid attention to strace's changes in sigprocmask, I realize that masks entering linux-user's signal processing handler would be wrong leaving the handler. Upon further investigation I noticed that the mask was getting written in the sig frame using __put_user but getting restored by simple assignment, so in this case it would result in the wrong value as qemu-i386 was running on a PowerPC with a different endianess than a x86. Looking around in the code I saw the 'generic' do_sigreturn used __get_user properly to retrieve it, so I copied over that bit of code into the x86 do_sigreturn, and it fixed the deadlock problem I was experiencing (which was caused by wrong sigprocmask). Here's the related patch:

Index: linux-user/signal.c
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/signal.c,v
retrieving revision 1.22
diff -u -r1.22 signal.c
--- linux-user/signal.c 22 Feb 2004 13:40:13 -0000      1.22
+++ linux-user/signal.c 18 Jun 2004 17:12:16 -0000
@@ -823,15 +823,17 @@
    struct sigframe *frame = (struct sigframe *)(env->regs[R_ESP] - 8);
    target_sigset_t target_set;
    sigset_t set;
-    int eax, i;
+    int eax;

#if defined(DEBUG_SIGNAL)
    fprintf(stderr, "do_sigreturn\n");
#endif
    /* set blocked signals */
-    target_set.sig[0] = frame->sc.oldmask;
-    for(i = 1; i < TARGET_NSIG_WORDS; i++)
-        target_set.sig[i] = frame->extramask[i - 1];
+    if (__get_user(target_set.sig[0], &frame->sc.oldmask)
+        || (TARGET_NSIG_WORDS > 1
+            && __copy_from_user(&target_set.sig[1], &frame->extramask,
+                                sizeof(frame->extramask))))
+            goto badframe;

    target_to_host_sigset(&set, &target_set);
    sigprocmask(SIG_SETMASK, &set, NULL);


The next problem I was running into was the sysinfo not implemented syscall. The problem would just run in a loop waiting to get a decent result from it, so I had to implement (so far tested by me and two others, all running PowerMac G3s with qemu-i386 as the target).

Index: linux-user/syscall.c
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/syscall.c,v
retrieving revision 1.49
diff -u -r1.49 syscall.c
--- linux-user/syscall.c        3 May 2004 19:23:07 -0000       1.49
+++ linux-user/syscall.c        18 Jun 2004 17:12:26 -0000
@@ -62,6 +62,9 @@
#include <linux/soundcard.h>
#include <linux/dirent.h>
#include <linux/kd.h>
+/* SYSINFO PATCH STARTS HERE */
+#include <sys/sysinfo.h>
+/* SYSINFO PATCH ENDS HERE */

#include "qemu.h"

@@ -230,6 +233,9 @@
#ifdef __NR_exit_group
_syscall1(int,exit_group,int,error_code)
#endif
+/* SYSINFO PATCH STARTS HERE */
+_syscall1(int,sysinfo,struct sysinfo *,info)
+/* SYSINFO PATCH ENDS HERE */

extern int personality(int);
extern int flock(int, int);
@@ -2348,7 +2354,31 @@
        ret = get_errno(swapoff((const char *)arg1));
        break;
    case TARGET_NR_sysinfo:
-        goto unimplemented;
+/* SYSINFO PATCH STARTS HERE */
+        {
+            struct target_sysinfo *target_value = (void *)arg1;
+            struct sysinfo value;
+            ret = get_errno(sysinfo(&value));
+            if (!is_error(ret) && target_value)
+            {
+                target_value->uptime = tswapl(value.uptime);
+                target_value->loads[0] = tswapl(value.loads[0]);
+                target_value->loads[1] = tswapl(value.loads[1]);
+                target_value->loads[2] = tswapl(value.loads[2]);
+                target_value->totalram = tswapl(value.totalram);
+                target_value->freeram = tswapl(value.freeram);
+                target_value->sharedram = tswapl(value.sharedram);
+                target_value->bufferram = tswapl(value.bufferram);
+                target_value->totalswap = tswapl(value.totalswap);
+                target_value->freeswap = tswapl(value.freeswap);
+                target_value->procs = tswap16(value.procs);
+                target_value->totalhigh = tswapl(value.totalhigh);
+                target_value->freehigh = tswapl(value.freehigh);
+                target_value->mem_unit = tswap32(value.mem_unit);
+            }
+        }
+        break;
+/* SYSINFO PATCH ENDS HERE */
    case TARGET_NR_ipc:
       ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
       break;
Index: linux-user/syscall_defs.h
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/syscall_defs.h,v
retrieving revision 1.20
diff -u -r1.20 syscall_defs.h
--- linux-user/syscall_defs.h   22 Feb 2004 14:57:26 -0000      1.20
+++ linux-user/syscall_defs.h   18 Jun 2004 17:12:27 -0000
@@ -1133,3 +1133,22 @@
/* vfat ioctls */
#define TARGET_VFAT_IOCTL_READDIR_BOTH    TARGET_IORU('r', 1)
#define TARGET_VFAT_IOCTL_READDIR_SHORT   TARGET_IORU('r', 2)
+/* SYSINFO PATCH STARTS HERE */
+/* from <linux/kernel.h> */
+struct target_sysinfo {
+    target_long uptime;             /* Seconds since boot */
+    target_ulong loads[3];          /* 1, 5, and 15 minute load averages */
+    target_ulong totalram;          /* Total usable main memory size */
+    target_ulong freeram;           /* Available memory size */
+    target_ulong sharedram;         /* Amount of shared memory */
+    target_ulong bufferram;         /* Memory used by buffers */
+    target_ulong totalswap;         /* Total swap space size */
+    target_ulong freeswap;          /* swap space still available */
+    unsigned short procs;           /* Number of current processes */
+    unsigned short pad;             /* explicit padding for m68k */
+    target_ulong totalhigh;         /* Total high memory size */
+    target_ulong freehigh;          /* Available high memory size */
+    unsigned int mem_unit;          /* Memory unit size in bytes */
+ char _f[20-2*sizeof(target_long)-sizeof(int)]; /* Padding: libc5 uses this.. */
+};
+/* SYSINFO PATCH ENDS HERE */

_________________________________________________________________
STOP MORE SPAM with the MSN Premium and get 2 months FREE* http://join.msn.com/?pgmarket=en-ca&page=byoa/prem&xAPID=1994&DI=1034&SU=http://hotmail.com/enca&HL=Market_MSNIS_Taglines





reply via email to

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