Search This Blog

Showing posts with label virtualization. Show all posts
Showing posts with label virtualization. Show all posts

Thursday, October 4, 2012

Second Level Address Translation - EPT/NPT

This post is more or less to summarize what I have found out so that I can refer to it once I forget. (I know that I will forget this)

A few posts earlier I described how page table walk occurs and here let me briefly describe how that occurs with virtualization software such as Hyper-V. In this post. I will just describe the overall process without any debugger examples.

First of all, overall page walk with virtualization is similar to regular page table walk. Let me put out the regular page table walk diagram from the wiki page.



However, with virtualization things are a bit different. Keep in mind that whatever guest physical address that the OS thinks cannot be real physical address as hypervisor is the one that manipulates the real hardware. So what has to happen is another set of translations from the guest physical addresses to system physical addresses. Both Intel and AMD provides a solution to this address translation and they call these in two different names i.e. EPT and NPT but they are essentially the same thing.

So with guest physical addresses in our hand, we can traverse the similar data structures to obtain the system physical addresses. On Intel, these data structures are traversed via PML4 table - Page Directory Pointer table(PDPT) - Page Directory(PD) - Page Table(PT).

There are a couple of twists here to watch out though.

  • If bit 7 of the EPT PDPT entry is '1', the EPT PDPTE maps 1-Gbyte page. Otherwise, it maps to 2-Mbyte page.
  • For each entry of the table, we need to know the processor's physical-address width to obtain the physical address of the next table. 

We can get processor's address width by executing __cpuid with 0x80000008 in EAX and the the physical address width is returned in bits 7:0 of EAX. Well, that does not sound easy. Here is what I did. Just go to MSDN __cpuid page and copy the code and create a C++ source file and use that to obtain the value. On my machine, I got 36 so I know that my machine supports upto 36bit width.

So once we have the guest physical address and EPTP, it is just a matter of translating each address using the entry that we get to and the interpretation for each entry is subject to the tables given in chapter 28. VMX Support for Address Translation of Intel Manual.

In order to verify this page table walk, we need EPTP address and guest physical address but I have not found a way to obtain VMCS from the debugger easily. I will follow up on this if I find a way to obtain this pointer. But for now, everything is still in theory.

Friday, June 15, 2012

Network Virtualization with SR-IOV in simple terms

It's exciting time for Hyper-V. There are so many new features with Windows 8 Hyper-V that it is worth mentioning. One of interesting new feature is SR-IOV which stands for "Single-Root I/O Virtualization". This feature is to offload all the work done by CPU to network card. Previously, Host OS had to process all the incoming/outgoing network packets which means that it required lots of CPU time just to process which VM the packet belongs to. However, with SR-IOV we can avoid that overhead!

Again, this is another cool feature that hardware brings into the virtualization space. From high-level point of view what this does is that the network card itself has virtual functions that act like ports. For regular network card, we just see one physical port as in the picture below.
However, SR-IOV network card has implemented virtual ports associated with physical port. Therefore, when the VM starts up, we can assign these virtual ports to the VM and from then on the VM can directly talk to network card. This way we do not have to consume all the CPU to figure out which VM the network packet belongs to. Instead we can cut down all the overhead and directly connect to the network card. Following is a diagram that I borrowed from MSDN.


Before I conclude today's post, let me introduce one more terminology that is equally important to get this feature working properly. That is IOMMU / Intel VT-d. When these network card interacts with the rest of the system, it either uses interrupt or DMA to either read from or write to memory location. With these virtual functions talking directly to VMs, it is also required that we process interrupts and memory access properly. What does this mean? For instance, when the network card wants to read the data from memory location that belongs to the VM, it accesses the memory location as if that is real physical address. However, that address might not be the right address for the VM as we have to share the memory address among all the VMs. Therefore, we need to translate the memory address and this is done by IOMMU. This is very similar to page table walk to translate virtual address to physical address. Yet, this is for virtual machines. Likewise, we have to map interrupts from these network device to the appropriate CPU by finding out which virtual port the interrupt is associated with and forwards it to the appropriate CPU.

I copied the following diagram from wiki page. Hopefully the idea will make sense with the picture below.


