qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/7] Add termios2 support to linux-user
@ 2025-08-30 13:14 Luca Bonissi
  2025-08-31 13:45 ` Andreas Schwab
  0 siblings, 1 reply; 10+ messages in thread
From: Luca Bonissi @ 2025-08-30 13:14 UTC (permalink / raw)
  To: Richard Henderson, Laurent Vivier; +Cc: qemu-devel

From f784259c584fa5f69172f5223b82e21e6054569f Mon Sep 17 00:00:00 2001
From: Luca Bonissi <qemu@bonslack.org>
Date: Sat, 30 Aug 2025 14:51:09 +0200
Subject: [PATCH 1/7] Add termios2 support to linux-user

Signed-off-by: Luca Bonissi <qemu@bonslack.org>
---
 linux-user/ioctls.h         |  6 +++
 linux-user/strace.c         | 63 +++++++++++++++++++++++++++++
 linux-user/syscall.c        | 80 +++++++++++++++++++++++++++++++++++++
 linux-user/syscall_types.h  |  3 ++
 linux-user/user-internals.h |  3 ++
 5 files changed, 155 insertions(+)

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 3b41128fd7..0b2deb2824 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -1,5 +1,11 @@
      /* emulated ioctl list */
 
+#ifdef TARGET_TCGETS2
+     IOCTL(TCGETS2, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios2)))
+     IOCTL(TCSETS2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
+     IOCTL(TCSETSW2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
+     IOCTL(TCSETSF2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
+#endif
      IOCTL(TCGETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
      IOCTL(TCSETS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
      IOCTL(TCSETSF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 786354627a..ce35769f92 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1933,6 +1933,69 @@ print_termios(void *arg)
     qemu_log("}");
 }
 
+#ifdef TARGET_TCGETS2
+void
+print_termios2(void *arg)
+{
+    const struct target_termios2 *target = arg;
+
+    target_tcflag_t iflags = tswap32(target->c_iflag);
+    target_tcflag_t oflags = tswap32(target->c_oflag);
+    target_tcflag_t cflags = tswap32(target->c_cflag);
+    target_tcflag_t lflags = tswap32(target->c_lflag);
+
+    qemu_log("{");
+
+    qemu_log("c_iflag = ");
+    print_flags(termios_iflags, iflags, 0);
+
+    qemu_log("c_oflag = ");
+    target_tcflag_t oflags_clean =  oflags & ~(TARGET_NLDLY | TARGET_CRDLY |
+                                               TARGET_TABDLY | TARGET_BSDLY |
+                                               TARGET_VTDLY | TARGET_FFDLY);
+    print_flags(termios_oflags, oflags_clean, 0);
+    if (oflags & TARGET_NLDLY) {
+        print_enums(termios_oflags_NLDLY, oflags & TARGET_NLDLY, 0);
+    }
+    if (oflags & TARGET_CRDLY) {
+        print_enums(termios_oflags_CRDLY, oflags & TARGET_CRDLY, 0);
+    }
+    if (oflags & TARGET_TABDLY) {
+        print_enums(termios_oflags_TABDLY, oflags & TARGET_TABDLY, 0);
+    }
+    if (oflags & TARGET_BSDLY) {
+        print_enums(termios_oflags_BSDLY, oflags & TARGET_BSDLY, 0);
+    }
+    if (oflags & TARGET_VTDLY) {
+        print_enums(termios_oflags_VTDLY, oflags & TARGET_VTDLY, 0);
+    }
+    if (oflags & TARGET_FFDLY) {
+        print_enums(termios_oflags_FFDLY, oflags & TARGET_FFDLY, 0);
+    }
+
+    qemu_log("c_cflag = ");
+    if (cflags & TARGET_CBAUD) {
+        print_enums(termios_cflags_CBAUD, cflags & TARGET_CBAUD, 0);
+    }
+    if (cflags & TARGET_CSIZE) {
+        print_enums(termios_cflags_CSIZE, cflags & TARGET_CSIZE, 0);
+    }
+    target_tcflag_t cflags_clean = cflags & ~(TARGET_CBAUD | TARGET_CSIZE);
+    print_flags(termios_cflags, cflags_clean, 0);
+
+    qemu_log("c_lflag = ");
+    print_flags(termios_lflags, lflags, 0);
+
+    qemu_log("c_cc = ");
+    qemu_log("\"%s\",", target->c_cc);
+
+    qemu_log("c_line = ");
+    print_raw_param("\'%c\'", target->c_line, 1);
+
+    qemu_log("}");
+}
+#endif
+
 #undef UNUSED
 
 #ifdef TARGET_NR_accept
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 91360a072c..41ef690e52 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -88,6 +88,7 @@
 #endif
 
 #define termios host_termios
+#define termios2 host_termios2
 #define winsize host_winsize
 #define termio host_termio
 #define sgttyb host_sgttyb /* same as target */
@@ -5887,6 +5888,85 @@ static const StructEntry struct_termios_def = {
     .print = print_termios,
 };
 
+#ifdef TARGET_TCGETS2
+static void target_to_host_termios2 (void *dst, const void *src)
+{
+    struct host_termios2 *host = dst;
+    const struct target_termios2 *target = src;
+
+    host->c_iflag =
+        target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
+    host->c_oflag =
+        target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
+    host->c_cflag =
+        target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
+    host->c_lflag =
+        target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
+    host->c_line = target->c_line;
+
+    memset(host->c_cc, 0, sizeof(host->c_cc));
+    host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
+    host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
+    host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
+    host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
+    host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
+    host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
+    host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
+    host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
+    host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
+    host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
+    host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
+    host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
+    host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
+    host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
+    host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
+    host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
+    host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
+}
+
+static void host_to_target_termios2 (void *dst, const void *src)
+{
+    struct target_termios2 *target = dst;
+    const struct host_termios2 *host = src;
+
+    target->c_iflag =
+        tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
+    target->c_oflag =
+        tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
+    target->c_cflag =
+        tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
+    target->c_lflag =
+        tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
+    target->c_line = host->c_line;
+
+    memset(target->c_cc, 0, sizeof(target->c_cc));
+    target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
+    target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
+    target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
+    target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
+    target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
+    target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
+    target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
+    target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
+    target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
+    target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
+    target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
+    target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
+    target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
+    target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
+    target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
+    target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
+    target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
+}
+
+static const StructEntry struct_termios2_def = {
+    .convert = { host_to_target_termios2, target_to_host_termios2 },
+    .size = { sizeof(struct target_termios2), sizeof(struct host_termios2) },
+    .align = { __alignof__(struct target_termios2), __alignof__(struct host_termios2) },
+    .print = print_termios2,
+};
+#endif
+
 /* If the host does not provide these bits, they may be safely discarded. */
 #ifndef MAP_SYNC
 #define MAP_SYNC 0
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index 6dd7a80ce5..ac45705acf 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -1,4 +1,7 @@
 STRUCT_SPECIAL(termios)
+#ifdef TARGET_TCGETS2
+STRUCT_SPECIAL(termios2)
+#endif
 
 STRUCT(winsize,
        TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
index 691b9a1775..191e01c3a8 100644
--- a/linux-user/user-internals.h
+++ b/linux-user/user-internals.h
@@ -127,6 +127,9 @@ static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
 #endif /* TARGET_ABI_BITS != 32 */
 
 void print_termios(void *arg);
+#ifdef TARGET_TCGETS2
+void print_termios2(void *arg);
+#endif
 
 /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
 #ifdef TARGET_ARM
-- 
2.50.1




^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/7] Add termios2 support to linux-user
  2025-08-30 13:14 Luca Bonissi
@ 2025-08-31 13:45 ` Andreas Schwab
  2025-10-31 12:42   ` Luca Bonissi
  0 siblings, 1 reply; 10+ messages in thread
From: Andreas Schwab @ 2025-08-31 13:45 UTC (permalink / raw)
  To: Luca Bonissi; +Cc: Richard Henderson, Laurent Vivier, qemu-devel

On Aug 30 2025, Luca Bonissi wrote:

> @@ -5887,6 +5888,85 @@ static const StructEntry struct_termios_def = {
>      .print = print_termios,
>  };
>  
> +#ifdef TARGET_TCGETS2
> +static void target_to_host_termios2 (void *dst, const void *src)
> +{
> +    struct host_termios2 *host = dst;
> +    const struct target_termios2 *target = src;
> +
> +    host->c_iflag =
> +        target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
> +    host->c_oflag =
> +        target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
> +    host->c_cflag =
> +        target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
> +    host->c_lflag =
> +        target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
> +    host->c_line = target->c_line;
> +
> +    memset(host->c_cc, 0, sizeof(host->c_cc));
> +    host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
> +    host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
> +    host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
> +    host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
> +    host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
> +    host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
> +    host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
> +    host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
> +    host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
> +    host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
> +    host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
> +    host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
> +    host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
> +    host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
> +    host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
> +    host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
> +    host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
> +}
> +
> +static void host_to_target_termios2 (void *dst, const void *src)
> +{
> +    struct target_termios2 *target = dst;
> +    const struct host_termios2 *host = src;
> +
> +    target->c_iflag =
> +        tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
> +    target->c_oflag =
> +        tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
> +    target->c_cflag =
> +        tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
> +    target->c_lflag =
> +        tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
> +    target->c_line = host->c_line;
> +
> +    memset(target->c_cc, 0, sizeof(target->c_cc));
> +    target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
> +    target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
> +    target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
> +    target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
> +    target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
> +    target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
> +    target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
> +    target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
> +    target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
> +    target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
> +    target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
> +    target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
> +    target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
> +    target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
> +    target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
> +    target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
> +    target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
> +}

That fails to copy c_[io]speed.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/7] Add termios2 support to linux-user
  2025-08-31 13:45 ` Andreas Schwab
