summaryrefslogtreecommitdiffstats
path: root/semihosting/console.c
diff options
context:
space:
mode:
authorRichard Henderson2022-06-28 06:54:30 +0200
committerRichard Henderson2022-06-28 06:54:31 +0200
commitad4c7f529a279685da84297773b4ec8080153c2d (patch)
treeb5cc9c2dab4334b6ccd544a71a372424e3bd0f74 /semihosting/console.c
parentMerge tag 'pull-target-arm-20220627' of https://git.linaro.org/people/pmaydel... (diff)
parenttarget/nios2: Move nios2-semi.c to nios2_softmmu_ss (diff)
downloadqemu-ad4c7f529a279685da84297773b4ec8080153c2d.tar.gz
qemu-ad4c7f529a279685da84297773b4ec8080153c2d.tar.xz
qemu-ad4c7f529a279685da84297773b4ec8080153c2d.zip
Merge tag 'pull-semi-20220628' of https://gitlab.com/rth7680/qemu into staging
Semihosting syscall reorg: * Split out semihosting/syscalls.c with common implementations. * Reorg arm-compat-semi.c to use syscalls.c. * Minor prep cleanups to m68k, mips, nios2. # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmK6iSodHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV8SEwgAmmowW2oeFA9uCrwz # gUJo17AJ+RmRF/zXHyu5CPswylvfwH0zJXAm5BV7P/pVdyaL36b8YcgSEf+EWLsf # rLFHxCshTYEnZSk6yFtWk5bn5azfevHm9/ObPeS9XGL4seQqGy7C/FReoTQ7/zI0 # W3zUDd3bWah3fXw8XYgSzh/RCrC5E2gFFc1G1g+6SIVZ7pbgkre2rRk5WMmylCLd # jf9pmyswrheaKumCoBxU/S4XDgxVpaf3khiIqdbo8A20MDGnK/SZUWsBwJLK3QB8 # SKKv8o1ovbnl/HykABaszCIkO/LIu6SX3LoK7pF2CujkgSuwEN3WW0DOml6+b3fU # J7YeZg== # =sTbM # -----END PGP SIGNATURE----- # gpg: Signature made Tue 28 Jun 2022 10:22:58 AM +0530 # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate] * tag 'pull-semi-20220628' of https://gitlab.com/rth7680/qemu: (60 commits) target/nios2: Move nios2-semi.c to nios2_softmmu_ss target/nios2: Eliminate nios2_semi_is_lseek target/mips: Drop pread and pwrite syscalls from semihosting target/mips: Add UHI errno values target/mips: Use an exception for semihosting target/m68k: Make semihosting system only target/m68k: Eliminate m68k_semi_is_fseek semihosting: Create semihost_sys_poll_one semihosting: Remove qemu_semihosting_console_outs semihosting: Use console_out_gf for SYS_WRITE0 semihosting: Remove qemu_semihosting_console_outc semihosting: Use console_out_gf for SYS_WRITEC semihosting: Use console_in_gf for SYS_READC semihosting: Create qemu_semihosting_guestfd_init semihosting: Add GuestFDConsole semihosting: Create qemu_semihosting_console_write semihosting: Cleanup chardev init semihosting: Expand qemu_semihosting_console_inc to read semihosting: Pass CPUState to qemu_semihosting_console_inc semihosting: Fix docs comment for qemu_semihosting_console_inc ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'semihosting/console.c')
-rw-r--r--semihosting/console.c147
1 files changed, 56 insertions, 91 deletions
diff --git a/semihosting/console.c b/semihosting/console.c
index ef6958d844..cda7cf1905 100644
--- a/semihosting/console.c
+++ b/semihosting/console.c
@@ -27,89 +27,10 @@
#include "qapi/error.h"
#include "qemu/fifo8.h"
-int qemu_semihosting_log_out(const char *s, int len)
-{
- Chardev *chardev = semihosting_get_chardev();
- if (chardev) {
- return qemu_chr_write_all(chardev, (uint8_t *) s, len);
- } else {
- return write(STDERR_FILENO, s, len);
- }
-}
-
-/*
- * A re-implementation of lock_user_string that we can use locally
- * instead of relying on softmmu-semi. Hopefully we can deprecate that
- * in time. Copy string until we find a 0 or address error.
- */
-static GString *copy_user_string(CPUArchState *env, target_ulong addr)
-{
- CPUState *cpu = env_cpu(env);
- GString *s = g_string_sized_new(128);
- uint8_t c;
-
- do {
- if (cpu_memory_rw_debug(cpu, addr++, &c, 1, 0) == 0) {
- if (c) {
- s = g_string_append_c(s, c);
- }
- } else {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: passed inaccessible address " TARGET_FMT_lx,
- __func__, addr);
- break;
- }
- } while (c!=0);
-
- return s;
-}
-
-static void semihosting_cb(CPUState *cs, target_ulong ret, target_ulong err)
-{
- if (ret == (target_ulong) -1) {
- qemu_log("%s: gdb console output failed ("TARGET_FMT_ld")",
- __func__, err);
- }
-}
-
-int qemu_semihosting_console_outs(CPUArchState *env, target_ulong addr)
-{
- GString *s = copy_user_string(env, addr);
- int out = s->len;
-
- if (use_gdb_syscalls()) {
- gdb_do_syscall(semihosting_cb, "write,2,%x,%x", addr, s->len);
- } else {
- out = qemu_semihosting_log_out(s->str, s->len);
- }
-
- g_string_free(s, true);
- return out;
-}
-
-void qemu_semihosting_console_outc(CPUArchState *env, target_ulong addr)
-{
- CPUState *cpu = env_cpu(env);
- uint8_t c;
-
- if (cpu_memory_rw_debug(cpu, addr, &c, 1, 0) == 0) {
- if (use_gdb_syscalls()) {
- gdb_do_syscall(semihosting_cb, "write,2,%x,%x", addr, 1);
- } else {
- qemu_semihosting_log_out((const char *) &c, 1);
- }
- } else {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: passed inaccessible address " TARGET_FMT_lx,
- __func__, addr);
- }
-}
-
-#define FIFO_SIZE 1024
-
/* Access to this structure is protected by the BQL */
typedef struct SemihostingConsole {
CharBackend backend;
+ Chardev *chr;
GSList *sleeping_cpus;
bool got;
Fifo8 fifo;
@@ -117,6 +38,17 @@ typedef struct SemihostingConsole {
static SemihostingConsole console;
+int qemu_semihosting_log_out(const char *s, int len)
+{
+ if (console.chr) {
+ return qemu_chr_write_all(console.chr, (uint8_t *) s, len);
+ } else {
+ return write(STDERR_FILENO, s, len);
+ }
+}
+
+#define FIFO_SIZE 1024
+
static int console_can_read(void *opaque)
{
SemihostingConsole *c = opaque;
@@ -145,27 +77,58 @@ static void console_read(void *opaque, const uint8_t *buf, int size)
c->sleeping_cpus = NULL;
}
-target_ulong qemu_semihosting_console_inc(CPUArchState *env)
+bool qemu_semihosting_console_ready(void)
+{
+ SemihostingConsole *c = &console;
+
+ g_assert(qemu_mutex_iothread_locked());
+ return !fifo8_is_empty(&c->fifo);
+}
+
+void qemu_semihosting_console_block_until_ready(CPUState *cs)
{
- uint8_t ch;
SemihostingConsole *c = &console;
+
g_assert(qemu_mutex_iothread_locked());
- g_assert(current_cpu);
+
+ /* Block if the fifo is completely empty. */
if (fifo8_is_empty(&c->fifo)) {
- c->sleeping_cpus = g_slist_prepend(c->sleeping_cpus, current_cpu);
- current_cpu->halted = 1;
- current_cpu->exception_index = EXCP_HALTED;
- cpu_loop_exit(current_cpu);
+ c->sleeping_cpus = g_slist_prepend(c->sleeping_cpus, cs);
+ cs->halted = 1;
+ cs->exception_index = EXCP_HALTED;
+ cpu_loop_exit(cs);
/* never returns */
}
- ch = fifo8_pop(&c->fifo);
- return (target_ulong) ch;
}
-void qemu_semihosting_console_init(void)
+int qemu_semihosting_console_read(CPUState *cs, void *buf, int len)
{
- Chardev *chr = semihosting_get_chardev();
+ SemihostingConsole *c = &console;
+ int ret = 0;
+
+ qemu_semihosting_console_block_until_ready(cs);
+
+ /* Read until buffer full or fifo exhausted. */
+ do {
+ *(char *)(buf + ret) = fifo8_pop(&c->fifo);
+ ret++;
+ } while (ret < len && !fifo8_is_empty(&c->fifo));
+
+ return ret;
+}
+int qemu_semihosting_console_write(void *buf, int len)
+{
+ if (console.chr) {
+ return qemu_chr_write_all(console.chr, (uint8_t *)buf, len);
+ } else {
+ return fwrite(buf, 1, len, stderr);
+ }
+}
+
+void qemu_semihosting_console_init(Chardev *chr)
+{
+ console.chr = chr;
if (chr) {
fifo8_create(&console.fifo, FIFO_SIZE);
qemu_chr_fe_init(&console.backend, chr, &error_abort);
@@ -175,4 +138,6 @@ void qemu_semihosting_console_init(void)
NULL, NULL, &console,
NULL, true);
}
+
+ qemu_semihosting_guestfd_init();
}