aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/aarch64/cpu_loop.c1
-rw-r--r--linux-user/arm/cpu_loop.c1
-rw-r--r--linux-user/arm/semihost.c27
3 files changed, 29 insertions, 0 deletions
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
index 31c845a70d..bbe9fefca8 100644
--- a/linux-user/aarch64/cpu_loop.c
+++ b/linux-user/aarch64/cpu_loop.c
@@ -130,6 +130,7 @@ void cpu_loop(CPUARMState *env)
break;
case EXCP_SEMIHOST:
env->xregs[0] = do_arm_semihosting(env);
+ env->pc += 4;
break;
case EXCP_YIELD:
/* nothing to do here for user-mode, just resume guest code */
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index 7be4071751..1fae90c6df 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -377,6 +377,7 @@ void cpu_loop(CPUARMState *env)
break;
case EXCP_SEMIHOST:
env->regs[0] = do_arm_semihosting(env);
+ env->regs[15] += env->thumb ? 2 : 4;
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
diff --git a/linux-user/arm/semihost.c b/linux-user/arm/semihost.c
index a16b525eec..a1f0f6050e 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 <termios.h>
int qemu_semihosting_console_outs(CPUArchState *env, target_ulong addr)
{
@@ -47,3 +48,29 @@ void qemu_semihosting_console_outc(CPUArchState *env, target_ulong addr)
}
}
}
+
+/*
+ * For linux-user we can safely block. However as we want to return as
+ * soon as a character is read we need to tweak the termio to disable
+ * line buffering. We restore the old mode afterwards in case the
+ * program is expecting more normal behaviour. This is slow but
+ * nothing using semihosting console reading is expecting to be fast.
+ */
+target_ulong qemu_semihosting_console_inc(CPUArchState *env)
+{
+ uint8_t c;
+ struct termios old_tio, new_tio;
+
+ /* Disable line-buffering and echo */
+ tcgetattr(STDIN_FILENO, &old_tio);
+ new_tio = old_tio;
+ new_tio.c_lflag &= (~ICANON & ~ECHO);
+ tcsetattr(STDIN_FILENO, TCSANOW, &new_tio);
+
+ c = getchar();
+
+ /* restore config */
+ tcsetattr(STDIN_FILENO, TCSANOW, &old_tio);
+
+ return (target_ulong) c;
+}