@ 2025-10-31 12:42   ` Luca Bonissi
  0 siblings, 0 replies; 10+ messages in thread
From: Luca Bonissi @ 2025-10-31 12:42 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Richard Henderson, Laurent Vivier, qemu-devel

On 31/08/25 15:45, Andreas Schwab wrote:
> On Aug 30 2025, Luca Bonissi wrote:
> 
>> +#ifdef TARGET_TCGETS2
>> +static void target_to_host_termios2 (void *dst, const void *src)
>> +{
>> +    struct host_termios2 *host = dst;
>> +    const struct target_termios2 *target = src;
>> +
>> [...]
>> +}
>> +
>> +static void host_to_target_termios2 (void *dst, const void *src)
>> +{
>> +    struct target_termios2 *target = dst;
>> +    const struct host_termios2 *host = src;
>> +
>> [...]
>> +}
> 
> That fails to copy c_[io]speed.
> 

You are right!!

I added also c-[io]speed copy. Will follow new patches.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/7] Add termios2 support to linux-user
@ 2025-10-31 13:23 Luca Bonissi
  2025-11-02 10:29 ` Andreas Schwab
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Luca Bonissi @ 2025-10-31 13:23 UTC (permalink / raw)
  To: Richard Henderson, Laurent Vivier; +Cc: qemu-devel

From 6ddab7d3ba1035b5e2a6016bde4776436267c18b Mon Sep 17 00:00:00 2001
From: Luca Bonissi <qemu@bonslack.org>
Date: Fri, 31 Oct 2025 13:29:19 +0100
Subject: [PATCH 1/7] Add termios2 support to linux-user

Signed-off-by: Luca Bonissi <qemu@bonslack.org>
---
 linux-user/ioctls.h         |  6 +++
 linux-user/strace.c         | 69 ++++++++++++++++++++++++++++++
 linux-user/syscall.c        | 84 +++++++++++++++++++++++++++++++++++++
 linux-user/syscall_types.h  |  3 ++
 linux-user/user-internals.h |  3 ++
 5 files changed, 165 insertions(+)

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 2f62fd2cb9..6ecfe6306e 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -1,5 +1,11 @@
      /* emulated ioctl list */
 
