1 /*
2  *  Semihosting support for systems modeled on the Arm "Angel"
3  *  semihosting syscalls design. This includes Arm and RISC-V processors
4  *
5  *  Copyright (c) 2005, 2007 CodeSourcery.
6  *  Copyright (c) 2019 Linaro
7  *  Written by Paul Brook.
8  *
9  *  Copyright © 2020 by Keith Packard <keithp@keithp.com>
10  *  Adapted for systems other than ARM, including RISC-V, by Keith Packard
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
24  *
25  *  ARM Semihosting is documented in:
26  *     Semihosting for AArch32 and AArch64 Release 2.0
27  *     https://static.docs.arm.com/100863/0200/semihosting.pdf
28  *
29  *  RISC-V Semihosting is documented in:
30  *     RISC-V Semihosting
31  *     https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc
32  */
33 
34 #include "qemu/osdep.h"
35 #include "semihosting/semihost.h"
36 #include "semihosting/console.h"
37 #include "semihosting/common-semi.h"
38 #include "semihosting/guestfd.h"
39 #include "qemu/timer.h"
40 #include "exec/gdbstub.h"
41 
42 #ifdef CONFIG_USER_ONLY
43 #include "qemu.h"
44 
45 #define COMMON_SEMI_HEAP_SIZE (128 * 1024 * 1024)
46 #else
47 #include "qemu/cutils.h"
48 #include "hw/loader.h"
49 #include "hw/boards.h"
50 #endif
51 
52 #define TARGET_SYS_OPEN        0x01
53 #define TARGET_SYS_CLOSE       0x02
54 #define TARGET_SYS_WRITEC      0x03
55 #define TARGET_SYS_WRITE0      0x04
56 #define TARGET_SYS_WRITE       0x05
57 #define TARGET_SYS_READ        0x06
58 #define TARGET_SYS_READC       0x07
59 #define TARGET_SYS_ISERROR     0x08
60 #define TARGET_SYS_ISTTY       0x09
61 #define TARGET_SYS_SEEK        0x0a
62 #define TARGET_SYS_FLEN        0x0c
63 #define TARGET_SYS_TMPNAM      0x0d
64 #define TARGET_SYS_REMOVE      0x0e
65 #define TARGET_SYS_RENAME      0x0f
66 #define TARGET_SYS_CLOCK       0x10
67 #define TARGET_SYS_TIME        0x11
68 #define TARGET_SYS_SYSTEM      0x12
69 #define TARGET_SYS_ERRNO       0x13
70 #define TARGET_SYS_GET_CMDLINE 0x15
71 #define TARGET_SYS_HEAPINFO    0x16
72 #define TARGET_SYS_EXIT        0x18
73 #define TARGET_SYS_SYNCCACHE   0x19
74 #define TARGET_SYS_EXIT_EXTENDED 0x20
75 #define TARGET_SYS_ELAPSED     0x30
76 #define TARGET_SYS_TICKFREQ    0x31
77 
78 /* ADP_Stopped_ApplicationExit is used for exit(0),
79  * anything else is implemented as exit(1) */
80 #define ADP_Stopped_ApplicationExit     (0x20026)
81 
82 #ifndef O_BINARY
83 #define O_BINARY 0
84 #endif
85 
86 static int gdb_open_modeflags[12] = {
87     GDB_O_RDONLY,
88     GDB_O_RDONLY,
89     GDB_O_RDWR,
90     GDB_O_RDWR,
91     GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
92     GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
93     GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
94     GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
95     GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
96     GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
97     GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
98     GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
99 };
100 
101 static int open_modeflags[12] = {
102     O_RDONLY,
103     O_RDONLY | O_BINARY,
104     O_RDWR,
105     O_RDWR | O_BINARY,
106     O_WRONLY | O_CREAT | O_TRUNC,
107     O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
108     O_RDWR | O_CREAT | O_TRUNC,
109     O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
110     O_WRONLY | O_CREAT | O_APPEND,
111     O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
112     O_RDWR | O_CREAT | O_APPEND,
113     O_RDWR | O_CREAT | O_APPEND | O_BINARY
114 };
115 
116 #ifndef CONFIG_USER_ONLY
117 
118 /**
119  * common_semi_find_bases: find information about ram and heap base
120  *
121  * This function attempts to provide meaningful numbers for RAM and
122  * HEAP base addresses. The rambase is simply the lowest addressable
123  * RAM position. For the heapbase we ask the loader to scan the
124  * address space and the largest available gap by querying the "ROM"
125  * regions.
126  *
127  * Returns: a structure with the numbers we need.
128  */
129 
130 typedef struct LayoutInfo {
131     target_ulong rambase;
132     size_t ramsize;
133     hwaddr heapbase;
134     hwaddr heaplimit;
135 } LayoutInfo;
136 
137 static bool find_ram_cb(Int128 start, Int128 len, const MemoryRegion *mr,
138                         hwaddr offset_in_region, void *opaque)
139 {
140     LayoutInfo *info = (LayoutInfo *) opaque;
141     uint64_t size = int128_get64(len);
142 
143     if (!mr->ram || mr->readonly) {
144         return false;
145     }
146 
147     if (size > info->ramsize) {
148         info->rambase = int128_get64(start);
149         info->ramsize = size;
150     }
151 
152     /* search exhaustively for largest RAM */
153     return false;
154 }
155 
156 static LayoutInfo common_semi_find_bases(CPUState *cs)
157 {
158     FlatView *fv;
159     LayoutInfo info = { 0, 0, 0, 0 };
160 
161     RCU_READ_LOCK_GUARD();
162 
163     fv = address_space_to_flatview(cs->as);
164     flatview_for_each_range(fv, find_ram_cb, &info);
165 
166     /*
167      * If we have found the RAM lets iterate through the ROM blobs to
168      * work out the best place for the remainder of RAM and split it
169      * equally between stack and heap.
170      */
171     if (info.rambase || info.ramsize > 0) {
172         RomGap gap = rom_find_largest_gap_between(info.rambase, info.ramsize);
173         info.heapbase = gap.base;
174         info.heaplimit = gap.base + gap.size;
175     }
176 
177     return info;
178 }
179 
180 #endif
181 
182 #include "common-semi-target.h"
183 
184 /*
185  * The semihosting API has no concept of its errno being thread-safe,
186  * as the API design predates SMP CPUs and was intended as a simple
187  * real-hardware set of debug functionality. For QEMU, we make the
188  * errno be per-thread in linux-user mode; in softmmu it is a simple
189  * global, and we assume that the guest takes care of avoiding any races.
190  */
191 #ifndef CONFIG_USER_ONLY
192 static target_ulong syscall_err;
193 
194 #include "semihosting/softmmu-uaccess.h"
195 #endif
196 
197 static inline uint32_t get_swi_errno(CPUState *cs)
198 {
199 #ifdef CONFIG_USER_ONLY
200     TaskState *ts = cs->opaque;
201 
202     return ts->swi_errno;
203 #else
204     return syscall_err;
205 #endif
206 }
207 
208 static target_ulong common_semi_syscall_len;
209 
210 static void common_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
211 {
212     if (err) {
213 #ifdef CONFIG_USER_ONLY
214         TaskState *ts = cs->opaque;
215         ts->swi_errno = err;
216 #else
217         syscall_err = err;
218 #endif
219     } else {
220         /* Fixup syscalls that use nonstardard return conventions.  */
221         target_ulong reg0 = common_semi_arg(cs, 0);
222         switch (reg0) {
223         case TARGET_SYS_WRITE:
224         case TARGET_SYS_READ:
225             ret = common_semi_syscall_len - ret;
226             break;
227         case TARGET_SYS_SEEK:
228             ret = 0;
229             break;
230         default:
231             break;
232         }
233     }
234     common_semi_set_ret(cs, ret);
235 }
236 
237 /*
238  * Return an address in target memory of 64 bytes where the remote
239  * gdb should write its stat struct. (The format of this structure
240  * is defined by GDB's remote protocol and is not target-specific.)
241  * We put this on the guest's stack just below SP.
242  */
243 static target_ulong common_semi_flen_buf(CPUState *cs)
244 {
245     target_ulong sp = common_semi_stack_bottom(cs);
246     return sp - 64;
247 }
248 
249 static void
250 common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
251 {
252     if (!err) {
253         /* The size is always stored in big-endian order, extract the value. */
254         uint64_t size;
255         cpu_memory_rw_debug(cs, common_semi_flen_buf(cs) +
256                             offsetof(struct gdb_stat, gdb_st_size),
257                             &size, 8, 0);
258         ret = be64_to_cpu(size);
259     }
260     common_semi_cb(cs, ret, err);
261 }
262 
263 static int common_semi_open_guestfd;
264 
265 static void
266 common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
267 {
268     if (err) {
269         dealloc_guestfd(common_semi_open_guestfd);
270     } else {
271         associate_guestfd(common_semi_open_guestfd, ret);
272         ret = common_semi_open_guestfd;
273     }
274     common_semi_cb(cs, ret, err);
275 }
276 
277 /*
278  * Types for functions implementing various semihosting calls
279  * for specific types of guest file descriptor. These must all
280  * do the work and return the required return value to the guest
281  * via common_semi_cb.
282  */
283 typedef void sys_closefn(CPUState *cs, GuestFD *gf);
284 typedef void sys_writefn(CPUState *cs, GuestFD *gf,
285                          target_ulong buf, uint32_t len);
286 typedef void sys_readfn(CPUState *cs, GuestFD *gf,
287                         target_ulong buf, uint32_t len);
288 typedef void sys_isattyfn(CPUState *cs, GuestFD *gf);
289 typedef void sys_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset);
290 typedef void sys_flenfn(CPUState *cs, GuestFD *gf);
291 
292 static void host_closefn(CPUState *cs, GuestFD *gf)
293 {
294     int ret;
295     /*
296      * Only close the underlying host fd if it's one we opened on behalf
297      * of the guest in SYS_OPEN.
298      */
299     if (gf->hostfd == STDIN_FILENO ||
300         gf->hostfd == STDOUT_FILENO ||
301         gf->hostfd == STDERR_FILENO) {
302         ret = 0;
303     } else {
304         ret = close(gf->hostfd);
305     }
306     common_semi_cb(cs, ret, ret ? errno : 0);
307 }
308 
309 static void host_writefn(CPUState *cs, GuestFD *gf,
310                          target_ulong buf, uint32_t len)
311 {
312     CPUArchState *env = cs->env_ptr;
313     uint32_t ret = 0;
314     char *s = lock_user(VERIFY_READ, buf, len, 1);
315     (void) env; /* Used in arm softmmu lock_user implicitly */
316     if (s) {
317         ret = write(gf->hostfd, s, len);
318         unlock_user(s, buf, 0);
319         if (ret == (uint32_t)-1) {
320             ret = 0;
321         }
322     }
323     /* Return bytes not written, on error as well. */
324     common_semi_cb(cs, len - ret, 0);
325 }
326 
327 static void host_readfn(CPUState *cs, GuestFD *gf,
328                         target_ulong buf, uint32_t len)
329 {
330     CPUArchState *env = cs->env_ptr;
331     uint32_t ret = 0;
332     char *s = lock_user(VERIFY_WRITE, buf, len, 0);
333     (void) env; /* Used in arm softmmu lock_user implicitly */
334     if (s) {
335         do {
336             ret = read(gf->hostfd, s, len);
337         } while (ret == -1 && errno == EINTR);
338         unlock_user(s, buf, len);
339         if (ret == (uint32_t)-1) {
340             ret = 0;
341         }
342     }
343     /* Return bytes not read, on error as well. */
344     common_semi_cb(cs, len - ret, 0);
345 }
346 
347 static void host_isattyfn(CPUState *cs, GuestFD *gf)
348 {
349     common_semi_cb(cs, isatty(gf->hostfd), 0);
350 }
351 
352 static void host_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
353 {
354     off_t ret = lseek(gf->hostfd, offset, SEEK_SET);
355     common_semi_cb(cs, ret, ret == -1 ? errno : 0);
356 }
357 
358 static void host_flenfn(CPUState *cs, GuestFD *gf)
359 {
360     struct stat buf;
361 
362     if (fstat(gf->hostfd, &buf)) {
363         common_semi_cb(cs, -1, errno);
364     } else {
365         common_semi_cb(cs, buf.st_size, 0);
366     }
367 }
368 
369 static void gdb_closefn(CPUState *cs, GuestFD *gf)
370 {
371     gdb_do_syscall(common_semi_cb, "close,%x", gf->hostfd);
372 }
373 
374 static void gdb_writefn(CPUState *cs, GuestFD *gf,
375                         target_ulong buf, uint32_t len)
376 {
377     common_semi_syscall_len = len;
378     gdb_do_syscall(common_semi_cb, "write,%x,%x,%x", gf->hostfd, buf, len);
379 }
380 
381 static void gdb_readfn(CPUState *cs, GuestFD *gf,
382                        target_ulong buf, uint32_t len)
383 {
384     common_semi_syscall_len = len;
385     gdb_do_syscall(common_semi_cb, "read,%x,%x,%x", gf->hostfd, buf, len);
386 }
387 
388 static void gdb_isattyfn(CPUState *cs, GuestFD *gf)
389 {
390     gdb_do_syscall(common_semi_cb, "isatty,%x", gf->hostfd);
391 }
392 
393 static void gdb_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
394 {
395     gdb_do_syscall(common_semi_cb, "lseek,%x,%x,0", gf->hostfd, offset);
396 }
397 
398 static void gdb_flenfn(CPUState *cs, GuestFD *gf)
399 {
400     gdb_do_syscall(common_semi_flen_cb, "fstat,%x,%x",
401                    gf->hostfd, common_semi_flen_buf(cs));
402 }
403 
404 #define SHFB_MAGIC_0 0x53
405 #define SHFB_MAGIC_1 0x48
406 #define SHFB_MAGIC_2 0x46
407 #define SHFB_MAGIC_3 0x42
408 
409 /* Feature bits reportable in feature byte 0 */
410 #define SH_EXT_EXIT_EXTENDED (1 << 0)
411 #define SH_EXT_STDOUT_STDERR (1 << 1)
412 
413 static const uint8_t featurefile_data[] = {
414     SHFB_MAGIC_0,
415     SHFB_MAGIC_1,
416     SHFB_MAGIC_2,
417     SHFB_MAGIC_3,
418     SH_EXT_EXIT_EXTENDED | SH_EXT_STDOUT_STDERR, /* Feature byte 0 */
419 };
420 
421 static void staticfile_closefn(CPUState *cs, GuestFD *gf)
422 {
423     /* Nothing to do */
424     common_semi_cb(cs, 0, 0);
425 }
426 
427 static void staticfile_writefn(CPUState *cs, GuestFD *gf,
428                                target_ulong buf, uint32_t len)
429 {
430     /* This fd can never be open for writing */
431     common_semi_cb(cs, -1, EBADF);
432 }
433 
434 static void staticfile_readfn(CPUState *cs, GuestFD *gf,
435                               target_ulong buf, uint32_t len)
436 {
437     CPUArchState *env = cs->env_ptr;
438     uint32_t i = 0;
439     char *s;
440 
441     (void) env; /* Used in arm softmmu lock_user implicitly */
442     s = lock_user(VERIFY_WRITE, buf, len, 0);
443     if (s) {
444         for (i = 0; i < len; i++) {
445             if (gf->staticfile.off >= gf->staticfile.len) {
446                 break;
447             }
448             s[i] = gf->staticfile.data[gf->staticfile.off];
449             gf->staticfile.off++;
450         }
451         unlock_user(s, buf, len);
452     }
453 
454     /* Return number of bytes not read */
455     common_semi_cb(cs, len - i, 0);
456 }
457 
458 static void staticfile_isattyfn(CPUState *cs, GuestFD *gf)
459 {
460     common_semi_cb(cs, 0, 0);
461 }
462 
463 static void staticfile_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
464 {
465     gf->staticfile.off = offset;
466     common_semi_cb(cs, 0, 0);
467 }
468 
469 static void staticfile_flenfn(CPUState *cs, GuestFD *gf)
470 {
471     common_semi_cb(cs, gf->staticfile.len, 0);
472 }
473 
474 typedef struct GuestFDFunctions {
475     sys_closefn *closefn;
476     sys_writefn *writefn;
477     sys_readfn *readfn;
478     sys_isattyfn *isattyfn;
479     sys_seekfn *seekfn;
480     sys_flenfn *flenfn;
481 } GuestFDFunctions;
482 
483 static const GuestFDFunctions guestfd_fns[] = {
484     [GuestFDHost] = {
485         .closefn = host_closefn,
486         .writefn = host_writefn,
487         .readfn = host_readfn,
488         .isattyfn = host_isattyfn,
489         .seekfn = host_seekfn,
490         .flenfn = host_flenfn,
491     },
492     [GuestFDGDB] = {
493         .closefn = gdb_closefn,
494         .writefn = gdb_writefn,
495         .readfn = gdb_readfn,
496         .isattyfn = gdb_isattyfn,
497         .seekfn = gdb_seekfn,
498         .flenfn = gdb_flenfn,
499     },
500     [GuestFDStatic] = {
501         .closefn = staticfile_closefn,
502         .writefn = staticfile_writefn,
503         .readfn = staticfile_readfn,
504         .isattyfn = staticfile_isattyfn,
505         .seekfn = staticfile_seekfn,
506         .flenfn = staticfile_flenfn,
507     },
508 };
509 
510 /*
511  * Read the input value from the argument block; fail the semihosting
512  * call if the memory read fails. Eventually we could use a generic
513  * CPUState helper function here.
514  */
515 
516 #define GET_ARG(n) do {                                 \
517     if (is_64bit_semihosting(env)) {                    \
518         if (get_user_u64(arg ## n, args + (n) * 8)) {   \
519             goto do_fault;                              \
520         }                                               \
521     } else {                                            \
522         if (get_user_u32(arg ## n, args + (n) * 4)) {   \
523             goto do_fault;                              \
524         }                                               \
525     }                                                   \
526 } while (0)
527 
528 #define SET_ARG(n, val)                                 \
529     (is_64bit_semihosting(env) ?                        \
530      put_user_u64(val, args + (n) * 8) :                \
531      put_user_u32(val, args + (n) * 4))
532 
533 
534 /*
535  * Do a semihosting call.
536  *
537  * The specification always says that the "return register" either
538  * returns a specific value or is corrupted, so we don't need to
539  * report to our caller whether we are returning a value or trying to
540  * leave the register unchanged. We use 0xdeadbeef as the return value
541  * when there isn't a defined return value for the call.
542  */
543 void do_common_semihosting(CPUState *cs)
544 {
545     CPUArchState *env = cs->env_ptr;
546     target_ulong args;
547     target_ulong arg0, arg1, arg2, arg3;
548     target_ulong ul_ret;
549     char * s;
550     int nr;
551     uint32_t ret;
552     uint32_t len;
553     GuestFD *gf;
554     int64_t elapsed;
555 
556     (void) env; /* Used implicitly by arm lock_user macro */
557     nr = common_semi_arg(cs, 0) & 0xffffffffU;
558     args = common_semi_arg(cs, 1);
559 
560     switch (nr) {
561     case TARGET_SYS_OPEN:
562     {
563         int ret, err = 0;
564         int hostfd;
565 
566         GET_ARG(0);
567         GET_ARG(1);
568         GET_ARG(2);
569         s = lock_user_string(arg0);
570         if (!s) {
571             goto do_fault;
572         }
573         if (arg1 >= 12) {
574             unlock_user(s, arg0, 0);
575             common_semi_cb(cs, -1, EINVAL);
576             break;
577         }
578 
579         if (strcmp(s, ":tt") == 0) {
580             /*
581              * We implement SH_EXT_STDOUT_STDERR, so:
582              *  open for read == stdin
583              *  open for write == stdout
584              *  open for append == stderr
585              */
586             if (arg1 < 4) {
587                 hostfd = STDIN_FILENO;
588             } else if (arg1 < 8) {
589                 hostfd = STDOUT_FILENO;
590             } else {
591                 hostfd = STDERR_FILENO;
592             }
593             ret = alloc_guestfd();
594             associate_guestfd(ret, hostfd);
595         } else if (strcmp(s, ":semihosting-features") == 0) {
596             /* We must fail opens for modes other than 0 ('r') or 1 ('rb') */
597             if (arg1 != 0 && arg1 != 1) {
598                 ret = -1;
599                 err = EACCES;
600             } else {
601                 ret = alloc_guestfd();
602                 staticfile_guestfd(ret, featurefile_data,
603                                    sizeof(featurefile_data));
604             }
605         } else if (use_gdb_syscalls()) {
606             unlock_user(s, arg0, 0);
607             common_semi_open_guestfd = alloc_guestfd();
608             gdb_do_syscall(common_semi_open_cb,
609                            "open,%s,%x,1a4", arg0, (int)arg2 + 1,
610                            gdb_open_modeflags[arg1]);
611             break;
612         } else {
613             hostfd = open(s, open_modeflags[arg1], 0644);
614             if (hostfd < 0) {
615                 ret = -1;
616                 err = errno;
617             } else {
618                 ret = alloc_guestfd();
619                 associate_guestfd(ret, hostfd);
620             }
621         }
622         unlock_user(s, arg0, 0);
623         common_semi_cb(cs, ret, err);
624         break;
625     }
626 
627     case TARGET_SYS_CLOSE:
628         GET_ARG(0);
629 
630         gf = get_guestfd(arg0);
631         if (!gf) {
632             goto do_badf;
633         }
634         guestfd_fns[gf->type].closefn(cs, gf);
635         dealloc_guestfd(arg0);
636         break;
637 
638     case TARGET_SYS_WRITEC:
639         qemu_semihosting_console_outc(cs->env_ptr, args);
640         common_semi_set_ret(cs, 0xdeadbeef);
641         break;
642 
643     case TARGET_SYS_WRITE0:
644         ret = qemu_semihosting_console_outs(cs->env_ptr, args);
645         common_semi_set_ret(cs, ret);
646         break;
647 
648     case TARGET_SYS_WRITE:
649         GET_ARG(0);
650         GET_ARG(1);
651         GET_ARG(2);
652         len = arg2;
653 
654         gf = get_guestfd(arg0);
655         if (!gf) {
656             goto do_badf;
657         }
658         guestfd_fns[gf->type].writefn(cs, gf, arg1, len);
659         break;
660 
661     case TARGET_SYS_READ:
662         GET_ARG(0);
663         GET_ARG(1);
664         GET_ARG(2);
665         len = arg2;
666 
667         gf = get_guestfd(arg0);
668         if (!gf) {
669             goto do_badf;
670         }
671         guestfd_fns[gf->type].readfn(cs, gf, arg1, len);
672         break;
673 
674     case TARGET_SYS_READC:
675         ret = qemu_semihosting_console_inc(cs->env_ptr);
676         common_semi_set_ret(cs, ret);
677         break;
678 
679     case TARGET_SYS_ISERROR:
680         GET_ARG(0);
681         common_semi_set_ret(cs, (target_long)arg0 < 0);
682         break;
683 
684     case TARGET_SYS_ISTTY:
685         GET_ARG(0);
686 
687         gf = get_guestfd(arg0);
688         if (!gf) {
689             goto do_badf;
690         }
691         guestfd_fns[gf->type].isattyfn(cs, gf);
692         break;
693 
694     case TARGET_SYS_SEEK:
695         GET_ARG(0);
696         GET_ARG(1);
697 
698         gf = get_guestfd(arg0);
699         if (!gf) {
700             goto do_badf;
701         }
702         guestfd_fns[gf->type].seekfn(cs, gf, arg1);
703         break;
704 
705     case TARGET_SYS_FLEN:
706         GET_ARG(0);
707 
708         gf = get_guestfd(arg0);
709         if (!gf) {
710             goto do_badf;
711         }
712         guestfd_fns[gf->type].flenfn(cs, gf);
713         break;
714 
715     case TARGET_SYS_TMPNAM:
716     {
717         int len;
718         char *p;
719 
720         GET_ARG(0);
721         GET_ARG(1);
722         GET_ARG(2);
723         len = asprintf(&s, "/tmp/qemu-%x%02x", getpid(), (int)arg1 & 0xff);
724         /* Make sure there's enough space in the buffer */
725         if (len < 0 || len >= arg2) {
726             common_semi_set_ret(cs, -1);
727             break;
728         }
729         p = lock_user(VERIFY_WRITE, arg0, len, 0);
730         if (!p) {
731             goto do_fault;
732         }
733         memcpy(p, s, len + 1);
734         unlock_user(p, arg0, len);
735         free(s);
736         common_semi_set_ret(cs, 0);
737         break;
738     }
739 
740     case TARGET_SYS_REMOVE:
741         GET_ARG(0);
742         GET_ARG(1);
743         if (use_gdb_syscalls()) {
744             gdb_do_syscall(common_semi_cb, "unlink,%s",
745                            arg0, (int)arg1 + 1);
746             break;
747         }
748         s = lock_user_string(arg0);
749         if (!s) {
750             goto do_fault;
751         }
752         ret = remove(s);
753         unlock_user(s, arg0, 0);
754         common_semi_cb(cs, ret, ret ? errno : 0);
755         break;
756 
757     case TARGET_SYS_RENAME:
758         GET_ARG(0);
759         GET_ARG(1);
760         GET_ARG(2);
761         GET_ARG(3);
762         if (use_gdb_syscalls()) {
763             gdb_do_syscall(common_semi_cb, "rename,%s,%s",
764                            arg0, (int)arg1 + 1, arg2, (int)arg3 + 1);
765         } else {
766             char *s2;
767 
768             s = lock_user_string(arg0);
769             if (!s) {
770                 goto do_fault;
771             }
772             s2 = lock_user_string(arg2);
773             if (!s2) {
774                 unlock_user(s, arg0, 0);
775                 goto do_fault;
776             }
777             ret = rename(s, s2);
778             unlock_user(s2, arg2, 0);
779             unlock_user(s, arg0, 0);
780             common_semi_cb(cs, ret, ret ? errno : 0);
781         }
782         break;
783 
784     case TARGET_SYS_CLOCK:
785         common_semi_set_ret(cs, clock() / (CLOCKS_PER_SEC / 100));
786         break;
787 
788     case TARGET_SYS_TIME:
789         ul_ret = time(NULL);
790         common_semi_cb(cs, ul_ret, ul_ret == -1 ? errno : 0);
791         break;
792 
793     case TARGET_SYS_SYSTEM:
794         GET_ARG(0);
795         GET_ARG(1);
796         if (use_gdb_syscalls()) {
797             gdb_do_syscall(common_semi_cb, "system,%s", arg0, (int)arg1 + 1);
798             break;
799         }
800         s = lock_user_string(arg0);
801         if (!s) {
802             goto do_fault;
803         }
804         ret = system(s);
805         unlock_user(s, arg0, 0);
806         common_semi_cb(cs, ret, ret == -1 ? errno : 0);
807         break;
808 
809     case TARGET_SYS_ERRNO:
810         common_semi_set_ret(cs, get_swi_errno(cs));
811         break;
812 
813     case TARGET_SYS_GET_CMDLINE:
814         {
815             /* Build a command-line from the original argv.
816              *
817              * The inputs are:
818              *     * arg0, pointer to a buffer of at least the size
819              *               specified in arg1.
820              *     * arg1, size of the buffer pointed to by arg0 in
821              *               bytes.
822              *
823              * The outputs are:
824              *     * arg0, pointer to null-terminated string of the
825              *               command line.
826              *     * arg1, length of the string pointed to by arg0.
827              */
828 
829             char *output_buffer;
830             size_t input_size;
831             size_t output_size;
832             int status = 0;
833 #if !defined(CONFIG_USER_ONLY)
834             const char *cmdline;
835 #else
836             TaskState *ts = cs->opaque;
837 #endif
838             GET_ARG(0);
839             GET_ARG(1);
840             input_size = arg1;
841             /* Compute the size of the output string.  */
842 #if !defined(CONFIG_USER_ONLY)
843             cmdline = semihosting_get_cmdline();
844             if (cmdline == NULL) {
845                 cmdline = ""; /* Default to an empty line. */
846             }
847             output_size = strlen(cmdline) + 1; /* Count terminating 0. */
848 #else
849             unsigned int i;
850 
851             output_size = ts->info->env_strings - ts->info->arg_strings;
852             if (!output_size) {
853                 /*
854                  * We special-case the "empty command line" case (argc==0).
855                  * Just provide the terminating 0.
856                  */
857                 output_size = 1;
858             }
859 #endif
860 
861             if (output_size > input_size) {
862                 /* Not enough space to store command-line arguments.  */
863                 common_semi_cb(cs, -1, E2BIG);
864                 break;
865             }
866 
867             /* Adjust the command-line length.  */
868             if (SET_ARG(1, output_size - 1)) {
869                 /* Couldn't write back to argument block */
870                 goto do_fault;
871             }
872 
873             /* Lock the buffer on the ARM side.  */
874             output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);
875             if (!output_buffer) {
876                 goto do_fault;
877             }
878 
879             /* Copy the command-line arguments.  */
880 #if !defined(CONFIG_USER_ONLY)
881             pstrcpy(output_buffer, output_size, cmdline);
882 #else
883             if (output_size == 1) {
884                 /* Empty command-line.  */
885                 output_buffer[0] = '\0';
886                 goto out;
887             }
888 
889             if (copy_from_user(output_buffer, ts->info->arg_strings,
890                                output_size)) {
891                 unlock_user(output_buffer, arg0, 0);
892                 goto do_fault;
893             }
894 
895             /* Separate arguments by white spaces.  */
896             for (i = 0; i < output_size - 1; i++) {
897                 if (output_buffer[i] == 0) {
898                     output_buffer[i] = ' ';
899                 }
900             }
901         out:
902 #endif
903             /* Unlock the buffer on the ARM side.  */
904             unlock_user(output_buffer, arg0, output_size);
905             common_semi_cb(cs, status, 0);
906         }
907         break;
908 
909     case TARGET_SYS_HEAPINFO:
910         {
911             target_ulong retvals[4];
912             int i;
913 #ifdef CONFIG_USER_ONLY
914             TaskState *ts = cs->opaque;
915             target_ulong limit;
916 #else
917             LayoutInfo info = common_semi_find_bases(cs);
918 #endif
919 
920             GET_ARG(0);
921 
922 #ifdef CONFIG_USER_ONLY
923             /*
924              * Some C libraries assume the heap immediately follows .bss, so
925              * allocate it using sbrk.
926              */
927             if (!ts->heap_limit) {
928                 abi_ulong ret;
929 
930                 ts->heap_base = do_brk(0);
931                 limit = ts->heap_base + COMMON_SEMI_HEAP_SIZE;
932                 /* Try a big heap, and reduce the size if that fails.  */
933                 for (;;) {
934                     ret = do_brk(limit);
935                     if (ret >= limit) {
936                         break;
937                     }
938                     limit = (ts->heap_base >> 1) + (limit >> 1);
939                 }
940                 ts->heap_limit = limit;
941             }
942 
943             retvals[0] = ts->heap_base;
944             retvals[1] = ts->heap_limit;
945             retvals[2] = ts->stack_base;
946             retvals[3] = 0; /* Stack limit.  */
947 #else
948             retvals[0] = info.heapbase;  /* Heap Base */
949             retvals[1] = info.heaplimit; /* Heap Limit */
950             retvals[2] = info.heaplimit; /* Stack base */
951             retvals[3] = info.heapbase;  /* Stack limit.  */
952 #endif
953 
954             for (i = 0; i < ARRAY_SIZE(retvals); i++) {
955                 bool fail;
956 
957                 if (is_64bit_semihosting(env)) {
958                     fail = put_user_u64(retvals[i], arg0 + i * 8);
959                 } else {
960                     fail = put_user_u32(retvals[i], arg0 + i * 4);
961                 }
962 
963                 if (fail) {
964                     /* Couldn't write back to argument block */
965                     goto do_fault;
966                 }
967             }
968             common_semi_set_ret(cs, 0);
969         }
970         break;
971 
972     case TARGET_SYS_EXIT:
973     case TARGET_SYS_EXIT_EXTENDED:
974         if (common_semi_sys_exit_extended(cs, nr)) {
975             /*
976              * The A64 version of SYS_EXIT takes a parameter block,
977              * so the application-exit type can return a subcode which
978              * is the exit status code from the application.
979              * SYS_EXIT_EXTENDED is an a new-in-v2.0 optional function
980              * which allows A32/T32 guests to also provide a status code.
981              */
982             GET_ARG(0);
983             GET_ARG(1);
984 
985             if (arg0 == ADP_Stopped_ApplicationExit) {
986                 ret = arg1;
987             } else {
988                 ret = 1;
989             }
990         } else {
991             /*
992              * The A32/T32 version of SYS_EXIT specifies only
993              * Stopped_ApplicationExit as normal exit, but does not
994              * allow the guest to specify the exit status code.
995              * Everything else is considered an error.
996              */
997             ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
998         }
999         gdb_exit(ret);
1000         exit(ret);
1001 
1002     case TARGET_SYS_ELAPSED:
1003         elapsed = get_clock() - clock_start;
1004         if (sizeof(target_ulong) == 8) {
1005             SET_ARG(0, elapsed);
1006         } else {
1007             SET_ARG(0, (uint32_t) elapsed);
1008             SET_ARG(1, (uint32_t) (elapsed >> 32));
1009         }
1010         common_semi_set_ret(cs, 0);
1011         break;
1012 
1013     case TARGET_SYS_TICKFREQ:
1014         /* qemu always uses nsec */
1015         common_semi_set_ret(cs, 1000000000);
1016         break;
1017 
1018     case TARGET_SYS_SYNCCACHE:
1019         /*
1020          * Clean the D-cache and invalidate the I-cache for the specified
1021          * virtual address range. This is a nop for us since we don't
1022          * implement caches. This is only present on A64.
1023          */
1024         if (common_semi_has_synccache(env)) {
1025             common_semi_set_ret(cs, 0);
1026             break;
1027         }
1028         /* fall through */
1029     default:
1030         fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
1031         cpu_dump_state(cs, stderr, 0);
1032         abort();
1033 
1034     do_badf:
1035         common_semi_cb(cs, -1, EBADF);
1036         break;
1037     do_fault:
1038         common_semi_cb(cs, -1, EFAULT);
1039         break;
1040     }
1041 }
1042