1. Initialize virtual PC-board
2. Initialize BIOS and virtual peripheral devices
ex). e1000 network device
3. Booting guest OS
분석에 앞서 나열한 1~3 항목을 보면 QEMU의 초기화 과정은 물리 PC의 초기화/시작 과정과 비교하였을 때 별반 다를바 없다는 사실을 알 수 있다. 차이점은 물리 PC환경처럼 준비된 장치나 BIOS 등이 없기 때문에 이 부분은 가상화 장치를 만들어 사용한다는 것이다.
1. Initialize virtual PC-board
Virtual PC-board에서 사용하는 아키텍처와 메모리맵
- I440fx architecture(출처 : https://wiki.qemu.org/Features/Q35)
GDB를 통해 QEMU가 가상으로 만드는 PC-board는 pc-i440fx 아키텍처로 확인된다. 아키텍처에 관하여 pc-q35도 있으며 실행시 인자에 따라 설정이 가능하다. PC-board를 초기화 하는 과정에서 memory map도 결정하는데 이는 e820 map을 사용한다.
- e820 memory map(출처 : https://www.researchgate.net/figure/Example-of-physical-memory-maps-obtained-by-BIOS-e820_fig3_273895166)
- GDB를 통한 아키텍처 확인 -
2. Initialize BIOS and virtual peripheral devices
bios-256k.bin(SeaBIOS)
- SeaBIOS open source project
SeaBIOS is an open-source implementation of an x86 BIOS, serving as a freely available firmware for x86 systems. Aiming for compatibility, it supports standard BIOS features and calling interfaces that are implemented by a typical proprietary x86 BIOS. SeaBIOS can either run on bare hardware as a coreboot payload, or can be used directly in emulators such as QEMU and Bochs.
QEMU는 BIOS를 SeaBIOS라고 하는 바이너리를 사용한다. 이는 QEMU에서도 직접 사용할 수 있다고 명시되어 있다. 어찌보면 당연한 선택인 것이 일반적인 하드웨어 BIOS를 사용한다면 가상으로 만들어둔 장치들을 탐색할 수 있을까? 일반적인 하드웨어 BIOS의 경우 IDSEL이라는 신호를 통하여 주변장치를 인식한다. 하지만 가상으로 만들어둔 장치들이 이에 반응할 리 없다.
- GDB를 통한 BIOS 확인 -
"e1000" peripheral device emulation
QEMU는 주변장치 또한 물리 PC 환경과 마찬가지로 PCI 장치로써 인식하게 해준다. 이로써 Guest OS에서는 실제 장치가 있는 것처럼 작동할 수 있는 것이다.
PCI configuration space 스펙에 맞게 값을 설정해주는 부분을 확인할 수 있다. PCI장치는 장치가 사용할 memory space을 BARs 영역에 기록한다. 하지만 위의 값 설정상 BARs에는 memory space 주소값이 할당되지 않은 모습을 알 수 있다.
왜 할당되지 않았을까?
앞서 1번 항목에서 설명한 memory map과 관련있다. PCI 장치가 스스로 memory address를 설정해버린다면 memory map을 위배할 수 있다. 따라서 PCI BARs는 BIOS 바이너리(bios-256k.bin)가 할당해준다. 실제 할당 부분은 bios-256k 소스코드를 확인하기 바란다.
"e1000" device가 실제 작동할 때 GDB를 통하여 PCI configuration 영역을 확인해보았다. 이 때는 BARs 영역에 사용하는 주소값이 기록되어 있다.
3. Booting guest OS
PC-board 및 emulation 장치를 모두 초기화한 후 bios-256k.bin를 실행한다. bios-256k.bin의 실행으로 부팅 디스크가 감지(0x55, 0xaa)될 것이고 Guest OS의 Bootloader를 통해 사용하고자 하는 OS가 실행된다. 실제 실행과 관련하여 tcg(CPU emulation)를 사용할 것이냐 KVM(hardware accelation)을 사용할 것이냐에 따라 나뉠 수 있고 이는 따로 포스트를 작성하려 한다.