]> git.proxmox.com Git - qemu.git/blobdiff - m68k-semi.c
iothread: replace fair_mutex with a condition variable
[qemu.git] / m68k-semi.c
index 27bdce8e2fb7f673822dbcc20b547b44cdf8f70d..7fde10e8f36254685058e153c93a39c4d4a28a94 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  m68k/ColdFire Semihosting syscall interface
- * 
+ *
  *  Copyright (c) 2005-2007 CodeSourcery.
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -14,8 +14,7 @@
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <sys/types.h>
 #include "qemu.h"
 #define SEMIHOSTING_HEAP_SIZE (128 * 1024 * 1024)
 #else
-#include "vl.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
 #include "softmmu-semi.h"
 #endif
+#include "sysemu.h"
 
 #define HOSTED_EXIT  0
 #define HOSTED_INIT_SIM 1
@@ -107,7 +108,9 @@ static void translate_stat(CPUState *env, target_ulong addr, struct stat *s)
 {
     struct m68k_gdb_stat *p;
 
-    p = lock_user(addr, sizeof(struct m68k_gdb_stat), 0);
+    if (!(p = lock_user(VERIFY_WRITE, addr, sizeof(struct m68k_gdb_stat), 0)))
+        /* FIXME - should this return an error code? */
+        return;
     p->gdb_st_dev = cpu_to_be32(s->st_dev);
     p->gdb_st_ino = cpu_to_be32(s->st_ino);
     p->gdb_st_mode = cpu_to_be32(s->st_mode);
@@ -116,8 +119,14 @@ static void translate_stat(CPUState *env, target_ulong addr, struct stat *s)
     p->gdb_st_gid = cpu_to_be32(s->st_gid);
     p->gdb_st_rdev = cpu_to_be32(s->st_rdev);
     p->gdb_st_size = cpu_to_be64(s->st_size);
+#ifdef _WIN32
+    /* Windows stat is missing some fields.  */
+    p->gdb_st_blksize = 0;
+    p->gdb_st_blocks = 0;
+#else
     p->gdb_st_blksize = cpu_to_be64(s->st_blksize);
     p->gdb_st_blocks = cpu_to_be64(s->st_blocks);
+#endif
     p->gdb_st_atime = cpu_to_be32(s->st_atime);
     p->gdb_st_mtime = cpu_to_be32(s->st_mtime);
     p->gdb_st_ctime = cpu_to_be32(s->st_ctime);
@@ -134,15 +143,23 @@ static void m68k_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
     if (m68k_semi_is_fseek) {
         /* FIXME: We've already lost the high bits of the fseek
            return value.  */
-        tput32(args, 0);
+        /* FIXME - handle put_user() failure */
+        put_user_u32(0, args);
         args += 4;
         m68k_semi_is_fseek = 0;
     }
-    tput32(args, ret);
-    tput32(args + 4, errno);
+    /* FIXME - handle put_user() failure */
+    put_user_u32(ret, args);
+    put_user_u32(errno, args + 4);
 }
 
-#define ARG(x) tget32(args + (x) * 4)
+#define ARG(n)                                 \
+({                                             \
+    target_ulong __arg;                                \
+    /* FIXME - handle get_user() failure */    \
+    get_user_ual(__arg, args + (n) * 4);       \
+    __arg;                                     \
+})
 #define PARG(x) ((unsigned long)ARG(x))
 void do_m68k_semihosting(CPUM68KState *env, int nr)
 {
@@ -155,6 +172,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
     args = env->dregs[1];
     switch (nr) {
     case HOSTED_EXIT:
+        gdb_exit(env, env->dregs[0]);
         exit(env->dregs[0]);
     case HOSTED_OPEN:
         if (use_gdb_syscalls()) {
@@ -162,9 +180,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
                            ARG(2), ARG(3));
             return;
         } else {
-            p = lock_user_string(ARG(0));
-            result = open(p, translate_openflags(ARG(2)), ARG(3));
-            unlock_user(p, ARG(0), 0);
+            if (!(p = lock_user_string(ARG(0)))) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = open(p, translate_openflags(ARG(2)), ARG(3));
+                unlock_user(p, ARG(0), 0);
+            }
         }
         break;
     case HOSTED_CLOSE:
@@ -190,9 +212,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
                            ARG(0), ARG(1), len);
             return;
         } else {
-            p = lock_user(ARG(1), len, 0);
-            result = read(ARG(0), p, len);
-            unlock_user(p, ARG(1), len);
+            if (!(p = lock_user(VERIFY_WRITE, ARG(1), len, 0))) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = read(ARG(0), p, len);
+                unlock_user(p, ARG(1), len);
+            }
         }
         break;
     case HOSTED_WRITE:
