qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, keithp@keithp.com,
	"Alex Bennée" <alex.bennee@linaro.org>,
	"Richard Henderson" <rth@twiddle.net>
Subject: [RFC PATCH] semihosting: suspend recieving CPU when blocked (HACK, WIP)
Date: Tue, 17 Dec 2019 12:14:43 +0000	[thread overview]
Message-ID: <20191217121443.14757-1-alex.bennee@linaro.org> (raw)
In-Reply-To: <77dd4863-6301-b17d-529c-451d491d4794@redhat.com>

Sleeping in the semihosting code is problematic as we deadlock the
whole system. This includes issuing a "quit" via the HMP or presumably
if gdbserver got involved. What we really want is to return to the
main loop and gt woken up when there is data to process. We can then
re-execute the instruction which will succeed this time.

[AJB:

So this at least solves the hang of not being able to quit system
emulation while blocked. However there are two things we still need to
ensure:

 - the PC has not advanced until completion so we can redo the instruction
 - we actually wake up the CPU in console_read

In my testcase console_read never seems to get called. I've tried with
both an external pipe loopback and using the ringbuf:

qemu-system-aarch64 -M virt --display none -cpu cortex-a57 -kernel systest-a64-with-console.axf -semihosting-config
 enable=on,chardev=sh0 -serial mon:stdio -chardev ringbuf,logfile=foo,id=sh0

]

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/exec/cpu-all.h   |  1 +
 hw/semihosting/console.c | 34 +++++++++++++++++-----------------
 2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index e96781a4559..093d7a76edd 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -31,6 +31,7 @@
 #define EXCP_HALTED     0x10003 /* cpu is halted (waiting for external event) */
 #define EXCP_YIELD      0x10004 /* cpu wants to yield timeslice to another */
 #define EXCP_ATOMIC     0x10005 /* stop-the-world and emulate atomic */
+#define EXCP_BLOCKED    0x10006 /* cpu is blocked (semihosting) */
 
 /* some important defines:
  *
diff --git a/hw/semihosting/console.c b/hw/semihosting/console.c
index 4db68d62270..bda457a0608 100644
--- a/hw/semihosting/console.c
+++ b/hw/semihosting/console.c
@@ -20,6 +20,7 @@
 #include "hw/semihosting/semihost.h"
 #include "hw/semihosting/console.h"
 #include "exec/gdbstub.h"
+#include "exec/exec-all.h"
 #include "qemu/log.h"
 #include "chardev/char.h"
 #include <pthread.h>
@@ -109,50 +110,49 @@ void qemu_semihosting_console_outc(CPUArchState *env, target_ulong addr)
 
 typedef struct SemihostingConsole {
     CharBackend         backend;
-    pthread_mutex_t     mutex;
-    pthread_cond_t      cond;
+    CPUState            *sleeping_cpu;
     bool                got;
     Fifo8               fifo;
 } SemihostingConsole;
 
-static SemihostingConsole console = {
-    .mutex = PTHREAD_MUTEX_INITIALIZER,
-    .cond = PTHREAD_COND_INITIALIZER
-};
+static SemihostingConsole console;
 
 static int console_can_read(void *opaque)
 {
     SemihostingConsole *c = opaque;
     int ret;
-    pthread_mutex_lock(&c->mutex);
+    g_assert(qemu_mutex_iothread_locked());
     ret = (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 = opaque;
-    pthread_mutex_lock(&c->mutex);
+    g_assert(qemu_mutex_iothread_locked());
     while (size-- && !fifo8_is_full(&c->fifo)) {
         fifo8_push(&c->fifo, *buf++);
     }
-    pthread_cond_broadcast(&c->cond);
-    pthread_mutex_unlock(&c->mutex);
+    if (c->sleeping_cpu) {
+        cpu_resume(c->sleeping_cpu);
+    }
 }
 
 target_ulong qemu_semihosting_console_inc(CPUArchState *env)
 {
     uint8_t ch;
     SemihostingConsole *c = &console;
-    qemu_mutex_unlock_iothread();
-    pthread_mutex_lock(&c->mutex);
-    while (fifo8_is_empty(&c->fifo)) {
-        pthread_cond_wait(&c->cond, &c->mutex);
+    g_assert(qemu_mutex_iothread_locked());
+    g_assert(current_cpu);
+    if (fifo8_is_empty(&c->fifo)) {
+        c->sleeping_cpu = current_cpu;
+        c->sleeping_cpu->stop = true;
+        c->sleeping_cpu->exception_index = EXCP_BLOCKED;
+        cpu_loop_exit(c->sleeping_cpu);
+        /* never returns */
     }
