Table of Contents#
- Prerequisites
- Understanding QEMU Output Mechanisms
- Method 1: Redirect via Serial Port (Most Reliable)
- Method 2: Use
-nographicto Disable QEMU GUI - Capturing All Boot Messages (Logging)
- Troubleshooting: Common Issues and Fixes
- Conclusion
- 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-armfor ARM). Install viasudo apt install qemu-system-x86(Debian/Ubuntu) orsudo dnf install qemu-system-x86(Fedora). - Linux Kernel Image: A compiled kernel (e.g.,
bzImagefor x86) or a prebuilt kernel. - Initial RAM Filesystem (initramfs/initrd): Required for booting the kernel (generate with
mkinitramfsor build with the kernel). - Basic Kernel Configuration Knowledge: Familiarity with
make menuconfigto 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.,
ttyS0on 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:
- Configure the kernel to output all boot messages to the serial port.
- 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:
-
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).
- Navigate to:
-
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,115200for ttyS0 at 115200 baud).
- Navigate to:
Step 2: Verify the Configuration#
After saving the config, verify the settings in .config:
grep -E "CONFIG_SERIAL_8250_CONSOLE|CONFIG_EARLY_PRINTK" .configYou 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.gz3.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 (bzImagefor x86).-initrd: Path to the initial RAM filesystem (required for booting).-append: Kernel command-line parameters:console=ttyS0,115200: Tell the kernel to output tottyS0(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-kvmNotes:#
- Exiting QEMU: With
-nographic, pressCtrl+afollowed byxto 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=ttyS0is 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.txtExample:
qemu-system-x86_64 -kernel bzImage -initrd initramfs.cpio.gz -append "console=ttyS0,115200 earlyprintk=serial" -serial stdio | tee boot_log.txt5.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.logExample:
script -c "qemu-system-x86_64 -kernel bzImage -initrd initramfs.cpio.gz -append 'console=ttyS0,115200' -nographic" boot_session.logThis 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=yin.config. Recompile the kernel if missing.
Issue 2: Missing Early Boot Messages#
- Cause:
earlyprintknot enabled. - Fix: Add
earlyprintk=serialto-appendand ensureCONFIG_EARLY_PRINTK=yin.config.
Issue 3: Garbled Text in Terminal#
- Cause: Baud rate mismatch between kernel and QEMU.
- Fix: Use
115200for 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, runsudo modprobe kvmand ensure your user is in thekvmgroup: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.