1. 程式人生 > >我見過最全的剖析QEMU原理的文章[Z]

我見過最全的剖析QEMU原理的文章[Z]

轉自:

目錄

建置 QEMU

QEMU 1.0 預設會編譯成 PIE,這對舊版的 GDB 會有影響。強制開啟 IO thread。使用 Clang 編譯 QEMU 會出現以下訊息1)2)3)

In file included from /z/tmp/chenwj/qemu-1.0/user-exec.c:21:/z/tmp/chenwj/qemu-1.0/dyngen-exec.h:64:20: error: global register variables are not supportedregister CPUState *env asm(AREG0);                   ^1 warning and 1 error generated.

TCI 沒有用到 global register variable。

$ ../qemu-1.0/configure --target-list=i386-bsd-user --enable-tcg-interpreter --cc=clang \  --extra-cflags="-v" --disable-smartcard-nss        

User Mode

目前 QEMU 將 glib2.0 列為必要,The GTK+ Project4)

  1. 如果系統沒有安裝 glib,則自行安裝。

    $ apt-get install zlib1g-dev pkg-config libglib2.0-dev$ wget http://ftp.gnome.org/pub/gnome/sources/glib/2.28/glib-2.28.0.tar.gz; tar xvf glib-2.28.0.tar.gz$ mkdir build; cd build$ ../glib-2.28.0/configure --prefix=$INSTALL$ make install                    
  2. 下載 QEMU。

                            # http://wiki.qemu.org/download/qemu-0.15.1.tar.gz$ git clone git://git.qemu.org/qemu.git
  3. 修改 configure。

                            # glib support probe#if $pkg_config --modversion gthread-2.0 > /dev/null 2>&1 ; then    # 用 pkg-config 查詢    glib_cflags="-pthread -I$INSTALL/include/glib-2.0/ -I$INSTALL/lib/glib-2.0/include/"    glib_libs="-L$INSTALL/lib -pthread -lgthread-2.0 -lrt -lglib-2.0"    LIBS="$glib_libs $LIBS"    libs_qga="$glib_libs $libs_qga"#else# echo "glib-2.0 required to compile QEMU"# exit 1#fi                    
  4. 編譯並安裝 QEMU。

                            # config.log 可以用來檢查設定 QEMU 時哪裡出錯$ mkdir build; cd build$ ../qemu/configure --prefix=$INSTALL --target-list=i386-linux-user --enable-debug$ make; make install                    
  5. 如果 glib 是自行安裝。

    $ export LD_LIBRARY_PATH=$INSTALL/lib/# -m32 會編譯 32-bit 執行檔$ gcc -m32 hello.c -o hello$ qemu-i386 hello

SPARC

關於 SPARC V8 (32-bit)、V8PLUS (64-bit with 32-bit ABI) 和 V9 (64-bit) 架構的差異請見 ABI Compliance and Global Registers Usage in SPARC V8 and V9 Architecture。QEMU 對 v9 支援最完整 5)。64-bit with 32-bit ABI 和在 x86_64 上執行 x86 binary 不一樣。64-bit with 32-bit ABI 代表程式可以存取 64-bit 硬體資源,但其記憶體空間仍只侷限在 32-bit; x86 binary 執行在 x86_64 上不能存取 64-bit 硬體資源 6)

$ uname -aLinux sparc 2.6.37-rc5-git #1 SMP Tue Dec 21 17:03:53 CST 2010 sparc64 sun4v UltraSparc T2 (Niagara2) GNU/Linux$ file /bin/ls/bin/ls: ELF 32-bit MSB executable, SPARC32PLUS, V8+ Required, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped# 雖然機器是 64-bit,但是裝的是 32-bit OS# --sparc_cpu=v9 改用 sparc64-linux-gcc$ configure --prefix=$INSTALL --target-list=i386-linux-user --sparc_cpu=v8plus

PowerPC

