|
@@ -520,6 +520,21 @@ static void host_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete,
|
|
|
unlock_user(p, tv_addr, sizeof(struct gdb_timeval));
|
|
|
}
|
|
|
|
|
|
+#ifndef CONFIG_USER_ONLY
|
|
|
+static void host_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
|
|
|
+ GuestFD *gf, GIOCondition cond, int timeout)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * Since this is only used by xtensa in system mode, and stdio is
|
|
|
+ * handled through GuestFDConsole, and there are no semihosting
|
|
|
+ * system calls for sockets and the like, that means this descriptor
|
|
|
+ * must be a normal file. Normal files never block and are thus
|
|
|
+ * always ready.
|
|
|
+ */
|
|
|
+ complete(cs, cond & (G_IO_IN | G_IO_OUT), 0);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/*
|
|
|
* Static file semihosting syscall implementations.
|
|
|
*/
|
|
@@ -628,6 +643,34 @@ static void console_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
|
|
|
complete(cs, ret ? -1 : 0, ret ? -ret : 0);
|
|
|
}
|
|
|
|
|
|
+#ifndef CONFIG_USER_ONLY
|
|
|
+static void console_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
|
|
|
+ GuestFD *gf, GIOCondition cond, int timeout)
|
|
|
+{
|
|
|
+ /* The semihosting console does not support urgent data or errors. */
|
|
|
+ cond &= G_IO_IN | G_IO_OUT;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Since qemu_semihosting_console_write never blocks, we can
|
|
|
+ * consider output always ready -- leave G_IO_OUT alone.
|
|
|
+ * All that remains is to conditionally signal input ready.
|
|
|
+ * Since output ready causes an immediate return, only block
|
|
|
+ * for G_IO_IN alone.
|
|
|
+ *
|
|
|
+ * TODO: Implement proper timeout. For now, only support
|
|
|
+ * indefinite wait or immediate poll.
|
|
|
+ */
|
|
|
+ if (cond == G_IO_IN && timeout < 0) {
|
|
|
+ qemu_semihosting_console_block_until_ready(cs);
|
|
|
+ /* We returned -- input must be ready. */
|
|
|
+ } else if ((cond & G_IO_IN) && !qemu_semihosting_console_ready()) {
|
|
|
+ cond &= ~G_IO_IN;
|
|
|
+ }
|
|
|
+
|
|
|
+ complete(cs, cond, 0);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/*
|
|
|
* Syscall entry points.
|
|
|
*/
|
|
@@ -906,3 +949,30 @@ void semihost_sys_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete,
|
|
|
host_gettimeofday(cs, complete, tv_addr, tz_addr);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+#ifndef CONFIG_USER_ONLY
|
|
|
+void semihost_sys_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
|
|
|
+ int fd, GIOCondition cond, int timeout)
|
|
|
+{
|
|
|
+ GuestFD *gf = get_guestfd(fd);
|
|
|
+
|
|
|
+ if (!gf) {
|
|
|
+ complete(cs, G_IO_NVAL, 1);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ switch (gf->type) {
|
|
|
+ case GuestFDGDB:
|
|
|
+ complete(cs, G_IO_NVAL, 1);
|
|
|
+ break;
|
|
|
+ case GuestFDHost:
|
|
|
+ host_poll_one(cs, complete, gf, cond, timeout);
|
|
|
+ break;
|
|
|
+ case GuestFDConsole:
|
|
|
+ console_poll_one(cs, complete, gf, cond, timeout);
|
|
|
+ break;
|
|
|
+ case GuestFDStatic:
|
|
|
+ default:
|
|
|
+ g_assert_not_reached();
|
|
|
+ }
|
|
|
+}
|
|
|
+#endif
|