target/arm: Use gen_gvec_ool_arg_zzz for do_zip, do_zip_q
[qemu.git] / semihosting / arm-compat-semi.c
blobb6ddaf863ade2abab32e65c787aa52fa5e2d5a0a
1 /*
2 * Semihosting support for systems modeled on the Arm "Angel"
3 * semihosting syscalls design. This includes Arm and RISC-V processors
5 * Copyright (c) 2005, 2007 CodeSourcery.
6 * Copyright (c) 2019 Linaro
7 * Written by Paul Brook.
9 * Copyright © 2020 by Keith Packard <keithp@keithp.com>
10 * Adapted for systems other than ARM, including RISC-V, by Keith Packard
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.
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.
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/>.
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
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
34 #include "qemu/osdep.h"
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"
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
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
80 /* ADP_Stopped_ApplicationExit is used for exit(0),
81 * anything else is implemented as exit(1) */
82 #define ADP_Stopped_ApplicationExit (0x20026)
84 #ifndef O_BINARY
85 #define O_BINARY 0
86 #endif
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
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
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
126 typedef enum GuestFDType {
127 GuestFDUnused = 0,
128 GuestFDHost = 1,
129 GuestFDGDB = 2,
130 GuestFDFeatureFile = 3,
131 } GuestFDType;
134 * Guest file descriptors are integer indexes into an array of
135 * these structures (we will dynamically resize as necessary).
137 typedef struct GuestFD {
138 GuestFDType type;
139 union {
140 int hostfd;
141 target_ulong featurefile_offset;
143 } GuestFD;
145 static GArray *guestfd_array;
147 #ifndef CONFIG_USER_ONLY
150 * common_semi_find_bases: find information about ram and heap base
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.
158 * Returns: a structure with the numbers we need.
161 typedef struct LayoutInfo {
162 target_ulong rambase;
163 size_t ramsize;
164 hwaddr heapbase;
165 hwaddr heaplimit;
166 } LayoutInfo;
168 static bool find_ram_cb(Int128 start, Int128 len, const MemoryRegion *mr,
169 hwaddr offset_in_region, void *opaque)
171 LayoutInfo *info = (LayoutInfo *) opaque;
172 uint64_t size = int128_get64(len);
174 if (!mr->ram || mr->readonly) {
175 return false;
178 if (size > info->ramsize) {
179 info->rambase = int128_get64(start);
180 info->ramsize = size;
183 /* search exhaustively for largest RAM */
184 return false;
187 static LayoutInfo common_semi_find_bases(CPUState *cs)
189 FlatView *fv;
190 LayoutInfo info = { 0, 0, 0, 0 };
192 RCU_READ_LOCK_GUARD();
194 fv = address_space_to_flatview(cs->as);
195 flatview_for_each_range(fv, find_ram_cb, &info);
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.
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;
208 return info;
211 #endif
213 #ifdef TARGET_ARM
214 static inline target_ulong
215 common_semi_arg(CPUState *cs, int argno)
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];
226 static inline void
227 common_semi_set_ret(CPUState *cs, target_ulong ret)
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;
238 static inline bool
239 common_semi_sys_exit_extended(CPUState *cs, int nr)
241 return (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(cs->env_ptr));
244 #endif /* TARGET_ARM */
246 #ifdef TARGET_RISCV
247 static inline target_ulong
248 common_semi_arg(CPUState *cs, int argno)
250 RISCVCPU *cpu = RISCV_CPU(cs);
251 CPURISCVState *env = &cpu->env;
252 return env->gpr[xA0 + argno];
255 static inline void
256 common_semi_set_ret(CPUState *cs, target_ulong ret)
258 RISCVCPU *cpu = RISCV_CPU(cs);
259 CPURISCVState *env = &cpu->env;
260 env->gpr[xA0] = ret;
263 static inline bool
264 common_semi_sys_exit_extended(CPUState *cs, int nr)
266 return (nr == TARGET_SYS_EXIT_EXTENDED || sizeof(target_ulong) == 8);
269 #endif
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.
278 static int alloc_guestfd(void)
280 guint i;
282 if (!guestfd_array) {
283 /* New entries zero-initialized, i.e. type GuestFDUnused */
284 guestfd_array = g_array_new(FALSE, TRUE, sizeof(GuestFD));
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);
291 if (gf->type == GuestFDUnused) {
292 return i;
296 /* All elements already in use: expand the array */
297 g_array_set_size(guestfd_array, i + 1);
298 return i;
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.
306 static GuestFD *do_get_guestfd(int guestfd)
308 if (!guestfd_array) {
309 return NULL;
312 if (guestfd <= 0 || guestfd >= guestfd_array->len) {
313 return NULL;
316 return &g_array_index(guestfd_array, GuestFD, guestfd);
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.
324 static void associate_guestfd(int guestfd, int hostfd)
326 GuestFD *gf = do_get_guestfd(guestfd);
328 assert(gf);
329 gf->type = use_gdb_syscalls() ? GuestFDGDB : GuestFDHost;
330 gf->hostfd = hostfd;
334 * Deallocate the specified guest file descriptor. This doesn't
335 * close the host fd, it merely undoes the work of alloc_fd().
337 static void dealloc_guestfd(int guestfd)
339 GuestFD *gf = do_get_guestfd(guestfd);
341 assert(gf);
342 gf->type = GuestFDUnused;
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.
353 static GuestFD *get_guestfd(int guestfd)
355 GuestFD *gf = do_get_guestfd(guestfd);
357 if (!gf || gf->type == GuestFDUnused) {
358 return NULL;
360 return gf;
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.
370 #ifndef CONFIG_USER_ONLY
371 static target_ulong syscall_err;
373 #include "exec/softmmu-semi.h"
374 #endif
376 static inline uint32_t set_swi_errno(CPUState *cs, uint32_t code)
378 if (code == (uint32_t)-1) {
379 #ifdef CONFIG_USER_ONLY
380 TaskState *ts = cs->opaque;
382 ts->swi_errno = errno;
383 #else
384 syscall_err = errno;
385 #endif
387 return code;
390 static inline uint32_t get_swi_errno(CPUState *cs)
392 #ifdef CONFIG_USER_ONLY
393 TaskState *ts = cs->opaque;
395 return ts->swi_errno;
396 #else
397 return syscall_err;
398 #endif
401 static target_ulong common_semi_syscall_len;
403 static void common_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
405 target_ulong reg0 = common_semi_arg(cs, 0);
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;
426 common_semi_set_ret(cs, reg0);
429 static target_ulong common_semi_flen_buf(CPUState *cs)
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.
438 ARMCPU *cpu = ARM_CPU(cs);
439 CPUARMState *env = &cpu->env;
441 if (is_a64(env)) {
442 sp = env->xregs[31];
443 } else {
444 sp = env->regs[13];
446 #endif
447 #ifdef TARGET_RISCV
448 RISCVCPU *cpu = RISCV_CPU(cs);
449 CPURISCVState *env = &cpu->env;
451 sp = env->gpr[xSP];
452 #endif
454 return sp - 64;
457 static void
458 common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
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);
471 static int common_semi_open_guestfd;
473 static void
474 common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
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;
484 common_semi_set_ret(cs, ret);
487 static target_ulong
488 common_semi_gdb_syscall(CPUState *cs, gdb_syscall_complete_cb cb,
489 const char *fmt, ...)
491 va_list va;
493 va_start(va, fmt);
494 gdb_do_syscallv(cb, fmt, va);
495 va_end(va);
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.)
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.
514 return common_semi_arg(cs, 0);
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.
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);
533 static uint32_t host_closefn(CPUState *cs, GuestFD *gf)
536 * Only close the underlying host fd if it's one we opened on behalf
537 * of the guest in SYS_OPEN.
539 if (gf->hostfd == STDIN_FILENO ||
540 gf->hostfd == STDOUT_FILENO ||
541 gf->hostfd == STDERR_FILENO) {
542 return 0;
544 return set_swi_errno(cs, close(gf->hostfd));
547 static uint32_t host_writefn(CPUState *cs, GuestFD *gf,
548 target_ulong buf, uint32_t len)
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;
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;
563 /* Return bytes not written */
564 return len - ret;
567 static uint32_t host_readfn(CPUState *cs, GuestFD *gf,
568 target_ulong buf, uint32_t len)
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;
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;
585 /* Return bytes not read */
586 return len - ret;
589 static uint32_t host_isattyfn(CPUState *cs, GuestFD *gf)
591 return isatty(gf->hostfd);
594 static uint32_t host_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
596 uint32_t ret = set_swi_errno(cs, lseek(gf->hostfd, offset, SEEK_SET));
597 if (ret == (uint32_t)-1) {
598 return -1;
600 return 0;
603 static uint32_t host_flenfn(CPUState *cs, GuestFD *gf)
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;
610 return buf.st_size;
613 static uint32_t gdb_closefn(CPUState *cs, GuestFD *gf)
615 return common_semi_gdb_syscall(cs, common_semi_cb, "close,%x", gf->hostfd);
618 static uint32_t gdb_writefn(CPUState *cs, GuestFD *gf,
619 target_ulong buf, uint32_t len)
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);
626 static uint32_t gdb_readfn(CPUState *cs, GuestFD *gf,
627 target_ulong buf, uint32_t len)
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);
634 static uint32_t gdb_isattyfn(CPUState *cs, GuestFD *gf)
636 return common_semi_gdb_syscall(cs, common_semi_cb, "isatty,%x", gf->hostfd);
639 static uint32_t gdb_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
641 return common_semi_gdb_syscall(cs, common_semi_cb, "lseek,%x,%x,0",
642 gf->hostfd, offset);
645 static uint32_t gdb_flenfn(CPUState *cs, GuestFD *gf)
647 return common_semi_gdb_syscall(cs, common_semi_flen_cb, "fstat,%x,%x",
648 gf->hostfd, common_semi_flen_buf(cs));
651 #define SHFB_MAGIC_0 0x53
652 #define SHFB_MAGIC_1 0x48
653 #define SHFB_MAGIC_2 0x46
654 #define SHFB_MAGIC_3 0x42
656 /* Feature bits reportable in feature byte 0 */
657 #define SH_EXT_EXIT_EXTENDED (1 << 0)
658 #define SH_EXT_STDOUT_STDERR (1 << 1)
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 */
668 static void init_featurefile_guestfd(int guestfd)
670 GuestFD *gf = do_get_guestfd(guestfd);
672 assert(gf);
673 gf->type = GuestFDFeatureFile;
674 gf->featurefile_offset = 0;
677 static uint32_t featurefile_closefn(CPUState *cs, GuestFD *gf)
679 /* Nothing to do */
680 return 0;
683 static uint32_t featurefile_writefn(CPUState *cs, GuestFD *gf,
684 target_ulong buf, uint32_t len)
686 /* This fd can never be open for writing */
688 errno = EBADF;
689 return set_swi_errno(cs, -1);
692 static uint32_t featurefile_readfn(CPUState *cs, GuestFD *gf,
693 target_ulong buf, uint32_t len)
695 CPUArchState *env = cs->env_ptr;
696 uint32_t i;
697 char *s;
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;
705 for (i = 0; i < len; i++) {
706 if (gf->featurefile_offset >= sizeof(featurefile_data)) {
707 break;
709 s[i] = featurefile_data[gf->featurefile_offset];
710 gf->featurefile_offset++;
713 unlock_user(s, buf, len);
715 /* Return number of bytes not read */
716 return len - i;
719 static uint32_t featurefile_isattyfn(CPUState *cs, GuestFD *gf)
721 return 0;
724 static uint32_t featurefile_seekfn(CPUState *cs, GuestFD *gf,
725 target_ulong offset)
727 gf->featurefile_offset = offset;
728 return 0;
731 static uint32_t featurefile_flenfn(CPUState *cs, GuestFD *gf)
733 return sizeof(featurefile_data);
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;
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,
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,
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,
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.
777 static inline bool is_64bit_semihosting(CPUArchState *env)
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
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); \
795 } else { \
796 if (get_user_u32(arg ## n, args + (n) * 4)) { \
797 errno = EFAULT; \
798 return set_swi_errno(cs, -1); \
801 } while (0)
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))
810 * Do a semihosting call.
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.
818 target_ulong do_common_semihosting(CPUState *cs)
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;
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);
835 switch (nr) {
836 case TARGET_SYS_OPEN:
838 int guestfd;
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);
848 if (arg1 >= 12) {
849 unlock_user(s, arg0, 0);
850 errno = EINVAL;
851 return set_swi_errno(cs, -1);
854 guestfd = alloc_guestfd();
855 if (guestfd < 0) {
856 unlock_user(s, arg0, 0);
857 errno = EMFILE;
858 return set_swi_errno(cs, -1);
861 if (strcmp(s, ":tt") == 0) {
862 int result_fileno;
865 * We implement SH_EXT_STDOUT_STDERR, so:
866 * open for read == stdin
867 * open for write == stdout
868 * open for append == stderr
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;
877 associate_guestfd(guestfd, result_fileno);
878 unlock_user(s, arg0, 0);
879 return guestfd;
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);
889 init_featurefile_guestfd(guestfd);
890 return guestfd;
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;
907 unlock_user(s, arg0, 0);
908 return ret;
910 case TARGET_SYS_CLOSE:
911 GET_ARG(0);
913 gf = get_guestfd(arg0);
914 if (!gf) {
915 errno = EBADF;
916 return set_swi_errno(cs, -1);
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;
933 gf = get_guestfd(arg0);
934 if (!gf) {
935 errno = EBADF;
936 return set_swi_errno(cs, -1);
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;
946 gf = get_guestfd(arg0);
947 if (!gf) {
948 errno = EBADF;
949 return set_swi_errno(cs, -1);
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);
961 gf = get_guestfd(arg0);
962 if (!gf) {
963 errno = EBADF;
964 return set_swi_errno(cs, -1);
967 return guestfd_fns[gf->type].isattyfn(cs, gf);
968 case TARGET_SYS_SEEK:
969 GET_ARG(0);
970 GET_ARG(1);
972 gf = get_guestfd(arg0);
973 if (!gf) {
974 errno = EBADF;
975 return set_swi_errno(cs, -1);
978 return guestfd_fns[gf->type].seekfn(cs, gf, arg1);
979 case TARGET_SYS_FLEN:
980 GET_ARG(0);
982 gf = get_guestfd(arg0);
983 if (!gf) {
984 errno = EBADF;
985 return set_swi_errno(cs, -1);
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;
997 ul_ret = (target_ulong) -1;
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;
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);
1020 ret = set_swi_errno(cs, remove(s));
1021 unlock_user(s, arg0, 0);
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));
1043 if (s2)
1044 unlock_user(s2, arg2, 0);
1045 if (s)
1046 unlock_user(s, arg0, 0);
1047 return ret;
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);
1065 ret = set_swi_errno(cs, system(s));
1066 unlock_user(s, arg0, 0);
1067 return ret;
1069 case TARGET_SYS_ERRNO:
1070 return get_swi_errno(cs);
1071 case TARGET_SYS_GET_CMDLINE:
1073 /* Build a command-line from the original argv.
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.
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.
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. */
1105 output_size = strlen(cmdline) + 1; /* Count terminating 0. */
1106 #else
1107 unsigned int i;
1109 output_size = ts->info->env_strings - ts->info->arg_strings;
1110 if (!output_size) {
1112 * We special-case the "empty command line" case (argc==0).
1113 * Just provide the terminating 0.
1115 output_size = 1;
1117 #endif
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);
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);
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);
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;
1149 if (copy_from_user(output_buffer, ts->info->arg_strings,
1150 output_size)) {
1151 errno = EFAULT;
1152 status = set_swi_errno(cs, -1);
1153 goto out;
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] = ' ';
1162 out:
1163 #endif
1164 /* Unlock the buffer on the ARM side. */
1165 unlock_user(output_buffer, arg0, output_size);
1167 return status;
1169 case TARGET_SYS_HEAPINFO:
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
1180 GET_ARG(0);
1182 #ifdef CONFIG_USER_ONLY
1184 * Some C libraries assume the heap immediately follows .bss, so
1185 * allocate it using sbrk.
1187 if (!ts->heap_limit) {
1188 abi_ulong ret;
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;
1198 limit = (ts->heap_base >> 1) + (limit >> 1);
1200 ts->heap_limit = limit;
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
1214 for (i = 0; i < ARRAY_SIZE(retvals); i++) {
1215 bool fail;
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);
1223 if (fail) {
1224 /* Couldn't write back to argument block */
1225 errno = EFAULT;
1226 return set_swi_errno(cs, -1);
1229 return 0;
1231 case TARGET_SYS_EXIT:
1232 case TARGET_SYS_EXIT_EXTENDED:
1233 if (common_semi_sys_exit_extended(cs, nr)) {
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.
1241 GET_ARG(0);
1242 GET_ARG(1);
1244 if (arg0 == ADP_Stopped_ApplicationExit) {
1245 ret = arg1;
1246 } else {
1247 ret = 1;
1249 } else {
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.
1256 ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
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));
1268 return 0;
1269 case TARGET_SYS_TICKFREQ:
1270 /* qemu always uses nsec */
1271 return 1000000000;
1272 case TARGET_SYS_SYNCCACHE:
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.
1278 #ifdef TARGET_ARM
1279 if (is_a64(cs->env_ptr)) {
1280 return 0;
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();