因為 PS3 記憶體不足,可能導致 GCC 編譯 QEMU 失敗 7)8)。改以 debug 模式編譯。

  1. 註解 assert。

                            --- qemu-0.13.0/tcg/tcg.c.orig 2010-10-16 04:56:09.000000000 +0800+++ qemu-0.13.0/tcg/tcg.c 2011-02-24 09:46:28.796899001 [email protected]@ -1031,7 +1031,7 @@         def = &tcg_op_defs[op]; #if defined(CONFIG_DEBUG_TCG)         /* Duplicate entry in op definitions? */- assert(!def->used);+ //assert(!def->used);         def->used = 1; #endif         nb_args = def->nb_iargs + def->nb_oargs;
  2. 拷貝 x86 函式庫供 powerpc 上的 qemu-i386 使用。函式庫必須放在以 lib 為名的目錄底下。

    $ mkdir $HOME/tools/lib$ cp /lib32/ld-linux.so.2 $HOME/tools/lib$ cp /lib32/libc.so.6 $HOME/tools/lib$ export LD_LIBRARY_PATH=$HOME/tools/lib$ qemu-i386 -L $HOME/tools hello

ARM

    1. 下載並安裝 crosstool-ng。

                                      # 預設安裝在 $HOME/x-tools 下。# 注意執行 QEMU 平臺的核心,這裡要選較其為舊的核心建立工具鏈。# 請記得將 crosstool.config 更名為 .config。$ wget http://ymorin.is-a-geek.org/download/crosstool-ng/crosstool-ng-1.9.2.tar.bz2; tar xvf crosstool-ng-1.9.2.tar.bz2$ cd crosstool-ng-1.9.2;$ ./configure --prefix=$INSTALL$ make install                            
    2. 建置交叉工具鏈。

      $ mkdir toolchain-build$ cp $INSTALL/lib/ct-ng-1.9.2/samples/arm-unknown-linux-gnueabi/* .$ mv crosstool.config .config$ ct-ng menuconfig$ ct-ng build
  1. 安裝執行時期函式庫。如果要安裝預編譯好的執行時期函式庫。可以到 linux-arm.org 下載。

                            # mount cramfs 要有 root 許可權。可以改採下面的作法,使用 fakeroot-ng。$ wget http://www.linux-arm.org/git?p=ael.git;a=blob_plain;f=filesystem/bin/alip-ael-armv6-full-reduced.cramfs;hb=2010q4$ fakeroot-ng# /sbin/cramfsck filesystem_bin_alip-ael-armv6-full-reduced.cramfs -x runtime/# cp runtime/lib/* /path/to/runtime/lib# exit$

    也可以使用 crosstool-NG,在建立工具鏈時同時也會得到執行時期函式庫。預設安裝在 $HOME/x-tools/arm-unknown-linux-gnueabi/arm-unknown-linux-gnueabi/sys-root/lib。PowerPC64 需要為 sys-root/lib64 和 sys-root/usr/lib64 建立軟鏈結,請 chmod u+w sys-root 和 chmod u+w sys-root/usr。

  2. 執行 QEMU。假設 runtime 裝在 /path/to/runtime/lib。

    $ qemu-arm -L /path/to/runtime hello$ qemu-ppc64 $HOME/x-tools/powerpc64-unknown-linux-gnu/powerpc64-unknown-linux-gnu/sys-root hello

System Mode

  1. 編譯 QEMU。

    $ wget http://download.savannah.gnu.org/releases/qemu/qemu-0.14.1.tar.gz; tar xvf qemu-0.14.1.tar.gz$ mkdir build; cd build# i386-softmmu 執行檔名稱為 qemu。將在 QEMU 1.0 修正。$ ../qemu-0.14.1  --prefix=$INSTALL --target-list=i386-softmmu,arm-softmmu$ make && make install                    
  2. 編譯核心映像。

    •                                 # 取得 arch/i386/boot/bzImage 和 vmlinux 兩個檔案# kernel hacking 開啟 debug$ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.20.tar.gz; tar xvf linux-2.6.20.tar.gz# http://blog.csdn.net/livingpark/article/details/3732679# 在 scripts/mod/sumversion.c 加上 #include <limits.h>$ cd linux-2.6.20# make mrproper 清理原始檔和設定$ make mrproper; make ARCH=i386 menuconfig; make ARCH=i386
  3. 準備 root file system。如果沒有 root 許可權的話,可以安裝 fakeroot 或是 fakeroot-ng,或是用 buildroot

    • $ wget http://busybox.net/downloads/busybox-1.18.5.tar.bz2; tar xvf busybox-1.18.5.tar.bz2$ cd busybox-1.18.5# Enable Busybox setting/Build Options/Build busybox as static binary$ make menuconfig$ make; make install$ cd ..; fakeroot-ng;# mkdir root; cd root# mkdir dev bin# mknod dev/console c 5 1# mknod dev/tty2 c 4 2# mknod dev/tty3 c 4 3# mknod dev/tty4 c 4 4# cp ../busybox-1.18.5/busybox bin# ln -s bin/busybox init# cd bin# ln -s busybox sh# cd ..# find . | cpio -o -H newc | gzip > ../initramfs                            

      或是直接使用 QEMU 官網上的測試檔。

      $ wget http://wiki.qemu.org/download/arm-test-0.2.tar.gz; tar xvf arm-test-0.2.tar.gz$ cd arm-test# zImage.integrator 是核心檔案。arm_root.img 是根檔案系統。# gzip -dc arm_root.img | cpio -idv$ qemu-system-arm -kernel zImage.integrator -initrd arm_root.img -nographic -append "console=ttyAMA0"$ wget http://wiki.qemu.org/download/minix204.tar.bz2; tar xvf minix204.tar.bz2$ cd minix204$ qemu -m 8M -fda vfloppya.img -hda minix204.img -boot c -vnc 0.0.0.0:1$ wget http://wiki.qemu.org/download/linux-0.2.img.bz2$ bunzip2 linux-0.2.img.bz2# 使用 vncviwer 連至 server:1 即可得到輸出。# 使用非常類似的 2.6.20 config。# http://bellard.org/jslinux/linuxstart-20110820.tar.gz#qemu -S -kernel bzImage -hda linux-0.2.img -append "root=/dev/hda" -vnc 0.0.0.0:1$ qemu linux-0.2.img -vnc 0.0.0.0:1                            
  • 可以用 E2tools 或 guestfish 修改硬碟映像。或是在 output/targets 放置檔案,再重新 make

    $ /sbin/e2fsck -f rootfs.ext2# 先把 rootfs 放大$ /sbin/resize2fs rootfs.ext2 5G$ e2mkdir rootfs.ext2:/root/tmp/$ e2cp SPEC_CPU2006_v1.1.tgz rootfs.ext2:/root/tmp/                    
  • -kernel <kernel image> : -kernel 引數後面接核心映像檔名,如果不指定路徑,則在當前目錄下尋找。-kernel bzImage 表示指定 bzImage 作為核心映象檔案。

  • -initrd <initial ram disk image> : 需要為核心加在的初始 RAM 磁碟,裡面包含檔案系統。

  • -hda linux-0.2.img 表示 linux-0.2.img 中的檔案系統都放在 hda 中。

  • -nographic : 由於這裡模擬的目標板沒有圖形裝置,所以我們也沒必要讓 QEMU 模擬圖形裝置,所以這裡使用此引數。

  • -append <parameters> : 一般的,我們在啟動 linux 時,我們有時需要給核心傳遞一些引數,比如 init=/etc/init 指定核心啟動後,最後將從執行位於 /etc 目錄下的 init 檔案 (該檔案預設位於 /sbin/ 目錄下)。這裡,我們設定 console=ttyAMA0 表示核心使用 /dev/ttyAMA0 裝置作為控制檯,該裝置由 QEMU 建立,這樣目標板就有了一個作為終端的偽序列裝置。-append "root=/dev/hda" :-append 後接命令列引數,這裡表示根檔案系統裝置使用 hda 。

退出 QEMU 操作為:Ctrl + A ,然後按下 X 鍵。注意,它不會提醒你是否要退出,而是直接退出,所以操作時要小心。

QEMU 的 LInux 映像檔裡包含 NBench,分數越高越好。要切換到 nbench 的目錄底下執行 nbench 這隻測試程式,否則會噴出以下訊息:

CPU:NNET--error in opening file!

製作 QEMU 官網上的硬碟映像。

  1. Create the RAM disk whose size is 64M.

    $ dd if=/dev/zero of=disk.img bs=4096 count=16384                    
  2. Partition the disk.

    $ /sbin/fdisk -C 16065 -H 255 -S 63 disk.img
  3. Format the filesystem.

  4. Copy file system.

  5. Build the bootloader by grub.

  6. Boot system with your new disk.

shutdown 和 reboot 不會導致重開機,exit 登出 shell 會導致重開機。linux-0.11 登出後不會重開機10)

# -no-shutdown -no-reboot: 登出後,出現 "machine restart" 之後停住。(qemu) system_powerdown 無反應(qemu) system_reset QEMU 停止運作# -no-reboot: 登出後,離開 QEMU。(exit instead of rebooting)(qemu) system_powerdown 無反應(qemu) system_reset 關閉 QEMU# -no-shutdown: 登出後,重啟系統。(stop before shutdown)(qemu) system_powerdown 無反應(qemu) system_reset 重啟系統# 不加 -no-shutdown -no-reboot(qemu) system_powerdown 無反應(qemu) system_reset 重啟系統

安裝系統

$ wget http://releases.ubuntu.com/12.04/ubuntu-12.04-server-amd64.iso$ qemu-img create -f qcow2 ubuntu_x86_64.qcow2 3G$ qemu-system-x86_64 -m 1024M -boot d -cdrom ubuntu-12.04-server-amd64.iso \  -hda ubuntu_x86_64.qcow2 -vnc 0.0.0.0:1$ qemu-system-x86_64 -m 1024M -hda ubuntu_x86_64.qcow2 -vnc 0.0.0.0:1        
$ wget http://people.debian.org/~aurel32/qemu/armel/vmlinuz-2.6.32-5-versatile$ wget http://people.debian.org/~aurel32/qemu/armel/initrd.img-2.6.32-5-versatile$ wget http://people.debian.org/~aurel32/qemu/armel/debian_squeeze_armel_desktop.qcow2$ qemu-system-arm -M versatilepb -kernel vmlinuz-2.6.32-5-versatile \  -initrd initrd.img-2.6.32-5-versatile \  -hda debian_squeeze_armel_desktop.qcow2 -append "root=/dev/sda1" -vnc 0.0.0.0:1# 請到 http://ftp.de.debian.org/debian/dists/ 找類似 Debian6.0.4/main/installer-armel/current/images/versatile/netboot# 的路徑,下載 initrd.gz。$ qemu-img create -f qcow2 hda.img 3G$ qemu-system-arm -M versatilepb \  -kernel vmlinuz-2.6.32-5-versatile -initrd initrd.gz \  -hda hda.img -append "root=/dev/ram" -vnc 0.0.0.0:1# 安裝完後,關閉 QEMU。並改用底下指令開機。$ qemu-system-arm -M versatilepb \  -initrd initrd.img-2.6.32-5-versatile \  -hda hda.img -append "root=/dev/sda1" -vnc 0.0.0.0:1# 或是改從 console 輸出。$ qemu-system-arm -M versatilepb \  -initrd initrd.img-2.6.32-5-versatile \  -hda hda.img -append "root=/dev/sda1 console=ttyAMA0" -nographic# 下載 linux kernel tarball,解開後在 arch/arm/configs 找 config。$ wget 'http://linux-arm.org/git?p=ael.git;a=blob_plain;f=kernel/config/config-ael-2011.06.00-realview-v7-smp-thumb;hb=2011.06'        

Buildroot

            # http://buildroot.uclibc.org/downloads/snapshots/buildroot-snapshot.tar.bz2$ wget http://buildroot.uclibc.org/downloads/buildroot-2011.11.tar.gz; tar vxf buildroot-2011.11.tar.gz$ cd buildroot-2011.11# for kernel,請見 arch/i386/defconfig 或 arch/arm/configs。make help 可以看到更多資訊。# 先產生 qemu 用的 default config。$ make qemu_x86_defconfig# 設定 linux kernel version。最後生成的 rfs 格式,initramfs。# 注意編譯 kernel 時所用的 config 從哪裡來。## - gzip, tar## - rpm## - dropbear: openssh 會一直要求改密碼。#$ make menuconfig$ make# 使用 QEMU 內部的 DHCP 以便存取網路。$ vi output/target/etc/network/interfacesauto eth0iface eth0 inet dhcp$ cd output/images/# 建議先轉成 qcow2 以便動態增長硬碟大小。rootfs.qcow2 只能增長成原本硬碟映像的大小。$ qemu-img convert -O qcow2 rootfs.ext2 rootfs.qcow2$ qemu-img resize rootfs.qcow2 +3G$ qemu-img info rootfs.qcow2image: rootfs.qcow2file format: qcow2virtual size: 3.2G (3399145472 bytes)disk size: 159Mcluster_size: 65536$ qemu-system-i386 -kernel bzImage -initrd rootfs.cpio -vnc 0.0.0.0:1$ qemu-system-i386 -kernel bzImage -hda rootfs.ext2 -append "root=/dev/sda console=ttyAMA0" -nographic \  -redir tcp:2222::22 \  -redir tcp:3333::3333# 登入後,修改密碼。$ passwd new_passwd# 修改密碼若失敗,請修改 /etc/sshd_config,在其中將 UsePrivilegeSeparation 開啟:# UsePrivilegeSeparation yes$ ssh -p 2222 [email protected]

有些套件需要 wchar 支援。12)

Monitor

# 有時候會遇到 vnc 無法開啟的情況,使用 screendump 輸出螢幕內容。# 再用 http://www.online-convert.com 轉成 jpeg 觀看。(qemu) screendump screenshot.ppm
(qemu) info jitTranslation buffer state:gen code size       3785504/4089856TB count            11244/32768TB avg target size  14 max=595 bytesTB avg host size    336 bytes (expansion ratio: 23.4)cross page TB count 25 (0%) // guest TB 對映的 guest binary 跨 guest page 的個數和比例。direct jump count   7569 (67%) (2 jumps=5173 46%)Statistics:TB flush count      0TB invalidate count 2737TLB flush count     13869
# 印出客戶機虛擬位址處的內容。(qemu) x /2 0x08d3100808d31008: 0x64636261 0x00006665# 印出客戶機物理位址處的內容。(qemu) xp /2 0x016030080000000001603008: 0x64636261 0x00006665# 顯示記憶體、MMIO、IO 地址分佈。# 以縮排顯示階層關係。(qemu) info mtreeI/O0000000000000000-000000000000ffff (prio 0): io  0000000000000020-0000000000000021 (prio 0): pic

使用 Ctrl + Alt + 2 組合鍵切換到 QEMU 終端 (QEMU Monitor),然後輸入 gdbserver ,啟動 gdbserver 服務。 這時啟動另外一個終端視窗,輸入 gdb vmlinux 命令進行除錯:

            (gdb) target remote localhost:1234               /*使用 gdbserver 進行除錯命令*/

