runtime: clh: Add reclaim_guest_freed_memory [BACKPORT]

We're bringing to *Cloud Hypervisor only* the reclaim_guest_freed_memory
option already present in the runtime-rs.

This allows us to use virtio-balloon for the hypervisor to reclaim
memory freed by the guest.

The reason we're not touching other hypervisors is because we're very
much aware of avoiding to clutter the go code at this point, so we'll
leave it for whoever really needs this on other hypervisor (and trust
me, we really do need it for Cloud Hypervisor right now ;-)).

Signed-off-by: Champ-Goblem <cameron@northflank.com>
Signed-off-by: Fabiano Fidêncio <fidencio@northflank.com>
This commit is contained in:
Champ-Goblem 2025-04-24 10:56:39 +02:00 committed by Fabiano Fidêncio
parent 1c72d22212
commit 9f76467cb7
7 changed files with 34 additions and 0 deletions

View File

@ -185,6 +185,16 @@ block_device_driver = "virtio-blk"
# Default false
#block_device_cache_direct = true
# Reclaim guest freed memory.
# Enabling this will result in the VM balloon device having f_reporting=on set.
# Then the hypervisor will use it to reclaim guest freed memory.
# This is useful for reducing the amount of memory used by a VM.
# Enabling this feature may sometimes reduce the speed of memory access in
# the VM.
#
# Default false
#reclaim_guest_freed_memory = true
# Enable huge pages for VM RAM, default false
# Enabling this will result in the VM memory
# being allocated using huge pages.

View File

@ -76,6 +76,7 @@ const defaultBlockDeviceCacheDirect bool = false
const defaultBlockDeviceCacheNoflush bool = false
const defaultEnableIOThreads bool = false
const defaultEnableMemPrealloc bool = false
const defaultEnableReclaimGuestFreedMemory bool = false
const defaultEnableHugePages bool = false
const defaultEnableIOMMU bool = false
const defaultEnableIOMMUPlatform bool = false

View File

@ -147,6 +147,7 @@ type hypervisor struct {
VhostUserDeviceReconnect uint32 `toml:"vhost_user_reconnect_timeout_sec"`
DisableBlockDeviceUse bool `toml:"disable_block_device_use"`
MemPrealloc bool `toml:"enable_mem_prealloc"`
ReclaimGuestFreedMemory bool `toml:"reclaim_guest_freed_memory"`
HugePages bool `toml:"enable_hugepages"`
VirtioMem bool `toml:"enable_virtio_mem"`
IOMMU bool `toml:"enable_iommu"`
@ -1082,6 +1083,7 @@ func newClhHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
VirtioFSCacheSize: h.VirtioFSCacheSize,
VirtioFSCache: h.VirtioFSCache,
MemPrealloc: h.MemPrealloc,
ReclaimGuestFreedMemory: h.ReclaimGuestFreedMemory,
HugePages: h.HugePages,
FileBackedMemRootDir: h.FileBackedMemRootDir,
FileBackedMemRootList: h.FileBackedMemRootList,
@ -1434,6 +1436,7 @@ func GetDefaultHypervisorConfig() vc.HypervisorConfig {
DisableBlockDeviceUse: defaultDisableBlockDeviceUse,
DefaultBridges: defaultBridgesCount,
MemPrealloc: defaultEnableMemPrealloc,
ReclaimGuestFreedMemory: defaultEnableReclaimGuestFreedMemory,
HugePages: defaultEnableHugePages,
IOMMU: defaultEnableIOMMU,
IOMMUPlatform: defaultEnableIOMMUPlatform,

View File

@ -705,6 +705,12 @@ func addHypervisorMemoryOverrides(ocispec specs.Spec, sbConfig *vc.SandboxConfig
sbConfig.HypervisorConfig.FileBackedMemRootDir = value
}
if err := newAnnotationConfiguration(ocispec, vcAnnotations.ReclaimGuestFreedMemory).setBool(func(reclaimGuestFreedMemory bool) {
sbConfig.HypervisorConfig.ReclaimGuestFreedMemory = reclaimGuestFreedMemory
}); err != nil {
return err
}
if err := newAnnotationConfiguration(ocispec, vcAnnotations.HugePages).setBool(func(hugePages bool) {
sbConfig.HypervisorConfig.HugePages = hugePages
}); err != nil {

View File

@ -527,7 +527,15 @@ func (clh *cloudHypervisor) CreateVM(ctx context.Context, id string, network Net
hotplugSize := clh.config.DefaultMaxMemorySize
// OpenAPI only supports int64 values
clh.vmconfig.Memory.HotplugSize = func(i int64) *int64 { return &i }(int64((utils.MemUnit(hotplugSize) * utils.MiB).ToBytes()))
if clh.config.ReclaimGuestFreedMemory {
// Create VM with a balloon config so we can enable free page reporting (size of the balloon can be set to zero)
clh.vmconfig.Balloon = chclient.NewBalloonConfig(0)
// Set the free page reporting flag for ballooning to be true
clh.vmconfig.Balloon.SetFreePageReporting(true)
}
}
// Set initial amount of cpu's for the virtual machine
clh.vmconfig.Cpus = chclient.NewCpusConfig(int32(clh.config.NumVCPUs()), int32(clh.config.DefaultMaxVCPUs))

View File

@ -612,6 +612,9 @@ type HypervisorConfig struct {
// MemPrealloc specifies if the memory should be pre-allocated
MemPrealloc bool
// ReclaimGuestFreedMemory is a sandbox annotation that specifies whether the memory freed by the guest will be reclaimed by the hypervisor or not.
ReclaimGuestFreedMemory bool
// HugePages specifies if the memory should be pre-allocated from huge pages
HugePages bool

View File

@ -167,6 +167,9 @@ const (
// MemPrealloc is a sandbox annotation that specifies the memory space used for nvdimm device by the hypervisor.
MemPrealloc = kataAnnotHypervisorPrefix + "enable_mem_prealloc"
// ReclaimGuestFreedMemory is a sandbox annotation that specifies whether the memory freed by the guest will be reclaimed by the hypervisor or not.
ReclaimGuestFreedMemory = kataAnnotHypervisorPrefix + "reclaim_guest_freed_memory"
// HugePages is a sandbox annotation to specify if the memory should be pre-allocated from huge pages
HugePages = kataAnnotHypervisorPrefix + "enable_hugepages"