Qemu is VMM ( virtual machine monitor. That means QEMU helps to run your virtual machine. This can be a full visualization in software or a hardware assisted one( VT ). KVM (Kernel-based Virtual Machine) is a visualization infrastructure for the Linux kernel that turns linux into a hypervisor. KVM comes in form of a kernel module. QEMU can use this kernel module to avail the visualizationfunctionalists of processor. QEMU avails them thru ioctl calls to kernel.
I referred kvm-76 source code to make this doc. I picked up an older version to understand KVM better.
I have copy/pasted source code from kvm-76 to here and used C style syntax for better code flow understanding. Those who are familiar with C language can understand it better. I have colored functions to understand the nesting better
- BLACK , RED, ORANGE , GREEN, BLUE
main() {
layer_0 () {
layer_1 () {
layer_2 () {
layer_3()
layer_4()
/* main() function is in file qemu/vl.c */
main() {
/* If you have seen manual page of qemu, you might be aware of various
* types of machines that qemu can emulate. This can be selected using a
* command line option to qemu executable. All these different machine types
* are stored as QEMUMachine in the qemu source code. All these machines needs
* to be stored in a linked list. register_machine() routine does that job.
*/
register_machines();
/* if we have KVM defined & kvm is supported; Let us initialise KVM */
#if USE_KVM
kvm_qemu_init() {
/* kvm_init() function malloc memory for kvm_context_t structure. This
* structure important data structure like below.
* struct kvm_context {
* /* Filedescriptor to /dev/kvm */
* int fd;
* /* file descriptor to virtual machine */
* int vm_fd;
* /* file descriptor to no of vcpus */
* int vcpu_fd[MAX_VCPUS];
* struct kvm_run *run[MAX_VCPUS];
* /* Callbacks that KVM uses to emulate
* * various unvirtualizable functionality
* *
* struct kvm_callbacks *callbacks;
* }
*
*
* /dev/kvm device file is opened in read-write mode.
* /dev/kvm device node is created upon insmod of kvm kernel module.
* The file handle ( of /dev/kvm ) that opened in last step is
* assigned to fd member in kvm_context_t. kvm_context_t has got an
* interesting member called "callback" (which is of type
* structure "kvm_callbacks").
* This structure holds pointers to various functions that KVM will
* call them when it encounters something that cannot be virtualised,
* such as accessing hardware devices via MMIO or regular IO.
* This structure contains routines like (*inb)(),(*outb)(),
* (*mmio_read)(), (*halt)(), (*io_window)(),
* (*try_push_interrupts)(), (*post_kvm_run)(), (*pre_kvm_run)().
i * This structure is statically initialized and passed to vm_init()
* and the same is assigned to kvm->callbacks member.
*/
kvm_init( ) {
kvm_context_t kvm;
fd = open("/dev/kvm", O_RDWR);
kvm->fd = fd;
kvm->vm_fd = -1;
kvm->callbacks = callbacks;
kvm->opaque = opaque;
}
/* chapter 3 is dedicated to talk about kvm_callbacks. please refer
* that chapter for more info.
*/
/* We got handle to /dev/kvm in previous code snippet. we can
* create a VM thru ioctl call to this file handle. There will be
* a file handle for each vm created. The same is stored in vm_fd
* member of kvm_context
*/
kvm_qemu_create_context() {
kvm_create() {
kvm_create_vm() {
/* we will explain more on VM creation and running
* in next chapter. As you can see VM creation is thru
* an ioctl call to /dev/kvm.
*/
fd = ioctl(kvm_context->fd, KVM_CREATE_VM, 0);
kvm_context->vm_fd = fd;
}
}
}
/* We can specify "how much memory a VM machine should use" as
* a parameter to qemu executable. The same is allocated and stored in
* phy_ram_base. I did not plan to explore more on the ram
* allocation. Is anybody out there to help me ? i will add it then.
*/
phys_ram_base = qemu_alloc_physram(phys_ram_size);
/* QEMUMachine structure has a function called .init() .
* This is different for each machine type.
*
* Lets take the case of pc_machine.
* QEMUMachine pc_machine = {
* .name = "pc",
* .desc = "Standard PC",
* .init = pc_init_pci,
* .ram_require = VGA_RAM_SIZE + PC_MAX_BIOS_SIZE,
* };
* .init() routine is the one who actually loads os , bootloader etc.
*
*/
machine->init(ram_size, vga_ram_size, boot_devices, ds,
kernel_filename, kernel_cmdline, initrd_filename, cpu_model) {
pc_init_pci() {
pc_init1() {
/* allocate memory and register */
ram_addr = qemu_ram_alloc(0xa0000);
cpu_register_physical_memory(0, 0xa0000, ram_addr) {
kvm_register_phys_mem() {
/* KVM_SET_USER_MEMORY_REGION is covered
* little bit more in datail in
* in chapter 4
*/
r = ioctl(kvm->vm_fd,
KVM_SET_USER_MEMORY_REGION, &memory);
}
}
}
}
/* Load linux kernel image if we have specified qemu to load
* a linux image as a command line parameter to qemy
*/
load_linux(kernel_filename, initrd_filename, kernel_cmdline);
}
/* sleep for events */
main_loop() {
kvm_main_loop() {
while (1) {
main_loop_wait(1000);
}
}
}
}
No comments:
Post a Comment