或是將 QEMU 終端導至標準輸出。

$ qemu -hda linux-0.2.img -vnc 0.0.0.0:1 -monitor stdio

Snapshot

  1. 先確定裝置格式支援 snapshot。raw 不支援 snapshot。Monitor

    (qemu) info blockide0-hd0: removable=0 io-status=ok file=linux-0.2.img ro=0 drv=raw encrypted=0ide1-cd0: removable=1 locked=0 tray-open=0 io-status=ok [not inserted]floppy0: removable=1 locked=0 tray-open=0 [not inserted]sd0: removable=1 locked=0 tray-open=0 [not inserted](qemu) savevmDevice 'ide0-hd0' is writable but does not support snapshots.
  2. 用 qemu-img 轉換硬碟映像成 qcow2 格式。

    $ qemu-img convert -O qcow2 linux-0.2.img linux-0.2.qcow2
  3. 在 monitor 在下 savevm 把 RAM、device state 和 disk 存到當前使用的硬碟映像13)

    (qemu) savevm(qemu) loadvm(qemu) info snapshots

Network

QEMU 可以透過虛擬網絡卡連至 vlan,vlan 之間可以透過 slirp,socket,tap 或是 vde 連線。在 Documentation/Networking 提到的 virtual network device 即為虛擬網絡卡,network backend 負責將虛擬網絡卡送出的資料放到真實網路上,可以是 slirp,socket,tap 或是 vde。QEMU Networking 裡面的 usermode network stack 即為 slirp,slirp 為預設網路後端,見下圖。QEMU 內部會啟動一個 DHCP 伺服器,宿主作業系統不可見。

  1. 存取宿主機的資料。

                            # 在 host 執行底下命令。$ cd path/to/shared/files && python -m SimpleHTTPServer# 在 guest 執行底下命令。$ wget http://10.0.2.2:8000/README
  2. 存取客戶機的資料。

                            # 將 host TCP 連線 127.0.0.1:8000 導到 guest 內部 DHCP 預設 IP 埠 8000。$ qemu-system-x86_64 -m 1024M -hda ubuntu_x86_64.qcow2 \  -net user,hostfwd=tcp:127.0.0.1:8000-:8000 \  -vnc 0.0.0.0:1$ wget localhost:8000/README
