BIOS execution in QEMU: first I/O interaction

In the previous articles of this series, we analyzed how QEMU starts executing the BIOS firmware (see here) and how addresses are translated from the emulated physical space to the host memory (see here). The proposal now is to discuss what these first instructions are doing and how the first I/O interaction with virtual hardware looks like.

After the initial long jump at the entry point, the BIOS firmware has the following i8086 instructions:

The first comparison is to check whether the VM is resuming or rebooting. Assuming the latter, the stack segment selector is set to 0x0 and the stack pointer to 0x7000. According to the Memory Regions map, the stack will be located in ram-below-4g. An address value, which belongs to the pc.bios region, is finally loaded into the EDX register and a jump to a different block occurs. Source code is available here and here.

Continue reading “BIOS execution in QEMU: first I/O interaction”

BIOS execution in QEMU: software MMU address translation

In the previous article (BIOS execution in QEMU: where it all starts) we described how QEMU starts executing the BIOS image and what binary translation means. Even though we found the BIOS image instructions in the host memory and established a sort of correlation to emulated physical addresses executed by QEMU’s CPU, there was still a leap in-between. That is what we will explore now.

Modern CPUs view memory as a virtual and continuous range. A hardware component called MMU (Memory Management Unit) does a translation between virtual and physical addresses, that ultimately go into the system memory bus. To increase performance, MMUs implement a cache scheme called TLB (Translation Lookaside Buffer). These same concepts of ‘translating between two disjoint address spaces’ and ‘caching translations’ are implemented by QEMU’s software MMU (softmmu).

Continue reading “BIOS execution in QEMU: software MMU address translation”

BIOS execution in QEMU: where it all starts

Reading Linux Inside (by 0xAX) and the early steps of the kernel boot process sparked my curiosity about the BIOS code executed immediately after power-on. Somehow related to that, tinkering with QEMU has been on my backlog for quite some time. That made the recipe for a new -and quick- challenge: debug QEMU while executing the first instructions of the BIOS firmware.

The first step was to setup an environment to compile and debug QEMU. The compiling capability is actually optional. My RPM-based environment runs on top of Fedora 31 (x86_64). QEMU version is 4.1.1. Binary translation mode has been used for emulation -hardware acceleration may come in a follow up-.

With no other preamble, let’s go straight to the task.

Continue reading “BIOS execution in QEMU: where it all starts”