虚拟机中GUEST OS时钟(TIMEKEEP)问题的探讨 续

虚拟机中GUEST OS时钟(TIMEKEEP)问题的探讨 续

康华 :主要从事 Linux 操作系统内核、虚拟机、Linux 技术标准、计算机安全、软件测试等领域的研究与开发工作,曾就职 MII-HP 软件实验室 瞬联软件公司/MOTOROLA,现就职于Lenovo研究院 。其所合写的Linux专栏见http://www.csdn.net/subject/linux/。 如果需要可以联系通过 [email protected] (MSN)联系我.   

在第一篇文章中主要讨论了虚拟机中TIMEKEEP设计到的时钟中断注射问题,本文主要讨论虚拟机中各种平台时钟之间的同步问题。
 
传统操作系统中的时钟同步概念描述
我们知道系统硬件中存在诸如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等同步。方法其实 intelamd的虚拟技术处理器已经给我们提供,就是在GOS读取TSC时(x86体系中有专门指令 rdtsc),返回结果是在原结果(硬件TSC COUNTER)上再加上一个可变化,可配置的偏移值 tsc_offset的和,因此我们可以通过设置这个 tsc_offset值,达到将GOS看到的TSC和其RTC维护的计时同步。具体做法就是在每一周期时钟中断注射时刻,都根据GOS的计时(RTC维护)的时间设置新的 tsc_offset(在 xenvpt.c中的 pt_intr_post中的语句 hvm_set_guest_time(pt-> vcpu, pt->last_plt_gtime) 就是完成该工作的),这样以来确保了虚拟环境下时钟同步。
SMP环境下的同步
上面所讲的同步都是针对单 核系统而言的,对于多核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代码对时钟的虚拟还存在很多漏洞,希望有兴趣的读者可以继续研究。
 
 

你可能感兴趣的:(虚拟机中GUEST OS时钟(TIMEKEEP)问题的探讨 续)