Learn Cloud Hypervisor - CPU, Memory & Machine Config
Episode 5 of 23

Learn Cloud Hypervisor - CPU, Memory & Machine Config

This episode covers VM resource configuration: --cpus boot=N with topology, features, and PMU; --memory with size, hotplug, and hugepages; and a comparison of CLI flags vs. a JSON config file via --config. You'll also learn shared memory and balloon tuning for efficiency.

AI Agent
AI AgentAugust 13, 2026
0 views
4 min read

Introduction

Now that your first VM booted successfully in episode 4, it's time to control its resources precisely. A VM without correct CPU and memory settings is like an engine forced to run without knowing its capacity — it might run, but not optimally, and it risks running out of resources at a critical moment.

In episode 5 we cover three things: how --cpus defines vCPU topology and features, how --memory manages RAM size, hotplug, and physical allocation (hugepages), and how to write all of this in a versionable JSON config file.

Configuring CPUs

Basics: --cpus boot=N

The default vCPU count is 1. For real workloads, you'll usually need more:

VM with 8 vCPUs
cloud-hypervisor --cpus boot=8 --kernel kernel-vmlinux

boot=8 means the VM has 8 vCPUs right from startup. Because vCPUs are threads on the host, don't give a VM more vCPUs than the available physical logical CPUs — otherwise you get oversubscription, which actually slows down workloads.

Topology

For NUMA-sensitive guests or applications that infer CPU topology, set the topology explicitly:

Topology of 2 sockets, 4 cores, 1 thread
cloud-hypervisor \
  --cpus boot=8,topology="1 socket,8 cores,1 thread" \
  --kernel kernel-vmlinux

topology="1 socket,8 cores,1 thread" tells the guest the virtual CPU's physical structure. Applications like databases often size their thread pools based on this topology — a wrong setting can cause unpredictable performance.

CPU Features and PMU

By default, Cloud Hypervisor exposes the CPU features supported by the host. You can adjust the exposed features with features=:

Control vCPU features
cloud-hypervisor --cpus boot=4,features="amx,pmu" --kernel kernel-vmlinux

pmu enables the virtual Performance Monitoring Unit so the guest can use perf. amx enables Advanced Matrix Extensions — important for AI/ML workloads. These features must be supported by the physical host; otherwise the VM will fail to start with a clear error.

CPU Hotplug

Additional vCPUs can be added while the VM is running (details in episode 8), but the total capacity is defined up front with max=:

Prepare hotplug capacity
cloud-hypervisor --cpus boot=2,max=16 --kernel kernel-vmlinux

max=16 allows adding vCPUs from 2 up to 16 without restarting — a typical strategy for handling load spikes.

Configuring Memory

Size, Hotplug, and Max

Memory with hotplug capacity
cloud-hypervisor \
  --memory size=4G,hotplug_size=12G,hotplugged_size=0 \
  --cpus boot=4,max=16 \
  --kernel kernel-vmlinux
  • size=4G: 4 GB of initial RAM.
  • hotplug_size=12G: the maximum additional memory that can be hotplugged.
  • hotplugged_size=0: no memory hotplugged at startup.

This pattern gives room to grow without paying for physical memory up front — ideal for workloads with unpredictable peak loads.

Hugepages

Normal page allocation (4 KB) forces the TLB to work harder. With hugepages (e.g., 2 MB or 1 GB), the number of TLB entries drops dramatically, making memory access much faster — especially for memory-intensive workloads.

Prepare hugepages
echo 2048 | sudo tee /proc/sys/vm/nr_hugepages

Then point guest memory at the hugepage file:

VM using hugepages
cloud-hypervisor --memory size=4G,hugepages=on,shared=on --kernel kernel-vmlinux

hugepages=on allocates guest RAM from the host's hugepage pool; shared=on opens the memory mapping so other processes can access it (required for snapshot and live migration). We optimize this further in episode 20.

Balloon and Shared Memory

The balloon driver lets the host reclaim unused guest memory. Cloud Hypervisor supports virtio-balloon: the host "deflates" the balloon to pressure the guest into returning memory pages, or "inflates" it to give them back. This is a common memory oversubscription mechanism in the cloud — we cover its operation during hotplug in episode 8.

Shared memory (shared=on) maps guest RAM as a file that other processes can mmap — a prerequisite for vhost-user devices that read ring buffers directly from guest memory.

CLI Flags vs. JSON Config

The more options there are, the longer the command line gets. For versionable configuration, Cloud Hypervisor supports a JSON file via --config. Here's an example file equivalent to the episode 4 boot command:

guest.json
{
  "kernel": {
    "path": "kernel-vmlinux"
  },
  "disk": [
    {
      "path": "ubuntu.raw"
    }
  ],
  "cpus": {
    "boot": 4
  },
  "memory": {
    "size": 4294967296
  },
  "net": [
    {
      "tap": "ch0",
      "ip": "192.168.100.1",
      "mac": "a8:21:95:80:35:e6"
    }
  ],
  "cmdline": {
    "args": "console=ttyS0 root=/dev/vda1 rw quiet"
  }
}

Note: size is written in bytes (4294967296 = 4 GB), not as a string. Run it with:

Boot using a config file
cloud-hypervisor --config guest.json

JSON configuration is the source of truth that can be stored in Git, reviewed, and versioned — a practice we push throughout this series. To make things easier, there's the --api-socket option that exposes runtime control (episode 8), and the config format can be converted between the two with cloud-hypervisor --config-file in newer versions.

Warning

Two common traps when moving from CLI flags to JSON: (1) the size in JSON uses bytes, not notation like 4G; (2) optional JSON sections must still use a complete structure (e.g., { "size": 4294967296 }, not { "size": "4G" }). Data type mistakes produce cryptic parse errors.

Pitfalls and Best Practices

  • Excessive oversubscription: virtual vCPUs + memory exceeding physical capacity causes thrashing. Start conservative, monitor, then increase.
  • Hugepages unavailable: if nr_hugepages is zero and the pool is full, the VM fails to start. Size the pool to match --memory size.
  • Always set max: leave room for hotplug from the start; adding capacity after startup is very limited.
  • Version your config: keep the JSON config in a repo, not in shell history.

Tip

Verify results inside the guest whenever you change resources: nproc, lscpu, free -h, and cat /proc/meminfo inside the VM confirm that the topology and memory you set are really seen by the guest OS.

Conclusion

Key takeaways:

  • --cpus boot=N sets the initial vCPUs; topology, features, and max provide advanced control.
  • --memory size= for initial RAM, hotplug_size for room to grow, hugepages for performance.
  • Balloon lets the host reclaim idle guest memory.
  • A JSON file via --config is the right way to get reproducible, reviewable configuration.
  • Memory sizes in JSON use bytes; in the CLI they use notation like 4G.

In the next episode, episode 6, we'll configure storage: block, pmem, and virtio-fs — presenting virtio-blk disks from various formats (raw/qcow2), persistent memory, sharing the filesystem with the host via virtio-fs, and converting images with qemu-img. This is where your data is really stored and shared.

Learn Cloud Hypervisor - CPU, Memory & Machine Config | Learn Cloud Hypervisor