+#ifdef TARGET_TCGETS2
+     IOCTL(TCGETS2, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios2)))
+     IOCTL(TCSETS2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
+     IOCTL(TCSETSW2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
+     IOCTL(TCSETSF2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
+#endif
      IOCTL(TCGETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
      IOCTL(TCSETS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
      IOCTL(TCSETSF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 758c5d32b6..7afb94544f 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1935,6 +1935,75 @@ print_termios(void *arg)
     qemu_log("}");
 }
 
+#ifdef TARGET_TCGETS2
+void
+print_termios2(void *arg)
+{
+    const struct target_termios2 *target = arg;
+
+    target_tcflag_t iflags = tswap32(target->c_iflag);
+    target_tcflag_t oflags = tswap32(target->c_oflag);
+    target_tcflag_t cflags = tswap32(target->c_cflag);
+    target_tcflag_t lflags = tswap32(target->c_lflag);
+
+    qemu_log("{");
+
+    qemu_log("c_iflag = ");
+    print_flags(termios_iflags, iflags, 0);
+
+    qemu_log("c_oflag = ");
+    target_tcflag_t oflags_clean =  oflags & ~(TARGET_NLDLY | TARGET_CRDLY |
+                                               TARGET_TABDLY | TARGET_BSDLY |
+                                               TARGET_VTDLY | TARGET_FFDLY);
+    print_flags(termios_oflags, oflags_clean, 0);
+    if (oflags & TARGET_NLDLY) {
+        print_enums(termios_oflags_NLDLY, oflags & TARGET_NLDLY, 0);
+    }
+    if (oflags & TARGET_CRDLY) {
+        print_enums(termios_oflags_CRDLY, oflags & TARGET_CRDLY, 0);
+    }
+    if (oflags & TARGET_TABDLY) {
+        print_enums(termios_oflags_TABDLY, oflags & TARGET_TABDLY, 0);
+    }
+    if (oflags & TARGET_BSDLY) {
+        print_enums(termios_oflags_BSDLY, oflags & TARGET_BSDLY, 0);
+    }
+    if (oflags & TARGET_VTDLY) {
+        print_enums(termios_oflags_VTDLY, oflags & TARGET_VTDLY, 0);
+    }
+    if (oflags & TARGET_FFDLY) {
+        print_enums(termios_oflags_FFDLY, oflags & TARGET_FFDLY, 0);
+    }
+
+    qemu_log("c_cflag = ");
+    if (cflags & TARGET_CBAUD) {
+        print_enums(termios_cflags_CBAUD, cflags & TARGET_CBAUD, 0);
+    }
+    if (cflags & TARGET_CSIZE) {
+        print_enums(termios_cflags_CSIZE, cflags & TARGET_CSIZE, 0);
+    }
+    target_tcflag_t cflags_clean = cflags & ~(TARGET_CBAUD | TARGET_CSIZE);
+    print_flags(termios_cflags, cflags_clean, 0);
+
+    qemu_log("c_lflag = ");
+    print_flags(termios_lflags, lflags, 0);
+
+    qemu_log("c_ispeed = ");
+    print_raw_param("%u", tswap32(target->c_ispeed), 0);
+
+    qemu_log("c_ospeed = ");
+    print_raw_param("%u", tswap32(target->c_ospeed), 0);
+
+    qemu_log("c_cc = ");
+    qemu_log("\"%s\",", target->c_cc);
+
+    qemu_log("c_line = ");
+    print_raw_param("\'%c\'", target->c_line, 1);
+
+    qemu_log("}");
+}
+#endif
+
 #undef UNUSED
 
 #ifdef TARGET_NR_accept
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8546f48a05..920bf23406 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -86,6 +86,7 @@
 #endif
 
 #define termios host_termios
+#define termios2 host_termios2
 #define winsize host_winsize
 #define termio host_termio
 #define sgttyb host_sgttyb /* same as target */
@@ -5885,6 +5886,89 @@ static const StructEntry struct_termios_def = {
     .print = print_termios,
 };
 
+#ifdef TARGET_TCGETS2
+static void target_to_host_termios2 (void *dst, const void *src)
+{
+    struct host_termios2 *host = dst;
+    const struct target_termios2 *target = src;
+
+    host->c_iflag =
+        target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
+    host->c_oflag =
+        target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
+    host->c_cflag =
+        target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
+    host->c_lflag =
+        target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
+    host->c_line = target->c_line;
+    host->c_ispeed = tswap32(target->c_ispeed);
+    host->c_ospeed = tswap32(target->c_ospeed);
+
+    memset(host->c_cc, 0, sizeof(host->c_cc));
+    host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
+    host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
+    host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
+    host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
+    host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
+    host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
+    host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
+    host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
+    host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
+    host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
+    host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
+    host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
+    host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
+    host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
+    host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
+    host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
+    host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
+}
+
+static void host_to_target_termios2 (void *dst, const void *src)
+{
+    struct target_termios2 *target = dst;
+    const struct host_termios2 *host = src;
+
+    target->c_iflag =
+        tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
+    target->c_oflag =
+        tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
+    target->c_cflag =
+        tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
+    target->c_lflag =
+        tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
+    target->c_line = host->c_line;
+    target->c_ispeed = tswap32(host->c_ispeed);
+    target->c_ospeed = tswap32(host->c_ospeed);
+
+    memset(target->c_cc, 0, sizeof(target->c_cc));
+    target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
+    target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
+    target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
+    target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
+    target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
+    target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
+    target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
+    target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
+    target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
+    target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
+    target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
+    target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
+    target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
+    target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
+    target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
+    target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
+    target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
+}
+
+static const StructEntry struct_termios2_def = {
+    .convert = { host_to_target_termios2, target_to_host_termios2 },
+    .size = { sizeof(struct target_termios2), sizeof(struct host_termios2) },
+    .align = { __alignof__(struct target_termios2), __alignof__(struct host_termios2) },
+    .print = print_termios2,
+};
+#endif
+
 /* If the host does not provide these bits, they may be safely discarded. */
 #ifndef MAP_SYNC
 #define MAP_SYNC 0
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index 6dd7a80ce5..ac45705acf 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -1,4 +1,7 @@
 STRUCT_SPECIAL(termios)
+#ifdef TARGET_TCGETS2
+STRUCT_SPECIAL(termios2)
+#endif
 
 STRUCT(winsize,
        TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
index 7099349ec8..067c02bb93 100644
--- a/linux-user/user-internals.h
+++ b/linux-user/user-internals.h
@@ -129,6 +129,9 @@ static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
 #endif /* TARGET_ABI_BITS != 32 */
 
 void print_termios(void *arg);
+#ifdef TARGET_TCGETS2
+void print_termios2(void *arg);
+#endif
 
 /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
 #ifdef TARGET_ARM
-- 
2.50.1




^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/7] Add termios2 support to linux-user
  2025-10-31 13:23 [PATCH 1/7] Add termios2 support to linux-user Luca Bonissi
@ 2025-11-02 10:29 ` Andreas Schwab
  2025-12-03 12:15 ` Daniel P. Berrangé
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Andreas Schwab @ 2025-11-02 10:29 UTC (permalink / raw)
  To: Luca Bonissi; +Cc: Richard Henderson, Laurent Vivier, qemu-devel

Please test with the glibc testsuite:

$ ~-/qemu-x86_64 termios/tst-termios-linux | head -30
warning: could not become root outside namespace (Operation not permitted)
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ospeed = 0, expected 123456
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 0, expected 123456
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 75, expected 1200
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 9600, expected 456789
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ospeed = 0, expected 54321
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 0, expected 1234567890
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 0, expected 2400
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 50, expected 2400
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 2400, expected 50
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 75, expected 2400
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 2400, expected 75
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 110, expected 2400
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 2400, expected 110
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 134, expected 2400
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 2400, expected 134
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 150, expected 2400
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 2400, expected 150
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 200, expected 2400
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 2400, expected 200
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 300, expected 2400
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 2400, expected 300
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 600, expected 2400
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 2400, expected 600
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 1200, expected 2400
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 2400, expected 1200
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 1800, expected 2400
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 2400, expected 1800
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 4800, expected 2400
error: ../sysdeps/unix/sysv/linux/tst-termios-linux.c:194: c_ispeed = 2400, expected 4800

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/7] Add termios2 support to linux-user
  2025-10-31 13:23 [PATCH 1/7] Add termios2 support to linux-user Luca Bonissi
  2025-11-02 10:29 ` Andreas Schwab
@ 2025-12-03 12:15 ` Daniel P. Berrangé
  2025-12-03 14:37   ` Luca Bonissi
  2025-12-04 12:48 ` Heinrich Schuchardt
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Daniel P. Berrangé @ 2025-12-03 12:15 UTC (permalink / raw)
  To: Luca Bonissi; +Cc: Richard Henderson, Laurent Vivier, qemu-devel

On Fri, Oct 31, 2025 at 02:23:21PM +0100, Luca Bonissi wrote:
> From 6ddab7d3ba1035b5e2a6016bde4776436267c18b Mon Sep 17 00:00:00 2001
> From: Luca Bonissi <qemu@bonslack.org>
> Date: Fri, 31 Oct 2025 13:29:19 +0100
> Subject: [PATCH 1/7] Add termios2 support to linux-user

You've added this for a handful of archiecture targets, but
in Fedora we're seeing the incompatibility affect s390x and
aarch64 too, which this series hasn't implemented.

BTW, ideally send a cover letter with a multi-patch
series; there are tools which make this easier than
using git send-email directly:

  https://www.qemu.org/docs/master/devel/submitting-a-patch.html#submitting-your-patches

> 
> Signed-off-by: Luca Bonissi <qemu@bonslack.org>
> ---
>  linux-user/ioctls.h         |  6 +++
>  linux-user/strace.c         | 69 ++++++++++++++++++++++++++++++
>  linux-user/syscall.c        | 84 +++++++++++++++++++++++++++++++++++++
>  linux-user/syscall_types.h  |  3 ++
>  linux-user/user-internals.h |  3 ++
>  5 files changed, 165 insertions(+)
> 
> diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
> index 2f62fd2cb9..6ecfe6306e 100644
> --- a/linux-user/ioctls.h
> +++ b/linux-user/ioctls.h
> @@ -1,5 +1,11 @@
>       /* emulated ioctl list */
>  
> +#ifdef TARGET_TCGETS2
> +     IOCTL(TCGETS2, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios2)))
> +     IOCTL(TCSETS2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
> +     IOCTL(TCSETSW2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
> +     IOCTL(TCSETSF2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
> +#endif
>       IOCTL(TCGETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
>       IOCTL(TCSETS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
>       IOCTL(TCSETSF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
> diff --git a/linux-user/strace.c b/linux-user/strace.c
> index 758c5d32b6..7afb94544f 100644
> --- a/linux-user/strace.c
> +++ b/linux-user/strace.c
> @@ -1935,6 +1935,75 @@ print_termios(void *arg)
>      qemu_log("}");
>  }
>  
> +#ifdef TARGET_TCGETS2
> +void
> +print_termios2(void *arg)
> +{
> +    const struct target_termios2 *target = arg;
> +
> +    target_tcflag_t iflags = tswap32(target->c_iflag);
> +    target_tcflag_t oflags = tswap32(target->c_oflag);
> +    target_tcflag_t cflags = tswap32(target->c_cflag);
> +    target_tcflag_t lflags = tswap32(target->c_lflag);
> +
> +    qemu_log("{");
> +
> +    qemu_log("c_iflag = ");
> +    print_flags(termios_iflags, iflags, 0);
> +
> +    qemu_log("c_oflag = ");
> +    target_tcflag_t oflags_clean =  oflags & ~(TARGET_NLDLY | TARGET_CRDLY |
> +                                               TARGET_TABDLY | TARGET_BSDLY |
> +                                               TARGET_VTDLY | TARGET_FFDLY);
> +    print_flags(termios_oflags, oflags_clean, 0);
> +    if (oflags & TARGET_NLDLY) {
> +        print_enums(termios_oflags_NLDLY, oflags & TARGET_NLDLY, 0);
> +    }
> +    if (oflags & TARGET_CRDLY) {
> +        print_enums(termios_oflags_CRDLY, oflags & TARGET_CRDLY, 0);
> +    }
> +    if (oflags & TARGET_TABDLY) {
> +        print_enums(termios_oflags_TABDLY, oflags & TARGET_TABDLY, 0);
> +    }
> +    if (oflags & TARGET_BSDLY) {
> +        print_enums(termios_oflags_BSDLY, oflags & TARGET_BSDLY, 0);
> +    }
> +    if (oflags & TARGET_VTDLY) {
> +        print_enums(termios_oflags_VTDLY, oflags & TARGET_VTDLY, 0);
> +    }
> +    if (oflags & TARGET_FFDLY) {
> +        print_enums(termios_oflags_FFDLY, oflags & TARGET_FFDLY, 0);
> +    }
> +
> +    qemu_log("c_cflag = ");
> +    if (cflags & TARGET_CBAUD) {
> +        print_enums(termios_cflags_CBAUD, cflags & TARGET_CBAUD, 0);
> +    }
> +    if (cflags & TARGET_CSIZE) {
> +        print_enums(termios_cflags_CSIZE, cflags & TARGET_CSIZE, 0);
> +    }
> +    target_tcflag_t cflags_clean = cflags & ~(TARGET_CBAUD | TARGET_CSIZE);
> +    print_flags(termios_cflags, cflags_clean, 0);
> +
> +    qemu_log("c_lflag = ");
> +    print_flags(termios_lflags, lflags, 0);
> +
> +    qemu_log("c_ispeed = ");
> +    print_raw_param("%u", tswap32(target->c_ispeed), 0);
> +
> +    qemu_log("c_ospeed = ");
> +    print_raw_param("%u", tswap32(target->c_ospeed), 0);
> +
> +    qemu_log("c_cc = ");
> +    qemu_log("\"%s\",", target->c_cc);
> +
> +    qemu_log("c_line = ");
> +    print_raw_param("\'%c\'", target->c_line, 1);
> +
> +    qemu_log("}");
> +}
> +#endif
> +
>  #undef UNUSED
>  
>  #ifdef TARGET_NR_accept
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 8546f48a05..920bf23406 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -86,6 +86,7 @@
>  #endif
>  
>  #define termios host_termios
> +#define termios2 host_termios2
>  #define winsize host_winsize
>  #define termio host_termio
>  #define sgttyb host_sgttyb /* same as target */
> @@ -5885,6 +5886,89 @@ static const StructEntry struct_termios_def = {
>      .print = print_termios,
>  };
>  
> +#ifdef TARGET_TCGETS2
> +static void target_to_host_termios2 (void *dst, const void *src)
> +{
> +    struct host_termios2 *host = dst;
> +    const struct target_termios2 *target = src;
> +
> +    host->c_iflag =
> +        target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
> +    host->c_oflag =
> +        target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
> +    host->c_cflag =
> +        target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
> +    host->c_lflag =
> +        target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
> +    host->c_line = target->c_line;
> +    host->c_ispeed = tswap32(target->c_ispeed);
> +    host->c_ospeed = tswap32(target->c_ospeed);
> +
> +    memset(host->c_cc, 0, sizeof(host->c_cc));
> +    host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
> +    host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
> +    host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
> +    host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
> +    host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
> +    host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
> +    host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
> +    host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
> +    host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
> +    host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
> +    host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
> +    host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
> +    host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
> +    host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
> +    host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
> +    host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
> +    host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
> +}
> +
> +static void host_to_target_termios2 (void *dst, const void *src)
> +{
> +    struct target_termios2 *target = dst;
> +    const struct host_termios2 *host = src;
> +
> +    target->c_iflag =
> +        tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
> +    target->c_oflag =
> +        tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
> +    target->c_cflag =
> +        tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
> +    target->c_lflag =
> +        tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
> +    target->c_line = host->c_line;
> +    target->c_ispeed = tswap32(host->c_ispeed);
> +    target->c_ospeed = tswap32(host->c_ospeed);
> +
> +    memset(target->c_cc, 0, sizeof(target->c_cc));
> +    target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
> +    target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
> +    target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
> +    target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
> +    target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
> +    target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
> +    target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
> +    target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
> +    target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
> +    target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
> +    target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
> +    target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
> +    target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
> +    target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
> +    target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
> +    target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
> +    target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
> +}
> +
> +static const StructEntry struct_termios2_def = {
> +    .convert = { host_to_target_termios2, target_to_host_termios2 },
> +    .size = { sizeof(struct target_termios2), sizeof(struct host_termios2) },
> +    .align = { __alignof__(struct target_termios2), __alignof__(struct host_termios2) },
> +    .print = print_termios2,
> +};
> +#endif
> +
>  /* If the host does not provide these bits, they may be safely discarded. */
>  #ifndef MAP_SYNC
>  #define MAP_SYNC 0
> diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
> index 6dd7a80ce5..ac45705acf 100644
> --- a/linux-user/syscall_types.h
> +++ b/linux-user/syscall_types.h
> @@ -1,4 +1,7 @@
>  STRUCT_SPECIAL(termios)
> +#ifdef TARGET_TCGETS2
> +STRUCT_SPECIAL(termios2)
> +#endif
>  
>  STRUCT(winsize,
>         TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
> diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
> index 7099349ec8..067c02bb93 100644
> --- a/linux-user/user-internals.h
> +++ b/linux-user/user-internals.h
> @@ -129,6 +129,9 @@ static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
>  #endif /* TARGET_ABI_BITS != 32 */
>  
>  void print_termios(void *arg);
> +#ifdef TARGET_TCGETS2
> +void print_termios2(void *arg);
> +#endif
>  
>  /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
>  #ifdef TARGET_ARM
> -- 
> 2.50.1
> 
> 
> 

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/7] Add termios2 support to linux-user
  2025-12-03 12:15 ` Daniel P. Berrangé
@ 2025-12-03 14:37   ` Luca Bonissi
  0 siblings, 0 replies; 10+ messages in thread
From: Luca Bonissi @ 2025-12-03 14:37 UTC (permalink / raw)
  To: Daniel P. Berrangé; +Cc: Richard Henderson, Laurent Vivier, qemu-devel

On 03/12/25 13:15, Daniel P. Berrangé wrote:
> You've added this for a handful of archiecture targets, but
> in Fedora we're seeing the incompatibility affect s390x and
> aarch64 too, which this series hasn't implemented.

The patch is for all targets, but some specific targets use a custom 
termbits.h include file and require the addition of the structures 
and/or TCGETS2/TCSETS2 defines that was missing.

Specifically, s390x and aarch64 use the generic/termbits.h include that 
was already ok.

> BTW, ideally send a cover letter with a multi-patch
> series; there are tools which make this easier than
> using git send-email directly:
> 
>    https://www.qemu.org/docs/master/devel/submitting-a-patch.html#submitting-your-patches

Thank! I will use git send-email the next time.

Luca


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/7] Add termios2 support to linux-user
  2025-10-31 13:23 [PATCH 1/7] Add termios2 support to linux-user Luca Bonissi
  2025-11-02 10:29 ` Andreas Schwab
  2025-12-03 12:15 ` Daniel P. Berrangé
@ 2025-12-04 12:48 ` Heinrich Schuchardt
  2025-12-15 16:42 ` Icenowy Zheng
  2025-12-15 16:44 ` Icenowy Zheng
  4 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2025-12-04 12:48 UTC (permalink / raw)
  To: Luca Bonissi
  Cc: qemu-devel, Richard Henderson, Laurent Vivier,
	Daniel P. Berrangé

On 10/31/25 14:23, Luca Bonissi wrote:
>>From 6ddab7d3ba1035b5e2a6016bde4776436267c18b Mon Sep 17 00:00:00 2001
> From: Luca Bonissi <qemu@bonslack.org>
> Date: Fri, 31 Oct 2025 13:29:19 +0100
> Subject: [PATCH 1/7] Add termios2 support to linux-user
> 
> Signed-off-by: Luca Bonissi <qemu@bonslack.org>

This patch fixes the detection of the tty console in foreign 
architecture Docker containers when the host is using glibc 2.42 as on 
Ubuntu 25.10 and 26.04.

I tested with an x86_64 host and foreign architectures aarch64 and riscv64.

@Luca:

Patches should provide a commit message explaining why the change is needed.

When respinning a patch it is preferable to mark it with a version 
number (e.g. '[PATCH v2 1/7]) and to provide a change history under a 
'---' line.

Maybe you could resend the series with a proper commit message and mark 
it as v3.

     git format-patch --cover-letter --subject-prefix='PATCH v3'

Please, use git send-email so that the patches of the series and the 
cover-letter arrive as related mails. git send-email sets the 
In-Reply-To header for this purpose.

Tested-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>

> ---
>   linux-user/ioctls.h         |  6 +++
>   linux-user/strace.c         | 69 ++++++++++++++++++++++++++++++
>   linux-user/syscall.c        | 84 +++++++++++++++++++++++++++++++++++++
>   linux-user/syscall_types.h  |  3 ++
>   linux-user/user-internals.h |  3 ++
>   5 files changed, 165 insertions(+)
> 
> diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
> index 2f62fd2cb9..6ecfe6306e 100644
> --- a/linux-user/ioctls.h
> +++ b/linux-user/ioctls.h
> @@ -1,5 +1,11 @@
>        /* emulated ioctl list */
>   
> +#ifdef TARGET_TCGETS2
> +     IOCTL(TCGETS2, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios2)))
> +     IOCTL(TCSETS2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
> +     IOCTL(TCSETSW2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
> +     IOCTL(TCSETSF2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
> +#endif
>        IOCTL(TCGETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
>        IOCTL(TCSETS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
>        IOCTL(TCSETSF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
> diff --git a/linux-user/strace.c b/linux-user/strace.c
> index 758c5d32b6..7afb94544f 100644
> --- a/linux-user/strace.c
> +++ b/linux-user/strace.c
> @@ -1935,6 +1935,75 @@ print_termios(void *arg)
>       qemu_log("}");
>   }
>   
> +#ifdef TARGET_TCGETS2
> +void
> +print_termios2(void *arg)
> +{
> +    const struct target_termios2 *target = arg;
> +
> +    target_tcflag_t iflags = tswap32(target->c_iflag);
> +    target_tcflag_t oflags = tswap32(target->c_oflag);
> +    target_tcflag_t cflags = tswap32(target->c_cflag);
> +    target_tcflag_t lflags = tswap32(target->c_lflag);
> +
> +    qemu_log("{");
> +
> +    qemu_log("c_iflag = ");
> +    print_flags(termios_iflags, iflags, 0);
> +
> +    qemu_log("c_oflag = ");
> +    target_tcflag_t oflags_clean =  oflags & ~(TARGET_NLDLY | TARGET_CRDLY |
> +                                               TARGET_TABDLY | TARGET_BSDLY |
> +                                               TARGET_VTDLY | TARGET_FFDLY);
> +    print_flags(termios_oflags, oflags_clean, 0);
> +    if (oflags & TARGET_NLDLY) {
> +        print_enums(termios_oflags_NLDLY, oflags & TARGET_NLDLY, 0);
> +    }
> +    if (oflags & TARGET_CRDLY) {
> +        print_enums(termios_oflags_CRDLY, oflags & TARGET_CRDLY, 0);
> +    }
> +    if (oflags & TARGET_TABDLY) {
> +        print_enums(termios_oflags_TABDLY, oflags & TARGET_TABDLY, 0);
> +    }
> +    if (oflags & TARGET_BSDLY) {
> +        print_enums(termios_oflags_BSDLY, oflags & TARGET_BSDLY, 0);
> +    }
> +    if (oflags & TARGET_VTDLY) {
> +        print_enums(termios_oflags_VTDLY, oflags & TARGET_VTDLY, 0);
> +    }
> +    if (oflags & TARGET_FFDLY) {
> +        print_enums(termios_oflags_FFDLY, oflags & TARGET_FFDLY, 0);
> +    }
> +
> +    qemu_log("c_cflag = ");
> +    if (cflags & TARGET_CBAUD) {
> +        print_enums(termios_cflags_CBAUD, cflags & TARGET_CBAUD, 0);
> +    }
> +    if (cflags & TARGET_CSIZE) {
> +        print_enums(termios_cflags_CSIZE, cflags & TARGET_CSIZE, 0);
> +    }
> +    target_tcflag_t cflags_clean = cflags & ~(TARGET_CBAUD | TARGET_CSIZE);
> +    print_flags(termios_cflags, cflags_clean, 0);
> +
> +    qemu_log("c_lflag = ");
> +    print_flags(termios_lflags, lflags, 0);
> +
> +    qemu_log("c_ispeed = ");
> +    print_raw_param("%u", tswap32(target->c_ispeed), 0);
> +
> +    qemu_log("c_ospeed = ");
> +    print_raw_param("%u", tswap32(target->c_ospeed), 0);
> +
> +    qemu_log("c_cc = ");
> +    qemu_log("\"%s\",", target->c_cc);
> +
> +    qemu_log("c_line = ");
> +    print_raw_param("\'%c\'", target->c_line, 1);
> +
> +    qemu_log("}");
> +}
> +#endif
> +
>   #undef UNUSED
>   
>   #ifdef TARGET_NR_accept
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 8546f48a05..920bf23406 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -86,6 +86,7 @@
>   #endif
>   
>   #define termios host_termios
> +#define termios2 host_termios2
>   #define winsize host_winsize
>   #define termio host_termio
>   #define sgttyb host_sgttyb /* same as target */
> @@ -5885,6 +5886,89 @@ static const StructEntry struct_termios_def = {
>       .print = print_termios,
>   };
>   
> +#ifdef TARGET_TCGETS2
> +static void target_to_host_termios2 (void *dst, const void *src)
> +{
> +    struct host_termios2 *host = dst;
> +    const struct target_termios2 *target = src;
> +
> +    host->c_iflag =
> +        target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
> +    host->c_oflag =
> +        target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
> +    host->c_cflag =
> +        target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
> +    host->c_lflag =
> +        target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
> +    host->c_line = target->c_line;
> +    host->c_ispeed = tswap32(target->c_ispeed);
> +    host->c_ospeed = tswap32(target->c_ospeed);
> +
> +    memset(host->c_cc, 0, sizeof(host->c_cc));
> +    host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
> +    host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
> +    host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
> +    host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
> +    host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
> +    host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
> +    host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
> +    host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
> +    host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
> +    host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
> +    host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
> +    host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
> +    host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
> +    host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
> +    host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
> +    host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
> +    host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
> +}
> +
> +static void host_to_target_termios2 (void *dst, const void *src)
> +{
> +    struct target_termios2 *target = dst;
> +    const struct host_termios2 *host = src;
> +
> +    target->c_iflag =
> +        tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
> +    target->c_oflag =
> +        tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
> +    target->c_cflag =
> +        tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
> +    target->c_lflag =
> +        tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
> +    target->c_line = host->c_line;
> +    target->c_ispeed = tswap32(host->c_ispeed);
> +    target->c_ospeed = tswap32(host->c_ospeed);
> +
> +    memset(target->c_cc, 0, sizeof(target->c_cc));
> +    target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
> +    target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
> +    target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
> +    target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
> +    target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
> +    target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
> +    target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
> +    target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
> +    target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
> +    target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
> +    target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
> +    target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
> +    target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
> +    target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
> +    target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
> +    target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
> +    target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
> +}
> +
> +static const StructEntry struct_termios2_def = {
> +    .convert = { host_to_target_termios2, target_to_host_termios2 },
> +    .size = { sizeof(struct target_termios2), sizeof(struct host_termios2) },
> +    .align = { __alignof__(struct target_termios2), __alignof__(struct host_termios2) },
> +    .print = print_termios2,
> +};
> +#endif
> +
>   /* If the host does not provide these bits, they may be safely discarded. */
>   #ifndef MAP_SYNC
>   #define MAP_SYNC 0
> diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
> index 6dd7a80ce5..ac45705acf 100644
> --- a/linux-user/syscall_types.h
> +++ b/linux-user/syscall_types.h
> @@ -1,4 +1,7 @@
>   STRUCT_SPECIAL(termios)
> +#ifdef TARGET_TCGETS2
> +STRUCT_SPECIAL(termios2)
> +#endif
>   
>   STRUCT(winsize,
>          TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
> diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
> index 7099349ec8..067c02bb93 100644
> --- a/linux-user/user-internals.h
> +++ b/linux-user/user-internals.h
> @@ -129,6 +129,9 @@ static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
>   #endif /* TARGET_ABI_BITS != 32 */
>   
>   void print_termios(void *arg);
> +#ifdef TARGET_TCGETS2
> +void print_termios2(void *arg);
> +#endif
>   
>   /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
>   #ifdef TARGET_ARM



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/7] Add termios2 support to linux-user
  2025-10-31 13:23 [PATCH 1/7] Add termios2 support to linux-user Luca Bonissi
                   ` (2 preceding siblings ...)
  2025-12-04 12:48 ` Heinrich Schuchardt
@ 2025-12-15 16:42 ` Icenowy Zheng
  2025-12-15 16:44 ` Icenowy Zheng
  4 siblings, 0 replies; 10+ messages in thread
From: Icenowy Zheng @ 2025-12-15 16:42 UTC (permalink / raw)
  To: Luca Bonissi, Richard Henderson, Laurent Vivier; +Cc: qemu-devel

在 2025-10-31星期五的 14:23 +0100,Luca Bonissi写道:
> > From 6ddab7d3ba1035b5e2a6016bde4776436267c18b Mon Sep 17 00:00:00
> > 2001
> From: Luca Bonissi <qemu@bonslack.org>
> Date: Fri, 31 Oct 2025 13:29:19 +0100
> Subject: [PATCH 1/7] Add termios2 support to linux-user

Sorry but this patch does not build on PowerPC hosts:

```
../linux-user/ioctls.h:4:12: error: ‘TCGETS2’ undeclared here (not in a
function); did you mean ‘TCGETS’?
    4 |      IOCTL(TCGETS2, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios2)))
      |            ^~~~~~~
../linux-user/syscall.c:5615:23: note: in definition of macro ‘IOCTL’
 5615 |     { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
      |                       ^~~
../linux-user/ioctls.h:5:12: error: ‘TCSETS2’ undeclared here (not in a
function); did you mean ‘TCSETS’?
    5 |      IOCTL(TCSETS2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
      |            ^~~~~~~
../linux-user/syscall.c:5615:23: note: in definition of macro ‘IOCTL’
 5615 |     { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
      |                       ^~~
../linux-user/ioctls.h:6:12: error: ‘TCSETSW2’ undeclared here (not in
a function); did you mean ‘TCSETSW’?
    6 |      IOCTL(TCSETSW2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
      |            ^~~~~~~~
../linux-user/syscall.c:5615:23: note: in definition of macro ‘IOCTL’
 5615 |     { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
      |                       ^~~
../linux-user/ioctls.h:7:12: error: ‘TCSETSF2’ undeclared here (not in
a function); did you mean ‘TCSETSF’?
    7 |      IOCTL(TCSETSF2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
      |            ^~~~~~~~
../linux-user/syscall.c:5615:23: note: in definition of macro ‘IOCTL’
 5615 |     { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
      |                       ^~~
../linux-user/syscall.c: In function ‘target_to_host_termios2’:
../linux-user/syscall.c:5940:9: error: invalid use of undefined type
‘struct host_termios2’
 5940 |     host->c_iflag =
      |         ^~
../linux-user/syscall.c:5942:9: error: invalid use of undefined type
‘struct host_termios2’
 5942 |     host->c_oflag =
      |         ^~
../linux-user/syscall.c:5944:9: error: invalid use of undefined type
‘struct host_termios2’
 5944 |     host->c_cflag =
      |         ^~
../linux-user/syscall.c:5946:9: error: invalid use of undefined type
‘struct host_termios2’
 5946 |     host->c_lflag =
      |         ^~
../linux-user/syscall.c:5948:9: error: invalid use of undefined type
‘struct host_termios2’
 5948 |     host->c_line = target->c_line;
      |         ^~
../linux-user/syscall.c:5949:9: error: invalid use of undefined type
‘struct host_termios2’
 5949 |     host->c_ispeed = tswap32(target->c_ispeed);
      |         ^~
../linux-user/syscall.c:5950:9: error: invalid use of undefined type
‘struct host_termios2’
 5950 |     host->c_ospeed = tswap32(target->c_ospeed);
      |         ^~
../linux-user/syscall.c:5952:16: error: invalid use of undefined type
‘struct host_termios2’
 5952 |     memset(host->c_cc, 0, sizeof(host->c_cc));
      |                ^~
../linux-user/syscall.c:5952:38: error: invalid use of undefined type
‘struct host_termios2’
 5952 |     memset(host->c_cc, 0, sizeof(host->c_cc));
      |                                      ^~
../linux-user/syscall.c:5953:9: error: invalid use of undefined type
‘struct host_termios2’
 5953 |     host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
      |         ^~
../linux-user/syscall.c:5954:9: error: invalid use of undefined type
‘struct host_termios2’
 5954 |     host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
      |         ^~
../linux-user/syscall.c:5955:9: error: invalid use of undefined type
‘struct host_termios2’
 5955 |     host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
      |         ^~
../linux-user/syscall.c:5956:9: error: invalid use of undefined type
‘struct host_termios2’
 5956 |     host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
      |         ^~
../linux-user/syscall.c:5957:9: error: invalid use of undefined type
‘struct host_termios2’
 5957 |     host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
      |         ^~
../linux-user/syscall.c:5958:9: error: invalid use of undefined type
‘struct host_termios2’
 5958 |     host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
      |         ^~
../linux-user/syscall.c:5959:9: error: invalid use of undefined type
‘struct host_termios2’
 5959 |     host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
      |         ^~
../linux-user/syscall.c:5960:9: error: invalid use of undefined type
‘struct host_termios2’
 5960 |     host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
      |         ^~
../linux-user/syscall.c:5961:9: error: invalid use of undefined type
‘struct host_termios2’
 5961 |     host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
      |         ^~
../linux-user/syscall.c:5962:9: error: invalid use of undefined type
‘struct host_termios2’
 5962 |     host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
      |         ^~
../linux-user/syscall.c:5963:9: error: invalid use of undefined type
‘struct host_termios2’
 5963 |     host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
      |         ^~
../linux-user/syscall.c:5964:9: error: invalid use of undefined type
‘struct host_termios2’
 5964 |     host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
      |         ^~
../linux-user/syscall.c:5965:9: error: invalid use of undefined type
‘struct host_termios2’
 5965 |     host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
      |         ^~
../linux-user/syscall.c:5966:9: error: invalid use of undefined type
‘struct host_termios2’
 5966 |     host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
      |         ^~
../linux-user/syscall.c:5967:9: error: invalid use of undefined type
‘struct host_termios2’
 5967 |     host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
      |         ^~
../linux-user/syscall.c:5968:9: error: invalid use of undefined type
‘struct host_termios2’
 5968 |     host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
      |         ^~
../linux-user/syscall.c:5969:9: error: invalid use of undefined type
‘struct host_termios2’
 5969 |     host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
      |         ^~
In file included from ../linux-user/user-internals.h:21,
                 from ../linux-user/syscall.c:137:
../linux-user/syscall.c: In function ‘host_to_target_termios2’:
../linux-user/syscall.c:5978:44: error: invalid use of undefined type
‘const struct host_termios2’
 5978 |         tswap32(host_to_target_bitmask(host->c_iflag,
iflag_tbl));
      |                                            ^~
/var/cache/acbs/build/acbs.62hveo8z/qemu-
10.1.2/src.user/include/user/thunk.h:209:32: note: in definition of
macro ‘host_to_target_bitmask’
  209 |     host_to_target_bitmask_len(M, T, ARRAY_SIZE(T))
      |                                ^
../linux-user/syscall.c:5980:44: error: invalid use of undefined type
‘const struct host_termios2’
 5980 |         tswap32(host_to_target_bitmask(host->c_oflag,
oflag_tbl));
      |                                            ^~
/var/cache/acbs/build/acbs.62hveo8z/qemu-
10.1.2/src.user/include/user/thunk.h:209:32: note: in definition of
macro ‘host_to_target_bitmask’
  209 |     host_to_target_bitmask_len(M, T, ARRAY_SIZE(T))
      |                                ^
../linux-user/syscall.c:5982:44: error: invalid use of undefined type
‘const struct host_termios2’
 5982 |         tswap32(host_to_target_bitmask(host->c_cflag,
cflag_tbl));
      |                                            ^~
/var/cache/acbs/build/acbs.62hveo8z/qemu-
10.1.2/src.user/include/user/thunk.h:209:32: note: in definition of
macro ‘host_to_target_bitmask’
  209 |     host_to_target_bitmask_len(M, T, ARRAY_SIZE(T))
      |                                ^
../linux-user/syscall.c:5984:44: error: invalid use of undefined type
‘const struct host_termios2’
 5984 |         tswap32(host_to_target_bitmask(host->c_lflag,
lflag_tbl));
      |                                            ^~
/var/cache/acbs/build/acbs.62hveo8z/qemu-
10.1.2/src.user/include/user/thunk.h:209:32: note: in definition of
macro ‘host_to_target_bitmask’
  209 |     host_to_target_bitmask_len(M, T, ARRAY_SIZE(T))
      |                                ^
../linux-user/syscall.c:5985:26: error: invalid use of undefined type
‘const struct host_termios2’
 5985 |     target->c_line = host->c_line;
      |                          ^~
../linux-user/syscall.c:5986:36: error: invalid use of undefined type
‘const struct host_termios2’
 5986 |     target->c_ispeed = tswap32(host->c_ispeed);
      |                                    ^~
../linux-user/syscall.c:5987:36: error: invalid use of undefined type
‘const struct host_termios2’
 5987 |     target->c_ospeed = tswap32(host->c_ospeed);
      |                                    ^~
../linux-user/syscall.c:5990:38: error: invalid use of undefined type
‘const struct host_termios2’
 5990 |     target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
      |                                      ^~
../linux-user/syscall.c:5991:38: error: invalid use of undefined type
‘const struct host_termios2’
 5991 |     target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
      |                                      ^~
../linux-user/syscall.c:5992:39: error: invalid use of undefined type
‘const struct host_termios2’
 5992 |     target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
      |                                       ^~
../linux-user/syscall.c:5993:38: error: invalid use of undefined type
‘const struct host_termios2’
 5993 |     target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
      |                                      ^~
../linux-user/syscall.c:5994:37: error: invalid use of undefined type
‘const struct host_termios2’
 5994 |     target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
      |                                     ^~
../linux-user/syscall.c:5995:38: error: invalid use of undefined type
‘const struct host_termios2’
 5995 |     target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
      |                                      ^~
../linux-user/syscall.c:5996:37: error: invalid use of undefined type
‘const struct host_termios2’
 5996 |     target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
      |                                     ^~
../linux-user/syscall.c:5997:38: error: invalid use of undefined type
‘const struct host_termios2’
 5997 |     target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
      |                                      ^~
../linux-user/syscall.c:5998:39: error: invalid use of undefined type
‘const struct host_termios2’
 5998 |     target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
      |                                       ^~
../linux-user/syscall.c:5999:38: error: invalid use of undefined type
‘const struct host_termios2’
 5999 |     target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
      |                                      ^~
../linux-user/syscall.c:6000:38: error: invalid use of undefined type
‘const struct host_termios2’
 6000 |     target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
      |                                      ^~
../linux-user/syscall.c:6001:37: error: invalid use of undefined type
‘const struct host_termios2’
 6001 |     target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
      |                                     ^~
../linux-user/syscall.c:6002:41: error: invalid use of undefined type
‘const struct host_termios2’
 6002 |     target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
      |                                         ^~
../linux-user/syscall.c:6003:41: error: invalid use of undefined type
‘const struct host_termios2’
 6003 |     target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
      |                                         ^~
../linux-user/syscall.c:6004:40: error: invalid use of undefined type
‘const struct host_termios2’
 6004 |     target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
      |                                        ^~
../linux-user/syscall.c:6005:39: error: invalid use of undefined type
‘const struct host_termios2’
 6005 |     target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
      |                                       ^~
../linux-user/syscall.c:6006:38: error: invalid use of undefined type
‘const struct host_termios2’
 6006 |     target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
      |                                      ^~
../linux-user/syscall.c: At top level:
../linux-user/syscall.c:6011:54: error: invalid application of ‘sizeof’
to incomplete type ‘struct host_termios2’
 6011 |     .size = { sizeof(struct target_termios2), sizeof(struct
host_termios2) },
      |                                                      ^~~~~~
../linux-user/syscall.c:6012:65: error: invalid application of
‘__alignof__’ to incomplete type ‘struct host_termios2’
 6012 |     .align = { __alignof__(struct target_termios2),
__alignof__(struct host_termios2) },
      |                                                               
^~~~~~
```

(The whole patchset rebased onto v10.1.2)

It seems that PowerPC do not have a `termios2` interface in kernel --
the `termios` here is just `termios2` .

> 
> Signed-off-by: Luca Bonissi <qemu@bonslack.org>
> ---
>  linux-user/ioctls.h         |  6 +++
>  linux-user/strace.c         | 69 ++++++++++++++++++++++++++++++
>  linux-user/syscall.c        | 84
> +++++++++++++++++++++++++++++++++++++
>  linux-user/syscall_types.h  |  3 ++
>  linux-user/user-internals.h |  3 ++
>  5 files changed, 165 insertions(+)
> 
> diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
> index 2f62fd2cb9..6ecfe6306e 100644
> --- a/linux-user/ioctls.h
> +++ b/linux-user/ioctls.h
> @@ -1,5 +1,11 @@
>       /* emulated ioctl list */
>  
> +#ifdef TARGET_TCGETS2
> +     IOCTL(TCGETS2, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios2)))
> +     IOCTL(TCSETS2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
> +     IOCTL(TCSETSW2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
> +     IOCTL(TCSETSF2, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios2)))
> +#endif
>       IOCTL(TCGETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
>       IOCTL(TCSETS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
>       IOCTL(TCSETSF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
> diff --git a/linux-user/strace.c b/linux-user/strace.c
> index 758c5d32b6..7afb94544f 100644
> --- a/linux-user/strace.c
> +++ b/linux-user/strace.c
> @@ -1935,6 +1935,75 @@ print_termios(void *arg)
>      qemu_log("}");
>  }
>  
> +#ifdef TARGET_TCGETS2
> +void
> +print_termios2(void *arg)
> +{
> +    const struct target_termios2 *target = arg;
> +
> +    target_tcflag_t iflags = tswap32(target->c_iflag);
> +    target_tcflag_t oflags = tswap32(target->c_oflag);
> +    target_tcflag_t cflags = tswap32(target->c_cflag);
> +    target_tcflag_t lflags = tswap32(target->c_lflag);
> +
> +    qemu_log("{");
> +
> +    qemu_log("c_iflag = ");
> +    print_flags(termios_iflags, iflags, 0);
> +
> +    qemu_log("c_oflag = ");
> +    target_tcflag_t oflags_clean =  oflags & ~(TARGET_NLDLY |
> TARGET_CRDLY |
> +                                               TARGET_TABDLY |
> TARGET_BSDLY |
> +                                               TARGET_VTDLY |
> TARGET_FFDLY);
> +    print_flags(termios_oflags, oflags_clean, 0);
> +    if (oflags & TARGET_NLDLY) {
> +        print_enums(termios_oflags_NLDLY, oflags & TARGET_NLDLY, 0);
> +    }
> +    if (oflags & TARGET_CRDLY) {
> +        print_enums(termios_oflags_CRDLY, oflags & TARGET_CRDLY, 0);
> +    }
> +    if (oflags & TARGET_TABDLY) {
> +        print_enums(termios_oflags_TABDLY, oflags & TARGET_TABDLY,
> 0);
> +    }
> +    if (oflags & TARGET_BSDLY) {
> +        print_enums(termios_oflags_BSDLY, oflags & TARGET_BSDLY, 0);
> +    }
> +    if (oflags & TARGET_VTDLY) {
> +        print_enums(termios_oflags_VTDLY, oflags & TARGET_VTDLY, 0);
> +    }
> +    if (oflags & TARGET_FFDLY) {
> +        print_enums(termios_oflags_FFDLY, oflags & TARGET_FFDLY, 0);
> +    }
> +
> +    qemu_log("c_cflag = ");
> +    if (cflags & TARGET_CBAUD) {
> +        print_enums(termios_cflags_CBAUD, cflags & TARGET_CBAUD, 0);
> +    }
> +    if (cflags & TARGET_CSIZE) {
> +        print_enums(termios_cflags_CSIZE, cflags & TARGET_CSIZE, 0);
> +    }
> +    target_tcflag_t cflags_clean = cflags & ~(TARGET_CBAUD |
> TARGET_CSIZE);
> +    print_flags(termios_cflags, cflags_clean, 0);
> +
> +    qemu_log("c_lflag = ");
> +    print_flags(termios_lflags, lflags, 0);
> +
> +    qemu_log("c_ispeed = ");
> +    print_raw_param("%u", tswap32(target->c_ispeed), 0);
> +
> +    qemu_log("c_ospeed = ");
> +    print_raw_param("%u", tswap32(target->c_ospeed), 0);
> +
> +    qemu_log("c_cc = ");
> +    qemu_log("\"%s\",", target->c_cc);
> +
> +    qemu_log("c_line = ");
> +    print_raw_param("\'%c\'", target->c_line, 1);
> +
> +    qemu_log("}");
> +}
> +#endif
> +
>  #undef UNUSED
>  
>  #ifdef TARGET_NR_accept
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 8546f48a05..920bf23406 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -86,6 +86,7 @@
>  #endif
>  
>  #define termios host_termios
> +#define termios2 host_termios2
>  #define winsize host_winsize
>  #define termio host_termio
>  #define sgttyb host_sgttyb /* same as target */
> @@ -5885,6 +5886,89 @@ static const StructEntry struct_termios_def =
> {
>      .print = print_termios,
>  };
>  
> +#ifdef TARGET_TCGETS2
> +static void target_to_host_termios2 (void *dst, const void *src)
> +{
> +    struct host_termios2 *host = dst;
> +    const struct target_termios2 *target = src;
> +
> +    host->c_iflag =
> +        target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
> +    host->c_oflag =
> +        target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
> +    host->c_cflag =
> +        target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
> +    host->c_lflag =
> +        target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
> +    host->c_line = target->c_line;
> +    host->c_ispeed = tswap32(target->c_ispeed);
> +    host->c_ospeed = tswap32(target->c_ospeed);
> +
> +    memset(host->c_cc, 0, sizeof(host->c_cc));
> +    host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
> +    host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
> +    host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
> +    host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
> +    host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
> +    host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
> +    host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
> +    host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
> +    host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
> +    host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
> +    host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
> +    host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
> +    host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
> +    host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
> +    host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
> +    host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
> +    host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
> +}
> +
> +static void host_to_target_termios2 (void *dst, const void *src)
> +{
> +    struct target_termios2 *target = dst;
> +    const struct host_termios2 *host = src;
> +
> +    target->c_iflag =
> +        tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
> +    target->c_oflag =
> +        tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
> +    target->c_cflag =
> +        tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
> +    target->c_lflag =
> +        tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
> +    target->c_line = host->c_line;
> +    target->c_ispeed = tswap32(host->c_ispeed);
> +    target->c_ospeed = tswap32(host->c_ospeed);
> +
> +    memset(target->c_cc, 0, sizeof(target->c_cc));
> +    target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
> +    target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
> +    target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
> +    target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
> +    target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
> +    target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
> +    target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
> +    target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
> +    target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
> +    target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
> +    target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
> +    target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
> +    target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
> +    target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
> +    target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
> +    target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
> +    target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
> +}
> +
> +static const StructEntry struct_termios2_def = {
> +    .convert = { host_to_target_termios2, target_to_host_termios2 },
> +    .size = { sizeof(struct target_termios2), sizeof(struct
> host_termios2) },
> +    .align = { __alignof__(struct target_termios2),
> __alignof__(struct host_termios2) },
> +    .print = print_termios2,
> +};
> +#endif
> +
>  /* If the host does not provide these bits, they may be safely
> discarded. */
>  #ifndef MAP_SYNC
>  #define MAP_SYNC 0
> diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
> index 6dd7a80ce5..ac45705acf 100644
> --- a/linux-user/syscall_types.h
> +++ b/linux-user/syscall_types.h
> @@ -1,4 +1,7 @@
>  STRUCT_SPECIAL(termios)
> +#ifdef TARGET_TCGETS2
> +STRUCT_SPECIAL(termios2)
> +#endif
>  
>  STRUCT(winsize,
>         TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
> diff --git a/linux-user/user-internals.h b/linux-user/user-
> internals.h
> index 7099349ec8..067c02bb93 100644
> --- a/linux-user/user-internals.h
> +++ b/linux-user/user-internals.h
> @@ -129,6 +129,9 @@ static inline uint64_t target_offset64(uint64_t
> word0, uint64_t word1)
>  #endif /* TARGET_ABI_BITS != 32 */
>  
>  void print_termios(void *arg);
> +#ifdef TARGET_TCGETS2
> +void print_termios2(void *arg);
> +#endif
>  
>  /* ARM EABI and MIPS expect 64bit types aligned even on pairs or
> registers */
>  #ifdef TARGET_ARM



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/7] Add termios2 support to linux-user
  2025-10-31 13:23 [PATCH 1/7] Add termios2 support to linux-user Luca Bonissi
                   ` (3 preceding siblings ...)
  2025-12-15 16:42 ` Icenowy Zheng
@ 2025-12-15 16:44 ` Icenowy Zheng
  4 siblings, 0 replies; 10+ messages in thread
From: Icenowy Zheng @ 2025-12-15 16:44 UTC (permalink / raw)
  To: Luca Bonissi, Richard Henderson, Laurent Vivier; +Cc: qemu-devel

在 2025-10-31星期五的 14:23 +0100,Luca Bonissi写道:
> > From 6ddab7d3ba1035b5e2a6016bde4776436267c18b Mon Sep 17 00:00:00
> > 2001
> From: Luca Bonissi <qemu@bonslack.org>
> Date: Fri, 31 Oct 2025 13:29:19 +0100
> Subject: [PATCH 1/7] Add termios2 support to linux-user

By the way, please add a v3 tag in your subject (like [PATCH v3 1/7])
when resending this patchset again.

I failed to differienate two revisions of your patchset.

> 
> Signed-off-by: Luca Bonissi <qemu@bonslack.org>


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2025-12-15 17:05 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-31 13:23 [PATCH 1/7] Add termios2 support to linux-user Luca Bonissi
2025-11-02 10:29 ` Andreas Schwab
2025-12-03 12:15 ` Daniel P. Berrangé
2025-12-03 14:37   ` Luca Bonissi
2025-12-04 12:48 ` Heinrich Schuchardt
2025-12-15 16:42 ` Icenowy Zheng
2025-12-15 16:44 ` Icenowy Zheng
  -- strict thread matches above, loose matches on Subject: below --
2025-08-30 13:14 Luca Bonissi
2025-08-31 13:45 ` Andreas Schwab
2025-10-31 12:42   ` Luca Bonissi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).