Expand description
Lazy loader and pager for guest virtual machine.
Background
Lazy loading is a technique that delays resource allocations until the resource is required. Lazy paging in project 3 implements the principle of lazy loading, which involves delaying the reading from file and loading of guest OS’s memory (such as text section of guest OS) into the host machine until a specific physical page of the guest is required.
Lazy paging in project 3 enhances the performance of the initial booting process since there is no need to read and load all the pages guest OS at once. This approache also helps the reducing the memory usage of the guest OS by avoiding the allocation of memory which is not used
In KeV projects, we will launch as KeOS as a guest operting system for the simplicity.
The build.rs
automatically build the guest KeOS (gKeOS) from the guests/project3/
and build the file system from the rootfs/
with the compiled gKeOS.
KeOS’s file system is rough. It only supports file without grow. There is no more abstraction than file such as directory or symbolic link.
Executable and Linkage Format
The ELF (Executable and Linkable Format) is a file format for executable programs in Unix-based operating systems.
The ELF header contains information about the ELF metadata, type of file (executable, shared library, object file), the architecture (x86_64, ARM, …), the entry point (where execution should begin), and others. In summary, ELF header contains the following sections:
- e_type: Type of tile
- e_machine: Set of the machine instrutions (SPARC, x86_64, ARM, MIPS…)
- e_version: Version of the elf (default is 1)
- e_entry: Start entry of the program
- e_phoff: Start offset of the program header table
- e_phnum: Entry size of the program header …
The ELF Program header (PHDR) contains the information about the program’s memory segments (sections of memory allocated for different parts of the program), including their virtual address, physical address, file offsets, sizes, and access permissions. In summary, the Program header contains the following sections:
- p_type: Type of the program header
- p_offset: Offset in file
- p_vaddr: Virtual address to be loaded
- p_paddr: Physical address to be loaded
- p_filesz: Size on file
- p_memsz: Size in memory
- p_flags: Flags for Read, Write, Execute
The operating system (Hypervisor) loads and executes the program (Guest OS) by parsing the ELF format reading from a file. The operating system should parse the ELF headers to locate and load the program’s memory, setup the program’s execution environment, and begin executing the program from its entry point.
Tasks
Translate kernel entry into Physical Address
The initial step to enable the lazy pager is to parse the kernel and populate the KernelVmPager
struct.
Unlike the user level ELF program, kernel loading operates on physical address.
In this task, you must have to find the entry point of the kernel to be used for initial entry point for the guest kernel.
The physical address of the kernel entry point can be obtained by subtracting the virtual address of the Phdr
from the kernel entry address ELF::entry()
.
Load phdr to loader
The next step to have to implement is the [load_phdr
] to enable the registeration of loaders that map physicall address in the Phdr
to the pager.
The implementation requires reading from the kernel image file through kernel.peeker().file
starting from the specified page offset
to page offset + size. Page offset and the size can be obtained from the Phdr
.
See the File
for the apis to operate with the file system.
Load page to extended page table
Lastly, you have to implement [load_page
] that called on EPT violation.
[load_page
] maps a page to the extended page table with permission set to READ, WRITE, and EXECUTABLE.
You MUST consider the case that multiple cores trigger EPT violations on the same physical page.