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