董衛宇,蔣烈輝,王立新,唐永鶴,焦建華
(信息工程大學 數學工程與先進計算國家重點實驗室,河南 鄭州450000)
跨平臺系統虛擬機 (cross-platform system virtual machine)利用動態二進制翻譯 (dynamic binary translation,DBT)、內存虛擬化、I/O仿真等技術,可使針對某處理器平臺 (源平臺)編譯的操作系統和應用程序運行于其它處理器平臺 (目標平臺),實現軟件的跨平臺透明移植,對體系結構創新和新型處理器推廣具有重要意義[1]。另外,跨平臺系統虛擬機技術在動態二進制優化、漏洞挖掘和利用、體系結構模擬等領域也有廣泛的用途[2-4]。
除了對源平臺指令集架構 (instruction set architecture,ISA)兼容的完備性之外,性能是跨平臺系統虛擬機需優先考慮的問題。源平臺與目標平臺的ISA間在指令集、存儲管理單元 (memory management unit,MMU)、I/O接口等方面的差異,有可能嚴重制約跨平臺系統虛擬機的效率。
目前,提升跨平臺系統虛擬機效率的做法主要有兩類,一是利用軟硬件協同設計技術[1,5,6],在目標平臺CPU中增加硬件資源來模擬源平臺;二是利用軟件方法,通過分析源平臺ISA的特性來簡化或去除不必要的模擬操作。第一類做法可獲得較大加速比,但對CPU進行修改須面臨成本、技術、驗證等多重風險,處理器廠商對此種方案一般很謹慎。第二類做法如果運用得當也可以獲得可觀的收益,風險很小,出現錯誤易于修改,并且可以為軟硬件協同設計提供依據。本文以基于申威處理器 (SW-410,以下簡稱SW)的x86系統虛擬機監控器為實例來討論跨平臺系統虛擬機的訪存操作的軟件優化方法。
不同于某些進程級虛擬機[7,8],跨平臺系統虛擬機需要模擬源平臺的MMU,在訪存前進行虛實地址轉換,以及缺頁或內存保護異常檢測。由于源平臺和目標平臺的MMU往往存在很大差異,一般無法使用同構系統虛擬化中的影子頁表、EPT (extended page table)等技術,而只能利用軟件來串行模擬原本可以用MMU硬件并行完成的工作,因此開銷很大,優化價值也很大。
本文的主要工作如下:①介紹了跨平臺系統虛擬機ARCH-BRIDGE及其設計;②對ARCH-BRIDGE存儲子系統的性能瓶頸進行了識別和分析;③提出了x86段級存儲仿真優化、頁級存儲仿真優化、連續內存訪問優化等方法;④對上述方法進行了實現和測試,應用上述方法,ARCHBRIDGE的訪存性能提升了2.4倍~3倍,操作系統引導性能提升了30.4%。
ARCH-BRIDGE是首個基于申威處理器的跨平臺系統虛擬機監控器。為豐富申威處理器的軟件來源,并考慮到x86ISA在業界的壟斷地位,ARCH-BRIDGE選擇x86作為源平臺。該項目的目的是研究申威與x86間的ISA差異,識別基于申威平臺的x86系統虛擬機的性能瓶頸,提出面向x86架構兼容的申威處理器優化擴展方案,并在后續硬件支持的基礎上最終演化為一款軟硬件協同設計虛擬機監控器 (co-designed Virtual machine monitor),實現x86操作系統和應用程序在申威平臺上的透明高效運行。
目前,ARCH-BRIDGE運行于采用SW處理器的神威服務器平臺,支持Intel P6處理器定義的全部定點指令、FPU指令和 MMX指令,支持PCI總線、南北橋、IDE、VGA、APIC等典型x86接口,能夠運行基于x86Linux 2.6內核的操作系統,能夠運行BusyBox工具集中的全部應用程序,通過了SPEC CPU 2006測試集中全部定點程序和12個浮點程序的測試 (另外6個浮點程序為Fortran程序,由于虛擬機映像內運行時庫問題暫未測試)。支持Windows操作系統運行以及軟硬件協同設計虛擬機的工作正在進行中。
ARCH-BRIDGE的設計方案如圖1所示,下面從x86處理器虛擬化、內存虛擬化和I/O虛擬化3個方面介紹其設計。
動態二進制翻譯技術是在異構平臺上進行x86處理器虛擬化的關鍵技術。ARCH-BRIDGE的利用DBT引擎完成動態二進制工作,其主要設計要點如下:

