@@ -34,8 +34,6 @@
#include "qemu/log.h"
#include "sysemu/sysemu.h"
-static CharBackend *xtensa_sim_console;
-
enum {
TARGET_SYS_exit = 1,
TARGET_SYS_read = 3,
@@ -153,12 +151,45 @@ static uint32_t errno_h2g(int host_errno)
}
}
+typedef struct SimInputBuffer {
+ char buffer[16];
+ size_t offset;
+} SimInputBuffer;
+
+static CharBackend *xtensa_sim_console;
+static SimInputBuffer sim_input_buffer;
+
+static IOCanReadHandler xtensa_sim_console_can_read;
+static int xtensa_sim_console_can_read(void *opaque)
+{
+ SimInputBuffer *p = opaque;
+
+ return sizeof(p->buffer) - p->offset;
+}
+
+static IOReadHandler xtensa_sim_console_read;
+static void xtensa_sim_console_read(void *opaque, const uint8_t *buf, int size)
+{
+ SimInputBuffer *p = opaque;
+ size_t copy = sizeof(p->buffer) - p->offset;
+
+ if (size < copy) {
+ copy = size;
+ }
+ memcpy(p->buffer + p->offset, buf, copy);
+ p->offset += copy;
+}
+
void xtensa_sim_open_console(Chardev *chr)
{
static CharBackend console;
qemu_chr_fe_init(&console, chr, &error_abort);
- qemu_chr_fe_set_handlers(&console, NULL, NULL, NULL, NULL, NULL, NULL, true);
+ qemu_chr_fe_set_handlers(&console,
+ xtensa_sim_console_can_read,
+ xtensa_sim_console_read,
+ NULL, NULL, &sim_input_buffer,
+ NULL, true);
xtensa_sim_console = &console;
}
@@ -200,6 +231,22 @@ void HELPER(simcall)(CPUXtensaState *env)
io_done = qemu_chr_fe_write_all(xtensa_sim_console,
buf, io_sz);
regs[3] = errno_h2g(errno);
+ } else if (!is_write && fd == 0) {
+ if (sim_input_buffer.offset) {
+ io_done = sim_input_buffer.offset;
+ if (io_sz < io_done) {
+ io_done = io_sz;
+ }
+ memcpy(buf, sim_input_buffer.buffer, io_done);
+ memmove(sim_input_buffer.buffer,
+ sim_input_buffer.buffer + io_done,
+ sim_input_buffer.offset - io_done);
+ sim_input_buffer.offset -= io_done;
+ qemu_chr_fe_accept_input(xtensa_sim_console);
+ } else {
+ io_done = -1;
+ regs[3] = TARGET_EAGAIN;
+ }
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"%s fd %d is not supported with chardev console\n",
@@ -295,6 +342,8 @@ void HELPER(simcall)(CPUXtensaState *env)
if (fd < 3 && xtensa_sim_console) {
if ((fd == 1 || fd == 2) && rq == SELECT_ONE_WRITE) {
regs[2] = 1;
+ } else if (fd == 0 && rq == SELECT_ONE_READ) {
+ regs[2] = sim_input_buffer.offset > 0;
} else {
regs[2] = 0;
}
Complete xtensa-semi chardev console implementation: allow reading input characters from file descriptor 0 and call sys_select_one simcall on it. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> --- target/xtensa/xtensa-semi.c | 55 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-)