(特别提示:本人所有文章都是凭记忆书写,不保证准确、正确,请读者注意鉴别!)
初识KVM API 这篇文章介绍了KVM API,那有了这套API,能干点什么?这有点历史故事。KVM API印象里2009年或更早就出现了,但大家都局限于用它来做虚拟机。Josh Triplett在2015年9月有篇文章,介绍了KVM API之后专门讲了它的应用。我认为非常经典,引用如下(https://lwn.net/Articles/658511/):
Applications of the KVM API
Other than learning, debugging a virtual machine implementation, or as a party trick, why use /dev/kvm directly?
Virtual machines like qemu-kvm or kvmtool typically emulate the standard hardware of the target architecture; for instance, a standard x86 PC. While they can support other devices and virtio hardware, if you want to emulate a completely different type of system that shares little more than the instruction set architecture, you might want to implement a new VM instead. And even within an existing virtual machine implementation, authors of a new class of virtio hardware device will want a clear understanding of the KVM API.
Efforts like novm and kvmtool use the KVM API to construct a lightweight VM, dedicated to running Linux rather than an arbitrary OS. More recently, the Clear Containers project uses kvmtool to run containers using hardware virtualization.
Alternatively, a VM need not run an OS at all. A KVM-based VM could instead implement a hardware-assisted sandbox with no virtual hardware devices and no OS, providing arbitrary virtual "hardware" devices as the API between the sandbox and the sandboxing VM.
While running a full virtual machine remains the primary use case for hardware virtualization, we've seen many innovative uses of the KVM API recently, and we can certainly expect more in the future.
重点在倒数第二段:你要OS干什么?
在初始KVM API里,我们看到启动一个虚拟机,运行一段代码,非常直观、简单。有很多场景,如函数计算。用户的代码编译成KVM能跑的代码,拉起一个KVM就跑。这解决了函数计算的多个痛点:1)冷启动问题;2)成本问题。现在问题来了,KVM能拉起来就跑的代码该怎么写、编译呢?
Bare metal programming!
没错,我们写代码直接跑在KVM上,就是写操作系统。说到怎么实现一个操作系统,就不得不提一个著名的博客了:https://os.phil-opp.com/ 。这一系列文章讲明白了怎么从零实现操作系统。认真学习完,手就不慌了。
三个重要的概念:1)freestanding;2)booting;3)paging。我们直接针对KVM编程,目的不是实现一个完整的操作系统,而只是跑一段代码的话。上述三个概念都可以更简单地实现。
一:freestanding,可以使用rust,c,c++实现,最好选用rust。因为rust把core库从std库分离,因此rust freestanding编程有大量的高阶类,如String, VecQueue,甚至async/await。rust-vmm crate又把KVM API包装得很好,走过路过不要错过。
二:Phil的博客的第一版详细介绍了booting的过程,第二版估计是觉得booting太繁琐又很格式化,所以booting封装成了工具。直接针对KVM编程的话,booting该怎么做呢?其实非常简单了。正如我前面那篇博客的代码,可以直接通过KVM API完成booting的任务,即设置寄存器,把内核拷贝到内存,启动CPU。虚拟机或物理机的启动通常还有个CPU执行模式升级的过程,一般是从real到protected,再到long。使用KVM API,可以一步到位。
三:paging太复杂了。操作系统的复杂性,除了进程管理就是paging,而且进程管理里最复杂的部分也是内存方面的代码。认真学习完phil的博客就会发现,直接针对KVM编程,就选择最简单的identity mapping好了。更妙的是,这个mapping可以在启动之前完成。
https://rstforums.com/forum/topic/109893-note-learning-kvm-implement-your-own-linux-kernel/ 这篇文章详细介绍了,如何通过KVM API直接创建KVM虚机,进入Long mode,设置好页表。
以上资料都学明白了,就可以开始用KVM干活了。