圖1 ARCH-BRIDGE設計方案
(1)DBT引擎以動態基本塊為翻譯單位。為提高翻譯效率,采用x86指令到SW指令直接翻譯和寄存器靜態映射的方式,沒有采用其它虛擬機監控器所采用的中間表示以及動態寄存器分配方案。某些x86指令 (如INT指令)的操作十分復雜,ARCH-BRIDGE利用輔助的C代碼仿真這些指令。
(2)為提高翻譯代碼的重用率,DBT引擎采用了代碼緩存 (code cache)機制來保存翻譯過的x86基本塊,當代碼緩存滿時,采用簡單的全清空策略清除所有翻譯塊。
(3)為降低DBT引擎與翻譯塊間的上下文切換開銷,DBT引擎采用了翻譯塊鏈 (Block Chaining)機制來鏈接翻譯過的代碼塊,為避免構成循環的翻譯塊阻礙對中斷的響應,需定期將當前正在執行的翻譯塊從塊鏈中移除,以便返回執行引擎檢查中斷。
(4)在取指令 (實際是訪存的一種形式)或翻譯塊執行過程中檢測到x86異常時,采用longjmp()將流程轉移到DBT引擎入口位置,進行異常檢查和派發工作。ARCHBRIGE支持精確異常,可確保在異常派發前將機器狀態(包括通用寄存器、標志寄存器、EIP、內存內容)恢復到異常指令執行前的狀態。
(5)采用懶惰計算思想,在執行翻譯塊時不更新EIP的值,僅在塊尾部或遇到異常時才恢復EIP的值;在翻譯影響標志位的指令時,僅插入SW指令保存x86指令的操作、執行結果和源操作數 (目的操作數可以由上面3個信息恢復出來),僅在需要引用標志位時才計算標志位的值。
內存虛擬化包括兩個任務:一是MMU虛擬化,主要是模擬x86對頁表和TLB的相關操作,完成客戶虛擬地址(guest virtual address,GVA)到 客 戶 物 理 地 址 (guest physical address,GPA)的轉換。由于頁表屬于x86ISA的一部分,因此ARCH-BRIDGE需精確模擬頁表的查找過程。由于x86TLB對軟件透明,因此TLB虛擬化不受實際硬件的限制,ARCH-BRIDGE以HASH表的形式對TLB進行模擬;二是物理內存虛擬化,ARCH-BRIDGE使用進程地址空間的一部分來模擬虛擬機的物理內存,因此需要建立客戶物理地址GPA到宿主機虛擬地址 (host virtual address,HVA)間的映射。由于x86的物理地址空間很可能存在空洞,并考慮到對PAE機制 (36位物理地址)的支持,ARCH-BRIDGE采用3級目錄結構來保存這種映射關系。每個映射關系將一個4KB的虛擬機物理頁面映射到一個4KB的宿主機虛擬頁面。若x86物理頁面為RAM或ROM,則映射關系給出物理頁面對應的HVA。若x86物理頁面以MMIO方式映射到I/O設備的存儲區域,則映射關系以回調函數方式給出訪問設備存儲區域對應的I/O動作。
I/O虛擬化主要工作有四方面:一是I/O寄存器模擬;二是內存映射 (MMIO)的設備存儲模擬;三是設備中斷;四是設備的DMA操作。除此之外,ARCH-BRIDGE還實現了軟時鐘、字符設備抽象層、塊設備抽象層等模塊,以提供對設備仿真的共性支持。ARCH-BRIDGE的I/O仿真的主要做法是:
(1)在設備初始化時向ARCH-BRIDGE注冊I/O端口或MMIO存儲的訪問回調函數;
(2)在翻譯塊執行過程中,若訪問I/O端口或 MMIO存儲,上述回調函數將被調用,I/O操作得到同步處理;
(3)ARCH-BRIDGE以定時輪詢的方式檢測鍵盤輸入、定時器超時等I/O事件,并在必要時以中斷注入的方式通知虛擬機;
(4)ARCH-BRIDGE在基本塊的邊界檢測外部中斷并進行中斷派發。
ARCH-BRIDGE對訪存指令的翻譯工作可以分為兩個部分:
(1)根據指令指定的尋址方式生成用于計算x86線性地址的SW指令序列;
(2)生成調用mmu_rd或mmu_wt所需的SW指令序列。其中mmu_rd和mmu_wt為C函數,用于進行訪存涉及的復雜的TLB查詢、地址轉換和訪問宿主機內存的操作。
ARCH-BRIDGE前期的實驗數據表明,在引導Linux-2.6.38內核時,從開機到出現登錄界面總消耗時間約為65s左右,由于采用指令直接翻譯和寄存器靜態映射技術,指令翻譯效率較高,僅占用了2.1s,但訪存時間消耗高達31.7s,約占到了虛擬機總執行時間的48.8%,對虛擬機的性能影響很大,存在很大的優化價值。分析發現,ARCH-BRIDGE的訪存操作至少存在如下一些優化機會:
(1)x86訪存操作存在復雜的段級存儲管理階段,每個訪存操作都需要將有效地址加上段基址來生成線性地址并進行段邊界檢查,精確模擬上述機制需要一定數量的SW指令。但由于x86操作系統大多繞過了段級機制,采用平面模式內存管理 (段基址為0,段界限為0xFFFFFFFF),精確模擬沒有實際意義,存在優化機會。
(2)如圖2所示,DBT引擎與翻譯塊共用一套SW結構寄存器,從DBT引擎切換到翻譯塊執行需要一次上下文切換;當遇到訪存操作時 (翻譯塊內往往存在多次訪存),從翻譯塊中調用mmu_rd和mmu_wt又引入了額外的上下文切換。另外,利用C函數實現mmu_rd和mmu_wt的效率也不高。mmu_rd和mmu_wt的3項主要工作是TLB查詢、TLB脫靶情況下的頁表查詢、以及宿主存儲器訪問,其中第1、3項工作比較簡單。測試表明,ARCH-BRIDGE的TLB命中率為99.4%,大多數情況下無需頁表查詢操作,因此可考慮利用較短的SW指令序列對頁級存儲仿真進行優化。

