Commit 03efcb7cfd for qemu.org

commit 03efcb7cfdef40ee3124a80b2609d800ec1df1db
Author: Oleksij Samorukov <samm@net-art.cz>
Date:   Sat Oct 17 22:19:05 2026 +0200

    qga: set FreeBSD virtio-serial channel to raw mode

    On FreeBSD the virtio-console port is a tty, unlike Linux's
    /dev/virtio-ports which is a character device.  It defaults to canonical
    mode with echo and software flow control enabled, so the QGA stream
    protocol does not work: the initial guest-sync handshake is held in the
    line discipline and the host eventually times out.

    The existing FreeBSD-specific code only clears ECHO.  Configure the port
    the same way as the ISA serial path: disable canonical mode, echo and
    software flow control, and set VMIN/VTIME.  Use TCSANOW instead of
    TCSAFLUSH so a handshake that arrives between open() and tcsetattr() is
    not discarded.

    Tested on FreeBSD 15.1 aarch64 under UTM/QEMU.  Before the change
    utmctl ip-address timed out and the guest received zero bytes; after the
    change QGA commands and guest-set-time work.

    Cc: qemu-stable@nongnu.org
    Fixes: c6cd588bb3a29a831c862780631a7d2145ade5de ("qga: Add initial FreeBSD support")
    Signed-off-by: Oleksij Samorukov <samm@net-art.cz>
    Reviewed-by: Kostiantyn Kostiuk <kkostiuk@redhat.com>
    Tested-by: Roman Bogorodskiy <bogorodskiy@gmail.com>
    Link: https://lore.kernel.org/qemu-devel/20261017201905.12211-1-samm@net-art.cz
    Signed-off-by: Kostiantyn Kostiuk <kkostiuk@redhat.com>

diff --git a/qga/channel-posix.c b/qga/channel-posix.c
index 9ccc8b7bd1..c6dfb2df63 100644
--- a/qga/channel-posix.c
+++ b/qga/channel-posix.c
@@ -156,9 +156,10 @@ static gboolean ga_channel_open(GAChannel *c, const gchar *path,
 #endif
 #ifdef __FreeBSD__
         /*
-         * In the default state channel sends echo of every command to a
-         * client. The client program doesn't expect this and raises an
-         * error. Suppress echo by resetting ECHO terminal flag.
+         * FreeBSD's virtio-console port is a tty (unlike Linux's
+         * /dev/virtio-ports, which is a character device) and defaults to
+         * canonical mode with echo and software flow control enabled.
+         * QGA uses a raw stream protocol, so put the port in raw mode.
          */
         struct termios tio;
         if (tcgetattr(fd, &tio) < 0) {
@@ -166,8 +167,19 @@ static gboolean ga_channel_open(GAChannel *c, const gchar *path,
             close(fd);
             return false;
         }
-        tio.c_lflag &= ~ECHO;
-        if (tcsetattr(fd, TCSAFLUSH, &tio) < 0) {
+        tio.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP |
+                         INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY |
+                         IMAXBEL);
+        tio.c_oflag = 0;
+        tio.c_lflag = 0;
+        tio.c_cflag |= CLOCAL | CREAD;
+        tio.c_cc[VMIN] = 1;
+        tio.c_cc[VTIME] = 0;
+        /*
+         * Use TCSANOW rather than TCSAFLUSH: the host may already have sent
+         * the initial handshake between open() and tcsetattr().
+         */
+        if (tcsetattr(fd, TCSANOW, &tio) < 0) {
             error_setg_errno(errp, errno, "error setting channel termios attrs");
             close(fd);
             return false;