tag:blogger.com,1999:blog-8304185770976201542024-09-02T01:41:58.884-07:00Avi Kivity's blogAn irregular diary of a kernel developerAvi Kivityhttp://www.blogger.com/profile/18164860902822919006noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-830418577097620154.post-36737909415521831112011-08-25T05:08:00.000-07:002011-08-25T05:42:30.557-07:00C, assembly, and securityLet's look at the innocent C statement:<div><pre> a = b + c;</pre><pre></pre><pre></pre>What could possible go wrong? Let us list the ways:</div><div><ol><li>a, b, or c are the not the variables we want</li><li>We specified addition, but we wanted something else</li><li>The addition operation overflows</li><li>a and b are unsigned, while c is signed and negative; the result becomes unsigned</li><li>a has a smaller size than b or c; the assignment operation overflows</li><li>a is signed while b or c are unsigned; a becomes negative while b+c are positive</li><li>a is unsigned, while b and c are signed; again we have an overflow</li><li>We used the wrong indentation level and people are unhappy about it</li></ol>We can't expect the language to prevent all of these errors, but can we make C safer by trapping some of them at least during runtime? Turns out we can't do that without sacrificing performance:</div><div> <br /></div><div><ul><li>to handle (3), we need trapping signed addition and trapping unsigned addition instructions</li><li>to handle (4), we need a mixed signedness trapping add</li><li>to handle (5), we need a trapping store unsigned and trapping store signed instructions, which check that the value in the register fits into the memory location specified</li><li>ditto with (6) and (7)</li></ul>these (and similar) issues show up regularly in security vulnerabilities; it's hard to fix them because the necessary processor instructions are not there. We could emulate them by using sequences of existing instructions, but that would bloat the code and hurt performance; since performance is something that can be benchmarked but security is not, we end up with exploitable code.</div><div> <br /></div><div>So why are those instructions missing? In the 70's and 80's when the industry was ramping up performance was a much greater concern than security. Code was smaller and easier to audit; CPU cycles were longer and therefore more important to conserve; networks were small and private; truly malicious attacks were rare.</div><div> <br /></div><div>An unvirtuous cycle followed: C tried to make the most of exising processors, so its semantics mimic the instruction set of those days. It then became wildly successful, so processors were optimized for running C code; naturally they implemented or optimized instructions which directly translated to C concepts. This made C even more popular.</div><div> <br /></div><div>A pair of examples from the x86 world are the INTO and BOUND instructions. INTO (INTerrupt on Overflow) can follow an addition or subtraction instruction, effectively turning it into a trapping signed instruction. BOUND performs an array subscript bounds checking, trapping if the index is out of bounds. But the first implementations were rarely used, so they were not optimized in later iterations of the processor. Finally, the 64-bit extensions to the x86 instruction set removed those two instructions for good.</div><div> <br /></div><div> <br /></div>Avi Kivityhttp://www.blogger.com/profile/18164860902822919006noreply@blogger.com2tag:blogger.com,1999:blog-830418577097620154.post-81155810376027514092009-09-06T12:14:00.000-07:002009-09-06T13:11:12.569-07:00Nested vmx support coming to kvmAlmost exactly a year ago I <a href="http://avikivity.blogspot.com/2008/09/nested-svm-virtualization-for-kvm.html">reported</a> on nested svm for kvm - a way to run hypervisors as kvm guests, on AMD hosts. I'm happy to follow up with the corresponding feature for Intel hosts - nested vmx.<br /><br />Unlike the nested svm patchset, which was relatively simple, nested vmx is relatively complex. This is due to several reasons:<br /><br /><ul><li>While svm uses a memory region to communicate between hypervisor and processor, vmx uses special instructions -- VMREAD and VMWRITE. kvm must trap and emulate the effect of these instructions, instead of allowing the guest to read and write as it pleases.</li><li>vmx is significantly more complex than svm: vmx uses 144 fields for hypervisor-to-processor communications, while svm gets along with just 91. All of those fields have to be virtualized. Note that nested virtualization must reconcile the way kvm uses those fields with the way its guest (which is also a hypervisor) uses those fields; this causes complexity to increase even more.<br /></li><li>The nested vmx patchset implements support for Extended Page Tables (EPT) in the guest hypervisor, in addition to existing support in the host. This means that kvm must now support guest pagetables in the 32-bit format, 64-bit format, and now the EPT format.</li></ul><br />Support for EPT in the guest deserves special mention, since it is critical for obtaining reasonable performance. Without nested EPT, the guest hypervisor will have to trap writes to guest page tables and context switches. The the guest hypervisor has to service those traps - by issuing the VMREAD and VMWRITE to communicate with the processor. Since those instructions must trap to kvm, any trap taken by the guest is multiplied by quite a large factor into kvm traps.<br /><br />So how does nested EPT work?<br /><br />Without nesting, EPT provides for two levels of address translation:<br /><ol><li> The first level is managed by the guest, and translates <span style="font-style: italic;">guest virtual addresses</span> (gva) to <span style="font-style: italic;">guest physical addresses</span> (gpa).</li><li>The second address translation level translates <span style="font-style: italic;">guest physical addresses</span> into <span style="font-style: italic;">host physical adresses </span>(hpa). This second level is managed by the host (kvm).</li></ol><br />When nesting is introduced, we now have three levels of address translation:<br /><ol><li>Nested guest virtual address (ngva) to nested guest physical address (ngpa) (managed by the nested guest)<br /></li><li>Nested guest physical address (ngpa) to guest physical address (gpa) (managed by the guest hypervisor)<br /></li><li>Guest physical address (gpa) to host physical address (hpa) (managed by the host - kvm)<br /></li></ol>Given that the hardware only supports two levels of address translation, we need to invoke software wizardry. Fortunately, we already have code in kvm that can fold two levels of address translation into one - the shadow mmu.<br /><br />The shadow mmu, which is used when EPT or NPT are not available, folds the gva→gpa→hpa translation into a single gva→hpa translation which is supported by hardware. We can reuse this code to fold the ngpa→gpa→hpa translation into a single ngpa→hpa. Since the hardware supports two levels, it will happily translate ngva→ngpa→hpa.<br /><br />But what about performance? Weren't NPT and EPT introduced to solve performance problems with the shadow mmu? Shadow mmu performance depends heavily on the rate of change of the two translation levels folded together. Virtual address translations (gva→gpa or ngva→ngpa) do change very frequently, but physical address translations (ngpa→gpa or gpa→hpa) change only rarely, usually in response to a guest starting up or swapping activity. So, while the code is complex and relatively expensive, it will only be invoked rarely.<br /><br />To summarize, nested vmx looks to be one of the most complicated features in kvm, especially if we wish to maintain reasonable performance. It is expected that it will take Orit Wasserman and the rest of the IBM team some time to mature this code, but once this work is complete, kvm users will be able to enjoy another unique kvm feature.Avi Kivityhttp://www.blogger.com/profile/18164860902822919006noreply@blogger.com6tag:blogger.com,1999:blog-830418577097620154.post-42676808450160581672008-12-24T14:19:00.000-08:002008-12-24T14:56:32.692-08:00kvm userspace merging into upstream qemuRecently, <a href="http://blog.codemonkey.ws">Anthony Liguori</a>, one of the qemu maintainers has included kvm support into stock <a href="http://bellard.org/qemu/">Qemu</a>. This is tremendously important.<br /><br />Why? you might ask. It has to do with how software <a href="http://en.wikipedia.org/wiki/Fork_(software_development)">fork</a>s are managed.<br /><br />When a software project is forked, there are two ways to go about it. One can add new features, <a href="http://en.wikipedia.org/wiki/Code_refactoring">restructuring</a> code along the way so that the new code fits in snugly. This allows you to easily make large changes, but has the side effect of diverging from the original code. Over time, it is no longer possible (or at least very difficult) to incorporate fixes and new features that evolved in the original code, since the two code bases are wildly different.<br /><br />An alternative strategy is to add the new features in a way that makes as little impact as possible on the original code. This allows updating from the origin to pick up fixes and new features relatively frequently. The downside is that we become severely limited in the kind of changes we can make to our copy of Qemu without diverging too much.<br /><br />We have mostly followed the second strategy. Adaptations to qemu were as small as possible, and we have "encouraged" non-kvm-specific changes to be contributed directly to qemu upstream. This kept the amount and scope of local modifications at a minimum.<br /><br />But now that kvm has been merged, it is possible to make larger modifications to qemu in order to make it fit virtualization roles better. <a href="http://lwn.net/Articles/223839/">Live migration</a> and <a href="http://lwn.net/Articles/239238/">virtio</a> have already been merged. Device and cpu hotplug are on the queue. Deeper changes, like modifying how qemu manages memory and performs DMA, are pending. And, of course, kvm integration is much cleaner and more maintainable.<br /><br />There is of course some friction involved. The new implementation has a few bugs and several missing features (for example, support for true SMP and Windows patching), so it will be rough for a while. However, once the transition is complete, kvm and qemu will be able to evolve at a faster pace, to the benefit of both.Avi Kivityhttp://www.blogger.com/profile/18164860902822919006noreply@blogger.com0tag:blogger.com,1999:blog-830418577097620154.post-33104077083525506172008-09-02T02:16:00.000-07:002009-09-06T13:11:55.716-07:00Nested svm virtualization for kvmYesterday I found a nice <a href="http://thread.gmane.org/gmane.comp.emulators.kvm.devel/21119">surprise</a> in my inbox - a post, by Alex Graf, adding support for virtualizing AMD's SVM instruction set when running KVM on AMD SVM.<br /><br />What does this mean? up until now, when kvm virtualizes a processor, the guest sees a cpu that is similar to the host processor, but <i>does not have virtualization extensions</i>. This means that you cannot run a hypervisor that needs these virtualization extensions within a guest (you can still run hypervisors that do not rely on these extensions, such as VMware, but with lower performance). With the new patches, the virtualized cpu does include the virtualization extensions; this means the guest can run a hypervisor, including kvm, and have its own guests.<br /><br />There are two uses that immediately spring to mind: debugging hypervisors and embedded hypervisors. Obviously having svm enabled in a guest means that one can debug a hypervisor in a guest, which is a lot easier that debugging on bare metal. The other use is to have a hypervisor running in the firmware at all times; up until now this meant you couldn't run another hypervisor on such a machine. With nested virtualization, you can.<br /><br />The reason the post surprised me was the relative simplicity in which nested virtualization was implemented: less than a thousand lines of code. This is due to the clever design of the svm instruction set, and the ingenuity of the implementers (Alex Graf and Jörg Rödel) in exploiting the instruction set and meshing the implementation so well with the existing kvm code.Avi Kivityhttp://www.blogger.com/profile/18164860902822919006noreply@blogger.com4tag:blogger.com,1999:blog-830418577097620154.post-47396298297249122752008-05-13T11:04:00.001-07:002008-05-13T11:25:15.751-07:00How kvm does securityLike most software, kvm does security in layers.<br /><br />At the inner privilege layer is the kvm module. This code interacts directly with the guest and also has full access to the machine. If breached, a guest could potentially take over the host and any virtual machines running on it.<br /><br />The outer privilege layer is qemu. While it is much larger than the kvm kernel module, it is relatively easy to contain a qemu breach so that it doesn't affect the rest of the host:<br /><ul><li>The kernel already protects itself from non-root user processes; if you run kvm as an unprivileged user, the kernel will not let you harm it.</li><li>Processes that run as different users are also restricted; so if you run each guest under a distinct user ID, more isolation is gained.</li><li>Mandatory access control systems such as <a href="http://www.nsa.gov/selinux/">selinux</a> can be used to further restrict the damage that a breached qemu can inflict.<br /></li></ul>What are the most vulnerable submodules in kvm?<br /><ul><li>Probably the most critical piece is the x86 instruction emulator, which is invoked whenever the guest accesses I/O registers or the its page tables. This code weighs in at about 2000 lines.</li><li>If the kvm mmu can be tricked into mapping an arbitrary host page into guest memory, then the guest can potentially insert its own code into the kernel. The mmu is about 3000 lines in length, but it has been the subject of endless inspection, so it is likely a very difficult target.<br /></li></ul>So again the "reuse Linux" theme repeats: kvm leverages the existing Linux kernel both to reduce the attack surface presented to malicious guests, and also to contain the damage should a security breach occur.Avi Kivityhttp://www.blogger.com/profile/18164860902822919006noreply@blogger.com0tag:blogger.com,1999:blog-830418577097620154.post-76379602759137884722008-05-02T08:14:00.000-07:002008-05-02T08:40:04.414-07:00Comparing code sizeStarting with Linux 2.6.26, kvm supports four different machine architectures: x86, s390 (System Z, or mainframes), ia64 (Intel's Itanium), and embedded PowerPC processors. It is interesting to compare the size of the code supporting each architecture:<br /><br /><table><thead><tr><td><b>arch</b></td><td><b>lines</b></td></tr></thead><tbody><tr><td>x86</td><td>17442</td></tr><tr><td>ia64</td><td>8154</td></tr><tr><td>s390</td><td>2509</td></tr><tr><td>ppc</td><td>2229</td></tr></tbody></table><br /><br />x86 is old and crufty; it supports three instruction sets and four paging modes; its long and successful history means that it needs the most kvm support code. There are two different virtualization extensions that kvm supports on x86 (Intel's VT and AMD's SVM). It is also the architecture that has been supported by kvm for the longest time. It is no surprise that it leads the pack by a significant amount.<br /><br />ia64 is a newer architecture, but a quite complex one. The mechanism by which is supports virtualization, with a module loaded into the host kernel and a second module loaded into the guest address space, also adds complexity. So it comes in second, though far behind x86.<br /><br />s390 is older (and probably far cruftier) than x86. But on the other hand, its hardware virtualization support is so mature and complete that a complete hypervisor fits in a fraction of the lines required for x86. Indeed, it will take a while until x86 can support 64-way guests.<br /><br />ppc 44x, the embedded PowerPC variant targeted by kvm, has a simple software-managed tlb model, and the regular instruction set encoding favored by RISC processors, so it gets by with just a seventh of the amount of code required by x86.<br /><br />As we add more features, kvm code size will continue to grow slowly, but the relative comparison will no doubt remain valid. And kvm will likely remain the smallest full virtualization solution available.Avi Kivityhttp://www.blogger.com/profile/18164860902822919006noreply@blogger.com0tag:blogger.com,1999:blog-830418577097620154.post-85373918033484822972008-04-27T12:37:00.000-07:002008-04-27T12:44:14.857-07:00KVM Forum 2008 Agenda postedThe near-final <a href="http://kforum.qumranet.com/KVMForum/agenda.php">agenda</a> for the KVM Forum 2008 has been posted! I'm pleased to see a well-rounded set of presentations, covering all aspects of kvm development.<br /><br />If you're interested in kvm development, and haven't already, make sure to <a href="http://kforum.qumranet.com/KVMForum/register_now.php">register</a> now.<br /><br /><br />See you all in Napa!Avi Kivityhttp://www.blogger.com/profile/18164860902822919006noreply@blogger.com0tag:blogger.com,1999:blog-830418577097620154.post-29586734169381470382008-04-25T03:03:00.000-07:002008-04-25T03:30:05.479-07:00I/O: Maintainability vs PerformanceI/O performance is of great importance to a hypervisor. I/O is also a huge maintenance burden, due to the large number of hardware devices that need to be supported, numerous I/O protocols, high availability options, and management for it all.<br /><br />VMware opted for the performance option, but putting the I/O stack in the hypervisor. Unfortunately the VMware kernel is proprietary, so that means VMware has to write and maintain the entire I/O stack. That means a slow development rate, and that your hardware may take a while to be supported.<br /><br />Xen took the maintainability route, by doing all I/O within a Linux guest, called "domain 0". By reusing Linux for I/O, the Xen maintainers don't have to write an entire I/O stack. Unfortunately, this eats away performance: every interrupt has to go through the Xen scheduler so that Xen can switch to domain 0, and everything has to go through an additional layer of mapping.<br /><br />Not that Xen solved the maintainability problem completely: the Xen domain 0 kernel is still stuck on the ancient Linux 2.6.18 release (whereas 2.6.25 is now available). These problems have led Fedora 9 to <a href="http://www.nabble.com/Re%3A-Plans-for-paravirt_ops-kernel-xen-p15885042.html">drop</a> support for hosting Xen guests, leaving kvm as the sole hypervisor.<br /><br />So how does kvm fare here? like VMware, I/O is done within the hypervisor context, so full performance is retained. Like Xen, it reuses the entire Linux I/O stack, so kvm users enjoy the latest drivers and I/O stack improvements. Who said you can't have your cake and eat it?Avi Kivityhttp://www.blogger.com/profile/18164860902822919006noreply@blogger.com4tag:blogger.com,1999:blog-830418577097620154.post-3234024184943499602008-04-15T07:37:00.000-07:002008-04-15T07:41:53.930-07:00Memory overcommit with kvmkvm supports (or rather, <i>will</i> support; this is work in progress) several ways of running guests with more memory that you have on the host:<br /><dl><br /><dt>Swapping</dt><dd>This is the classical way to support overcommit; the host picks some memory pages from one of the guests and writes them out to disk, freeing the memory for use. Should a guest require memory that has been swapped, the host reads it back from the disk.</dd><br /><dt>Ballooning</dt><dd>With ballooning, the guest and host cooperate on which page is evicted. It is the guest's responsibility to pick the page and swap it out if necessary.<br /></dd><br /><dt>Page sharing</dt><dd>The hypervisor looks for memory pages that have identical data; these pages are all merged into a single page, which is marked read only. If a guest writes to a shared page, it is unshared before granting the guest write access.</dd><br /><dt>Live migration</dt><dd>The hypervisor moves one or more guests to a different host, freeing the memory used by these guests</dd><br /></dl><br />Why does kvm need four ways of overcommitting memory? Each method provides different reliability/performance tradeoffs.<br /><br /><b>Ballooning</b> is fairly efficient since it relies on the guest to pick the memory to be evicted. Many times the guest can simply shrink its cache in order to free memory, which can have a very low guest impact. The problem with ballooning is that it relies on guest cooperation, which reduces its reliability.<br /><br /><b>Swapping</b> does not depend on the guest at all, so it is completely reliable from the host's point of view. However, the host has less knowledge than the guest about the guest's memory, so swapping is less performant than ballooning.<br /><br /><b>Page sharing</b> relies on the guest behavior indirectly. As long as guests run similar applications, the host will achieve a high share ratio. But if a guest starts running new applications, the share ratio will decrease and free memory in the host will drop.<br /><br /><b>Live migration</b> does not depend on the guest, but instead on the availablity of free memory on other hosts in the virtualization pool; if other hosts do not have free space, you cannot migrate to them. In addition, live migration takes time, which the host may not have when facing a memory shortage.<br /><br />So kvm uses a mixed strategy: page sharing and ballooning are used as the preferred methods for memory overcommit since they are efficient. Live migration is used for long-term balancing of memory requirements and resources. Swapping is used as a last resort in order to guarantee that services to not fail.Avi Kivityhttp://www.blogger.com/profile/18164860902822919006noreply@blogger.com17tag:blogger.com,1999:blog-830418577097620154.post-47997442478038069852008-04-10T07:47:00.000-07:002008-04-10T08:10:12.187-07:00Paravirtualization is deadWell, not all paravirtualization. I/O device virtualization is certainly the best way to get good I/O performance out of virtual machines, and paravirtualized clocks are still necessary to avoid clock-drift issues.<br /><br />But mmu paravirtualization, hacking your guest operating system's memory management to cooperate with the hypervisor, is going away. The combination of hardware paging (NPT/EPT) and large pages match or beat paravirtualization on most workloads. Talking to a hypervisor is simply more expensive than letting the hardware handle everything transparently, even before taking into account the costs introduced by paravirtualization, like slower system calls.<br /><br />The design of the kvm paravirtualized mmu reflects this planned obsolescence. Instead of an all or nothing approach, kvm paravirtualization is divided into a set of features which can be enabled or disabled independently. The guest picks the features it supports and starts using them.<br /><br />The trick is that when the host supports NPT or EPT, kvm does not expose the paravirtualized mmu to the guest; in turn the guest doesn't use these features, and receives the benefit of the more powerful hardware. All this is done transparently without any user intervention.Avi Kivityhttp://www.blogger.com/profile/18164860902822919006noreply@blogger.com1tag:blogger.com,1999:blog-830418577097620154.post-14136683972872540622008-03-28T11:41:00.000-07:002008-03-28T12:29:28.472-07:00True mythsThe appearance of kvm naturally provoked reactions from the competition, which are interesting in the way they imply some untruths while being 100% accurate:<br /><ul><br /><li><span style="font-weight:bold;">kvm is good for desktop</span> -- that is eminently true, by being integrated with Linux kvm inherits all the desktop and laptop goodies, like excellent power management, suspend/resume, good regular (non-virtual-machine) process performance, and driver integration.<br /><br>The implication, however, is that kvm is not suitable for server use. This is wrong: kvm also inherits from Linux its server qualities, including excellent scalability, advanced memory management, security, and I/O stack.<br /></li><br /><li><span style="font-weight:bold;">you need a bare metal hypervisor for server workloads</span> -- that is also true, without complete control of the hardware a hypervisor will be hopelessly inefficient.<br><br />Somehow the people who say this ignore the fact that kvm <i>is</i> a bare metal hypervisor, accessing the hardware directly. In fact kvm is much closer to the bare metal than Xen, which can only access I/O devices through a special guest, "dom0", which is definitely not running on bare metal.<br /></li><br /><li><b>A thin hypervisor gives better security</b> -- true again, the smaller your <a href="http://en.wikipedia.org/wiki/Trusted_computing_base">trusted computing base</a> is, the greater confidence you have in your hypervisor.<br><br />The same speakers then go on about how thin Xen is. But they seem to ignore that the entire I/O and management plane is in fact a Linux guest -- and that it is part of the trusted computing base. Now which is smaller, Linux, or Xen with a trusted Linux guest?<br /></li><br /></ul><br />Developers, of course, <a href="http://udrepper.livejournal.com/15795.html">realize</a> all of this immediately; but it will take some time and counter-marketing to repair the damage already done. Hence this article.Avi Kivityhttp://www.blogger.com/profile/18164860902822919006noreply@blogger.com4