xref: /qemu/semihosting/arm-compat-semi.c (revision d0fb9657)
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 
36 #include "semihosting/semihost.h"
37 #include "semihosting/console.h"
38 #include "semihosting/common-semi.h"
39 #include "qemu/timer.h"
40 #ifdef CONFIG_USER_ONLY
41 #include "qemu.h"
42 
43 #define COMMON_SEMI_HEAP_SIZE (128 * 1024 * 1024)
44 #else
45 #include "exec/gdbstub.h"
46 #include "qemu/cutils.h"
47 #ifdef TARGET_ARM
48 #include "hw/arm/boot.h"
49 #endif
50 #include "hw/boards.h"
51 #endif
52 
53 #define TARGET_SYS_OPEN        0x01
54 #define TARGET_SYS_CLOSE       0x02
55 #define TARGET_SYS_WRITEC      0x03
56 #define TARGET_SYS_WRITE0      0x04
57 #define TARGET_SYS_WRITE       0x05
58 #define TARGET_SYS_READ        0x06
59 #define TARGET_SYS_READC       0x07
60 #define TARGET_SYS_ISERROR     0x08
61 #define TARGET_SYS_ISTTY       0x09
62 #define TARGET_SYS_SEEK        0x0a
63 #define TARGET_SYS_FLEN        0x0c
64 #define TARGET_SYS_TMPNAM      0x0d
65 #define TARGET_SYS_REMOVE      0x0e
66 #define TARGET_SYS_RENAME      0x0f
67 #define TARGET_SYS_CLOCK       0x10
68 #define TARGET_SYS_TIME        0x11
69 #define TARGET_SYS_SYSTEM      0x12
70 #define TARGET_SYS_ERRNO       0x13
71 #define TARGET_SYS_GET_CMDLINE 0x15
72 #define TARGET_SYS_HEAPINFO    0x16
73 #define TARGET_SYS_EXIT        0x18
74 #define TARGET_SYS_SYNCCACHE   0x19
75 #define TARGET_SYS_EXIT_EXTENDED 0x20
76 #define TARGET_SYS_ELAPSED     0x30
77 #define TARGET_SYS_TICKFREQ    0x31
78 
79 /* ADP_Stopped_ApplicationExit is used for exit(0),
80  * anything else is implemented as exit(1) */
81 #define ADP_Stopped_ApplicationExit     (0x20026)
82 
83 #ifndef O_BINARY
84 #define O_BINARY 0
85 #endif
86 
87 #define GDB_O_RDONLY  0x000
88 #define GDB_O_WRONLY  0x001
89 #define GDB_O_RDWR    0x002
90 #define GDB_O_APPEND  0x008
91 #define GDB_O_CREAT   0x200
92 #define GDB_O_TRUNC   0x400
93 #define GDB_O_BINARY  0
94 
95 static int gdb_open_modeflags[12] = {
96     GDB_O_RDONLY,
97     GDB_O_RDONLY | GDB_O_BINARY,
98     GDB_O_RDWR,
99     GDB_O_RDWR | GDB_O_BINARY,
100     GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
101     GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
102     GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
103     GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
104     GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
105     GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY,
106     GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
107     GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY
108 };
109 
110 static int open_modeflags[12] = {
111     O_RDONLY,
112     O_RDONLY | O_BINARY,
113     O_RDWR,
114     O_RDWR | O_BINARY,
115     O_WRONLY | O_CREAT | O_TRUNC,
116     O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
117     O_RDWR | O_CREAT | O_TRUNC,
118     O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
119     O_WRONLY | O_CREAT | O_APPEND,
120     O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
121     O_RDWR | O_CREAT | O_APPEND,
122     O_RDWR | O_CREAT | O_APPEND | O_BINARY
123 };
124 
125 typedef enum GuestFDType {
126     GuestFDUnused = 0,
127     GuestFDHost = 1,
128     GuestFDGDB = 2,
129     GuestFDFeatureFile = 3,
130 } GuestFDType;
131 
132 /*
133  * Guest file descriptors are integer indexes into an array of
134  * these structures (we will dynamically resize as necessary).
135  */
136 typedef struct GuestFD {
137     GuestFDType type;
138     union {
139         int hostfd;
140         target_ulong featurefile_offset;
141     };
142 } GuestFD;
143 
144 static GArray *guestfd_array;
145 
146 #ifndef CONFIG_USER_ONLY
147 #include "exec/address-spaces.h"
148 /*
149  * Find the base of a RAM region containing the specified address
150  */
151 static inline hwaddr
152 common_semi_find_region_base(hwaddr addr)
153 {
154     MemoryRegion *subregion;
155 
156     /*
157      * Find the chunk of R/W memory containing the address.  This is
158      * used for the SYS_HEAPINFO semihosting call, which should
159      * probably be using information from the loaded application.
160      */
161     QTAILQ_FOREACH(subregion, &get_system_memory()->subregions,
162                    subregions_link) {
163         if (subregion->ram && !subregion->readonly) {
164             Int128 top128 = int128_add(int128_make64(subregion->addr),
165                                        subregion->size);
166             Int128 addr128 = int128_make64(addr);
167             if (subregion->addr <= addr && int128_lt(addr128, top128)) {
168                 return subregion->addr;
169             }
170         }
171     }
172     return 0;
173 }
174 #endif
175 
176 #ifdef TARGET_ARM
177 static inline target_ulong
178 common_semi_arg(CPUState *cs, int argno)
179 {
180     ARMCPU *cpu = ARM_CPU(cs);
181     CPUARMState *env = &cpu->env;
182     if (is_a64(env)) {
183         return env->xregs[argno];
184     } else {
185         return env->regs[argno];
186     }
187 }
188 
189 static inline void
190 common_semi_set_ret(CPUState *cs, target_ulong ret)
191 {
192     ARMCPU *cpu = ARM_CPU(cs);
193     CPUARMState *env = &cpu->env;
194     if (is_a64(env)) {
195         env->xregs[0] = ret;
196     } else {
197         env->regs[0] = ret;
198     }
199 }
200 
201 static inline bool
202 common_semi_sys_exit_extended(CPUState *cs, int nr)
203 {
204     return (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(cs->env_ptr));
205 }
206 
207 #ifndef CONFIG_USER_ONLY
208 #include "hw/arm/boot.h"
209 static inline target_ulong
210 common_semi_rambase(CPUState *cs)
211 {
212     CPUArchState *env = cs->env_ptr;
213     const struct arm_boot_info *info = env->boot_info;
214     target_ulong sp;
215 
216     if (info) {
217         return info->loader_start;
218     }
219 
220     if (is_a64(env)) {
221         sp = env->xregs[31];
222     } else {
223         sp = env->regs[13];
224     }
225     return common_semi_find_region_base(sp);
226 }
227 #endif
228 
229 #endif /* TARGET_ARM */
230 
231 #ifdef TARGET_RISCV
232 static inline target_ulong
233 common_semi_arg(CPUState *cs, int argno)
234 {
235     RISCVCPU *cpu = RISCV_CPU(cs);
236     CPURISCVState *env = &cpu->env;
237     return env->gpr[xA0 + argno];
238 }
239 
240 static inline void
241 common_semi_set_ret(CPUState *cs, target_ulong ret)
242 {
243     RISCVCPU *cpu = RISCV_CPU(cs);
244     CPURISCVState *env = &cpu->env;
245     env->gpr[xA0] = ret;
246 }
247 
248 static inline bool
249 common_semi_sys_exit_extended(CPUState *cs, int nr)
250 {
251     return (nr == TARGET_SYS_EXIT_EXTENDED || sizeof(target_ulong) == 8);
252 }
253 
254 #ifndef CONFIG_USER_ONLY
255 
256 static inline target_ulong
257 common_semi_rambase(CPUState *cs)
258 {
259     RISCVCPU *cpu = RISCV_CPU(cs);
260     CPURISCVState *env = &cpu->env;
261     return common_semi_find_region_base(env->gpr[xSP]);
262 }
263 #endif
264 
265 #endif
266 
267 /*
268  * Allocate a new guest file descriptor and return it; if we
269  * couldn't allocate a new fd then return -1.
270  * This is a fairly simplistic implementation because we don't
271  * expect that most semihosting guest programs will make very
272  * heavy use of opening and closing fds.
273  */
274 static int alloc_guestfd(void)
275 {
276     guint i;
277 
278     if (!guestfd_array) {
279         /* New entries zero-initialized, i.e. type GuestFDUnused */
280         guestfd_array = g_array_new(FALSE, TRUE, sizeof(GuestFD));
281     }
282 
283     /* SYS_OPEN should return nonzero handle on success. Start guestfd from 1 */
284     for (i = 1; i < guestfd_array->len; i++) {
285         GuestFD *gf = &g_array_index(guestfd_array, GuestFD, i);
286 
287         if (gf->type == GuestFDUnused) {
288             return i;
289         }
290     }
291 
292     /* All elements already in use: expand the array */
293     g_array_set_size(guestfd_array, i + 1);
294     return i;
295 }
296 
297 /*
298  * Look up the guestfd in the data structure; return NULL
299  * for out of bounds, but don't check whether the slot is unused.
300  * This is used internally by the other guestfd functions.
301  */
302 static GuestFD *do_get_guestfd(int guestfd)
303 {
304     if (!guestfd_array) {
305         return NULL;
306     }
307 
308     if (guestfd <= 0 || guestfd >= guestfd_array->len) {
309         return NULL;
310     }
311 
312     return &g_array_index(guestfd_array, GuestFD, guestfd);
313 }
314 
315 /*
316  * Associate the specified guest fd (which must have been
317  * allocated via alloc_fd() and not previously used) with
318  * the specified host/gdb fd.
319  */
320 static void associate_guestfd(int guestfd, int hostfd)
321 {
322     GuestFD *gf = do_get_guestfd(guestfd);
323 
324     assert(gf);
325     gf->type = use_gdb_syscalls() ? GuestFDGDB : GuestFDHost;
326     gf->hostfd = hostfd;
327 }
328 
329 /*
330  * Deallocate the specified guest file descriptor. This doesn't
331  * close the host fd, it merely undoes the work of alloc_fd().
332  */
333 static void dealloc_guestfd(int guestfd)
334 {
335     GuestFD *gf = do_get_guestfd(guestfd);
336 
337     assert(gf);
338     gf->type = GuestFDUnused;
339 }
340 
341 /*
342  * Given a guest file descriptor, get the associated struct.
343  * If the fd is not valid, return NULL. This is the function
344  * used by the various semihosting calls to validate a handle
345  * from the guest.
346  * Note: calling alloc_guestfd() or dealloc_guestfd() will
347  * invalidate any GuestFD* obtained by calling this function.
348  */
349 static GuestFD *get_guestfd(int guestfd)
350 {
351     GuestFD *gf = do_get_guestfd(guestfd);
352 
353     if (!gf || gf->type == GuestFDUnused) {
354         return NULL;
355     }
356     return gf;
357 }
358 
359 /*
360  * The semihosting API has no concept of its errno being thread-safe,
361  * as the API design predates SMP CPUs and was intended as a simple
362  * real-hardware set of debug functionality. For QEMU, we make the
363  * errno be per-thread in linux-user mode; in softmmu it is a simple
364  * global, and we assume that the guest takes care of avoiding any races.
365  */
366 #ifndef CONFIG_USER_ONLY
367 static target_ulong syscall_err;
368 
369 #include "exec/softmmu-semi.h"
370 #endif
371 
372 static inline uint32_t set_swi_errno(CPUState *cs, uint32_t code)
373 {
374     if (code == (uint32_t)-1) {
375 #ifdef CONFIG_USER_ONLY
376         TaskState *ts = cs->opaque;
377 
378         ts->swi_errno = errno;
379 #else
380         syscall_err = errno;
381 #endif
382     }
383     return code;
384 }
385 
386 static inline uint32_t get_swi_errno(CPUState *cs)
387 {
388 #ifdef CONFIG_USER_ONLY
389     TaskState *ts = cs->opaque;
390 
391     return ts->swi_errno;
392 #else
393     return syscall_err;
394 #endif
395 }
396 
397 static target_ulong common_semi_syscall_len;
398 
399 static void common_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
400 {
401     target_ulong reg0 = common_semi_arg(cs, 0);
402 
403     if (ret == (target_ulong)-1) {
404         errno = err;
405         set_swi_errno(cs, -1);
406         reg0 = ret;
407     } else {
408         /* Fixup syscalls that use nonstardard return conventions.  */
409         switch (reg0) {
410         case TARGET_SYS_WRITE:
411         case TARGET_SYS_READ:
412             reg0 = common_semi_syscall_len - ret;
413             break;
414         case TARGET_SYS_SEEK:
415             reg0 = 0;
416             break;
417         default:
418             reg0 = ret;
419             break;
420         }
421     }
422     common_semi_set_ret(cs, reg0);
423 }
424 
425 static target_ulong common_semi_flen_buf(CPUState *cs)
426 {
427     target_ulong sp;
428 #ifdef TARGET_ARM
429     /* Return an address in target memory of 64 bytes where the remote
430      * gdb should write its stat struct. (The format of this structure
431      * is defined by GDB's remote protocol and is not target-specific.)
432      * We put this on the guest's stack just below SP.
433      */
434     ARMCPU *cpu = ARM_CPU(cs);
435     CPUARMState *env = &cpu->env;
436 
437     if (is_a64(env)) {
438         sp = env->xregs[31];
439     } else {
440         sp = env->regs[13];
441     }
442 #endif
443 #ifdef TARGET_RISCV
444     RISCVCPU *cpu = RISCV_CPU(cs);
445     CPURISCVState *env = &cpu->env;
446 
447     sp = env->gpr[xSP];
448 #endif
449 
450     return sp - 64;
451 }
452 
453 static void
454 common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
455 {
456     /* The size is always stored in big-endian order, extract
457        the value. We assume the size always fit in 32 bits.  */
458     uint32_t size;
459     cpu_memory_rw_debug(cs, common_semi_flen_buf(cs) + 32,
460                         (uint8_t *)&size, 4, 0);
461     size = be32_to_cpu(size);
462     common_semi_set_ret(cs, size);
463     errno = err;
464     set_swi_errno(cs, -1);
465 }
466 
467 static int common_semi_open_guestfd;
468 
469 static void
470 common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
471 {
472     if (ret == (target_ulong)-1) {
473         errno = err;
474         set_swi_errno(cs, -1);
475         dealloc_guestfd(common_semi_open_guestfd);
476     } else {
477         associate_guestfd(common_semi_open_guestfd, ret);
478         ret = common_semi_open_guestfd;
479     }
480     common_semi_set_ret(cs, ret);
481 }
482 
483 static target_ulong
484 common_semi_gdb_syscall(CPUState *cs, gdb_syscall_complete_cb cb,
485                         const char *fmt, ...)
486 {
487     va_list va;
488 
489     va_start(va, fmt);
490     gdb_do_syscallv(cb, fmt, va);
491     va_end(va);
492 
493     /*
494      * FIXME: in softmmu mode, the gdbstub will schedule our callback
495      * to occur, but will not actually call it to complete the syscall
496      * until after this function has returned and we are back in the
497      * CPU main loop. Therefore callers to this function must not
498      * do anything with its return value, because it is not necessarily
499      * the result of the syscall, but could just be the old value of X0.
500      * The only thing safe to do with this is that the callers of
501      * do_common_semihosting() will write it straight back into X0.
502      * (In linux-user mode, the callback will have happened before
503      * gdb_do_syscallv() returns.)
504      *
505      * We should tidy this up so neither this function nor
506      * do_common_semihosting() return a value, so the mistake of
507      * doing something with the return value is not possible to make.
508      */
509 
510     return common_semi_arg(cs, 0);
511 }
512 
513 /*
514  * Types for functions implementing various semihosting calls
515  * for specific types of guest file descriptor. These must all
516  * do the work and return the required return value for the guest,
517  * setting the guest errno if appropriate.
518  */
519 typedef uint32_t sys_closefn(CPUState *cs, GuestFD *gf);
520 typedef uint32_t sys_writefn(CPUState *cs, GuestFD *gf,
521                              target_ulong buf, uint32_t len);
522 typedef uint32_t sys_readfn(CPUState *cs, GuestFD *gf,
523                             target_ulong buf, uint32_t len);
524 typedef uint32_t sys_isattyfn(CPUState *cs, GuestFD *gf);
525 typedef uint32_t sys_seekfn(CPUState *cs, GuestFD *gf,
526                             target_ulong offset);
527 typedef uint32_t sys_flenfn(CPUState *cs, GuestFD *gf);
528 
529 static uint32_t host_closefn(CPUState *cs, GuestFD *gf)
530 {
531     /*
532      * Only close the underlying host fd if it's one we opened on behalf
533      * of the guest in SYS_OPEN.
534      */
535     if (gf->hostfd == STDIN_FILENO ||
536         gf->hostfd == STDOUT_FILENO ||
537         gf->hostfd == STDERR_FILENO) {
538         return 0;
539     }
540     return set_swi_errno(cs, close(gf->hostfd));
541 }
542 
543 static uint32_t host_writefn(CPUState *cs, GuestFD *gf,
544                              target_ulong buf, uint32_t len)
545 {
546     CPUArchState *env = cs->env_ptr;
547     uint32_t ret;
548     char *s = lock_user(VERIFY_READ, buf, len, 1);
549     (void) env; /* Used in arm softmmu lock_user implicitly */
550     if (!s) {
551         /* Return bytes not written on error */
552         return len;
553     }
554     ret = set_swi_errno(cs, write(gf->hostfd, s, len));
555     unlock_user(s, buf, 0);
556     if (ret == (uint32_t)-1) {
557         ret = 0;
558     }
559     /* Return bytes not written */
560     return len - ret;
561 }
562 
563 static uint32_t host_readfn(CPUState *cs, GuestFD *gf,
564                             target_ulong buf, uint32_t len)
565 {
566     CPUArchState *env = cs->env_ptr;
567     uint32_t ret;
568     char *s = lock_user(VERIFY_WRITE, buf, len, 0);
569     (void) env; /* Used in arm softmmu lock_user implicitly */
570     if (!s) {
571         /* return bytes not read */
572         return len;
573     }
574     do {
575         ret = set_swi_errno(cs, read(gf->hostfd, s, len));
576     } while (ret == -1 && errno == EINTR);
577     unlock_user(s, buf, len);
578     if (ret == (uint32_t)-1) {
579         ret = 0;
580     }
581     /* Return bytes not read */
582     return len - ret;
583 }
584 
585 static uint32_t host_isattyfn(CPUState *cs, GuestFD *gf)
586 {
587     return isatty(gf->hostfd);
588 }
589 
590 static uint32_t host_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
591 {
592     uint32_t ret = set_swi_errno(cs, lseek(gf->hostfd, offset, SEEK_SET));
593     if (ret == (uint32_t)-1) {
594         return -1;
595     }
596     return 0;
597 }
598 
599 static uint32_t host_flenfn(CPUState *cs, GuestFD *gf)
600 {
601     struct stat buf;
602     uint32_t ret = set_swi_errno(cs, fstat(gf->hostfd, &buf));
603     if (ret == (uint32_t)-1) {
604         return -1;
605     }
606     return buf.st_size;
607 }
608 
609 static uint32_t gdb_closefn(CPUState *cs, GuestFD *gf)
610 {
611     return common_semi_gdb_syscall(cs, common_semi_cb, "close,%x", gf->hostfd);
612 }
613 
614 static uint32_t gdb_writefn(CPUState *cs, GuestFD *gf,
615                             target_ulong buf, uint32_t len)
616 {
617     common_semi_syscall_len = len;
618     return common_semi_gdb_syscall(cs, common_semi_cb, "write,%x,%x,%x",
619                                    gf->hostfd, buf, len);
620 }
621 
622 static uint32_t gdb_readfn(CPUState *cs, GuestFD *gf,
623                            target_ulong buf, uint32_t len)
624 {
625     common_semi_syscall_len = len;
626     return common_semi_gdb_syscall(cs, common_semi_cb, "read,%x,%x,%x",
627                                    gf->hostfd, buf, len);
628 }
629 
630 static uint32_t gdb_isattyfn(CPUState *cs, GuestFD *gf)
631 {
632     return common_semi_gdb_syscall(cs, common_semi_cb, "isatty,%x", gf->hostfd);
633 }
634 
635 static uint32_t gdb_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
636 {
637     return common_semi_gdb_syscall(cs, common_semi_cb, "lseek,%x,%x,0",
638                                    gf->hostfd, offset);
639 }
640 
641 static uint32_t gdb_flenfn(CPUState *cs, GuestFD *gf)
642 {
643     return common_semi_gdb_syscall(cs, common_semi_flen_cb, "fstat,%x,%x",
644                                    gf->hostfd, common_semi_flen_buf(cs));
645 }
646 
647 #define SHFB_MAGIC_0 0x53
648 #define SHFB_MAGIC_1 0x48
649 #define SHFB_MAGIC_2 0x46
650 #define SHFB_MAGIC_3 0x42
651 
652 /* Feature bits reportable in feature byte 0 */
653 #define SH_EXT_EXIT_EXTENDED (1 << 0)
654 #define SH_EXT_STDOUT_STDERR (1 << 1)
655 
656 static const uint8_t featurefile_data[] = {
657     SHFB_MAGIC_0,
658     SHFB_MAGIC_1,
659     SHFB_MAGIC_2,
660     SHFB_MAGIC_3,
661     SH_EXT_EXIT_EXTENDED | SH_EXT_STDOUT_STDERR, /* Feature byte 0 */
662 };
663 
664 static void init_featurefile_guestfd(int guestfd)
665 {
666     GuestFD *gf = do_get_guestfd(guestfd);
667 
668     assert(gf);
669     gf->type = GuestFDFeatureFile;
670     gf->featurefile_offset = 0;
671 }
672 
673 static uint32_t featurefile_closefn(CPUState *cs, GuestFD *gf)
674 {
675     /* Nothing to do */
676     return 0;
677 }
678 
679 static uint32_t featurefile_writefn(CPUState *cs, GuestFD *gf,
680                                     target_ulong buf, uint32_t len)
681 {
682     /* This fd can never be open for writing */
683 
684     errno = EBADF;
685     return set_swi_errno(cs, -1);
686 }
687 
688 static uint32_t featurefile_readfn(CPUState *cs, GuestFD *gf,
689                                    target_ulong buf, uint32_t len)
690 {
691     CPUArchState *env = cs->env_ptr;
692     uint32_t i;
693     char *s;
694 
695     (void) env; /* Used in arm softmmu lock_user implicitly */
696     s = lock_user(VERIFY_WRITE, buf, len, 0);
697     if (!s) {
698         return len;
699     }
700 
701     for (i = 0; i < len; i++) {
702         if (gf->featurefile_offset >= sizeof(featurefile_data)) {
703             break;
704         }
705         s[i] = featurefile_data[gf->featurefile_offset];
706         gf->featurefile_offset++;
707     }
708 
709     unlock_user(s, buf, len);
710 
711     /* Return number of bytes not read */
712     return len - i;
713 }
714 
715 static uint32_t featurefile_isattyfn(CPUState *cs, GuestFD *gf)
716 {
717     return 0;
718 }
719 
720 static uint32_t featurefile_seekfn(CPUState *cs, GuestFD *gf,
721                                    target_ulong offset)
722 {
723     gf->featurefile_offset = offset;
724     return 0;
725 }
726 
727 static uint32_t featurefile_flenfn(CPUState *cs, GuestFD *gf)
728 {
729     return sizeof(featurefile_data);
730 }
731 
732 typedef struct GuestFDFunctions {
733     sys_closefn *closefn;
734     sys_writefn *writefn;
735     sys_readfn *readfn;
736     sys_isattyfn *isattyfn;
737     sys_seekfn *seekfn;
738     sys_flenfn *flenfn;
739 } GuestFDFunctions;
740 
741 static const GuestFDFunctions guestfd_fns[] = {
742     [GuestFDHost] = {
743         .closefn = host_closefn,
744         .writefn = host_writefn,
745         .readfn = host_readfn,
746         .isattyfn = host_isattyfn,
747         .seekfn = host_seekfn,
748         .flenfn = host_flenfn,
749     },
750     [GuestFDGDB] = {
751         .closefn = gdb_closefn,
752         .writefn = gdb_writefn,
753         .readfn = gdb_readfn,
754         .isattyfn = gdb_isattyfn,
755         .seekfn = gdb_seekfn,
756         .flenfn = gdb_flenfn,
757     },
758     [GuestFDFeatureFile] = {
759         .closefn = featurefile_closefn,
760         .writefn = featurefile_writefn,
761         .readfn = featurefile_readfn,
762         .isattyfn = featurefile_isattyfn,
763         .seekfn = featurefile_seekfn,
764         .flenfn = featurefile_flenfn,
765     },
766 };
767 
768 /*
769  * Read the input value from the argument block; fail the semihosting
770  * call if the memory read fails. Eventually we could use a generic
771  * CPUState helper function here.
772  */
773 static inline bool is_64bit_semihosting(CPUArchState *env)
774 {
775 #if defined(TARGET_ARM)
776     return is_a64(env);
777 #elif defined(TARGET_RISCV)
778     return !riscv_cpu_is_32bit(env);
779 #else
780 #error un-handled architecture
781 #endif
782 }
783 
784 
785 #define GET_ARG(n) do {                                 \
786     if (is_64bit_semihosting(env)) {                    \
787         if (get_user_u64(arg ## n, args + (n) * 8)) {   \
788             errno = EFAULT;                             \
789             return set_swi_errno(cs, -1);               \
790         }                                               \
791     } else {                                            \
792         if (get_user_u32(arg ## n, args + (n) * 4)) {   \
793             errno = EFAULT;                             \
794             return set_swi_errno(cs, -1);              \
795         }                                               \
796     }                                                   \
797 } while (0)
798 
799 #define SET_ARG(n, val)                                 \
800     (is_64bit_semihosting(env) ?                        \
801      put_user_u64(val, args + (n) * 8) :                \
802      put_user_u32(val, args + (n) * 4))
803 
804 
805 /*
806  * Do a semihosting call.
807  *
808  * The specification always says that the "return register" either
809  * returns a specific value or is corrupted, so we don't need to
810  * report to our caller whether we are returning a value or trying to
811  * leave the register unchanged. We use 0xdeadbeef as the return value
812  * when there isn't a defined return value for the call.
813  */
814 target_ulong do_common_semihosting(CPUState *cs)
815 {
816     CPUArchState *env = cs->env_ptr;
817     target_ulong args;
818     target_ulong arg0, arg1, arg2, arg3;
819     target_ulong ul_ret;
820     char * s;
821     int nr;
822     uint32_t ret;
823     uint32_t len;
824     GuestFD *gf;
825     int64_t elapsed;
826 
827     (void) env; /* Used implicitly by arm lock_user macro */
828     nr = common_semi_arg(cs, 0) & 0xffffffffU;
829     args = common_semi_arg(cs, 1);
830 
831     switch (nr) {
832     case TARGET_SYS_OPEN:
833     {
834         int guestfd;
835 
836         GET_ARG(0);
837         GET_ARG(1);
838         GET_ARG(2);
839         s = lock_user_string(arg0);
840         if (!s) {
841             errno = EFAULT;
842             return set_swi_errno(cs, -1);
843         }
844         if (arg1 >= 12) {
845             unlock_user(s, arg0, 0);
846             errno = EINVAL;
847             return set_swi_errno(cs, -1);
848         }
849 
850         guestfd = alloc_guestfd();
851         if (guestfd < 0) {
852             unlock_user(s, arg0, 0);
853             errno = EMFILE;
854             return set_swi_errno(cs, -1);
855         }
856 
857         if (strcmp(s, ":tt") == 0) {
858             int result_fileno;
859 
860             /*
861              * We implement SH_EXT_STDOUT_STDERR, so:
862              *  open for read == stdin
863              *  open for write == stdout
864              *  open for append == stderr
865              */
866             if (arg1 < 4) {
867                 result_fileno = STDIN_FILENO;
868             } else if (arg1 < 8) {
869                 result_fileno = STDOUT_FILENO;
870             } else {
871                 result_fileno = STDERR_FILENO;
872             }
873             associate_guestfd(guestfd, result_fileno);
874             unlock_user(s, arg0, 0);
875             return guestfd;
876         }
877         if (strcmp(s, ":semihosting-features") == 0) {
878             unlock_user(s, arg0, 0);
879             /* We must fail opens for modes other than 0 ('r') or 1 ('rb') */
880             if (arg1 != 0 && arg1 != 1) {
881                 dealloc_guestfd(guestfd);
882                 errno = EACCES;
883                 return set_swi_errno(cs, -1);
884             }
885             init_featurefile_guestfd(guestfd);
886             return guestfd;
887         }
888 
889         if (use_gdb_syscalls()) {
890             common_semi_open_guestfd = guestfd;
891             ret = common_semi_gdb_syscall(cs, common_semi_open_cb,
892                                           "open,%s,%x,1a4", arg0, (int)arg2 + 1,
893                                           gdb_open_modeflags[arg1]);
894         } else {
895             ret = set_swi_errno(cs, open(s, open_modeflags[arg1], 0644));
896             if (ret == (uint32_t)-1) {
897                 dealloc_guestfd(guestfd);
898             } else {
899                 associate_guestfd(guestfd, ret);
900                 ret = guestfd;
901             }
902         }
903         unlock_user(s, arg0, 0);
904         return ret;
905     }
906     case TARGET_SYS_CLOSE:
907         GET_ARG(0);
908 
909         gf = get_guestfd(arg0);
910         if (!gf) {
911             errno = EBADF;
912             return set_swi_errno(cs, -1);
913         }
914 
915         ret = guestfd_fns[gf->type].closefn(cs, gf);
916         dealloc_guestfd(arg0);
917         return ret;
918     case TARGET_SYS_WRITEC:
919         qemu_semihosting_console_outc(cs->env_ptr, args);
920         return 0xdeadbeef;
921     case TARGET_SYS_WRITE0:
922         return qemu_semihosting_console_outs(cs->env_ptr, args);
923     case TARGET_SYS_WRITE:
924         GET_ARG(0);
925         GET_ARG(1);
926         GET_ARG(2);
927         len = arg2;
928 
929         gf = get_guestfd(arg0);
930         if (!gf) {
931             errno = EBADF;
932             return set_swi_errno(cs, -1);
933         }
934 
935         return guestfd_fns[gf->type].writefn(cs, gf, arg1, len);
936     case TARGET_SYS_READ:
937         GET_ARG(0);
938         GET_ARG(1);
939         GET_ARG(2);
940         len = arg2;
941 
942         gf = get_guestfd(arg0);
943         if (!gf) {
944             errno = EBADF;
945             return set_swi_errno(cs, -1);
946         }
947 
948         return guestfd_fns[gf->type].readfn(cs, gf, arg1, len);
949     case TARGET_SYS_READC:
950         return qemu_semihosting_console_inc(cs->env_ptr);
951     case TARGET_SYS_ISERROR:
952         GET_ARG(0);
953         return (target_long) arg0 < 0 ? 1 : 0;
954     case TARGET_SYS_ISTTY:
955         GET_ARG(0);
956 
957         gf = get_guestfd(arg0);
958         if (!gf) {
959             errno = EBADF;
960             return set_swi_errno(cs, -1);
961         }
962 
963         return guestfd_fns[gf->type].isattyfn(cs, gf);
964     case TARGET_SYS_SEEK:
965         GET_ARG(0);
966         GET_ARG(1);
967 
968         gf = get_guestfd(arg0);
969         if (!gf) {
970             errno = EBADF;
971             return set_swi_errno(cs, -1);
972         }
973 
974         return guestfd_fns[gf->type].seekfn(cs, gf, arg1);
975     case TARGET_SYS_FLEN:
976         GET_ARG(0);
977 
978         gf = get_guestfd(arg0);
979         if (!gf) {
980             errno = EBADF;
981             return set_swi_errno(cs, -1);
982         }
983 
984         return guestfd_fns[gf->type].flenfn(cs, gf);
985     case TARGET_SYS_TMPNAM:
986         GET_ARG(0);
987         GET_ARG(1);
988         GET_ARG(2);
989         if (asprintf(&s, "/tmp/qemu-%x%02x", getpid(),
990                      (int) (arg1 & 0xff)) < 0) {
991             return -1;
992         }
993         ul_ret = (target_ulong) -1;
994 
995         /* Make sure there's enough space in the buffer */
996         if (strlen(s) < arg2) {
997             char *output = lock_user(VERIFY_WRITE, arg0, arg2, 0);
998             strcpy(output, s);
999             unlock_user(output, arg0, arg2);
1000             ul_ret = 0;
1001         }
1002         free(s);
1003         return ul_ret;
1004     case TARGET_SYS_REMOVE:
1005         GET_ARG(0);
1006         GET_ARG(1);
1007         if (use_gdb_syscalls()) {
1008             ret = common_semi_gdb_syscall(cs, common_semi_cb, "unlink,%s",
1009                                           arg0, (int)arg1 + 1);
1010         } else {
1011             s = lock_user_string(arg0);
1012             if (!s) {
1013                 errno = EFAULT;
1014                 return set_swi_errno(cs, -1);
1015             }
1016             ret =  set_swi_errno(cs, remove(s));
1017             unlock_user(s, arg0, 0);
1018         }
1019         return ret;
1020     case TARGET_SYS_RENAME:
1021         GET_ARG(0);
1022         GET_ARG(1);
1023         GET_ARG(2);
1024         GET_ARG(3);
1025         if (use_gdb_syscalls()) {
1026             return common_semi_gdb_syscall(cs, common_semi_cb, "rename,%s,%s",
1027                                            arg0, (int)arg1 + 1, arg2,
1028                                            (int)arg3 + 1);
1029         } else {
1030             char *s2;
1031             s = lock_user_string(arg0);
1032             s2 = lock_user_string(arg2);
1033             if (!s || !s2) {
1034                 errno = EFAULT;
1035                 ret = set_swi_errno(cs, -1);
1036             } else {
1037                 ret = set_swi_errno(cs, rename(s, s2));
1038             }
1039             if (s2)
1040                 unlock_user(s2, arg2, 0);
1041             if (s)
1042                 unlock_user(s, arg0, 0);
1043             return ret;
1044         }
1045     case TARGET_SYS_CLOCK:
1046         return clock() / (CLOCKS_PER_SEC / 100);
1047     case TARGET_SYS_TIME:
1048         return set_swi_errno(cs, time(NULL));
1049     case TARGET_SYS_SYSTEM:
1050         GET_ARG(0);
1051         GET_ARG(1);
1052         if (use_gdb_syscalls()) {
1053             return common_semi_gdb_syscall(cs, common_semi_cb, "system,%s",
1054                                            arg0, (int)arg1 + 1);
1055         } else {
1056             s = lock_user_string(arg0);
1057             if (!s) {
1058                 errno = EFAULT;
1059                 return set_swi_errno(cs, -1);
1060             }
1061             ret = set_swi_errno(cs, system(s));
1062             unlock_user(s, arg0, 0);
1063             return ret;
1064         }
1065     case TARGET_SYS_ERRNO:
1066         return get_swi_errno(cs);
1067     case TARGET_SYS_GET_CMDLINE:
1068         {
1069             /* Build a command-line from the original argv.
1070              *
1071              * The inputs are:
1072              *     * arg0, pointer to a buffer of at least the size
1073              *               specified in arg1.
1074              *     * arg1, size of the buffer pointed to by arg0 in
1075              *               bytes.
1076              *
1077              * The outputs are:
1078              *     * arg0, pointer to null-terminated string of the
1079              *               command line.
1080              *     * arg1, length of the string pointed to by arg0.
1081              */
1082 
1083             char *output_buffer;
1084             size_t input_size;
1085             size_t output_size;
1086             int status = 0;
1087 #if !defined(CONFIG_USER_ONLY)
1088             const char *cmdline;
1089 #else
1090             TaskState *ts = cs->opaque;
1091 #endif
1092             GET_ARG(0);
1093             GET_ARG(1);
1094             input_size = arg1;
1095             /* Compute the size of the output string.  */
1096 #if !defined(CONFIG_USER_ONLY)
1097             cmdline = semihosting_get_cmdline();
1098             if (cmdline == NULL) {
1099                 cmdline = ""; /* Default to an empty line. */
1100             }
1101             output_size = strlen(cmdline) + 1; /* Count terminating 0. */
1102 #else
1103             unsigned int i;
1104 
1105             output_size = ts->info->arg_end - ts->info->arg_start;
1106             if (!output_size) {
1107                 /*
1108                  * We special-case the "empty command line" case (argc==0).
1109                  * Just provide the terminating 0.
1110                  */
1111                 output_size = 1;
1112             }
1113 #endif
1114 
1115             if (output_size > input_size) {
1116                 /* Not enough space to store command-line arguments.  */
1117                 errno = E2BIG;
1118                 return set_swi_errno(cs, -1);
1119             }
1120 
1121             /* Adjust the command-line length.  */
1122             if (SET_ARG(1, output_size - 1)) {
1123                 /* Couldn't write back to argument block */
1124                 errno = EFAULT;
1125                 return set_swi_errno(cs, -1);
1126             }
1127 
1128             /* Lock the buffer on the ARM side.  */
1129             output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);
1130             if (!output_buffer) {
1131                 errno = EFAULT;
1132                 return set_swi_errno(cs, -1);
1133             }
1134 
1135             /* Copy the command-line arguments.  */
1136 #if !defined(CONFIG_USER_ONLY)
1137             pstrcpy(output_buffer, output_size, cmdline);
1138 #else
1139             if (output_size == 1) {
1140                 /* Empty command-line.  */
1141                 output_buffer[0] = '\0';
1142                 goto out;
1143             }
1144 
1145             if (copy_from_user(output_buffer, ts->info->arg_start,
1146                                output_size)) {
1147                 errno = EFAULT;
1148                 status = set_swi_errno(cs, -1);
1149                 goto out;
1150             }
1151 
1152             /* Separate arguments by white spaces.  */
1153             for (i = 0; i < output_size - 1; i++) {
1154                 if (output_buffer[i] == 0) {
1155                     output_buffer[i] = ' ';
1156                 }
1157             }
1158         out:
1159 #endif
1160             /* Unlock the buffer on the ARM side.  */
1161             unlock_user(output_buffer, arg0, output_size);
1162 
1163             return status;
1164         }
1165     case TARGET_SYS_HEAPINFO:
1166         {
1167             target_ulong retvals[4];
1168             target_ulong limit;
1169             int i;
1170 #ifdef CONFIG_USER_ONLY
1171             TaskState *ts = cs->opaque;
1172 #else
1173             target_ulong rambase = common_semi_rambase(cs);
1174 #endif
1175 
1176             GET_ARG(0);
1177 
1178 #ifdef CONFIG_USER_ONLY
1179             /*
1180              * Some C libraries assume the heap immediately follows .bss, so
1181              * allocate it using sbrk.
1182              */
1183             if (!ts->heap_limit) {
1184                 abi_ulong ret;
1185 
1186                 ts->heap_base = do_brk(0);
1187                 limit = ts->heap_base + COMMON_SEMI_HEAP_SIZE;
1188                 /* Try a big heap, and reduce the size if that fails.  */
1189                 for (;;) {
1190                     ret = do_brk(limit);
1191                     if (ret >= limit) {
1192                         break;
1193                     }
1194                     limit = (ts->heap_base >> 1) + (limit >> 1);
1195                 }
1196                 ts->heap_limit = limit;
1197             }
1198 
1199             retvals[0] = ts->heap_base;
1200             retvals[1] = ts->heap_limit;
1201             retvals[2] = ts->stack_base;
1202             retvals[3] = 0; /* Stack limit.  */
1203 #else
1204             limit = current_machine->ram_size;
1205             /* TODO: Make this use the limit of the loaded application.  */
1206             retvals[0] = rambase + limit / 2;
1207             retvals[1] = rambase + limit;
1208             retvals[2] = rambase + limit; /* Stack base */
1209             retvals[3] = rambase; /* Stack limit.  */
1210 #endif
1211 
1212             for (i = 0; i < ARRAY_SIZE(retvals); i++) {
1213                 bool fail;
1214 
1215                 if (is_64bit_semihosting(env)) {
1216                     fail = put_user_u64(retvals[i], arg0 + i * 8);
1217                 } else {
1218                     fail = put_user_u32(retvals[i], arg0 + i * 4);
1219                 }
1220 
1221                 if (fail) {
1222                     /* Couldn't write back to argument block */
1223                     errno = EFAULT;
1224                     return set_swi_errno(cs, -1);
1225                 }
1226             }
1227             return 0;
1228         }
1229     case TARGET_SYS_EXIT:
1230     case TARGET_SYS_EXIT_EXTENDED:
1231         if (common_semi_sys_exit_extended(cs, nr)) {
1232             /*
1233              * The A64 version of SYS_EXIT takes a parameter block,
1234              * so the application-exit type can return a subcode which
1235              * is the exit status code from the application.
1236              * SYS_EXIT_EXTENDED is an a new-in-v2.0 optional function
1237              * which allows A32/T32 guests to also provide a status code.
1238              */
1239             GET_ARG(0);
1240             GET_ARG(1);
1241 
1242             if (arg0 == ADP_Stopped_ApplicationExit) {
1243                 ret = arg1;
1244             } else {
1245                 ret = 1;
1246             }
1247         } else {
1248             /*
1249              * The A32/T32 version of SYS_EXIT specifies only
1250              * Stopped_ApplicationExit as normal exit, but does not
1251              * allow the guest to specify the exit status code.
1252              * Everything else is considered an error.
1253              */
1254             ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
1255         }
1256         gdb_exit(ret);
1257         exit(ret);
1258     case TARGET_SYS_ELAPSED:
1259         elapsed = get_clock() - clock_start;
1260         if (sizeof(target_ulong) == 8) {
1261             SET_ARG(0, elapsed);
1262         } else {
1263             SET_ARG(0, (uint32_t) elapsed);
1264             SET_ARG(1, (uint32_t) (elapsed >> 32));
1265         }
1266         return 0;
1267     case TARGET_SYS_TICKFREQ:
1268         /* qemu always uses nsec */
1269         return 1000000000;
1270     case TARGET_SYS_SYNCCACHE:
1271         /*
1272          * Clean the D-cache and invalidate the I-cache for the specified
1273          * virtual address range. This is a nop for us since we don't
1274          * implement caches. This is only present on A64.
1275          */
1276 #ifdef TARGET_ARM
1277         if (is_a64(cs->env_ptr)) {
1278             return 0;
1279         }
1280 #endif
1281 #ifdef TARGET_RISCV
1282         return 0;
1283 #endif
1284         /* fall through -- invalid for A32/T32 */
1285     default:
1286         fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
1287         cpu_dump_state(cs, stderr, 0);
1288         abort();
1289     }
1290 }
1291