All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Subject: [PULL 29/68] target/arm/arm-semi: Restrict use of TaskState*
Date: Mon, 14 Oct 2019 17:03:25 +0100	[thread overview]
Message-ID: <20191014160404.19553-30-peter.maydell@linaro.org> (raw)
In-Reply-To: <20191014160404.19553-1-peter.maydell@linaro.org>

The semihosting code needs accuss to the linux-user only
TaskState pointer so it can set the semihosting errno per-thread
for linux-user mode. At the moment we do this by having some
ifdefs so that we define a 'ts' local in do_arm_semihosting()
which is either a real TaskState * or just a CPUARMState *,
depending on which mode we're compiling for.

This is awkward if we want to refactor do_arm_semihosting()
into other functions which might need to be passed the TaskState.
Restrict usage of the TaskState local by:
 * making set_swi_errno() always take the CPUARMState pointer
   and (for the linux-user version) get TaskState from that
 * creating a new get_swi_errno() which reads the errno
 * having the two semihosting calls which need the TaskState
   for other purposes (SYS_GET_CMDLINE and SYS_HEAPINFO)
   define a variable with scope restricted to just that code

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190916141544.17540-6-peter.maydell@linaro.org
---
 target/arm/arm-semi.c | 111 ++++++++++++++++++++++++------------------
 1 file changed, 63 insertions(+), 48 deletions(-)

diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c
index a4741d7e11b..2618588076f 100644
--- a/target/arm/arm-semi.c
+++ b/target/arm/arm-semi.c
@@ -213,26 +213,45 @@ static GuestFD *get_guestfd(int guestfd)
     return gf;
 }
 
-#ifdef CONFIG_USER_ONLY
-static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
-{
-    if (code == (uint32_t)-1)
-        ts->swi_errno = errno;
-    return code;
-}
-#else
+/*
+ * The semihosting API has no concept of its errno being thread-safe,
+ * as the API design predates SMP CPUs and was intended as a simple
+ * real-hardware set of debug functionality. For QEMU, we make the
+ * errno be per-thread in linux-user mode; in softmmu it is a simple
+ * global, and we assume that the guest takes care of avoiding any races.
+ */
+#ifndef CONFIG_USER_ONLY
 static target_ulong syscall_err;
 
+#include "exec/softmmu-semi.h"
+#endif
+
 static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
 {
     if (code == (uint32_t)-1) {
+#ifdef CONFIG_USER_ONLY
+        CPUState *cs = env_cpu(env);
+        TaskState *ts = cs->opaque;
+
+        ts->swi_errno = errno;
+#else
         syscall_err = errno;
+#endif
     }
     return code;
 }
 
-#include "exec/softmmu-semi.h"
+static inline uint32_t get_swi_errno(CPUARMState *env)
+{
+#ifdef CONFIG_USER_ONLY
+    CPUState *cs = env_cpu(env);
+    TaskState *ts = cs->opaque;
+
+    return ts->swi_errno;
+#else
+    return syscall_err;
 #endif
+}
 
 static target_ulong arm_semi_syscall_len;
 
@@ -379,12 +398,12 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
     if (is_a64(env)) {                                  \
         if (get_user_u64(arg ## n, args + (n) * 8)) {   \
             errno = EFAULT;                             \
-            return set_swi_errno(ts, -1);               \
+            return set_swi_errno(env, -1);              \
         }                                               \
     } else {                                            \
         if (get_user_u32(arg ## n, args + (n) * 4)) {   \
             errno = EFAULT;                             \
-            return set_swi_errno(ts, -1);               \
+            return set_swi_errno(env, -1);              \
         }                                               \
     }                                                   \
 } while (0)
@@ -413,11 +432,6 @@ target_ulong do_arm_semihosting(CPUARMState *env)
     int nr;
     uint32_t ret;
     uint32_t len;
-#ifdef CONFIG_USER_ONLY
-    TaskState *ts = cs->opaque;
-#else
-    CPUARMState *ts = env;
-#endif
     GuestFD *gf;
 
     if (is_a64(env)) {
@@ -440,19 +454,19 @@ target_ulong do_arm_semihosting(CPUARMState *env)
         s = lock_user_string(arg0);
         if (!s) {
             errno = EFAULT;
-            return set_swi_errno(ts, -1);
+            return set_swi_errno(env, -1);
         }
         if (arg1 >= 12) {
             unlock_user(s, arg0, 0);
             errno = EINVAL;
-            return set_swi_errno(ts, -1);
+            return set_swi_errno(env, -1);
         }
 
         guestfd = alloc_guestfd();
         if (guestfd < 0) {
             unlock_user(s, arg0, 0);
             errno = EMFILE;
-            return set_swi_errno(ts, -1);
+            return set_swi_errno(env, -1);
         }
 
         if (strcmp(s, ":tt") == 0) {
@@ -466,7 +480,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
             ret = arm_gdb_syscall(cpu, arm_semi_open_cb, "open,%s,%x,1a4", arg0,
                                   (int)arg2+1, gdb_open_modeflags[arg1]);
         } else {
-            ret = set_swi_errno(ts, open(s, open_modeflags[arg1], 0644));
+            ret = set_swi_errno(env, open(s, open_modeflags[arg1], 0644));
             if (ret == (uint32_t)-1) {
                 dealloc_guestfd(guestfd);
             } else {
@@ -483,13 +497,13 @@ target_ulong do_arm_semihosting(CPUARMState *env)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(ts, -1);
+            return set_swi_errno(env, -1);
         }
 
         if (use_gdb_syscalls()) {
             ret = arm_gdb_syscall(cpu, arm_semi_cb, "close,%x", gf->hostfd);
         } else {
-            ret = set_swi_errno(ts, close(gf->hostfd));
+            ret = set_swi_errno(env, close(gf->hostfd));
         }
         dealloc_guestfd(arg0);
         return ret;
@@ -507,7 +521,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(ts, -1);
+            return set_swi_errno(env, -1);
         }
 
         if (use_gdb_syscalls()) {
@@ -520,7 +534,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
                 /* Return bytes not written on error */
                 return len;
             }
-            ret = set_swi_errno(ts, write(gf->hostfd, s, len));
+            ret = set_swi_errno(env, write(gf->hostfd, s, len));
             unlock_user(s, arg1, 0);
             if (ret == (uint32_t)-1) {
                 ret = 0;
@@ -537,7 +551,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(ts, -1);
+            return set_swi_errno(env, -1);
         }
 
         if (use_gdb_syscalls()) {
@@ -551,7 +565,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
                 return len;
             }
             do {
-                ret = set_swi_errno(ts, read(gf->hostfd, s, len));
+                ret = set_swi_errno(env, read(gf->hostfd, s, len));
             } while (ret == -1 && errno == EINTR);
             unlock_user(s, arg1, len);
             if (ret == (uint32_t)-1) {
@@ -569,7 +583,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(ts, -1);
+            return set_swi_errno(env, -1);
         }
 
         if (use_gdb_syscalls()) {
@@ -584,14 +598,14 @@ target_ulong do_arm_semihosting(CPUARMState *env)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(ts, -1);
+            return set_swi_errno(env, -1);
         }
 
         if (use_gdb_syscalls()) {
             return arm_gdb_syscall(cpu, arm_semi_cb, "lseek,%x,%x,0",
                                    gf->hostfd, arg1);
         } else {
-            ret = set_swi_errno(ts, lseek(gf->hostfd, arg1, SEEK_SET));
+            ret = set_swi_errno(env, lseek(gf->hostfd, arg1, SEEK_SET));
             if (ret == (uint32_t)-1)
               return -1;
             return 0;
@@ -602,7 +616,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(ts, -1);
+            return set_swi_errno(env, -1);
         }
 
         if (use_gdb_syscalls()) {
@@ -610,7 +624,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
                                    gf->hostfd, arm_flen_buf(cpu));
         } else {
             struct stat buf;
-            ret = set_swi_errno(ts, fstat(gf->hostfd, &buf));
+            ret = set_swi_errno(env, fstat(gf->hostfd, &buf));
             if (ret == (uint32_t)-1)
                 return -1;
             return buf.st_size;
@@ -628,9 +642,9 @@ target_ulong do_arm_semihosting(CPUARMState *env)
             s = lock_user_string(arg0);
             if (!s) {
                 errno = EFAULT;
-                return set_swi_errno(ts, -1);
+                return set_swi_errno(env, -1);
             }
-            ret =  set_swi_errno(ts, remove(s));
+            ret =  set_swi_errno(env, remove(s));
             unlock_user(s, arg0, 0);
         }
         return ret;
@@ -648,9 +662,9 @@ target_ulong do_arm_semihosting(CPUARMState *env)
             s2 = lock_user_string(arg2);
             if (!s || !s2) {
                 errno = EFAULT;
-                ret = set_swi_errno(ts, -1);
+                ret = set_swi_errno(env, -1);
             } else {
-                ret = set_swi_errno(ts, rename(s, s2));
+                ret = set_swi_errno(env, rename(s, s2));
             }
             if (s2)
                 unlock_user(s2, arg2, 0);
@@ -661,7 +675,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
     case TARGET_SYS_CLOCK:
         return clock() / (CLOCKS_PER_SEC / 100);
     case TARGET_SYS_TIME:
-        return set_swi_errno(ts, time(NULL));
+        return set_swi_errno(env, time(NULL));
     case TARGET_SYS_SYSTEM:
         GET_ARG(0);
         GET_ARG(1);
@@ -672,18 +686,14 @@ target_ulong do_arm_semihosting(CPUARMState *env)
             s = lock_user_string(arg0);
             if (!s) {
                 errno = EFAULT;
-                return set_swi_errno(ts, -1);
+                return set_swi_errno(env, -1);
             }
-            ret = set_swi_errno(ts, system(s));
+            ret = set_swi_errno(env, system(s));
             unlock_user(s, arg0, 0);
             return ret;
         }
     case TARGET_SYS_ERRNO:
-#ifdef CONFIG_USER_ONLY
-        return ts->swi_errno;
-#else
-        return syscall_err;
-#endif
+        return get_swi_errno(env);
     case TARGET_SYS_GET_CMDLINE:
         {
             /* Build a command-line from the original argv.
@@ -706,6 +716,8 @@ target_ulong do_arm_semihosting(CPUARMState *env)
             int status = 0;
 #if !defined(CONFIG_USER_ONLY)
             const char *cmdline;
+#else
+            TaskState *ts = cs->opaque;
 #endif
             GET_ARG(0);
             GET_ARG(1);
@@ -733,21 +745,21 @@ target_ulong do_arm_semihosting(CPUARMState *env)
             if (output_size > input_size) {
                 /* Not enough space to store command-line arguments.  */
                 errno = E2BIG;
-                return set_swi_errno(ts, -1);
+                return set_swi_errno(env, -1);
             }
 
             /* Adjust the command-line length.  */
             if (SET_ARG(1, output_size - 1)) {
                 /* Couldn't write back to argument block */
                 errno = EFAULT;
-                return set_swi_errno(ts, -1);
+                return set_swi_errno(env, -1);
             }
 
             /* Lock the buffer on the ARM side.  */
             output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);
             if (!output_buffer) {
                 errno = EFAULT;
-                return set_swi_errno(ts, -1);
+                return set_swi_errno(env, -1);
             }
 
             /* Copy the command-line arguments.  */
@@ -763,7 +775,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
             if (copy_from_user(output_buffer, ts->info->arg_start,
                                output_size)) {
                 errno = EFAULT;
-                status = set_swi_errno(ts, -1);
+                status = set_swi_errno(env, -1);
                 goto out;
             }
 
@@ -785,6 +797,9 @@ target_ulong do_arm_semihosting(CPUARMState *env)
             target_ulong retvals[4];
             target_ulong limit;
             int i;
+#ifdef CONFIG_USER_ONLY
+            TaskState *ts = cs->opaque;
+#endif
 
             GET_ARG(0);
 
@@ -834,7 +849,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
                 if (fail) {
                     /* Couldn't write back to argument block */
                     errno = EFAULT;
-                    return set_swi_errno(ts, -1);
+                    return set_swi_errno(env, -1);
                 }
             }
             return 0;
