funwithlinux blog

How to Redirect QEMU Window Output to Terminal for Linux Kernel Boot Debugging: Capture All Messages

Debugging the Linux kernel during boot is a critical task for developers, whether you’re fixing a driver issue, resolving a panic, or optimizing boot time. By default, QEMU (Quick Emulator) displays the guest OS output in a separate graphical window (e.g., via SDL or GTK), which can be inconvenient for capturing, logging, or analyzing boot messages. Redirecting QEMU’s output to the terminal solves this problem, allowing you to view, search, and save all kernel boot messages in real time.

In this guide, we’ll explore step-by-step methods to redirect QEMU output to the terminal, configure the Linux kernel to send messages to the terminal, and capture logs for debugging. We’ll cover common pitfalls and best practices to ensure you don’t miss critical early boot messages.

2025-12

Table of Contents#

  1. Prerequisites
  2. Understanding QEMU Output Mechanisms
  3. Method 1: Redirect via Serial Port (Most Reliable)
  4. Method 2: Use -nographic to Disable QEMU GUI
  5. Capturing All Boot Messages (Logging)
  6. Troubleshooting: Common Issues and Fixes
  7. Conclusion
  8. References

Prerequisites#

Before starting, ensure you have the following tools and files:

  • QEMU Installed: Verify with qemu-system-x86_64 --version (adjust for your architecture, e.g., qemu-system-arm for ARM). Install via sudo apt install qemu-system-x86 (Debian/Ubuntu) or sudo dnf install qemu-system-x86 (Fedora).
  • Linux Kernel Image: A compiled kernel (e.g., bzImage for x86) or a prebuilt kernel.
  • Initial RAM Filesystem (initramfs/initrd): Required for booting the kernel (generate with mkinitramfs or build with the kernel).
  • Basic Kernel Configuration Knowledge: Familiarity with make menuconfig to enable serial console support.

Understanding QEMU Output Mechanisms#

QEMU provides multiple ways to display guest OS output. By default:

  • VGA Console: Outputs to a graphical window (SDL/GTK) via the emulated VGA card. This is the "QEMU window" you typically see.
  • Serial Port: Emulates a hardware serial port (e.g., ttyS0 on x86). The Linux kernel can be configured to send messages to this port, which QEMU can redirect to the host terminal.

Kernel boot messages are often sent to the serial port by default, but without redirection, they won’t appear in your terminal. Our goal is to:

  1. Configure the kernel to output all boot messages to the serial port.
  2. Tell QEMU to redirect the serial port output to the host terminal.

Method 1: Redirect via Serial Port (Most Reliable)#

This method uses QEMU’s serial port emulation to forward kernel messages to the terminal. It’s the most reliable way to capture all boot messages, including early-stage logs.

3.1 Configure the Linux Kernel for Serial Console#

First, ensure the kernel is compiled with serial console support.

Step 1: Enable Serial Console in Kernel Config#

Run make menuconfig (from your kernel source directory) and enable these options:

  1. Serial Driver Support:

    • Navigate to: Device Drivers → Character devices → Serial drivers
    • Enable 8250/16550 and compatible serial support (check the box).
    • Enable Console on 8250/16550 and compatible serial port (check the box).
  2. Early Printk (Optional but Critical for Early Messages):

    • Navigate to: Kernel hacking → Early printk
    • Enable Early printk via the serial port (check the box).
    • Set the serial port (e.g., 0x3f8,115200 for ttyS0 at 115200 baud).

Step 2: Verify the Configuration#

After saving the config, verify the settings in .config:

grep -E "CONFIG_SERIAL_8250_CONSOLE|CONFIG_EARLY_PRINTK" .config

You should see:

CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_EARLY_PRINTK=y
CONFIG_EARLY_PRINTK_SERIAL=y

Step 3: Recompile the Kernel#

Build the kernel and initramfs:

make -j$(nproc) bzImage  # Generates arch/x86/boot/bzImage (adjust for your arch)
make -j$(nproc) modules
sudo make modules_install
make initrd  # Or use mkinitramfs to generate initramfs.cpio.gz

3.2 Run QEMU with Serial Port Redirection#

Use QEMU’s -serial stdio flag to redirect the serial port to the host terminal. Combine this with kernel parameters to tell the kernel to use the serial port.