+    c->sleeping_cpu = NULL;
     ch = fifo8_pop(&c->fifo);
-    pthread_mutex_unlock(&c->mutex);
-    qemu_mutex_lock_iothread();
     return (target_ulong) ch;
 }
 
-- 
2.20.1



  reply	other threads:[~2019-12-17 12:16 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-23 19:26 [PATCH] Semihost SYS_READC implementation (v3) Keith Packard
2019-10-24 17:33 ` no-reply
2019-10-24 18:54   ` Paolo Bonzini
2019-10-24 22:46     ` [PATCH] Semihost SYS_READC implementation (v4) Keith Packard
2019-10-25  9:51       ` Alex Bennée
2019-10-25 16:36         ` Keith Packard
2019-10-25 16:49           ` Peter Maydell
2019-10-25 19:15             ` Keith Packard
2019-10-25 20:53               ` Peter Maydell
2019-10-25 23:18                 ` Keith Packard
2019-11-04 20:42                   ` [PATCH] Semihost SYS_READC implementation (v6) Keith Packard
2019-12-17  8:38                     ` Alex Bennée
2019-12-17  9:08                       ` Paolo Bonzini
2019-12-17  9:51                         ` Alex Bennée
2019-12-17 10:04                           ` Paolo Bonzini
2019-12-17 12:14                             ` Alex Bennée [this message]
2019-12-17 12:22                               ` [RFC PATCH] semihosting: suspend recieving CPU when blocked (HACK, WIP) Paolo Bonzini
2019-12-17 13:42                                 ` Alex Bennée
2019-12-17 13:48                                   ` Paolo Bonzini
2019-12-17 14:18                                     ` Alex Bennée
2019-12-17 14:39                                       ` Paolo Bonzini
2019-12-17 14:39                                       ` Paolo Bonzini
2019-12-18 17:36                                         ` Alex Bennée
2019-12-18 21:23                                           ` Paolo Bonzini
2019-11-05  5:10                 ` [PATCH] Semihost SYS_READC implementation (v4) Keith Packard
2019-11-11 14:51                   ` Peter Maydell
2019-11-14 15:46                     ` Alistair Francis
2019-11-14 17:43                       ` Keith Packard
2019-11-14 17:39                     ` Keith Packard
2019-11-14 17:47                       ` Peter Maydell
2019-11-14 19:20                         ` Peter Maydell
2019-11-14 16:14               ` Peter Maydell
2019-11-14 18:05                 ` Keith Packard
2019-11-14 18:18                   ` Peter Maydell
2019-11-14 19:18                 ` Richard Henderson
2019-11-14 19:29                   ` Peter Maydell
2019-11-14 20:52                     ` Richard Henderson
2019-11-14 21:04                       ` Peter Maydell
2019-11-14 22:26                   ` Keith Packard
2019-11-15 10:54                     ` Peter Maydell
2019-11-15 23:40                       ` Keith Packard
2019-10-25 17:02           ` Alex Bennée
2019-10-25 18:17       ` no-reply
2019-10-25 18:20       ` no-reply
2019-10-24 17:43 ` [PATCH] Semihost SYS_READC implementation (v3) no-reply

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=20191217121443.14757-1-alex.bennee@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=keithp@keithp.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).