$ qemu-system-i386 -kernel bzImage-x86 -hda disk-x86.raw -append "root=/dev/sda" \  -net nic -net tap,ifname=tap0,script=no -vnc :3 -monitor stdio

Tracing

請見 docs/tracing.txt。

$ wget http://download.savannah.gnu.org/releases/qemu/qemu-0.14.0.tar.gz$ tar xvf qemu-0.14.0.tar.gz$ vim qemu-0.14.0/trace-events # qemu-malloc.cqemu_malloc(size_t size, void *ptr) "size %zu ptr %p"qemu_realloc(void *ptr, size_t size, void *newptr) "ptr %p size %zu newptr %p"qemu_free(void *ptr) "ptr %p" $ make install build; cd build;$ ../qemu-0.14.0/configure --prefix=/path/to/install --target-list=i386-linux-user --enable-trace-backend=stderr$ ./path/to/install/qemu-i386 hello

Cross Compile

  1. 需要 zlib 的 ARM binary。

    $ wget http://zlib.net/zlib-1.2.5.tar.gz; tar xvf zlib-1.2.5.tar.gz# export PATH=/PATH/TO/CROSSTOOL:$PATH$ CC=arm-none-linux-gnueabi-gcc ./configure \  --prefix=$INSTALL                    
  2. 執行底下指令碼。

                            #!/bin/bash SOURCE_DIR=../user-modeZLIB_PREBUILT=$HOME/x-toolsTARGET_LIST=arm-linux-userCROSS_PREFIX=arm-none-linux-gnueabi-CPU=armv7lCFLAGS=-I$ZLIB_PREBUILT/includeLDFLAGS=-L$ZLIB_PREBUILT/libPREFIX=`pwd`OPT_FLAGS="--disable-sdl"DEBUG=--disable-stripSTATIC=--static $SOURCE_DIR/configure --target-list=$TARGET_LIST \  --cpu=$CPU \  --extra-ldflags=$LDFLAGS  \  --extra-cflags=$CFLAGS \  --cross-prefix=$CROSS_PREFIX \  --prefix=$PREFIX                    

