diff --git a/VMM_Implementaion.md b/VMM_Implementaion.md new file mode 100644 index 0000000..e04c8a4 --- /dev/null +++ b/VMM_Implementaion.md @@ -0,0 +1,106 @@ +# [VMM Impl](../src/vmm/src/lib.rs) + +The `Vmm` is the main structure that holds all the VMM resources. It is responsible for the high level management of the VMM. It is also responsible for the communication with the API and the VMM action handlers. + +```rs +pub struct Vmm { + vm: KvmVm, + kernel_cfg: KernelConfig, + guest_memory: GuestMemoryMmap, + device_mgr: Arc>, + event_mgr: EventManager>>, + exit_handler: WrappedExitHandler, + #[cfg(target_arch = "aarch64")] + num_vcpus: u64, +} + +``` +- `vm` - The KVM VM object. It is created when the VMM starts. It is wrapped in a `KvmVm` object that provides a safe interface to the KVM API. The `KvmVm` object also holds a reference to the `exit_handler` object. The `exit_handler` is responsible for handling the VM exits. The `KvmVm` object is responsible for running the VM. +- `kernel_cfg` - The kernel configuration. It holds the kernel image, the kernel command line and the kernel start address. +- `guest_memory` - The guest memory object. It is created when the VMM starts. It is wrapped in a `GuestMemoryMmap` object that provides a safe interface to the guest memory. +- `device_mgr` - The device manager object. It is created when the VMM starts. It is responsible for managing the devices attached to the VMM. +- `event_mgr` - The event manager object. It is created when the VMM starts. It is responsible for managing the events that are generated by the devices attached to the VMM. +- `exit_handler` - The exit handler object. It is created when the VMM starts. It is responsible for handling the VM exits. +- `device_mgr` , `event_mgr` and `exit_handler` are wrapped in an `Arc` and a `Mutex` to allow for multiple threads to access them. +- `num_vcpus` - The number of vCPUs. It is used only on AArch64. + +```rs +impl Vmm { +} +``` +__ Overview of the `Vmm` functions __ + +The `Vmm` structure exposes the following public functions: +```rs + pub fn run(&mut self) -> Result<()> { + } +``` + This function will start the event manager loop and will block until the VMM is stopped. The VMM is stopped when the VM exits or when an error occurs. In the latter case, the error is logged and the VMM is stopped. + +```rs +let kernel_load_addr = self.compute_kernel_load_addr(&load_result)?; +``` + - Loads the kernel in the guest memory. This function returns a `Result` that contains the `GuestAddress` where the kernel was loaded. This address is used to configure the boot source. If the kernel was loaded successfully, the `Vmm` state is updated to `KernelConfigured`. If the kernel was not loaded successfully, the `Vmm` state is updated to `KernelLoadFailed`. + +```rs +self.vm.run(Some(kernel_load_addr)).map_err(Error::Vm)?; +``` +- Starts the VM. This function returns a `Result` that contains the `ExitReason` of the VM. This `ExitReason` is used to update the `Vmm` state. If the VM exits successfully, the `Vmm` state is updated to `VmRunning`. If the VM exits with an error, the `Vmm` state is updated to `VmError`. + +```rs +fn create_guest_memory(memory_config: &MemoryConfig) -> Result { + let mem_size = ((memory_config.size_mib as u64) << 20) as usize; + let mem_regions = Vmm::create_memory_regions(mem_size); + + // Create guest memory from regions. + + + GuestMemoryMmap::from_ranges(&mem_regions) + .map_err(|e| Error::Memory(MemoryError::VmMemory(e))) + } +``` +- Creates the guest memory. This function returns a `Result` that contains the `GuestMemoryMmap` object. Represents the entire physical memory of the guest by tracking all its memory regions. Each region is an instance of GuestRegionMmap, being backed by a mapping in the virtual address space of the calling process. The guest memory is created from a list of memory regions. The memory regions are created from the `MemoryConfig` object. The `MemoryConfig` object contains the size of the guest memory in MiB. The `MemoryConfig` object is created when the VMM starts. +- `mem_size` is the size of the guest memory in bytes. +- `mem_regions` is a vector of memory regions. Each memory region is defined by a base address and a size. + + +```rs + fn load_kernel(&mut self) { + let mut kernel_image + let zero_page_addr + ... + let kernel_load = match Elf::load{ + }; + ... + let mut bootparams + ... + let mut cmdline + ... + load_cmdline( + ) + ... + + + // Write the boot parameters in the zeropage. + // + LinuxBootConfigurator::write_bootparams::( + &BootParams::new::(&bootparams, zero_page_addr), + &self.guest_memory, + ) + .map_err(Error::BootConfigure)?; + + Ok(kernel_load) + } + +``` +- Loads the kernel in the guest memory. This function returns a `Result` that contains the `KernelLoaderResult` object. The `KernelLoaderResult` object contains the entry point of the kernel and the kernel image size. The `KernelLoaderResult` object is used to configure the boot source. +- `kernel_image` is the kernel image file. It is opened in read-only mode. If the kernel image file is not opened successfully, the `Vmm` state is updated to `KernelLoadFailed`. +- `zero_page_addr` is the address of the zero page. The zero page is a 4 KiB page that is mapped at the start of the guest physical address space. It is used to pass information to the kernel at boot time. The zero page is defined by the `ZEROPG_START` constant. +- `kernel_load` is the result of loading the kernel in the guest memory. The kernel is loaded using the `Elf` or `BzImage` loader. +- `cmdline` is the kernel command line. It is created from the `cmdline` field of the `KernelConfig` object. The `KernelConfig` object is created when the VMM starts. +- `load_cmdline` is the result of loading the kernel command line in the guest memory. The kernel command line is loaded at the end of the zero page. The kernel command line is defined by the `CMDLINE_OFFSET` constant. +- `LinuxBootConfigurator::write_bootparams` is the result of writing the boot parameters in the zero page. The boot parameters are written at the beginning of the zero page. The boot parameters are defined by the `BOOTPARAMS_OFFSET` constant. + + + +