圖2 訪存時調用mmu_rd和mmu_wt的流程
(3)x86提供了 MOVS、SCAS、INS/OUTS等串指令,并且與REP等指令前綴配合來完成串操作。如表1所示,在系統引導過程中觀測到的約1.2×108次訪存中,串操作的訪存次數總和為53 732 810次,約占總訪存次數的44.7%。QEMU、Valgrind[9,10]等跨平臺虛擬機采用比較簡單的仿真方法,將串指令包含在一個循環內實現串操作,每次循環都需要進行虛實地址轉換工作。考慮到串操作具有連續訪問存儲器的特點,一旦確定了某個訪存操作對應的宿主機內存地址,只要不超出當前頁面,對后續的訪問無須進行GVA到HVA的代換,可以進一步省去TLB查詢的開銷。

表1 引導過程中的串指令訪存頻次
針對上述優化機會,本文分別提出了段級存儲仿真優化、頁級存儲仿真優化、連續內存訪問優化等方法,并在ARCH-BRIDGE進行了實現,具體做法將在第3節中介紹。
為優化對段級存儲的仿真,ARCH-BRIDGE在翻譯基本塊前檢查段寄存器的狀態,并將檢查結果記錄在翻譯塊描述信息中,每個段寄存器只需2位信息即可,分別表示段基址是否為0以及段邊界是否為0xFFFFFFFF。x86的6個段寄存器用一個12位的位圖描述即可。
當翻譯基本塊內的訪存指令時,若所使用的段基址為0,則無需生成SW指令進行有效地址與段基址的加法操作;若段界限為0xFFFFFFFF,則無需生成SW指令進行段界限保護檢查。由于訪存指令普遍存在,因此該優化可在一定程度上去除翻譯塊中的無效指令。
在存在代碼緩存和翻譯塊鏈的情況下,需要防止翻譯塊在段寄存器配置發生變化的情況下被執行。為此,ARCH-BRIDGE采用了以下兩點措施:首先,在進行代碼緩存查找時,除基本塊地址外,還比對段寄存器的當前配置與基本塊在翻譯時的段寄存器配置,若發生變化 (幾率很小),需在新的段寄存器配置下重新翻譯基本塊。其次,將所有修改段寄存器的指令視為基本塊結束條件,并且僅在塊以直接跳轉或直接函數調用指令結束時才與后續的塊建立塊鏈,任何修改段寄存器的指令執行后將返回DBT引擎,這保證了在構成塊鏈的一組基本塊中不可能存在修改段寄存器的指令,也就是說構成塊鏈的一組基本塊具有相同的段寄存器配置,在從代碼緩存中查找到一個翻譯塊進而進入塊鏈中執行后,無需擔心會執行到段寄存器配置與其初始翻譯時不符的翻譯塊。該過程如圖3所示。