@@ -202,9 +228,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
                            ARG(0), ARG(1), len);
             return;
         } else {
-            p = lock_user(ARG(1), len, 1);
-            result = write(ARG(0), p, len);
-            unlock_user(p, ARG(0), 0);
+            if (!(p = lock_user(VERIFY_READ, ARG(1), len, 1))) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = write(ARG(0), p, len);
+                unlock_user(p, ARG(0), 0);
+            }
         }
         break;
     case HOSTED_LSEEK:
@@ -217,21 +247,27 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
                                ARG(0), off, ARG(3));
             } else {
                 off = lseek(ARG(0), off, ARG(3));
-                tput32(args, off >> 32);
-                tput32(args + 4, off);
-                tput32(args + 8, errno);
+                /* FIXME - handle put_user() failure */
+                put_user_u32(off >> 32, args);
+                put_user_u32(off, args + 4);
+                put_user_u32(errno, args + 8);
             }
             return;
         }
     case HOSTED_RENAME:
         if (use_gdb_syscalls()) {
-            gdb_do_syscall(m68k_semi_cb, "rename,%s,%s", 
+            gdb_do_syscall(m68k_semi_cb, "rename,%s,%s",
                            ARG(0), (int)ARG(1), ARG(2), (int)ARG(3));
             return;
         } else {
             p = lock_user_string(ARG(0));
             q = lock_user_string(ARG(2));
-            result = rename(p, q);
+            if (!p || !q) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = rename(p, q);
+            }
             unlock_user(p, ARG(0), 0);
             unlock_user(q, ARG(2), 0);
         }
@@ -242,9 +278,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
                            ARG(0), (int)ARG(1));
             return;
         } else {
-            p = lock_user_string(ARG(0));
-            result = unlink(p);
-            unlock_user(p, ARG(0), 0);
+            if (!(p = lock_user_string(ARG(0)))) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = unlink(p);
+                unlock_user(p, ARG(0), 0);
+            }
         }
         break;
     case HOSTED_STAT:
@@ -254,9 +294,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
             return;
         } else {
             struct stat s;
-            p = lock_user_string(ARG(0));
-            result = stat(p, &s);
-            unlock_user(p, ARG(0), 0);
+            if (!(p = lock_user_string(ARG(0)))) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = stat(p, &s);
+                unlock_user(p, ARG(0), 0);
+            }
             if (result == 0) {
                 translate_stat(env, ARG(2), &s);
             }
@@ -281,14 +325,19 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
                            ARG(0), ARG(1));
             return;
         } else {
-            struct timeval tv;
+            qemu_timeval tv;
             struct gdb_timeval *p;
-            result = gettimeofday(&tv, NULL);
+            result = qemu_gettimeofday(&tv);
             if (result != 0) {
-                p = lock_user(ARG(0), sizeof(struct gdb_timeval), 0);
-                p->tv_sec = cpu_to_be32(tv.tv_sec);
-                p->tv_usec = cpu_to_be64(tv.tv_usec);
-                unlock_user(p, ARG(0), sizeof(struct gdb_timeval));
+                if (!(p = lock_user(VERIFY_WRITE,
+                                    ARG(0), sizeof(struct gdb_timeval), 0))) {
+                    /* FIXME - check error code? */
+                    result = -1;
+                } else {
+                    p->tv_sec = cpu_to_be32(tv.tv_sec);
+                    p->tv_usec = cpu_to_be64(tv.tv_usec);
+                    unlock_user(p, ARG(0), sizeof(struct gdb_timeval));
+                }
             }
         }
         break;
@@ -306,9 +355,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
                            ARG(0), (int)ARG(1));
             return;
         } else {
-            p = lock_user_string(ARG(0));
-            result = system(p);
-            unlock_user(p, ARG(0), 0);
+            if (!(p = lock_user_string(ARG(0)))) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = system(p);
+                unlock_user(p, ARG(0), 0);
+            }
         }
         break;
     case HOSTED_INIT_SIM:
@@ -317,7 +370,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
         TaskState *ts = env->opaque;
         /* Allocate the heap using sbrk.  */
         if (!ts->heap_limit) {
-            long ret;
+            abi_ulong ret;
             uint32_t size;
             uint32_t base;
 
@@ -326,8 +379,9 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
             /* Try a big heap, and reduce the size if that fails.  */
             for (;;) {
                 ret = do_brk(base + size);
-                if (ret != -1)
+                if (ret >= (base + size)) {
                     break;
+                }
                 size >>= 1;
             }
             ts->heap_limit = base + size;
@@ -348,6 +402,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
         cpu_abort(env, "Unsupported semihosting syscall %d\n", nr);
         result = 0;
     }
-    tput32(args, result);
-    tput32(args + 4, errno);
+    /* FIXME - handle put_user() failure */
+    put_user_u32(result, args);
+    put_user_u32(errno, args + 4);
 }