QEMU/KVM Guest OS Serial Port Access: Configuring Host Hardware and Virtual COM Ports for RS232 Communication


2 views

Many developers working with legacy systems in virtualized environments hit a roadblock when trying to access physical serial ports from guest operating systems. The confusion stems from QEMU's multiple serial port handling mechanisms and documentation that doesn't clearly differentiate between console redirection and actual hardware access.

QEMU provides three primary methods for serial communication:

1. -serial stdio (console redirection)
2. -serial /dev/ttyS0 (host device passthrough)
3. -serial pty (virtual serial port creation)

The critical distinction is that only the second option provides true hardware access, while others serve different purposes.

For direct access to host serial hardware, use this QEMU launch command:

qemu-system-x86_64 \
  -enable-kvm \
  -m 2048 \
  -hda guest_os.qcow2 \
  -serial /dev/ttyS0 \
  -chardev serial,id=serial0,path=/dev/ttyS0 \
  -device isa-serial,chardev=serial0

This configuration:

  • Maps host's /dev/ttyS0 directly to guest
  • Uses both legacy -serial and modern -chardev syntax
  • Creates a standard COM1 port in the guest OS

When physical ports aren't available, consider these alternatives:

Option 1: PTY-based virtual port

qemu-system-x86_64 \
  -serial pty \
  -monitor stdio

QEMU will output the PTY path which you can then connect to using socat or similar tools.

Option 2: TCP-based serial tunnel

qemu-system-x86_64 \
  -serial tcp::4555,server,nowait \
  -nographic

Option 3: UNIX socket

qemu-system-x86_64 \
  -serial unix:/tmp/virtual_serial.sock,server,nowait

Permission problems: Ensure the QEMU process has read/write access to /dev/ttyS* devices. Consider adding your user to the dialout group.

Windows host specifics: For COM port access, use this syntax:

-serial COM1 -chardev serial,id=serial0,path=COM1

Baud rate mismatches: Configure matching baud rates in both host and guest. This can be done through the guest OS terminal settings or via QEMU parameters:

-chardev serial,id=serial0,path=/dev/ttyS0,baud=115200

Remember that virtual ports created with -serial pty won't appear in the host's device manager - you'll need to check QEMU's console output for the assigned PTY path.


Contrary to some misconceptions, QEMU/KVM absolutely supports proper serial port passthrough to guest OSes - not just console redirection. The confusion stems from documentation gaps and improper configuration attempts. Let me clarify how this actually works.

For host machines with physical serial ports (/dev/ttyS* on Linux, COM ports on Windows), here's the definitive way to expose them to guests:

qemu-system-x86_64 \
    -chardev serial,id=hostserial0,path=/dev/ttyS0 \
    -device isa-serial,chardev=hostserial0 \
    ...other_parameters...

This creates a direct bridge between the host's /dev/ttyS0 and a standard COM port in the guest OS. The key is using both -chardev and -device parameters together.

When physical ports aren't available, consider these virtualization approaches:

# Option 1: TCP-based virtual serial port
-chardev socket,id=virtualserial0,host=127.0.0.1,port=4555,server,nowait \
-device isa-serial,chardev=virtualserial0

# Option 2: PTY-based virtual port (Linux)
-chardev pty,id=virtualserial1 \
-device isa-serial,chardev=virtualserial1

For Windows hosts needing COM port emulation, try this workaround with com0com:

# First install com0com to create paired COM ports
# Then reference the virtual port in QEMU:
-chardev serial,id=wincom0,path=\\.\COM3 \
-device isa-serial,chardev=wincom0

Here are frequent issues and their solutions:

  • Permission denied: Ensure the QEMU process has read/write access to /dev/tty*
  • Port not detected: Verify the guest has appropriate serial drivers loaded
  • Data corruption: Match baud rates between host and guest configurations

Here's a complete command for communicating with RS232 equipment through a Windows host:

qemu-system-x86_64 \
    -m 2048 \
    -enable-kvm \
    -chardev serial,id=legacydevice,path=\\.\COM4,baudrate=9600 \
    -device isa-serial,chardev=legacydevice \
    -drive file=legacy_os.img,format=raw

This configuration maintains proper hardware flow control and matches common industrial equipment baud rates.