Debug & Testing

$ git clone git://git.qemu.org/qemu-test.git$ cd qemu-test$ git submodule update --init$ make        

舊版 GDB 無法處理 PIE。

$ ../qemu-1.0/configure --prefix=$INSTALL --target-list=i386-softmmu --enable-debug --disable-pie        
            (gdb) handle SIG38 noprint pass# 定位感興趣的 guest pc 以便查詢其在 code cache 中的位址。(gdb) b gen_intermediate_code_internal if tb->pc == 0x801a3bc# 此時已生成 host binary,查詢 qemu.log。(gdb) b tb_find_fast

QEMU 內部會註冊 SIGNAL 供自己使用,例如 IO thread 執行完畢之後會傳送 SIGNAL 給 vcpu thread。

  1. 在 qemu_tcg_init_cpu_signals (cpus.c) 註冊 QEMU 內部使用的 SIGNAL。

                            static void qemu_tcg_init_cpu_signals(void){    sigset_t set;    struct sigaction sigact;     memset(&sigact, 0, sizeof(sigact));    sigact.sa_handler = cpu_signal;    sigaction(SIG_IPI, &sigact, NULL);     sigemptyset(&set);    sigaddset(&set, SIG_IPI);    pthread_sigmask(SIG_UNBLOCK, &set, NULL);}                    
  2. cpu_signal 會將執行從 code cache 拉出來,回到 QEMU 處理 singal。

                            static void cpu_signal(int sig){    if (cpu_single_env) {        cpu_exit(cpu_single_env);    }    exit_request = 1;}                    

Internal

QEMU 中的 target 有兩種意義,

  1. 描述被模擬的硬體

  2. 對 TCG 而言,target 描述產生何種宿主硬體程式碼

QEMU 0.9 版以前使用 dyngen,對於 dyngen 的描述可以參考以下檔案。QEMU 0.10 以後改採 TCG。可以從下載 QEMU Source Archive 原始碼。

  • QEMU does not have a high level design description document - only the source code tells the full story 8-)

  • HACKING 、CODING_STYLE 和 tcg/README。

  • QEMU 使用巨集展開。編譯時加上 –extra-cflags="-save-temps" 可以得到巨集展開之後的檔案 *.i。

  • 有些註解是 QEMU 0.9 以前的殘留。

原始碼目錄概觀

  • target-ARCH/

    • 定義被模擬硬體,反匯編

  • OS-user/

    • 作業系統相關

  • tcg/

    • 定義如何生成宿主平臺指令

Memory

QEMU 1.0 將有變動。請見 HACKING、docs/memory.txt 或 Planning/1.0

請見 memory.[ch]。

  • target_phys_addr_t (targphys.h) 代表客戶機實體地址空間。如果客戶機是 x86 開啟 PAE 的話,target_phys_addr_t