Example QEMU Command#

qemu-system-x86_64 \
  -kernel arch/x86/boot/bzImage \        # Path to your kernel image
  -initrd initramfs.cpio.gz \            # Path to your initramfs
  -append "console=ttyS0,115200 earlyprintk=serial" \  # Kernel parameters
  -serial stdio \                        # Redirect serial port to terminal
  -enable-kvm                            # Optional: Use KVM for faster emulation (if supported)

Explanation of Flags:#

  • -kernel: Path to the compiled kernel image (bzImage for x86).
  • -initrd: Path to the initial RAM filesystem (required for booting).
  • -append: Kernel command-line parameters:
    • console=ttyS0,115200: Tell the kernel to output to ttyS0 (serial port) at 115200 baud.
    • earlyprintk=serial: Enable early printk to capture messages before the serial driver loads.
  • -serial stdio: Redirect QEMU’s emulated serial port (ttyS0) to the host’s stdin/stdout (your terminal).
  • -enable-kvm: Optional but recommended for faster emulation (requires KVM support on the host).

Method 2: Use -nographic to Disable QEMU GUI#

If you don’t need the graphical window, use QEMU’s -nographic flag to disable the VGA console entirely. This forces all output (serial, VGA) to the terminal.

Step 1: Run QEMU with -nographic#

qemu-system-x86_64 \
  -kernel arch/x86/boot/bzImage \
  -initrd initramfs.cpio.gz \
  -append "console=ttyS0,115200 earlyprintk=serial" \
  -nographic \  # Disable GUI; all output to terminal
  -enable-kvm

Notes:#

  • Exiting QEMU: With -nographic, press Ctrl+a followed by x to quit (instead of closing the window).
  • No VGA Output: The VGA console is disabled, so all messages must go through the serial port. Ensure console=ttyS0 is set in -append.

Capturing All Boot Messages (Logging)#

To save boot messages for later analysis, redirect or log the terminal output.

5.1 Using tee to Log and View Output#

The tee command lets you view output in the terminal and save it to a file simultaneously:

qemu-system-x86_64 [your flags] | tee boot_log.txt

Example:

qemu-system-x86_64 -kernel bzImage -initrd initramfs.cpio.gz -append "console=ttyS0,115200 earlyprintk=serial" -serial stdio | tee boot_log.txt

5.2 Using script to Capture Full Session#

The script command records the entire terminal session, including interactive input (e.g., if you log into the guest OS):

script -c "qemu-system-x86_64 [your flags]" boot_session.log

Example:

script -c "qemu-system-x86_64 -kernel bzImage -initrd initramfs.cpio.gz -append 'console=ttyS0,115200' -nographic" boot_session.log

This captures all output, including QEMU startup messages and guest OS interactions.

Troubleshooting: Common Issues and Fixes#

Issue 1: No Output in Terminal#

  • Cause: Kernel not configured for serial console.
  • Fix: Verify CONFIG_SERIAL_8250_CONSOLE=y in .config. Recompile the kernel if missing.

Issue 2: Missing Early Boot Messages#

  • Cause: earlyprintk not enabled.
  • Fix: Add earlyprintk=serial to -append and ensure CONFIG_EARLY_PRINTK=y in .config.

Issue 3: Garbled Text in Terminal#

  • Cause: Baud rate mismatch between kernel and QEMU.
  • Fix: Use 115200 for both (set in -append "console=ttyS0,115200"; QEMU defaults to 115200 for -serial stdio).

Issue 4: QEMU Hangs with -enable-kvm#

  • Cause: KVM not supported or permissions issues.
  • Fix: Check KVM support with grep -E 'vmx|svm' /proc/cpuinfo (Intel/AMD). If supported, run sudo modprobe kvm and ensure your user is in the kvm group: sudo usermod -aG kvm $USER (log out and back in).

Conclusion#

Redirecting QEMU output to the terminal is a game-changer for Linux kernel debugging. By combining kernel serial console configuration with QEMU’s -serial stdio or -nographic flags, you can capture all boot messages in your terminal and log them for analysis. Remember to enable earlyprintk to catch early-stage logs and use tee or script to save output. With these tools, debugging kernel boot issues becomes faster and more efficient.

References#