diff --git a/qemu/qemu.go b/qemu/qemu.go index f2f4f5b8b2..6022fe470a 100644 --- a/qemu/qemu.go +++ b/qemu/qemu.go @@ -1126,6 +1126,10 @@ type Memory struct { // MaxMem is the maximum amount of memory that can be made available // to the guest through e.g. hot pluggable memory. MaxMem string + + // Path is the file path of the memory device. It points to a local + // file path used by FileBackedMem. + Path string } // Kernel is the guest kernel configuration structure. @@ -1167,6 +1171,13 @@ type Knobs struct { // MemPrealloc will allocate all the RAM upfront MemPrealloc bool + // FileBackedMem requires Memory.Size and Memory.Path of the VM to + // be set. + FileBackedMem bool + + // FileBackedMemShared will set the FileBackedMem device as shared. + FileBackedMemShared bool + // Mlock will control locking of memory // Only active when Realtime is set to true Mlock bool @@ -1474,6 +1485,21 @@ func (config *Config) appendKnobs() { config.qemuParams = append(config.qemuParams, "-device") config.qemuParams = append(config.qemuParams, deviceMemParam) } + } else if config.Knobs.FileBackedMem == true { + if config.Memory.Size != "" && config.Memory.Path != "" { + dimmName := "dimm1" + objMemParam := "memory-backend-file,id=" + dimmName + ",size=" + config.Memory.Size + ",mem-path=" + config.Memory.Path + if config.Knobs.FileBackedMemShared == true { + objMemParam += ",share=on" + } + numaMemParam := "node,memdev=" + dimmName + + config.qemuParams = append(config.qemuParams, "-object") + config.qemuParams = append(config.qemuParams, objMemParam) + + config.qemuParams = append(config.qemuParams, "-numa") + config.qemuParams = append(config.qemuParams, numaMemParam) + } } if config.Knobs.Realtime == true { diff --git a/qemu/qemu_test.go b/qemu/qemu_test.go index 895fe0f15c..09c6523771 100644 --- a/qemu/qemu_test.go +++ b/qemu/qemu_test.go @@ -390,13 +390,15 @@ func TestAppendEmptyDevice(t *testing.T) { func TestAppendKnobsAllTrue(t *testing.T) { var knobsString = "-no-user-config -nodefaults -nographic -daemonize -realtime mlock=on" knobs := Knobs{ - NoUserConfig: true, - NoDefaults: true, - NoGraphic: true, - Daemonize: true, - MemPrealloc: true, - Realtime: true, - Mlock: true, + NoUserConfig: true, + NoDefaults: true, + NoGraphic: true, + Daemonize: true, + MemPrealloc: true, + FileBackedMem: true, + FileBackedMemShared: true, + Realtime: true, + Mlock: true, } testAppend(knobs, knobsString, t) @@ -405,12 +407,14 @@ func TestAppendKnobsAllTrue(t *testing.T) { func TestAppendKnobsAllFalse(t *testing.T) { var knobsString = "-realtime mlock=off" knobs := Knobs{ - NoUserConfig: false, - NoDefaults: false, - NoGraphic: false, - MemPrealloc: false, - Realtime: false, - Mlock: false, + NoUserConfig: false, + NoDefaults: false, + NoGraphic: false, + MemPrealloc: false, + FileBackedMem: false, + FileBackedMemShared: false, + Realtime: false, + Mlock: false, } testAppend(knobs, knobsString, t) @@ -435,6 +439,7 @@ func TestAppendMemory(t *testing.T) { Size: "2G", Slots: 2, MaxMem: "3G", + Path: "", } testAppend(memory, memoryString, t)