* [Qemu-devel] [PATCH 1/3] target/xtensa: fix mapping direction in read/write simcalls
2017-05-12 23:36 [Qemu-devel] [PATCH 0/3] target/xtensa semihosting fixes Max Filippov
@ 2017-05-12 23:36 ` Max Filippov
2017-05-12 23:36 ` [Qemu-devel] [PATCH 2/3] target/xtensa: fix return value of " Max Filippov
2017-05-12 23:36 ` [Qemu-devel] [PATCH 3/3] target/xtensa: support output to chardev console Max Filippov
2 siblings, 0 replies; 4+ messages in thread
From: Max Filippov @ 2017-05-12 23:36 UTC (permalink / raw)
To: qemu-devel; +Cc: Max Filippov, qemu-stable
Read and write simcalls map physical memory to access I/O buffers, but
'read' simcall need to map it for writing and 'write' simcall need to
map it for reading, i.e. the opposite of what they do now. Fix that.
Cc: qemu-stable@nongnu.org
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/xtensa-semi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/target/xtensa/xtensa-semi.c b/target/xtensa/xtensa-semi.c
index a888a9d..98ae28c 100644
--- a/target/xtensa/xtensa-semi.c
+++ b/target/xtensa/xtensa-semi.c
@@ -173,7 +173,7 @@ void HELPER(simcall)(CPUXtensaState *env)
TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1));
uint32_t io_sz = page_left < len ? page_left : len;
hwaddr sz = io_sz;
- void *buf = cpu_physical_memory_map(paddr, &sz, is_write);
+ void *buf = cpu_physical_memory_map(paddr, &sz, !is_write);
if (buf) {
vaddr += io_sz;
@@ -182,7 +182,7 @@ void HELPER(simcall)(CPUXtensaState *env)
write(fd, buf, io_sz) :
read(fd, buf, io_sz);
regs[3] = errno_h2g(errno);
- cpu_physical_memory_unmap(buf, sz, is_write, sz);
+ cpu_physical_memory_unmap(buf, sz, !is_write, sz);
if (regs[2] == -1) {
break;
}
--
2.1.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH 2/3] target/xtensa: fix return value of read/write simcalls
2017-05-12 23:36 [Qemu-devel] [PATCH 0/3] target/xtensa semihosting fixes Max Filippov
2017-05-12 23:36 ` [Qemu-devel] [PATCH 1/3] target/xtensa: fix mapping direction in read/write simcalls Max Filippov
@ 2017-05-12 23:36 ` Max Filippov
2017-05-12 23:36 ` [Qemu-devel] [PATCH 3/3] target/xtensa: support output to chardev console Max Filippov
2 siblings, 0 replies; 4+ messages in thread
From: Max Filippov @ 2017-05-12 23:36 UTC (permalink / raw)
To: qemu-devel; +Cc: Max Filippov, qemu-stable
Return value of read/write simcalls is not calculated correctly in case
of operations crossing page boundary and in case of short reads/writes.
Read and write simcalls should return the size of data actually
read/written or -1 in case of error.
Cc: qemu-stable@nongnu.org
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/xtensa-semi.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/target/xtensa/xtensa-semi.c b/target/xtensa/xtensa-semi.c
index 98ae28c..ffcaf8d 100644
--- a/target/xtensa/xtensa-semi.c
+++ b/target/xtensa/xtensa-semi.c
@@ -166,6 +166,7 @@ void HELPER(simcall)(CPUXtensaState *env)
uint32_t fd = regs[3];
uint32_t vaddr = regs[4];
uint32_t len = regs[5];
+ uint32_t len_done = 0;
while (len > 0) {
hwaddr paddr = cpu_get_phys_page_debug(cs, vaddr);
@@ -174,24 +175,38 @@ void HELPER(simcall)(CPUXtensaState *env)
uint32_t io_sz = page_left < len ? page_left : len;
hwaddr sz = io_sz;
void *buf = cpu_physical_memory_map(paddr, &sz, !is_write);
+ uint32_t io_done;
+ bool error = false;
if (buf) {
vaddr += io_sz;
len -= io_sz;
- regs[2] = is_write ?
+ io_done = is_write ?
write(fd, buf, io_sz) :
read(fd, buf, io_sz);
regs[3] = errno_h2g(errno);
- cpu_physical_memory_unmap(buf, sz, !is_write, sz);
- if (regs[2] == -1) {
- break;
+ if (io_done == -1) {
+ error = true;
+ io_done = 0;
}
+ cpu_physical_memory_unmap(buf, sz, !is_write, io_done);
} else {
- regs[2] = -1;
+ error = true;
regs[3] = TARGET_EINVAL;
break;
}
+ if (error) {
+ if (!len_done) {
+ len_done = -1;
+ }
+ break;
+ }
+ len_done += io_done;
+ if (io_done < io_sz) {
+ break;
+ }
}
+ regs[2] = len_done;
}
break;
--
2.1.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH 3/3] target/xtensa: support output to chardev console
2017-05-12 23:36 [Qemu-devel] [PATCH 0/3] target/xtensa semihosting fixes Max Filippov
2017-05-12 23:36 ` [Qemu-devel] [PATCH 1/3] target/xtensa: fix mapping direction in read/write simcalls Max Filippov
2017-05-12 23:36 ` [Qemu-devel] [PATCH 2/3] target/xtensa: fix return value of " Max Filippov
@ 2017-05-12 23:36 ` Max Filippov
2 siblings, 0 replies; 4+ messages in thread
From: Max Filippov @ 2017-05-12 23:36 UTC (permalink / raw)
To: qemu-devel; +Cc: Max Filippov
In semihosting mode QEMU allows guest to read and write host file
descriptors directly, including descriptors 0..2, a.k.a. stdin, stdout
and stderr. Sometimes it's desirable to have semihosting console
controlled by -serial option, e.g. to connect it to network.
Add semihosting console to xtensa-semi.c, open it in the 'sim' machine
in the presence of -serial option and direct stdout and stderr to it
when it's present.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
hw/xtensa/sim.c | 4 +++
target/xtensa/cpu.h | 1 +
target/xtensa/xtensa-semi.c | 66 +++++++++++++++++++++++++++++++++++----------
3 files changed, 57 insertions(+), 14 deletions(-)
diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c
index b27e28d..5521e91 100644
--- a/hw/xtensa/sim.c
+++ b/hw/xtensa/sim.c
@@ -114,6 +114,9 @@ static void xtensa_sim_init(MachineState *machine)
xtensa_create_memory_regions(&sysram, "xtensa.sysram");
}
+ if (serial_hds[0]) {
+ xtensa_sim_open_console(serial_hds[0]);
+ }
if (kernel_filename) {
uint64_t elf_entry;
uint64_t elf_lowaddr;
@@ -136,6 +139,7 @@ static void xtensa_sim_machine_init(MachineClass *mc)
mc->is_default = true;
mc->init = xtensa_sim_init;
mc->max_cpus = 4;
+ mc->no_serial = 1;
}
DEFINE_MACHINE("sim", xtensa_sim_machine_init)
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index ecca17d..ee29fb1 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -483,6 +483,7 @@ void xtensa_translate_init(void);
void xtensa_breakpoint_handler(CPUState *cs);
void xtensa_finalize_config(XtensaConfig *config);
void xtensa_register_core(XtensaConfigList *node);
+void xtensa_sim_open_console(Chardev *chr);
void check_interrupts(CPUXtensaState *s);
void xtensa_irq_init(CPUXtensaState *env);
void *xtensa_get_extint(CPUXtensaState *env, unsigned extint);
diff --git a/target/xtensa/xtensa-semi.c b/target/xtensa/xtensa-semi.c
index ffcaf8d..01c622e 100644
--- a/target/xtensa/xtensa-semi.c
+++ b/target/xtensa/xtensa-semi.c
@@ -29,7 +29,12 @@
#include "cpu.h"
#include "exec/helper-proto.h"
#include "exec/semihost.h"
+#include "qapi/error.h"
#include "qemu/log.h"
+#include "sysemu/char.h"
+#include "sysemu/sysemu.h"
+
+static CharBackend *xtensa_sim_console;
enum {
TARGET_SYS_exit = 1,
@@ -148,6 +153,15 @@ static uint32_t errno_h2g(int host_errno)
}
}
+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, true);
+ xtensa_sim_console = &console;
+}
+
void HELPER(simcall)(CPUXtensaState *env)
{
CPUState *cs = CPU(xtensa_env_get_cpu(env));
@@ -181,10 +195,25 @@ void HELPER(simcall)(CPUXtensaState *env)
if (buf) {
vaddr += io_sz;
len -= io_sz;
- io_done = is_write ?
- write(fd, buf, io_sz) :
- read(fd, buf, io_sz);
- regs[3] = errno_h2g(errno);
+ if (fd < 3 && xtensa_sim_console) {
+ if (is_write && (fd == 1 || fd == 2)) {
+ io_done = qemu_chr_fe_write_all(xtensa_sim_console,
+ buf, io_sz);
+ regs[3] = errno_h2g(errno);
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s fd %d is not supported with chardev console\n",
+ is_write ?
+ "writing to" : "reading from", fd);
+ io_done = -1;
+ regs[3] = TARGET_EBADF;
+ }
+ } else {
+ io_done = is_write ?
+ write(fd, buf, io_sz) :
+ read(fd, buf, io_sz);
+ regs[3] = errno_h2g(errno);
+ }
if (io_done == -1) {
error = true;
io_done = 0;
@@ -256,10 +285,6 @@ void HELPER(simcall)(CPUXtensaState *env)
uint32_t target_tvv[2];
struct timeval tv = {0};
- fd_set fdset;
-
- FD_ZERO(&fdset);
- FD_SET(fd, &fdset);
if (target_tv) {
cpu_memory_rw_debug(cs, target_tv,
@@ -267,12 +292,25 @@ void HELPER(simcall)(CPUXtensaState *env)
tv.tv_sec = (int32_t)tswap32(target_tvv[0]);
tv.tv_usec = (int32_t)tswap32(target_tvv[1]);
}
- regs[2] = select(fd + 1,
- rq == SELECT_ONE_READ ? &fdset : NULL,
- rq == SELECT_ONE_WRITE ? &fdset : NULL,
- rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
- target_tv ? &tv : NULL);
- regs[3] = errno_h2g(errno);
+ if (fd < 3 && xtensa_sim_console) {
+ if ((fd == 1 || fd == 2) && rq == SELECT_ONE_WRITE) {
+ regs[2] = 1;
+ } else {
+ regs[2] = 0;
+ }
+ regs[3] = 0;
+ } else {
+ fd_set fdset;
+
+ FD_ZERO(&fdset);
+ FD_SET(fd, &fdset);
+ regs[2] = select(fd + 1,
+ rq == SELECT_ONE_READ ? &fdset : NULL,
+ rq == SELECT_ONE_WRITE ? &fdset : NULL,
+ rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
+ target_tv ? &tv : NULL);
+ regs[3] = errno_h2g(errno);
+ }
}
break;
--
2.1.4
^ permalink raw reply related [flat|nested] 4+ messages in thread