qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH v2 61/78] semihosting: add fallthrough pseudo-keyword


From: Emmanouil Pitsidianakis
Subject: [RFC PATCH v2 61/78] semihosting: add fallthrough pseudo-keyword
Date: Fri, 13 Oct 2023 10:57:28 +0300

In preparation of raising -Wimplicit-fallthrough to 5, replace all
fall-through comments with the fallthrough attribute pseudo-keyword.

Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
 semihosting/arm-compat-semi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
index 329ea11260..c7d32cfca0 100644
--- a/semihosting/arm-compat-semi.c
+++ b/semihosting/arm-compat-semi.c
@@ -354,446 +354,446 @@ static const uint8_t featurefile_data[] = {
 /*
  * Do a semihosting call.
  *
  * The specification always says that the "return register" either
  * returns a specific value or is corrupted, so we don't need to
  * report to our caller whether we are returning a value or trying to
  * leave the register unchanged.
  */
 void do_common_semihosting(CPUState *cs)
 {
     CPUArchState *env = cpu_env(cs);
     target_ulong args;
     target_ulong arg0, arg1, arg2, arg3;
     target_ulong ul_ret;
     char * s;
     int nr;
     int64_t elapsed;
 
     nr = common_semi_arg(cs, 0) & 0xffffffffU;
     args = common_semi_arg(cs, 1);
 
     switch (nr) {
     case TARGET_SYS_OPEN:
     {
         int ret, err = 0;
         int hostfd;
 
         GET_ARG(0);
         GET_ARG(1);
         GET_ARG(2);
         s = lock_user_string(arg0);
         if (!s) {
             goto do_fault;
         }
         if (arg1 >= 12) {
             unlock_user(s, arg0, 0);
             common_semi_cb(cs, -1, EINVAL);
             break;
         }
 
         if (strcmp(s, ":tt") == 0) {
             /*
              * We implement SH_EXT_STDOUT_STDERR, so:
              *  open for read == stdin
              *  open for write == stdout
              *  open for append == stderr
              */
             if (arg1 < 4) {
                 hostfd = STDIN_FILENO;
             } else if (arg1 < 8) {
                 hostfd = STDOUT_FILENO;
             } else {
                 hostfd = STDERR_FILENO;
             }
             ret = alloc_guestfd();
             associate_guestfd(ret, hostfd);
         } else if (strcmp(s, ":semihosting-features") == 0) {
             /* We must fail opens for modes other than 0 ('r') or 1 ('rb') */
             if (arg1 != 0 && arg1 != 1) {
                 ret = -1;
                 err = EACCES;
             } else {
                 ret = alloc_guestfd();
                 staticfile_guestfd(ret, featurefile_data,
                                    sizeof(featurefile_data));
             }
         } else {
             unlock_user(s, arg0, 0);
             semihost_sys_open(cs, common_semi_cb, arg0, arg2 + 1,
                               gdb_open_modeflags[arg1], 0644);
             break;
         }
         unlock_user(s, arg0, 0);
         common_semi_cb(cs, ret, err);
         break;
     }
 
     case TARGET_SYS_CLOSE:
         GET_ARG(0);
         semihost_sys_close(cs, common_semi_cb, arg0);
         break;
 
     case TARGET_SYS_WRITEC:
         /*
          * FIXME: the byte to be written is in a target_ulong slot,
          * which means this is wrong for a big-endian guest.
          */
         semihost_sys_write_gf(cs, common_semi_dead_cb,
                               &console_out_gf, args, 1);
         break;
 
     case TARGET_SYS_WRITE0:
         {
             ssize_t len = target_strlen(args);
             if (len < 0) {
                 common_semi_dead_cb(cs, -1, EFAULT);
             } else {
                 semihost_sys_write_gf(cs, common_semi_dead_cb,
                                       &console_out_gf, args, len);
             }
         }
         break;
 
     case TARGET_SYS_WRITE:
         GET_ARG(0);
         GET_ARG(1);
         GET_ARG(2);
         semihost_sys_write(cs, common_semi_rw_cb, arg0, arg1, arg2);
         break;
 
     case TARGET_SYS_READ:
         GET_ARG(0);
         GET_ARG(1);
         GET_ARG(2);
         semihost_sys_read(cs, common_semi_rw_cb, arg0, arg1, arg2);
         break;
 
     case TARGET_SYS_READC:
         semihost_sys_read_gf(cs, common_semi_readc_cb, &console_in_gf,
                              common_semi_stack_bottom(cs) - 1, 1);
         break;
 
     case TARGET_SYS_ISERROR:
         GET_ARG(0);
         common_semi_set_ret(cs, (target_long)arg0 < 0);
         break;
 
     case TARGET_SYS_ISTTY:
         GET_ARG(0);
         semihost_sys_isatty(cs, common_semi_istty_cb, arg0);
         break;
 
     case TARGET_SYS_SEEK:
         GET_ARG(0);
         GET_ARG(1);
         semihost_sys_lseek(cs, common_semi_seek_cb, arg0, arg1, GDB_SEEK_SET);
         break;
 
     case TARGET_SYS_FLEN:
         GET_ARG(0);
         semihost_sys_flen(cs, common_semi_flen_fstat_cb, common_semi_cb,
                           arg0, common_semi_flen_buf(cs));
         break;
 
     case TARGET_SYS_TMPNAM:
     {
         int len;
         char *p;
 
         GET_ARG(0);
         GET_ARG(1);
         GET_ARG(2);
         len = asprintf(&s, "%s/qemu-%x%02x", g_get_tmp_dir(),
                        getpid(), (int)arg1 & 0xff);
         if (len < 0) {
             common_semi_set_ret(cs, -1);
             break;
         }
 
         /* Allow for trailing NUL */
         len++;
         /* Make sure there's enough space in the buffer */
         if (len > arg2) {
             free(s);
             common_semi_set_ret(cs, -1);
             break;
         }
         p = lock_user(VERIFY_WRITE, arg0, len, 0);
         if (!p) {
             free(s);
             goto do_fault;
         }
         memcpy(p, s, len);
         unlock_user(p, arg0, len);
         free(s);
         common_semi_set_ret(cs, 0);
         break;
     }
 
     case TARGET_SYS_REMOVE:
         GET_ARG(0);
         GET_ARG(1);
         semihost_sys_remove(cs, common_semi_cb, arg0, arg1 + 1);
         break;
 
     case TARGET_SYS_RENAME:
         GET_ARG(0);
         GET_ARG(1);
         GET_ARG(2);
         GET_ARG(3);
         semihost_sys_rename(cs, common_semi_cb, arg0, arg1 + 1, arg2, arg3 + 
1);
         break;
 
     case TARGET_SYS_CLOCK:
         common_semi_set_ret(cs, clock() / (CLOCKS_PER_SEC / 100));
         break;
 
     case TARGET_SYS_TIME:
         ul_ret = time(NULL);
         common_semi_cb(cs, ul_ret, ul_ret == -1 ? errno : 0);
         break;
 
     case TARGET_SYS_SYSTEM:
         GET_ARG(0);
         GET_ARG(1);
         semihost_sys_system(cs, common_semi_cb, arg0, arg1 + 1);
         break;
 
     case TARGET_SYS_ERRNO:
         common_semi_set_ret(cs, get_swi_errno(cs));
         break;
 
     case TARGET_SYS_GET_CMDLINE:
         {
             /* Build a command-line from the original argv.
              *
              * The inputs are:
              *     * arg0, pointer to a buffer of at least the size
              *               specified in arg1.
              *     * arg1, size of the buffer pointed to by arg0 in
              *               bytes.
              *
              * The outputs are:
              *     * arg0, pointer to null-terminated string of the
              *               command line.
              *     * arg1, length of the string pointed to by arg0.
              */
 
             char *output_buffer;
             size_t input_size;
             size_t output_size;
             int status = 0;
 #if !defined(CONFIG_USER_ONLY)
             const char *cmdline;
 #else
             TaskState *ts = cs->opaque;
 #endif
             GET_ARG(0);
             GET_ARG(1);
             input_size = arg1;
             /* Compute the size of the output string.  */
 #if !defined(CONFIG_USER_ONLY)
             cmdline = semihosting_get_cmdline();
             if (cmdline == NULL) {
                 cmdline = ""; /* Default to an empty line. */
             }
             output_size = strlen(cmdline) + 1; /* Count terminating 0. */
 #else
             unsigned int i;
 
             output_size = ts->info->env_strings - ts->info->arg_strings;
             if (!output_size) {
                 /*
                  * We special-case the "empty command line" case (argc==0).
                  * Just provide the terminating 0.
                  */
                 output_size = 1;
             }
 #endif
 
             if (output_size > input_size) {
                 /* Not enough space to store command-line arguments.  */
                 common_semi_cb(cs, -1, E2BIG);
                 break;
             }
 
             /* Adjust the command-line length.  */
             if (SET_ARG(1, output_size - 1)) {
                 /* Couldn't write back to argument block */
                 goto do_fault;
             }
 
             /* Lock the buffer on the ARM side.  */
             output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);
             if (!output_buffer) {
                 goto do_fault;
             }
 
             /* Copy the command-line arguments.  */
 #if !defined(CONFIG_USER_ONLY)
             pstrcpy(output_buffer, output_size, cmdline);
 #else
             if (output_size == 1) {
                 /* Empty command-line.  */
                 output_buffer[0] = '\0';
                 goto out;
             }
 
             if (copy_from_user(output_buffer, ts->info->arg_strings,
                                output_size)) {
                 unlock_user(output_buffer, arg0, 0);
                 goto do_fault;
             }
 
             /* Separate arguments by white spaces.  */
             for (i = 0; i < output_size - 1; i++) {
                 if (output_buffer[i] == 0) {
                     output_buffer[i] = ' ';
                 }
             }
         out:
 #endif
             /* Unlock the buffer on the ARM side.  */
             unlock_user(output_buffer, arg0, output_size);
             common_semi_cb(cs, status, 0);
         }
         break;
 
     case TARGET_SYS_HEAPINFO:
         {
             target_ulong retvals[4];
             int i;
 #ifdef CONFIG_USER_ONLY
             TaskState *ts = cs->opaque;
             target_ulong limit;
 #else
             LayoutInfo info = common_semi_find_bases(cs);
 #endif
 
             GET_ARG(0);
 
 #ifdef CONFIG_USER_ONLY
             /*
              * Some C libraries assume the heap immediately follows .bss, so
              * allocate it using sbrk.
              */
             if (!ts->heap_limit) {
                 abi_ulong ret;
 
                 ts->heap_base = do_brk(0);
                 limit = ts->heap_base + COMMON_SEMI_HEAP_SIZE;
                 /* Try a big heap, and reduce the size if that fails.  */
                 for (;;) {
                     ret = do_brk(limit);
                     if (ret >= limit) {
                         break;
                     }
                     limit = (ts->heap_base >> 1) + (limit >> 1);
                 }
                 ts->heap_limit = limit;
             }
 
             retvals[0] = ts->heap_base;
             retvals[1] = ts->heap_limit;
             retvals[2] = ts->stack_base;
             retvals[3] = 0; /* Stack limit.  */
 #else
             retvals[0] = info.heapbase;  /* Heap Base */
             retvals[1] = info.heaplimit; /* Heap Limit */
             retvals[2] = info.heaplimit; /* Stack base */
             retvals[3] = info.heapbase;  /* Stack limit.  */
 #endif
 
             for (i = 0; i < ARRAY_SIZE(retvals); i++) {
                 bool fail;
 
                 if (is_64bit_semihosting(env)) {
                     fail = put_user_u64(retvals[i], arg0 + i * 8);
                 } else {
                     fail = put_user_u32(retvals[i], arg0 + i * 4);
                 }
 
                 if (fail) {
                     /* Couldn't write back to argument block */
                     goto do_fault;
                 }
             }
             common_semi_set_ret(cs, 0);
         }
         break;
 
     case TARGET_SYS_EXIT:
     case TARGET_SYS_EXIT_EXTENDED:
     {
         uint32_t ret;
 
         if (common_semi_sys_exit_extended(cs, nr)) {
             /*
              * The A64 version of SYS_EXIT takes a parameter block,
              * so the application-exit type can return a subcode which
              * is the exit status code from the application.
              * SYS_EXIT_EXTENDED is an a new-in-v2.0 optional function
              * which allows A32/T32 guests to also provide a status code.
              */
             GET_ARG(0);
             GET_ARG(1);
 
             if (arg0 == ADP_Stopped_ApplicationExit) {
                 ret = arg1;
             } else {
                 ret = 1;
             }
         } else {
             /*
              * The A32/T32 version of SYS_EXIT specifies only
              * Stopped_ApplicationExit as normal exit, but does not
              * allow the guest to specify the exit status code.
              * Everything else is considered an error.
              */
             ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
         }
         gdb_exit(ret);
         exit(ret);
     }
 
     case TARGET_SYS_ELAPSED:
         elapsed = get_clock() - clock_start;
         if (sizeof(target_ulong) == 8) {
             if (SET_ARG(0, elapsed)) {
                 goto do_fault;
             }
         } else {
             if (SET_ARG(0, (uint32_t) elapsed) ||
                 SET_ARG(1, (uint32_t) (elapsed >> 32))) {
                 goto do_fault;
             }
         }
         common_semi_set_ret(cs, 0);
         break;
 
     case TARGET_SYS_TICKFREQ:
         /* qemu always uses nsec */
         common_semi_set_ret(cs, 1000000000);
         break;
 
     case TARGET_SYS_SYNCCACHE:
         /*
          * Clean the D-cache and invalidate the I-cache for the specified
          * virtual address range. This is a nop for us since we don't
          * implement caches. This is only present on A64.
          */
         if (common_semi_has_synccache(env)) {
             common_semi_set_ret(cs, 0);
             break;
         }
-        /* fall through */
+        fallthrough;
     default:
         fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
         cpu_dump_state(cs, stderr, 0);
         abort();
 
     do_fault:
         common_semi_cb(cs, -1, EFAULT);
         break;
     }
 }
-- 
2.39.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]