05-06
2019
龙芯kvm虚拟机研发纪实
kvm虚拟机作为云计算环境的基础支撑组件,是信息技术产业领域典型的”硬科技”产品。为了满足自主信息化对云计算日益迫切的应用需求,龙芯公司于2019年第二季度发布了龙芯kvm虚拟机产品。这是国内技术团队首次完成”从cpu到系统”全链条虚拟机产品的自主研制。
kvm虚拟机的研发跨cpu芯片、操作系统内核、云计算等多个复杂技术领域,涵盖了cpu芯片的虚拟化设计、操作系统内核的系统级虚拟化支持、虚拟机模拟执行环境、云计算应用支撑环境等众多核心技术。从国际上看,仅有intel、arm等几家国外公司掌握了“从芯片到系统”的完整kvm虚拟机核心研发技术,这也导致虽然中国的云计算产业在应用规模等指标上已经达到国际先进水平,然而在虚拟机这一关键核心技术上,国内云厂商无一例外地深度依赖国外虚拟机产品和技术。龙芯kvm虚拟机系统的发布对完善国产cpu技术生态、推动云计算产业健康发展、培养云计算核心技术团队等方面都有着重要意义。
历史积累。龙芯虚拟化设计可以追溯到十多年前的龙芯2号研制时期,我们需要一款能够快速进行操作系统调试的虚拟验证环境。当时是2003年,后来著名的qemu模拟器还没有面世,我的师兄张福新就找来了一个90年代斯坦福大学发布的simos模拟器。斯坦福大学是mips cpu的诞生地,这个simos天生支持mips指令集,通过一些功能级的开发改造,我们很快就把龙芯2号的linux系统在simos上跑了起来。这个simos可以算是最早的龙芯虚拟机系统。我在读博士期间的2004年到2007年,又把龙芯2号的微结构时序模型和龙芯3号的多核架构支持加入到simos中。这个模拟器被用于龙芯cpu微结构设计、性能分析、操作系统开发和硅后验证,发挥了重要作用。后来2007年到2013年,龙芯系统组的历届博士生刘奇、蔡万伟、台运方等基于龙芯系统和模拟器环境,在cpu虚拟化、内存虚拟化和io虚拟化等方面进行了探索性研究,期间的论文和专利成果对龙芯kvm虚拟机的产品研制产生了积极影响。
cpu的硬件虚拟化支持。到了2013年,云计算应用发展使得对国产cpu虚拟化的需求日益强烈,龙芯公司决定在龙芯3a3000中首次加入对硬件虚拟化的支持。由于虚拟机的复杂性,为确保一次成功,公司总裁胡老师提出了“简化硬件和结构的复杂度,通过系统软硬件协同优化来提升效率”的虚拟化设计方针。从后来的项目发展来看,这一指导方针得到了充分贯彻并取得了预计效果。由于简化cpu硬件结构,3a3000的cpu硬件没有出现颠覆性的设计缺陷,cpu流片成功后就能研制和发布虚拟机。同时,软硬件协同优化的策略也给系统优化留下了空间。国内现在一讲创新就喜欢讲超越,然而在计算机领域,复杂的核心技术只能一步一步演进出来。一位国内同仁也跟我表达过类似观点,研发工程积累没有到达一定的程度前,盲目创新的结局只会是跌倒重来。
系统设计方案。从2017年初,龙芯3a3000完成了芯片产品化,开始启动kvm虚拟机软件系统的研制。考虑到kvm虚拟机的系统复杂性,我们采用了按“子系统-模块-场景-路径进行分解"的设计思路。即将整个kvm虚拟机分为cpu指令执行环境、存储管理、时钟、中断、io和配套环境等多个子系统,子系统按模块分解,模块按照场景进行组合,场景又按照执行路径进行具体化设计。当分解到路径时,设计和开发工作就已经非常明确了。由于子系统、模块、场景、路径之间是彼此高度耦合、相互交叉依赖,为了在设计阶段就将各种困难问题充分暴露,并针对各类复杂边界情况制定完备的设计方案,我们为每个场景或路径建立了项目管理平台redmine的对应任务,每个任务指定有一个硬件负责人和一个软件负责人,硬件负责人解释cpu的虚拟化行为,软件负责人则负责确定软件的设计方案。通过充分的讨论和沟通,逐步将虚拟化每个场景每个路径所应具备的功能确定下来,所需要考虑的边界条件和复杂的处理场景也都逐步清晰。后来统计,在长达五个月的设计过程中,总共建立了几十个任务,每个任务中包含的设计文档都经过多个版本,不断修正设计中的疏漏和不足之处。经过这“反复迭代、多轮修正”的设计过程,项目组对虚拟化系统有了全面和深入的把握,对其中的风险和问题进行了充分的评估,设计方案的完备度得到一致确认,可以进入到编码开发阶段。
编码与开发。谋定而后动,由于有前期充分的设计准备,编码开发工作变得如同普通的应用软件编程。大约两个月时间,基本的虚拟化支持代码开发完毕,可以进入调试和验证阶段。这时,我们采用了直接启动linux系统的联调方案,跳过了单元测试的环节,这里边的考虑有三。一是kvm的单元测试环境移植和搭建需要耗费时间和精力,而目前阶段我们应该尽快的迭代出产品;二是因为我们团队在内核方面有很深的积累,直接启动linux进行虚拟机调试,即便在内核层面出现复杂问题,按我们的积累和经验也能hold住;三是启动linux系统可以直接对接虚拟化场景,测试会更加具有针对性和复杂性。按照”虚拟机启动到哪里,验证和测试工作就跟进到哪里”的实施策略,项目进展迅速,期间解决了一些硬件bug和编码实现中的问题,到2018年初,我们已经可以完成虚拟机上linux系统启动,但是就产品而言,整个项目最艰难的时刻还远远未到,后面还有七个难关等着我们。
第一关 解决guest态漏执行问题。在2018年春节之后,我们遇到了一个偶发的系统故障,经常是测试一两天才冒出一个sigbus异常,错误现场留给我们的线索信息极少。大约有一个月左右的时间,我们的工作陷入了僵局。在我近二十年的系统研发工作中,经常遇到各种复杂的系统问题。问题经历多了,喜欢将解决复杂系统问题和警察破案相比较。我非常欣赏一位优秀刑警总结的破案经验,“破案时不要简单根据已有线索进行推断,而是要根据大胆的假定寻找新的线索”。程序员找系统bug和警察破案的工作是相似的。出现系统bug时,现场的信息和线索非常有限,如果只根据有限的线索进行逻辑推断,工作就会进入死胡同。此时,我们根据sigbus现场出现的有限信息,大胆地提出一个假定,即问题源于cpu在虚拟化模式下漏了一部分指令到普通模式下执行。在这个假设前提下,张爽爽和李星在内核中设计了相应的实验方案,一步一步找到新的线索,逐步验证了我们的猜想。最终线索聚焦到一个很小的执行场景,在负责cpu结构设计的吴瑞阳帮助下,确定问题机理是虚拟cpu在特定场景下有两拍的窗口间隙处于竞争不稳态,需要软件对执行模式进行控制。花了前后2个多月时间,解决完这个问题后,spec cpu2006这样的大型测试软件都可以正常运行通过。
第二关 解决云桌面界面卡顿。进入2018年的夏天,外界用户对龙芯虚拟化的支持已日益迫切。那段时间每周我们都接到大量对龙芯kvm虚拟机的咨询、催促、探寻合作的电话和邮件。通过访问合作的云厂商,我们了解到用户希望采用虚拟机云桌面(vdi)的需求。针对这一要求,我们完成了云桌面环境关键组件spice协议和qxl图形驱动的适配和优化,可以启动云桌面环境进行日常办公和娱乐,但在系统压力测试中,却又出现了一两天才偶发的界面卡顿问题。这个卡顿问题跟spice/qxl组件相关,包括内核qxl驱动、virtio驱动,x系统的qxl用户态驱动,remote-viewer等软件和模块,据我们统计,涉及到高达20多万行的源代码。我们需要在短时间内吃透这20多万行从未摸过的代码,并解决卡顿问题,这对项目团队是一个巨大的考验。好在龙芯系统研发部虽然规模不大,但各方面的人才储备比较全面,特别是我们有国内最好的图形驱动团队。虽然spice/qxl是一个我们未曾研究过的虚拟化图形驱动,但我们有过多款龙芯集显gpu图形驱动的开发经验。在技术原理上,qxl跟集显gpu是相通的。于是从操作系统图形组临时调来王洪虎和朱琛进行攻关,他俩很快就进入了状态。经过一个月的代码分析,我们就掌握了qxl的系统架构并摸清了问题线索,根据界面卡顿的现场反向分析,稳步推进,最终确定到卡顿原因为在某个复杂场景下spice协议传输中丢失了一次数据包。机理清楚后,解决bug就顺理成章,云桌面环境的卡顿现象完全消失。
第三关 解决偶发的系统崩溃。解决云桌面卡顿后,我们将kvm虚拟机交给了测试组进行更大规模和压力的系统测试,随之发现了偶发系统崩溃或者死机。从事系统研发的都知道,系统级的错误传播链极长,涉及到的软件源码量可达到上亿行之多,特别是排查错误时还需要经常进入自己不熟悉的领域,例如内核专家往往不甚了解systemd的运行机理,解决这类偶发的系统错误是最头疼的。经过长达两个月对错误现场的反复实验和分析,到了2018年9月的时候,我们推测是tlb的处理时发生了异常,导致访存错误。但由于错误出现时经过了多次传播,错误现场的线索极其有限,我们需要设计一个当错误发生时能够精确推断出错误机理的测试用例。这时我想到了lmbench测试集中有个测量内存延迟的用例,这个用例中相邻访存指令的数据结果是紧密依赖的,当出现错误时,可以立刻判断出错误的上一级来源。果然,用这个用例测试1个小时就能规律复现一次错误,确实是某次load操作时取到了一个错误的数据,但又怎么继续判断这个错误数据的来源呢?李星提出一个方案,将测试程序地址链接到一个特殊区域,这样可以很准确的用ejtag断住错误现场。断住错误现场是一个很重要的突破,没有现场就只能进行缺乏直接依据的猜测,而有了断点现场,工作就变成了“通过查勘错误现场进行有根有据的分析”。随后我们和负责cpu设计的汪文祥和吴瑞阳一起分析错误现场,反复查验tlb中的数据,对比错误程序的反汇编,最终确认错误来源于cpu在流水线切换时采用了错误的地址进行了访存。随后我们对流水线的切换模式进行了控制,这一偶发的系统崩溃问题经过前后近三个月的攻关,得到了机理清楚的彻底解决。
第四关 解决时钟子系统故障。随着测试工作的进一步深入,在2018年9月又出现了系统的rcu报警。经过分析排查,确认rcu故障不是第一错误现场,而是因为虚拟机的时钟中断偶尔间隔过长诱发。在虚拟机发生中断、迁移、异常、暂停等行为时,需要对虚拟机的时钟进行校准和补偿。由于进出虚拟机模式的时钟校准、补偿和管理系统异常复杂,我们自然而然的把主攻方向对准了虚拟机时钟补偿和校准系统,猜测可能是这里出了问题。而虚拟机的时钟系统调试又是一个特殊困难的挑战,因为常规的断点调试等手段本身会导致虚拟机时钟子系统异常,这样错误的浮现几率、现象和触发条件都会发生变化。经过1个月的攻关,我们把整个时钟补偿和校准系统捋了个透,发现并解决了一些时钟子系统的其他问题,但这些跟时钟中断间隔过长问题无关,工作暂时陷入了谜团。此时,龙芯组研究生王俊儒提出一个设想,可能是在处理特殊异常中更新cause寄存器时丢失了时钟中断,这个错误机理清晰明了,但却恰恰在我们主攻方向以外被忽视的部分。果然是山重水复疑无路,柳暗花明又一村。解决完这个问题之后,系统的可用性上了一个大台阶。
第五关 tlb性能优化。在系统级测试工作开展的同时,性能分析工作也在同步进行。针对spec cpu2000这样的典型测试集,我们发现个别程序的虚拟化性能效率不到30%。经过深入分析,判断是因为龙芯3a3000采用的单级tlb模式引起,在特殊应用模式下,tlb处理效率很低。根据这个性能机理,研究生王俊儒和邓向设计了一个软件优化方案大幅度提升了这类应用的性能。新加入龙芯的毛碧波,有多年的产品研发经验,进一步完善了这个设计,并解决实现中的一些关键bug。到了2018年年底,在龙芯3a3000虚拟机上,spec cpu2000等大型应用的性能效率基本都提升到了95%以上。
第六关解决非原子操作引发的虚拟机断网。在解决前面几个攻关问题时,测试组反馈虚拟机偶发断网。起初我没有太在意,以为是测试环境ip冲突或者硬件不稳定故障引起。后来发现这个问题在多个场景下都有出现,应该是虚拟机通过virtio-net模块与外界网络通信过程中的逻辑问题。经过一个多月的初步工作,到了2019年2月都还没有明确的思路和线索,我意识到这又是一个重量级的复杂bug,常规的工作组织机制是难以奏效的,于是召集大家开了一次攻关动员会。我先做了思想动员:kvm虚拟机经过2年的研发,目前到了最关键的阶段,胜利就在眼前,也是对我们项目组决心、能力和作风的一次考验,这个阶段我们绝对不能松劲;项目组每个同事都表现出了昂扬的斗志,一致表达了攻坚克难、不达目的、绝不收兵的决心。接下来这一个月,大家不分节假日、也不分上下班,按比996更紧张的节奏在工作。经过大家大量的实验和分析,并在关键场景上添加探测和判断条件,杨小娟精确推断出是由于某个队列头尾指针跳变引发同步异常。但我们的软件代码中,对指针的更新都是步进式加1处理,不会有跳变更改,会是什么原因导致的指针跳变呢?到了3月中旬的一天晚上,针对这个指针跳变问题,大家一起工作讨论到深夜,朱琛通过观察多次的错误现场记录,提出了一个猜想,有可能是对指针更新采用了非对齐访存,破坏了原子性引起。第二天一早,请来负责编译器的徐成华和负责cpu结构设计的吴瑞阳来一起分析,判断确实因非对齐访存引起。于是修改代码,加强原子性处理,经过严格的测试,措施有效,虚拟机网络稳定,断网现象不再出现。
第七关 openstack云环境。在完成断网问题处理后,其他方面的工作也都进展顺利。李雪峰发挥自己在acpi、功耗管理方面的特长,快速完成了动态加减核的功能。杨小娟经过3个月的工作,在pci、中断、hypercall等模块中实现了对虚拟机迁移的支持,顺利完成了虚拟机动态迁移的功能开发。刘学高效完成了虚拟机uefi开发,解决了大量外设驱动在虚拟机上的适配问题,通过性能优化显著改善了具体应用场景的用户体验。王洪亮解决虚拟网络的功能适配等问题。研究生吕晨解决了libvirt等模块中的一些功能问题,完成虚拟机balloon驱动的功能验证。田延辉和汪雷一起完成了复杂的openstack环境在龙芯平台上的搭建和验证,可以进行规模化的应用部署。李星2019年春节时也放弃了休息,在家里完成了将kvm开发分支向内核主干的迁移工作。马中征和南雄超完成了kvm自动化测试环境的构建,极大提高了测试效率。研发组和刘钟莹负责的测试组紧密配合,解决了大量虚拟机产品化的问题,最终确认虚拟机系统功能完备,具备了产品发布条件,并在2019年4月正式对外发布。
回顾这两年多来的虚拟机研发工作,复杂艰辛、攻坚克难的研发过程体现出项目团队不屈的意志品质,大家的忘我付出更令我极为感动。李星顾不上照顾那段时间生病的家人,经常吃住都在公司;杨小娟家里孩子很小,每天都很晚才回家,孩子只能长期扔给老家老人在带;朱琛老婆孩子都在外地,本来都提前买好了假日回家探亲的车票,因为项目原因毫不犹豫地退掉了;王洪虎、南雄超、马中征等经常通宵达旦,就是为了第二天一早,测试组能够拿到最新版本进行测试;刘学、毛碧波、田延辉等放弃了很多休息时间,一同加入到攻关组,不辞辛劳、不计得失,主动承担解决各种突发和临时问题的任务。我也经常因晚上工作太晚,好几天不回家,于是买了一个气垫床,晚上就在办公室里睡了。
天道酬勤,努力和辛勤付出没有白费。随着龙芯kvm虚拟机产品的正式发布,龙芯云应用生态将进入蓬勃发展的产品规模应用期。目前大量云厂商等乐鱼app下载的合作伙伴正基于龙芯kvm虚拟机开发云计算系统,满足对国产cpu云计算环境的迫切需求。
kvm虚拟机的成功研发是龙芯核心文化理念强大生命力的一次生动展示。正是多年来坚持自主研发道路所锤炼出的奋斗精神、所积累下的技术底蕴,让龙芯团队在面对高复杂系统研发的艰难险阻时,能一次次攻坚克难、砥砺奋进。“坚持自主创新、掌握核心技术”,龙芯将在产业化道路上乘风破浪,敦行致远。(本文作者为龙芯中科技术有限公司副总裁高翔)
kvm虚拟机的研发跨cpu芯片、操作系统内核、云计算等多个复杂技术领域,涵盖了cpu芯片的虚拟化设计、操作系统内核的系统级虚拟化支持、虚拟机模拟执行环境、云计算应用支撑环境等众多核心技术。从国际上看,仅有intel、arm等几家国外公司掌握了“从芯片到系统”的完整kvm虚拟机核心研发技术,这也导致虽然中国的云计算产业在应用规模等指标上已经达到国际先进水平,然而在虚拟机这一关键核心技术上,国内云厂商无一例外地深度依赖国外虚拟机产品和技术。龙芯kvm虚拟机系统的发布对完善国产cpu技术生态、推动云计算产业健康发展、培养云计算核心技术团队等方面都有着重要意义。
历史积累。龙芯虚拟化设计可以追溯到十多年前的龙芯2号研制时期,我们需要一款能够快速进行操作系统调试的虚拟验证环境。当时是2003年,后来著名的qemu模拟器还没有面世,我的师兄张福新就找来了一个90年代斯坦福大学发布的simos模拟器。斯坦福大学是mips cpu的诞生地,这个simos天生支持mips指令集,通过一些功能级的开发改造,我们很快就把龙芯2号的linux系统在simos上跑了起来。这个simos可以算是最早的龙芯虚拟机系统。我在读博士期间的2004年到2007年,又把龙芯2号的微结构时序模型和龙芯3号的多核架构支持加入到simos中。这个模拟器被用于龙芯cpu微结构设计、性能分析、操作系统开发和硅后验证,发挥了重要作用。后来2007年到2013年,龙芯系统组的历届博士生刘奇、蔡万伟、台运方等基于龙芯系统和模拟器环境,在cpu虚拟化、内存虚拟化和io虚拟化等方面进行了探索性研究,期间的论文和专利成果对龙芯kvm虚拟机的产品研制产生了积极影响。
cpu的硬件虚拟化支持。到了2013年,云计算应用发展使得对国产cpu虚拟化的需求日益强烈,龙芯公司决定在龙芯3a3000中首次加入对硬件虚拟化的支持。由于虚拟机的复杂性,为确保一次成功,公司总裁胡老师提出了“简化硬件和结构的复杂度,通过系统软硬件协同优化来提升效率”的虚拟化设计方针。从后来的项目发展来看,这一指导方针得到了充分贯彻并取得了预计效果。由于简化cpu硬件结构,3a3000的cpu硬件没有出现颠覆性的设计缺陷,cpu流片成功后就能研制和发布虚拟机。同时,软硬件协同优化的策略也给系统优化留下了空间。国内现在一讲创新就喜欢讲超越,然而在计算机领域,复杂的核心技术只能一步一步演进出来。一位国内同仁也跟我表达过类似观点,研发工程积累没有到达一定的程度前,盲目创新的结局只会是跌倒重来。
系统设计方案。从2017年初,龙芯3a3000完成了芯片产品化,开始启动kvm虚拟机软件系统的研制。考虑到kvm虚拟机的系统复杂性,我们采用了按“子系统-模块-场景-路径进行分解"的设计思路。即将整个kvm虚拟机分为cpu指令执行环境、存储管理、时钟、中断、io和配套环境等多个子系统,子系统按模块分解,模块按照场景进行组合,场景又按照执行路径进行具体化设计。当分解到路径时,设计和开发工作就已经非常明确了。由于子系统、模块、场景、路径之间是彼此高度耦合、相互交叉依赖,为了在设计阶段就将各种困难问题充分暴露,并针对各类复杂边界情况制定完备的设计方案,我们为每个场景或路径建立了项目管理平台redmine的对应任务,每个任务指定有一个硬件负责人和一个软件负责人,硬件负责人解释cpu的虚拟化行为,软件负责人则负责确定软件的设计方案。通过充分的讨论和沟通,逐步将虚拟化每个场景每个路径所应具备的功能确定下来,所需要考虑的边界条件和复杂的处理场景也都逐步清晰。后来统计,在长达五个月的设计过程中,总共建立了几十个任务,每个任务中包含的设计文档都经过多个版本,不断修正设计中的疏漏和不足之处。经过这“反复迭代、多轮修正”的设计过程,项目组对虚拟化系统有了全面和深入的把握,对其中的风险和问题进行了充分的评估,设计方案的完备度得到一致确认,可以进入到编码开发阶段。
编码与开发。谋定而后动,由于有前期充分的设计准备,编码开发工作变得如同普通的应用软件编程。大约两个月时间,基本的虚拟化支持代码开发完毕,可以进入调试和验证阶段。这时,我们采用了直接启动linux系统的联调方案,跳过了单元测试的环节,这里边的考虑有三。一是kvm的单元测试环境移植和搭建需要耗费时间和精力,而目前阶段我们应该尽快的迭代出产品;二是因为我们团队在内核方面有很深的积累,直接启动linux进行虚拟机调试,即便在内核层面出现复杂问题,按我们的积累和经验也能hold住;三是启动linux系统可以直接对接虚拟化场景,测试会更加具有针对性和复杂性。按照”虚拟机启动到哪里,验证和测试工作就跟进到哪里”的实施策略,项目进展迅速,期间解决了一些硬件bug和编码实现中的问题,到2018年初,我们已经可以完成虚拟机上linux系统启动,但是就产品而言,整个项目最艰难的时刻还远远未到,后面还有七个难关等着我们。
第一关 解决guest态漏执行问题。在2018年春节之后,我们遇到了一个偶发的系统故障,经常是测试一两天才冒出一个sigbus异常,错误现场留给我们的线索信息极少。大约有一个月左右的时间,我们的工作陷入了僵局。在我近二十年的系统研发工作中,经常遇到各种复杂的系统问题。问题经历多了,喜欢将解决复杂系统问题和警察破案相比较。我非常欣赏一位优秀刑警总结的破案经验,“破案时不要简单根据已有线索进行推断,而是要根据大胆的假定寻找新的线索”。程序员找系统bug和警察破案的工作是相似的。出现系统bug时,现场的信息和线索非常有限,如果只根据有限的线索进行逻辑推断,工作就会进入死胡同。此时,我们根据sigbus现场出现的有限信息,大胆地提出一个假定,即问题源于cpu在虚拟化模式下漏了一部分指令到普通模式下执行。在这个假设前提下,张爽爽和李星在内核中设计了相应的实验方案,一步一步找到新的线索,逐步验证了我们的猜想。最终线索聚焦到一个很小的执行场景,在负责cpu结构设计的吴瑞阳帮助下,确定问题机理是虚拟cpu在特定场景下有两拍的窗口间隙处于竞争不稳态,需要软件对执行模式进行控制。花了前后2个多月时间,解决完这个问题后,spec cpu2006这样的大型测试软件都可以正常运行通过。
第二关 解决云桌面界面卡顿。进入2018年的夏天,外界用户对龙芯虚拟化的支持已日益迫切。那段时间每周我们都接到大量对龙芯kvm虚拟机的咨询、催促、探寻合作的电话和邮件。通过访问合作的云厂商,我们了解到用户希望采用虚拟机云桌面(vdi)的需求。针对这一要求,我们完成了云桌面环境关键组件spice协议和qxl图形驱动的适配和优化,可以启动云桌面环境进行日常办公和娱乐,但在系统压力测试中,却又出现了一两天才偶发的界面卡顿问题。这个卡顿问题跟spice/qxl组件相关,包括内核qxl驱动、virtio驱动,x系统的qxl用户态驱动,remote-viewer等软件和模块,据我们统计,涉及到高达20多万行的源代码。我们需要在短时间内吃透这20多万行从未摸过的代码,并解决卡顿问题,这对项目团队是一个巨大的考验。好在龙芯系统研发部虽然规模不大,但各方面的人才储备比较全面,特别是我们有国内最好的图形驱动团队。虽然spice/qxl是一个我们未曾研究过的虚拟化图形驱动,但我们有过多款龙芯集显gpu图形驱动的开发经验。在技术原理上,qxl跟集显gpu是相通的。于是从操作系统图形组临时调来王洪虎和朱琛进行攻关,他俩很快就进入了状态。经过一个月的代码分析,我们就掌握了qxl的系统架构并摸清了问题线索,根据界面卡顿的现场反向分析,稳步推进,最终确定到卡顿原因为在某个复杂场景下spice协议传输中丢失了一次数据包。机理清楚后,解决bug就顺理成章,云桌面环境的卡顿现象完全消失。
第三关 解决偶发的系统崩溃。解决云桌面卡顿后,我们将kvm虚拟机交给了测试组进行更大规模和压力的系统测试,随之发现了偶发系统崩溃或者死机。从事系统研发的都知道,系统级的错误传播链极长,涉及到的软件源码量可达到上亿行之多,特别是排查错误时还需要经常进入自己不熟悉的领域,例如内核专家往往不甚了解systemd的运行机理,解决这类偶发的系统错误是最头疼的。经过长达两个月对错误现场的反复实验和分析,到了2018年9月的时候,我们推测是tlb的处理时发生了异常,导致访存错误。但由于错误出现时经过了多次传播,错误现场的线索极其有限,我们需要设计一个当错误发生时能够精确推断出错误机理的测试用例。这时我想到了lmbench测试集中有个测量内存延迟的用例,这个用例中相邻访存指令的数据结果是紧密依赖的,当出现错误时,可以立刻判断出错误的上一级来源。果然,用这个用例测试1个小时就能规律复现一次错误,确实是某次load操作时取到了一个错误的数据,但又怎么继续判断这个错误数据的来源呢?李星提出一个方案,将测试程序地址链接到一个特殊区域,这样可以很准确的用ejtag断住错误现场。断住错误现场是一个很重要的突破,没有现场就只能进行缺乏直接依据的猜测,而有了断点现场,工作就变成了“通过查勘错误现场进行有根有据的分析”。随后我们和负责cpu设计的汪文祥和吴瑞阳一起分析错误现场,反复查验tlb中的数据,对比错误程序的反汇编,最终确认错误来源于cpu在流水线切换时采用了错误的地址进行了访存。随后我们对流水线的切换模式进行了控制,这一偶发的系统崩溃问题经过前后近三个月的攻关,得到了机理清楚的彻底解决。
第四关 解决时钟子系统故障。随着测试工作的进一步深入,在2018年9月又出现了系统的rcu报警。经过分析排查,确认rcu故障不是第一错误现场,而是因为虚拟机的时钟中断偶尔间隔过长诱发。在虚拟机发生中断、迁移、异常、暂停等行为时,需要对虚拟机的时钟进行校准和补偿。由于进出虚拟机模式的时钟校准、补偿和管理系统异常复杂,我们自然而然的把主攻方向对准了虚拟机时钟补偿和校准系统,猜测可能是这里出了问题。而虚拟机的时钟系统调试又是一个特殊困难的挑战,因为常规的断点调试等手段本身会导致虚拟机时钟子系统异常,这样错误的浮现几率、现象和触发条件都会发生变化。经过1个月的攻关,我们把整个时钟补偿和校准系统捋了个透,发现并解决了一些时钟子系统的其他问题,但这些跟时钟中断间隔过长问题无关,工作暂时陷入了谜团。此时,龙芯组研究生王俊儒提出一个设想,可能是在处理特殊异常中更新cause寄存器时丢失了时钟中断,这个错误机理清晰明了,但却恰恰在我们主攻方向以外被忽视的部分。果然是山重水复疑无路,柳暗花明又一村。解决完这个问题之后,系统的可用性上了一个大台阶。
第五关 tlb性能优化。在系统级测试工作开展的同时,性能分析工作也在同步进行。针对spec cpu2000这样的典型测试集,我们发现个别程序的虚拟化性能效率不到30%。经过深入分析,判断是因为龙芯3a3000采用的单级tlb模式引起,在特殊应用模式下,tlb处理效率很低。根据这个性能机理,研究生王俊儒和邓向设计了一个软件优化方案大幅度提升了这类应用的性能。新加入龙芯的毛碧波,有多年的产品研发经验,进一步完善了这个设计,并解决实现中的一些关键bug。到了2018年年底,在龙芯3a3000虚拟机上,spec cpu2000等大型应用的性能效率基本都提升到了95%以上。
第六关解决非原子操作引发的虚拟机断网。在解决前面几个攻关问题时,测试组反馈虚拟机偶发断网。起初我没有太在意,以为是测试环境ip冲突或者硬件不稳定故障引起。后来发现这个问题在多个场景下都有出现,应该是虚拟机通过virtio-net模块与外界网络通信过程中的逻辑问题。经过一个多月的初步工作,到了2019年2月都还没有明确的思路和线索,我意识到这又是一个重量级的复杂bug,常规的工作组织机制是难以奏效的,于是召集大家开了一次攻关动员会。我先做了思想动员:kvm虚拟机经过2年的研发,目前到了最关键的阶段,胜利就在眼前,也是对我们项目组决心、能力和作风的一次考验,这个阶段我们绝对不能松劲;项目组每个同事都表现出了昂扬的斗志,一致表达了攻坚克难、不达目的、绝不收兵的决心。接下来这一个月,大家不分节假日、也不分上下班,按比996更紧张的节奏在工作。经过大家大量的实验和分析,并在关键场景上添加探测和判断条件,杨小娟精确推断出是由于某个队列头尾指针跳变引发同步异常。但我们的软件代码中,对指针的更新都是步进式加1处理,不会有跳变更改,会是什么原因导致的指针跳变呢?到了3月中旬的一天晚上,针对这个指针跳变问题,大家一起工作讨论到深夜,朱琛通过观察多次的错误现场记录,提出了一个猜想,有可能是对指针更新采用了非对齐访存,破坏了原子性引起。第二天一早,请来负责编译器的徐成华和负责cpu结构设计的吴瑞阳来一起分析,判断确实因非对齐访存引起。于是修改代码,加强原子性处理,经过严格的测试,措施有效,虚拟机网络稳定,断网现象不再出现。
第七关 openstack云环境。在完成断网问题处理后,其他方面的工作也都进展顺利。李雪峰发挥自己在acpi、功耗管理方面的特长,快速完成了动态加减核的功能。杨小娟经过3个月的工作,在pci、中断、hypercall等模块中实现了对虚拟机迁移的支持,顺利完成了虚拟机动态迁移的功能开发。刘学高效完成了虚拟机uefi开发,解决了大量外设驱动在虚拟机上的适配问题,通过性能优化显著改善了具体应用场景的用户体验。王洪亮解决虚拟网络的功能适配等问题。研究生吕晨解决了libvirt等模块中的一些功能问题,完成虚拟机balloon驱动的功能验证。田延辉和汪雷一起完成了复杂的openstack环境在龙芯平台上的搭建和验证,可以进行规模化的应用部署。李星2019年春节时也放弃了休息,在家里完成了将kvm开发分支向内核主干的迁移工作。马中征和南雄超完成了kvm自动化测试环境的构建,极大提高了测试效率。研发组和刘钟莹负责的测试组紧密配合,解决了大量虚拟机产品化的问题,最终确认虚拟机系统功能完备,具备了产品发布条件,并在2019年4月正式对外发布。
回顾这两年多来的虚拟机研发工作,复杂艰辛、攻坚克难的研发过程体现出项目团队不屈的意志品质,大家的忘我付出更令我极为感动。李星顾不上照顾那段时间生病的家人,经常吃住都在公司;杨小娟家里孩子很小,每天都很晚才回家,孩子只能长期扔给老家老人在带;朱琛老婆孩子都在外地,本来都提前买好了假日回家探亲的车票,因为项目原因毫不犹豫地退掉了;王洪虎、南雄超、马中征等经常通宵达旦,就是为了第二天一早,测试组能够拿到最新版本进行测试;刘学、毛碧波、田延辉等放弃了很多休息时间,一同加入到攻关组,不辞辛劳、不计得失,主动承担解决各种突发和临时问题的任务。我也经常因晚上工作太晚,好几天不回家,于是买了一个气垫床,晚上就在办公室里睡了。
天道酬勤,努力和辛勤付出没有白费。随着龙芯kvm虚拟机产品的正式发布,龙芯云应用生态将进入蓬勃发展的产品规模应用期。目前大量云厂商等乐鱼app下载的合作伙伴正基于龙芯kvm虚拟机开发云计算系统,满足对国产cpu云计算环境的迫切需求。
kvm虚拟机的成功研发是龙芯核心文化理念强大生命力的一次生动展示。正是多年来坚持自主研发道路所锤炼出的奋斗精神、所积累下的技术底蕴,让龙芯团队在面对高复杂系统研发的艰难险阻时,能一次次攻坚克难、砥砺奋进。“坚持自主创新、掌握核心技术”,龙芯将在产业化道路上乘风破浪,敦行致远。(本文作者为龙芯中科技术有限公司副总裁高翔)