In summary, SR-IOV enables to offload all the processing work from CPU with the help from both network card and CPU feature.
  • Virtual Ports/VIrtual Functions from SR-IOV network card
  • DMA/Interrupt remapping from CPU

Monday, May 28, 2012

Virtual Machine Extensions - second post

Earlier I described briefly how the current virtualization technology works. Today let me try to explain little bit further on the same topic.

I showed the diagram that I got from Intel manual and basically that shows how VMM/Hypervisor interacts with Guest OS. In summary, it uses several instructions such as VM Exit or VM Entry to move in and out of Guest OS. To a degree that is very similar to how system call works. In other words, on 64-bit machine when we execute 'syscall' instruction, it causes the change to kernel mode and the kernel knows which system service the user mode application requested because the system service number is passed via EAX register. In the similar fashion, when we execute VM Exit, that causes the change to VMM/Hypervisor mode and VMM/Hypervisor does what's necessary to provide the guest OS virtualized environment.

If we look at disassembly of NtReadFile from ntdll.dll, we can see that it is calling 'syscall' as follows.

0:013> u ntdll!ntreadfile
ntdll!NtReadFile:
000007fe`747d2e40 4c8bd1          mov     r10,rcx
000007fe`747d2e43 b804000000      mov     eax,4
000007fe`747d2e48 0f05            syscall

Then the natural question would be what about virtualization? Do we also generate similar code for VM Exit or VM Entry? The answer is 'No'. The way it works is somewhat different and you can find the detailed information in chapters 25-27 of Intel Software Developer Manual but let me briefly describe how that works here.

Basically we tell processors that VMM/Hypervisor wants to gain the control when the guest OS executes certain instruction. Or we specify that when the guest OS touches certain parts of memory, we want to obtain the control so that we can provide appropriate information to the guest OS.
For instance, we might want to control the time inside guest OS and the way OS may obtain the time information is via TSC. So for this we want to gain the control when the guest OS executes 'rdtsc' or 'rdtscp' instruction. So essentially there is a certain data structure called virtual-machine control structures that the processor uses when it executes instructions and all we need to do is that we program this data structure. Once we do that the mode will be changed to VMM/Hypervisor when the given instruction is executed on the guest OS. Similarly, when we gain the control, processor provides us information with regard to the reason why VM Exit occured and the guest addresses at the time it was exiting so that we can use those information. So essentially this makes things a lot easier to create virtualized environment compared to binary patching technology.

Next, let me briefly describe another hardware support for virtualization.
That's the support for memory address translation. If you think about it, we cannot really give guest OS to control entire memory as that could mean that the given guest OS can view pages belonging to other guest OSs. Hence, we will have to control guest OS memory access in VMM/Hypervisor. How do we do that? Earlier we did this by using some sort of software page table that was hidden from the guest OS. What does this mean? This means that when the application in guest OS attempts to read from the memory, that address has to be translated to physical address as the address the application uses is virtual address. However, in our case the physical address that the guest wants to use is actually fake physical address from VMM/Hypervisor's point of view. Hence, we needed a way to provide real hardware physical address so that the guest OS can access to the correct memory address. This additional translation was done in software and its technology is normally called 'shadow paging'. Obviously, keeping up with all the hidden page tables and execute translation caused more memory consumption and slow execution compared to native execution case. So the hardware vendor such as Intel or AMD came up with the hardware support for this so that these are done hardware behind the scene so that the software does not have to concern this translation task. This technology is called extended page table (EPT) from Intel and nested page table (NPT) from AMD.

Here is the diagram that I stole from one of Intel presentation slides:  Intel Virtualization Technology Roadmap and VT-d Support in Xen. I think the diagram does a great illustrating the point. As you can see, there is now new EPT base register that points to EPT page table


In addition, hardware vendor added the Virtual Processor Identifiers (VPIDs) so that we do not throw out the TLB cache for those that belong to other processors as it makes sense that we want to keep these cache mapping data to improve the overall performance.

So that's all for now and here is the summary of this post:

  • How to configure processor to gain control back when the guest OS executes certain instructions
  • Hardware support for hidden page table to translate guest physical to machine physical address
  • Keeping the address mapping data by using virtual processor id

I hope that this was useful to those who stop by my page. Thank you.