我們知道系統硬件中存在諸如RTC/PIT/HPET/ACPI PM TIMER/TSC等許多時鐘, 這些時鐘按其特點來說可分成兩類:以中斷形式存在的周期性時鐘, 如RTC/PIT/HPET等;另外一種是以COUNTER計數器存在的單步遞增性時鐘,如TSC。它們之間的區別在於,周期性時鐘是通過周期性發送中斷達到記時目的的,如心跳頻率一般。而單步遞增時鐘則不發送中斷,而時需要軟件主動去讀取其COUNTER寄存器來獲得時間的。
因而操作系統會有選擇的使用周期性時鐘作為timekeep的時鐘源,而使用單步遞增時鐘作時間校准或者性能統計之用。Linux系統window系統都是如此。
那麼我們這裡所指的時鐘同步是說:系統中的周期性時鐘需要和單步遞增時鐘同步,舉例來說。假如操作系統使用RTC時鐘作為TIMEKEEP的周期時鐘源,且頻率為100HZ,系統CPU頻率 3000MH,TSC頻率等同於CPU頻率,那麼應該每一次RTC中斷產生的同時(系統時間前進了1/100 秒),TSC的COUNTER也應增加1/100*3000M。如果上述關系穩定,那麼我們就稱系統時鐘同步。
那麼為什麼需要TSC和RTC同步呢?操作系統的TIMEKEEP過程中往往(至少Linux系統會這樣作,但window可能沒有)會使用TSC時間對RTC維持的時間(在Linux中就時jiffies)進行校正,這是因為RTC周期性中斷有可能偶然丟失(比如,中斷屏蔽等),而TSC計數器會穩定運行,不會丟失時間,因此RTC維持的系統計時就會落後於TSC計時,因此需要不斷的對RTC計時進行校准,也就是說讓其和TSC計時一致(具體校准動作在Linux系統中請看timer_interrupt中cur_timer所指的函數timer_tsc)。
在傳統環境下的操作系統無論TSC或是RTC都是硬件負責運轉,因此只要硬件穩定,那麼TSC和RTC等雖然是獨立運行,但都應該是同步的。因此同步問題在傳統環境下按理不成問題!
如果說在傳統環境下時鐘同步不成問題,那麼在虛擬環境下時鐘同步會有什麼問題呢?
虛擬環境和傳統環境下時鐘產生的條件變化了!RTC等周期性時鐘不是由相應硬件產生而是通過軟件定時器模擬而得(具體可見上一篇文章),但是TSC的獲得則不是通過模擬,還是讀硬件的TSC的COUNTER 寄存器獲得TSC值(只所以沒有模擬是因為我們無法通過軟件模擬出一個穩定單步增長的TSC COUNTER,直接讀取硬件的TSC更簡單且合理)。我們已經知道在虛擬環境下軟件模擬RTC等周期性時鐘中斷無法精確的觸發和遞交給GOS(虛擬環境下肯定會延遲且觸發間隔不穩定),RTC計時和TSC時間就發生了失步(TSC會跑的快)。在Linux系統上的現象就時輸出打印出很多信息“Losing too many ticks!”(對應代碼在timer_tsc中)。
對於Linux這樣需要TSC校正周期性時鐘計時的系統,我們需要想辦法將TSC和RTC等同步。方法其實intel和amd的虛擬技術處理器已經給我們提供,就是在GOS讀取TSC時(x86體系中有專門指令rdtsc),返回結果是在原結果(硬件TSC COUNTER)上再加上一個可變化,可配置的偏移值tsc_offset的和,因此我們可以通過設置這個tsc_offset值,達到將GOS看到的TSC和其RTC維護的計時同步。具體做法就是在每一周期時鐘中斷注射時刻,都根據GOS的計時(RTC維護)的時間設置新的tsc_offset(在xen中vpt.c中的pt_intr_post中的語句hvm_set_guest_time(pt->vcpu, pt->last_plt_gtime) 就是完成該工作的),這樣以來確保了虛擬環境下時鐘同步。
上面所講的同步都是針對單核系統而言的,對於多核SMP環境的同步除了上述要求之外,還需要多個核和上的時間同步――各個核上的TSC需要同步(每個核都有各自的TSC),TSC和系統周期性時鐘需要同步。
虛擬環境下多核同步有很多困難,想要完全同步要求多個模擬的核同步調度(同時被調度或被調出),否則有可能在給某個核提交周期時鐘中斷時,該核被調出,那麼顯然就會丟失時鐘中斷造成系統時間落後。就Xen代碼而言,目前為了提高整個系統性能各個核獨立調度,因此的確存上述丟失中斷的可能。
為此xen 將周期性時鐘綁定到BSP核上。由於AP核不收到時鐘中斷,以來Ap核不作timekeep操作(timekeep是在收到時鐘中斷後進行),所以不會進行系統計時操作和校對時間操作,也就不會報錯“Losing too many ticks!”,雖然此刻AP核上的TSC確實和RTC計時失步。
不過虛擬雙核無法保證兩個核的TSC同步,這點會影響很多性能測試工具的正常運行,因為很多性能測試工具(pcmark,winsat等)都會利用TSC作性能測量的,所以你很可能會發現這些攻擊在虛擬雙核下打分很低或者無法使用。這個問題對於xen來說還沒有解決或者說沒有被重視。
如果想要徹底解決多核時鐘問題,需要作很多輔助工作,比如在遞交周期時鐘中斷時,觸發ipi中斷通知其它核進行相應同步處理;在某個核被調度出去後,其它核的TSC也應該凍結等。
虛擬環境下時鐘問題有許多需要研究和完善的地方,我們兩篇文章這種就時鐘補償和同步進行了初步討論。虛擬時鐘的實現在虛擬化技術中是一個很重要的技術點,它會對系統整體性能和穩定性有重大影響。目前的xen代碼對時鐘的虛擬還存在很多漏洞,希望有興趣的讀者可以繼續研究。