Skip to content

Latest commit

 

History

16 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A hypervisor with a simple build-from-scratch guest kernel

make # or make debug for reg dumping
vmm/vmm.elf kernel/kernel.bin user/orw.elf /etc/os-release

VMM

KVM = VM implemented natively in Linux kernel.

A VM needs user memory region + virtual CPUs.

VMs created has private virtualized hardware e.g., network card, disk, graphic adapter, etc.

Steps: 1. Open KVM -> 2. Create a VM file descriptor -> 3. Set up memory for VM guest with ioctl -> 4. Create vCPU -> 5. Map memory for the vCPU -> 6. Put assembled code to user memory region -> 7. Set up vCPU registers -> 8. Run and handle exit reason

Kernel

The kernel in this repository is a single-process, x86-64 guest kernel designed to run inside a KVM-based virtual machine.

The kernel is not bare-metal, since it depends on the VMM to prepare memory, CPU state, host I/O interface.

The kernel initializes its space (page tables, perms) -> Map memory for user access at SP -> Copy args (program name, args, env vars) from the user program -> Execute the program (Load binary with the args on top of the kernel stack -> Guest kernel calls to VMM with syscalls)

Linker script loads executable code at address 0x0 (top of the kernel stack), and global/static variables at 0x3000.

How CPU distinguishes between kernel-mode and user-mode -> Controlled by description privilege level (rings). The CPU has two privilege contexts inside the VM: Guest kernel mode (ring 0) and guest user mode (ring 3).

When the user programs invokes system calls, they use SYSCALL to go to guest ring 0, after that the kernel uses SYSRETQ to enter ring 3.

Registers

We use the special register efer (collection of binary switches) to enable syscall/sysenter instruction.

// Switch on Long Mode Enable and Long Mode Activated with two 1 bits
sregs->efer = 0x500; // EFER_LME | EFER_LMA

// Switch on syscall as well with LME and LMA
//  0101 0000 0000
// |0000 0000 0001
// ----------------
//  0101 0000 0001 (last bit is syscall)
sregs->efer |= 0x1; // EFER_SCE

For syscalls, we register the syscall handler via setting special registers named MSR (Model Specific Registers). After the setup, we can invoke the syscall instruction and the program will jump to the handler we registered.

Page Directory Entry

Each PDE is a 64-bit value with control bits in lower positions + physical address in upper bits

[Physical Address] [Reserved] [Flags like PRESENT, RW, USER, DIRTY, etc.]
bits 63-12         bits 11-9   bits 8-0

Sorted bins

A storage structure to organize freed memory blocks using structured lists.

The heap manager categorizes free memory chunks to distinct bins based on their sizes.

Modes

Two modes (user vs. kernel) are distinguished by the dpl (ring)

Virtual addresses

A kernel virtual address points to a location inside the kernel address space. The addresses are used to access system data and hardware.

The page tables (MMU) translate the virtual addresses to the physical ones BEFORE the processor reads/writes memory.

ELF files

Standard binary format for executables, shared libs and object files on UNIX-like systems.

ELF header (overall structure) and Program header (How to load segment into memory)

ELF File Structure:
┌─────────────────────┐
│ Main Header (1)     │ ← Describes file overall
├─────────────────────┤
│ Program Header (1)  │ ← "Load this segment here"
│ Program Header (2)  │ ← "Load this segment here"
│ Program Header (3)  │ ← "Load this segment here"
├─────────────────────┤
│ Segment Data        │
│ (Code, Data, etc.)  │
└─────────────────────┘

↓ Loader reads program headers ↓

Memory Layout (Virtual Address Space):
┌──────────────────────┐
│ ... empty space ...  │
├──────────────────────┤
│ 0x400000: Segment 1  │ ← Placed here per Program Header 1
│ (code/data)          │
├──────────────────────┤
│ ... gap ...          │
├──────────────────────┤
│ 0x600000: Segment 2  │ ← Placed here per Program Header 2
│ (code/data)          │
├──────────────────────┤
│ ... more memory ...  │
└──────────────────────┘

ASLR

ASLR (Address Space Layout Randomization) is a security technique that randomizes where code, data, and stack are placed in a process's memory each time it runs.

About

Simple hypervisor with a minimal kernel

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages