From nobody Mon May 6 11:40:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1572900259; cv=none; d=zoho.com; s=zohoarc; b=ZTnC+Alksc7OEs0b631mludd6jpPJTBCg25F6QdPcLYK8bJ1ounQHCFLTAHxUtxNkXCwV5SYN8ThTJNhrc7eSQwbPoaHT4PimTgR18jQxLGky9Aysd3DMhc+zqmeFNgBWkOsqjKtz9GGU0uIVOsYRhAvxuu5AuxcFD4m1SiWStM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1572900259; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=exxTguUMLXdP2YkZRz+wOa1fpa3YtOxgRLwbhLgyyRU=; b=ccndaR/EDK03UWVXvCznWPnNMV1D8Zv8M/VJd1WvTtQjQdXOuEd4LIJI7En8meiuqvn2Hi5YpOzI17AjoUgL8BB8QBjmU4gOoau90eTAErGzLY3vZyrJjXX9QZTfr33tKvmEAf4JoR2ekuko5rPDllWYrEsz/ckiOXweriWXIM8= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 15729002590891019.2368983246818; Mon, 4 Nov 2019 12:44:19 -0800 (PST) Received: from localhost ([::1]:38248 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iRjCy-0001PD-Q0 for importer@patchew.org; Mon, 04 Nov 2019 15:44:16 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45620) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iRjBw-0000g2-Rs for qemu-devel@nongnu.org; Mon, 04 Nov 2019 15:43:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iRjBv-0000Pz-AD for qemu-devel@nongnu.org; Mon, 04 Nov 2019 15:43:12 -0500 Received: from home.keithp.com ([63.227.221.253]:44922 helo=elaine.keithp.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iRjBr-0000KS-Py; Mon, 04 Nov 2019 15:43:08 -0500 Received: from localhost (localhost [127.0.0.1]) by elaine.keithp.com (Postfix) with ESMTP id 8BEAB3F29351; Mon, 4 Nov 2019 12:43:04 -0800 (PST) Received: from elaine.keithp.com ([127.0.0.1]) by localhost (elaine.keithp.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id AGcna8d1lja5; Mon, 4 Nov 2019 12:43:04 -0800 (PST) Received: from keithp.com (unknown [216.9.110.15]) by elaine.keithp.com (Postfix) with ESMTPSA id F3ADA3F29315; Mon, 4 Nov 2019 12:43:03 -0800 (PST) Received: by keithp.com (Postfix, from userid 1000) id E8C9B158212D; Mon, 4 Nov 2019 12:42:59 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at keithp.com From: Keith Packard To: qemu-devel@nongnu.org, Peter Maydell Subject: [PATCH] Semihost SYS_READC implementation (v6) Date: Mon, 4 Nov 2019 12:42:30 -0800 Message-Id: <20191104204230.12249-1-keithp@keithp.com> X-Mailer: git-send-email 2.24.0.rc2 In-Reply-To: <87h83w4dod.fsf@keithp.com> References: <87h83w4dod.fsf@keithp.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 63.227.221.253 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Keith Packard , Riku Voipio , Laurent Vivier , qemu-arm@nongnu.org, Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Provides a blocking call to read a character from the console using semihosting.chardev, if specified. This takes some careful command line options to use stdio successfully as the serial ports, monitor and semihost all want to use stdio. Here's a sample set of command line options which share stdio betwen semihost, monitor and serial ports: qemu \ -chardev stdio,mux=3Don,id=3Dstdio0 \ -serial chardev:stdio0 \ -semihosting-config enable=3Don,chardev=3Dstdio0 \ -mon chardev=3Dstdio0,mode=3Dreadline This creates a chardev hooked to stdio and then connects all of the subsystems to it. A shorter mechanism would be good to hear about. Signed-off-by: Keith Packard --- v2: Add implementation in linux-user/arm/semihost.c v3: (thanks to Paolo Bonzini ) Replace hand-rolled fifo with fifo8 Avoid mixing code and declarations Remove spurious (void) cast of function parameters Define qemu_semihosting_console_init when CONFIG_USER_ONLY v4: Add qemu_semihosting_console_init to stubs/semihost.c for hosts that don't support semihosting v5: Move #include statements to the top of the file. Actually include the stubs/semihost.c patch that was supposed to be in v4 v6: Move call to qemu_semihosting_console_init earlier in main so that the mux starts connected to the serial device --- hw/semihosting/console.c | 72 +++++++++++++++++++++++++++++++ include/hw/semihosting/console.h | 12 ++++++ include/hw/semihosting/semihost.h | 4 ++ linux-user/arm/semihost.c | 23 ++++++++++ stubs/semihost.c | 4 ++ target/arm/arm-semi.c | 3 +- vl.c | 3 ++ 7 files changed, 119 insertions(+), 2 deletions(-) diff --git a/hw/semihosting/console.c b/hw/semihosting/console.c index b4b17c8afb..4db68d6227 100644 --- a/hw/semihosting/console.c +++ b/hw/semihosting/console.c @@ -22,6 +22,12 @@ #include "exec/gdbstub.h" #include "qemu/log.h" #include "chardev/char.h" +#include +#include "chardev/char-fe.h" +#include "sysemu/sysemu.h" +#include "qemu/main-loop.h" +#include "qapi/error.h" +#include "qemu/fifo8.h" =20 int qemu_semihosting_log_out(const char *s, int len) { @@ -98,3 +104,69 @@ void qemu_semihosting_console_outc(CPUArchState *env, t= arget_ulong addr) __func__, addr); } } + +#define FIFO_SIZE 1024 + +typedef struct SemihostingConsole { + CharBackend backend; + pthread_mutex_t mutex; + pthread_cond_t cond; + bool got; + Fifo8 fifo; +} SemihostingConsole; + +static SemihostingConsole console =3D { + .mutex =3D PTHREAD_MUTEX_INITIALIZER, + .cond =3D PTHREAD_COND_INITIALIZER +}; + +static int console_can_read(void *opaque) +{ + SemihostingConsole *c =3D opaque; + int ret; + pthread_mutex_lock(&c->mutex); + ret =3D (int) fifo8_num_free(&c->fifo); + pthread_mutex_unlock(&c->mutex); + return ret; +} + +static void console_read(void *opaque, const uint8_t *buf, int size) +{ + SemihostingConsole *c =3D opaque; + pthread_mutex_lock(&c->mutex); + while (size-- && !fifo8_is_full(&c->fifo)) { + fifo8_push(&c->fifo, *buf++); + } + pthread_cond_broadcast(&c->cond); + pthread_mutex_unlock(&c->mutex); +} + +target_ulong qemu_semihosting_console_inc(CPUArchState *env) +{ + uint8_t ch; + SemihostingConsole *c =3D &console; + qemu_mutex_unlock_iothread(); + pthread_mutex_lock(&c->mutex); + while (fifo8_is_empty(&c->fifo)) { + pthread_cond_wait(&c->cond, &c->mutex); + } + ch =3D fifo8_pop(&c->fifo); + pthread_mutex_unlock(&c->mutex); + qemu_mutex_lock_iothread(); + return (target_ulong) ch; +} + +void qemu_semihosting_console_init(void) +{ + Chardev *chr =3D semihosting_get_chardev(); + + if (chr) { + fifo8_create(&console.fifo, FIFO_SIZE); + qemu_chr_fe_init(&console.backend, chr, &error_abort); + qemu_chr_fe_set_handlers(&console.backend, + console_can_read, + console_read, + NULL, NULL, &console, + NULL, true); + } +} diff --git a/include/hw/semihosting/console.h b/include/hw/semihosting/cons= ole.h index 9be9754bcd..f7d5905b41 100644 --- a/include/hw/semihosting/console.h +++ b/include/hw/semihosting/console.h @@ -37,6 +37,18 @@ int qemu_semihosting_console_outs(CPUArchState *env, tar= get_ulong s); */ void qemu_semihosting_console_outc(CPUArchState *env, target_ulong c); =20 +/** + * qemu_semihosting_console_inc: + * @env: CPUArchState + * + * Receive single character from debug console. This + * may be the remote gdb session if a softmmu guest is currently being + * debugged. + * + * Returns: character read or -1 on error + */ +target_ulong qemu_semihosting_console_inc(CPUArchState *env); + /** * qemu_semihosting_log_out: * @s: pointer to string diff --git a/include/hw/semihosting/semihost.h b/include/hw/semihosting/sem= ihost.h index 60fc42d851..b8ce5117ae 100644 --- a/include/hw/semihosting/semihost.h +++ b/include/hw/semihosting/semihost.h @@ -56,6 +56,9 @@ static inline Chardev *semihosting_get_chardev(void) { return NULL; } +static inline void qemu_semihosting_console_init(void) +{ +} #else /* !CONFIG_USER_ONLY */ bool semihosting_enabled(void); SemihostingTarget semihosting_get_target(void); @@ -68,6 +71,7 @@ Chardev *semihosting_get_chardev(void); void qemu_semihosting_enable(void); int qemu_semihosting_config_options(const char *opt); void qemu_semihosting_connect_chardevs(void); +void qemu_semihosting_console_init(void); #endif /* CONFIG_USER_ONLY */ =20 #endif /* SEMIHOST_H */ diff --git a/linux-user/arm/semihost.c b/linux-user/arm/semihost.c index a16b525eec..4f998d6220 100644 --- a/linux-user/arm/semihost.c +++ b/linux-user/arm/semihost.c @@ -14,6 +14,7 @@ #include "cpu.h" #include "hw/semihosting/console.h" #include "qemu.h" +#include =20 int qemu_semihosting_console_outs(CPUArchState *env, target_ulong addr) { @@ -47,3 +48,25 @@ void qemu_semihosting_console_outc(CPUArchState *env, ta= rget_ulong addr) } } } + +target_ulong qemu_semihosting_console_inc(CPUArchState *env) +{ + uint8_t c; + struct pollfd pollfd =3D { + .fd =3D STDIN_FILENO, + .events =3D POLLIN + }; + + if (poll(&pollfd, 1, -1) !=3D 1) { + qemu_log_mask(LOG_UNIMP, "%s: unexpected read from stdin failure", + __func__); + return (target_ulong) -1; + } + + if (read(STDIN_FILENO, &c, 1) !=3D 1) { + qemu_log_mask(LOG_UNIMP, "%s: unexpected read from stdin failure", + __func__); + return (target_ulong) -1; + } + return (target_ulong) c; +} diff --git a/stubs/semihost.c b/stubs/semihost.c index f90589259c..1d8b37f7b2 100644 --- a/stubs/semihost.c +++ b/stubs/semihost.c @@ -69,3 +69,7 @@ void semihosting_arg_fallback(const char *file, const cha= r *cmd) void qemu_semihosting_connect_chardevs(void) { } + +void qemu_semihosting_console_init(void) +{ +} diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c index 6f7b6d801b..47d61f6fe1 100644 --- a/target/arm/arm-semi.c +++ b/target/arm/arm-semi.c @@ -802,8 +802,7 @@ target_ulong do_arm_semihosting(CPUARMState *env) =20 return guestfd_fns[gf->type].readfn(cpu, gf, arg1, len); case TARGET_SYS_READC: - qemu_log_mask(LOG_UNIMP, "%s: SYS_READC not implemented", __func__= ); - return 0; + return qemu_semihosting_console_inc(env); case TARGET_SYS_ISTTY: GET_ARG(0); =20 diff --git a/vl.c b/vl.c index 4489cfb2bb..7ea8a907fd 100644 --- a/vl.c +++ b/vl.c @@ -4284,6 +4284,9 @@ int main(int argc, char **argv, char **envp) qemu_opts_foreach(qemu_find_opts("mon"), mon_init_func, NULL, &error_fatal); =20 + /* connect semihosting console input if requested */ + qemu_semihosting_console_init(); + if (foreach_device_config(DEV_SERIAL, serial_parse) < 0) exit(1); if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0) --=20 2.24.0.rc2