-- 
2.20.1



  parent reply	other threads:[~2019-10-14 16:32 UTC|newest]

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-14 16:02 [PULL 00/68] target-arm queue Peter Maydell
2019-10-14 16:02 ` [PULL 01/68] linux headers: update against v5.4-rc1 Peter Maydell
2019-10-14 16:02 ` [PULL 02/68] intc/arm_gic: Support IRQ injection for more than 256 vpus Peter Maydell
2019-10-14 16:02 ` [PULL 03/68] ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for smp_cpus > 256 Peter Maydell
2019-10-14 16:03 ` [PULL 04/68] ptimer: Rename ptimer_init() to ptimer_init_with_bh() Peter Maydell
2019-10-14 16:03 ` [PULL 05/68] ptimer: Provide new transaction-based API Peter Maydell
2019-10-14 16:03 ` [PULL 06/68] tests/ptimer-test: Switch to transaction-based ptimer API Peter Maydell
2019-10-14 16:03 ` [PULL 07/68] hw/timer/arm_timer.c: " Peter Maydell
2019-10-14 16:03 ` [PULL 08/68] hw/arm/musicpal.c: " Peter Maydell
2019-10-14 16:03 ` [PULL 09/68] hw/timer/allwinner-a10-pit.c: " Peter Maydell
2019-10-14 16:03 ` [PULL 10/68] hw/timer/arm_mptimer.c: " Peter Maydell
2019-10-14 16:03 ` [PULL 11/68] hw/timer/cmsdk-apb-dualtimer.c: " Peter Maydell
2019-10-14 16:03 ` [PULL 12/68] hw/timer/cmsdk-apb-timer.c: " Peter Maydell
2019-10-14 16:03 ` [PULL 13/68] hw/timer/digic-timer.c: " Peter Maydell
2019-10-14 16:03 ` [PULL 14/68] hw/timer/exynos4210_mct.c: Switch GFRC " Peter Maydell
2019-10-14 16:03 ` [PULL 15/68] hw/timer/exynos4210_mct.c: Switch LFRC " Peter Maydell
2019-10-14 16:03 ` [PULL 16/68] hw/timer/exynos4210_mct.c: Switch ltick " Peter Maydell
2019-10-14 16:03 ` [PULL 17/68] hw/timer/exynos4210_pwm.c: Switch " Peter Maydell
2019-10-14 16:03 ` [PULL 18/68] hw/timer/exynos4210_rtc.c: Switch 1Hz ptimer to transaction-based API Peter Maydell
2019-10-14 16:03 ` [PULL 19/68] hw/timer/exynos4210_rtc.c: Switch main " Peter Maydell
2019-10-14 16:03 ` [PULL 20/68] hw/timer/imx_epit.c: Switch to transaction-based ptimer API Peter Maydell
2019-10-14 16:03 ` [PULL 21/68] hw/timer/imx_gpt.c: " Peter Maydell
2019-10-14 16:03 ` [PULL 22/68] hw/timer/mss-timerc: " Peter Maydell
2019-10-14 16:03 ` [PULL 23/68] hw/watchdog/cmsdk-apb-watchdog.c: " Peter Maydell
2019-10-14 16:03 ` [PULL 24/68] hw/net/lan9118.c: " Peter Maydell
2019-10-14 16:03 ` [PULL 25/68] target/arm/arm-semi: Capture errno in softmmu version of set_swi_errno() Peter Maydell
2019-10-14 16:03 ` [PULL 26/68] target/arm/arm-semi: Always set some kind of errno for failed calls Peter Maydell
2019-10-14 16:03 ` [PULL 27/68] target/arm/arm-semi: Correct comment about gdb syscall races Peter Maydell
2019-10-14 16:03 ` [PULL 28/68] target/arm/arm-semi: Make semihosting code hand out its own file descriptors Peter Maydell
2019-10-14 16:03 ` Peter Maydell [this message]
2019-10-14 16:03 ` [PULL 30/68] target/arm/arm-semi: Use set_swi_errno() in gdbstub callback functions Peter Maydell
2019-10-14 16:03 ` [PULL 31/68] target/arm/arm-semi: Factor out implementation of SYS_CLOSE Peter Maydell
2019-10-14 16:03 ` [PULL 32/68] target/arm/arm-semi: Factor out implementation of SYS_WRITE Peter Maydell
2019-10-14 16:03 ` [PULL 33/68] target/arm/arm-semi: Factor out implementation of SYS_READ Peter Maydell
2019-10-14 16:03 ` [PULL 34/68] target/arm/arm-semi: Factor out implementation of SYS_ISTTY Peter Maydell
2019-10-14 16:03 ` [PULL 35/68] target/arm/arm-semi: Factor out implementation of SYS_SEEK Peter Maydell
2019-10-14 16:03 ` [PULL 36/68] target/arm/arm-semi: Factor out implementation of SYS_FLEN Peter Maydell
2019-10-14 16:03 ` [PULL 37/68] target/arm/arm-semi: Implement support for semihosting feature detection Peter Maydell
2019-10-14 16:03 ` [PULL 38/68] target/arm/arm-semi: Implement SH_EXT_EXIT_EXTENDED extension Peter Maydell
2019-10-14 16:03 ` [PULL 39/68] target/arm/arm-semi: Implement SH_EXT_STDOUT_STDERR extension Peter Maydell
2019-10-14 16:03 ` [PULL 40/68] aspeed/wdt: Check correct register for clock source Peter Maydell
2019-10-14 16:03 ` [PULL 41/68] hw/sd/aspeed_sdhci: New device Peter Maydell
2019-10-14 16:03 ` [PULL 42/68] hw: aspeed_scu: Add AST2600 support Peter Maydell
2019-10-14 16:03 ` [PULL 43/68] aspeed/timer: Introduce an object class per SoC Peter Maydell
2019-10-14 16:03 ` [PULL 44/68] aspeed/timer: Add support for control register 3 Peter Maydell
2019-10-14 16:03 ` [PULL 45/68] aspeed/timer: Add AST2600 support Peter Maydell
2019-10-14 16:03 ` [PULL 46/68] aspeed/timer: Add support for IRQ status register on the AST2600 Peter Maydell
2019-10-14 16:03 ` [PULL 47/68] aspeed/sdmc: Introduce an object class per SoC Peter Maydell
2019-10-14 16:03 ` [PULL 48/68] aspeed/sdmc: Add AST2600 support Peter Maydell
2019-10-14 16:03 ` [PULL 49/68] watchdog/aspeed: Introduce an object class per SoC Peter Maydell
2019-10-14 16:03 ` [PULL 50/68] hw: wdt_aspeed: Add AST2600 support Peter Maydell
2019-10-14 16:03 ` [PULL 51/68] aspeed/smc: Introduce segment operations Peter Maydell
2019-10-14 16:03 ` [PULL 52/68] aspeed/smc: Add AST2600 support Peter Maydell
2019-10-14 16:03 ` [PULL 53/68] hw/gpio: Add in AST2600 specific implementation Peter Maydell
2019-10-14 16:03 ` [PULL 54/68] aspeed/i2c: Introduce an object class per SoC Peter Maydell
2019-10-14 16:03 ` [PULL 55/68] aspeed/i2c: Add AST2600 support Peter Maydell
2019-10-14 16:03 ` [PULL 56/68] aspeed: Introduce an object class per SoC Peter Maydell
2019-10-14 16:03 ` [PULL 57/68] aspeed/soc: Add AST2600 support Peter Maydell
2019-10-14 16:03 ` [PULL 58/68] m25p80: Add support for w25q512jv Peter Maydell
2019-10-14 16:03 ` [PULL 59/68] aspeed: Add an AST2600 eval board Peter Maydell
2019-10-15 17:03   ` Peter Maydell
2019-10-15 17:43     ` Cédric Le Goater
2019-10-15 17:55       ` Peter Maydell
2019-10-16 11:28         ` Joel Stanley
2019-10-16 12:20     ` Philippe Mathieu-Daudé
2019-10-16 12:41       ` Cédric Le Goater
2019-10-16 12:44         ` Philippe Mathieu-Daudé
2019-10-14 16:03 ` [PULL 60/68] aspeed: Parameterise number of MACs Peter Maydell
2019-10-14 16:03 ` [PULL 61/68] aspeed: add support for the Aspeed MII controller of the AST2600 Peter Maydell
2019-10-14 16:03 ` [PULL 62/68] aspeed/soc: Add ASPEED Video stub Peter Maydell
2019-10-14 16:03 ` [PULL 63/68] hw/arm/raspi: Use the IEC binary prefix definitions Peter Maydell
2019-10-14 16:04 ` [PULL 64/68] hw/arm/bcm2835_peripherals: Improve logging Peter Maydell
2019-10-14 16:04 ` [PULL 65/68] hw/arm/bcm2835_peripherals: Name various address spaces Peter Maydell
2019-10-14 16:04 ` [PULL 66/68] hw/arm/bcm2835: Rename some definitions Peter Maydell
2019-10-14 16:04 ` [PULL 67/68] hw/arm/bcm2835: Add various unimplemented peripherals Peter Maydell
2019-10-14 16:04 ` [PULL 68/68] hw/misc/bcm2835_mbox: Add trace events Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191014160404.19553-30-peter.maydell@linaro.org \
    --to=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.