圖3 ARCH-BRIDGE的基本塊終止和塊鏈退出
為進行頁級存儲仿真優化,ARCH-BRIDGE引入了指令片段mmu_rd_fast和mmu_wt_fast,負責TLB查詢以及TLB命中后的宿主存儲器訪問,大小為20條指令左右。在指令中的翻譯訪存操作時,會首先生成對mmu_rd_fast和mmu_wt_fast的調用指令,之后再生成對mmu_rd和mmu_wt的調用指令,僅當TLB未命中時,mmu_rd和mmu_wt才會得到執行。對mmu_rd_fast和mmu_wt_fast的調用只需增加3條指令,代碼膨脹很小。
ARCH-BRIDGE采用靜態寄存器分配,在翻譯塊中不會使用處理器 ABI(application binary interface)約定的參數傳遞寄存器 (r16~r21)和返回值寄存器 (r0)。由于mmu_rd_fast和mmu_wt_fast的任務比較簡單,僅使用寄存器r16~r21和r0即可完成工作,因此在調用這兩段指令片段時,而無需進行上下文切換。如前所述,TLB命中率很高,因此絕大部分訪存操作都可由mmu_rd_fast和mmu_wt_fast完成,可以在很大程度上提升訪存效率。
為簡化實現,mmu_rd_fast和mmu_wt_fast僅處理TLB命中的、不跨頁的、非MMIO的訪存操作,其它類型的訪存操作仍交由mmu_rd和mmu_wt處理。
為進行連續內存訪問優化,ARCH-BRIDGE以C函數方式來仿真串指令,僅在串指令進入新的頁面時,才進行一次GVA到HVA的代換,得到訪存所對應的頁面的基址。只要不離開該頁面,后續的訪存操作只要修正一個位移量就可以到所需要的HVA,之后進行內存讀寫操作。
以rep stos為例,優化后的串操作執行步驟如下:
(1)獲取 ECX/EDI/EAX的值;
(2)若ECX為0,轉第 (7)步;
(3)根據EDI進行地址代換,確定頁面的HVA;
(4)計算本頁面內可進行最小操作次數;
(5)將EAX的值循環存入本頁面內存區域;
(6)修正ECX/EDI的值,轉第 (2)步;
(7)結束。
對于大批量的內存初始化操作而言,rep stos的主要操作集中在了第v步,此時頁面內串指令的訪存速度可以接近宿主機本地的訪存速度。為簡化實現,我們僅對正向的(DF標志為1)、對齊的、且采用32位地址的串指令采用上述優化措施。
本文對上述優化措施的適用性以及優化后的存儲系統效率和操作系統引導效率進行了測試。主要測試環境如下:虛擬機監控器為ARCH-BRIDGE,宿主機為運行中標麒麟操作系統的SW-410平臺,虛擬機操作系統為經過服務裁剪的tty-linux (內核版本為2.6.38)。
我們通過采樣操作系統引導過程中的訪存操作來評估上述優化措施的適用性,見表2。其中,在指令流中 (靜態)存在的337 623處線性地址計算操作中,97.3%的操作可以被優化掉;在指令流中 (靜態)存在的337 133處段界限檢查操作中,99.9%的操作可以被優化掉。在動態監測到的25 770萬次訪存操作中,99.3%的操作可在mmu_rd_fast和mmu_wt_fast中完成。在以rep stos為例的44 692 206次串操作中,99.8%的訪存操作可以得到優化。因此上述優化措施具有很好的適用性。

表2 各個優化措施的適用性
本文采用STEAM內存帶寬測試程序來測試優化措施對訪存帶寬的影響。優化前后的ARCH-BRIDGE虛擬機訪存帶寬如圖4所示。由于STREAM中沒有采用串指令,因此我們忽略了對連續內存訪問優化的測試。測試表明,在啟用段級和頁級存儲仿真優化的情況下,虛擬機的訪存帶寬提升了2.4~3倍。
ARCH-BRIDGE在采用優化措施前后的操作系統平均引導時間如圖5所示,當綜合采用上述3種優化措施后,虛擬機的操作系統引導時間由65s降低為45.2s,速度提升了約30.4%。利用QEMU 0.10提供的TCG基址,我們將QEMU移植到了SW平臺,移植后的操作系統平均引導時間為48.7s,在僅采用訪存優化措施的情況下,ARCHBRIDGE的性能相比QEMU提升了7%。

圖4 采用優化措施前后的虛擬機訪存帶寬

圖5 采用優化措施前后的虛擬機OS平均引導時間
本文介紹了基于申威處理器的跨平臺系統虛擬機ARCH-BRIDGE及其設計,對其存儲子系統的性能瓶頸進行了識別和分析,并提出了x86段級存儲仿真優化、頁級存儲仿真優化、連續內存訪問優化等方法,使ARCHBRIDGE的訪存性能提升了2.4~3倍,操作系統引導速度提升了約30.4%。
相比典型的跨平臺系統虛擬機QEMU,本文的段級存儲仿真優化可以在確保兼容的情況下提升訪存效率,而QEMU為了換取性能,在訪存時并不進行段界限檢查,損失了兼容性;頁級存儲仿真優化利用宿主機的ABI特性,可在不增加上下文切換開銷和較小代碼膨脹的情況下提升訪存效率,而QEMU將每條x86訪存指令翻譯為幾十條宿主機指令并內聯在翻譯塊中,導致了很大的代碼膨脹,另外其寄存器動態分配機制還會導致訪存過程中的寄存器溢出,降低效率;連續內存訪問優化可以使串指令以接近本地的效率進行訪存,而QEMU只是簡單地將串指令的單次操作嵌套在循環中重復執行,帶來很多冗余操作,操作系統中存在許多使用串指令的任務,如C2級操作系統一般都存在將內存頁面清0的線程,因此該優化措施有助于提升系統性能。測試表明,在僅采用訪存優化措施的情況下,ARCHBRIDGE的操作系統引導性能相比QEMU提升了7%。
[1]CHEN Wei.Research on dynamic binary translation based codesigned virtual machine [D].Changsha:National University of Defense Technology,2010 (in Chinese).[陳微.基于動態二進制翻譯的協同設計虛擬機關鍵技術研究 [D].長沙:國防科學技術大學,2010.]
[2]Tong X,Luo J,Moshovos A.QTrace:An interface for customizable full system instrumentation [C]//IEEE International Symposium on Performance Analysis of System and Software,2013:132-133.
[3]Yin Heng,Song Dawn.TEMU-binary code analysis via wholesystem layered annotative execution [R].Berkeley: UC Berkeley,2010.
[4]Wang Z,Liu R,Chen Y.Coremu:A scalable and portable parallel full-system emulator [C]//Proceedings of the 16th ACM symposium on Principles and Practice of Parallel Programming.ACM,2011:213-222.
[5]El Ferezli E.FAx86:An open-source FPGA-accelerated x86 full-system emulator [D].University of Toronto,2011.
[6]Hu W,Wang J,Gao X.Godson-3:A scalable multicore RISC processor with X86emulation [J].Micro,IEEE,2009,29 (2):17-29.
[7]Guan HB,Ma RH,Yang HB.MTCrossBit:A dynamic binary translation system based on multithreaded optimization [J].Science China Information Sciences,2011,54 (10):2064-2078.
[8]Sridhar S,Shapiro JS,Bungale PP.HDTrans:A low-overhead dynamic translator [J].ACM SIGARCH Computer Architecture News,2007,35 (1):135-140.
[9]Ding JH,Chang PC,Hsu WC.PQEMU:A parallel system emulator based on QEMU [C]//IEEE 17th International Conference on Parallel and Distributed Systems,2011:276-283.
[10]Nicholas N,Seward J.Valgrind:A framework for heavyweight dynamic binary instrumentation [C]//ACM Sigplan Notices.ACM,2007,42 (6):89-100.