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