Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Configuration/UTMQemuConfiguration+Arguments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,11 @@ import Virtualization // for getting network interfaces
}
}

/// Keeps guest RAM resident so the host does not compress or swap it.
private var isMemoryLockUsed: Bool {
system.architecture == .x86_64 && isHypervisorUsed && qemu.hasMemoryLock
}

private var isTSOUsed: Bool {
system.architecture.hasTSOSupport && qemu.hasTSO
}
Expand Down Expand Up @@ -694,6 +699,10 @@ import Virtualization // for getting network interfaces
f("-m")
system.memorySize
f()
if isMemoryLockUsed {
f("-overcommit")
f("mem-lock=on")
}
}

var hasCustomBios: Bool {
Expand Down
5 changes: 5 additions & 0 deletions Configuration/UTMQemuConfigurationQEMU.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ struct UTMQemuConfigurationQEMU: Codable {

/// Add an interrupt remapping IOMMU for x86_64 q35 guests using the hypervisor on Intel.
var hasInterruptRemapping: Bool = true
/// Lock guest RAM in host memory for x86_64 guests using the hypervisor on Intel.
var hasMemoryLock: Bool = true

/// QEMU machine property that overrides the default property defined by UTM.
var machinePropertyOverride: String?
Expand Down Expand Up @@ -96,6 +98,7 @@ struct UTMQemuConfigurationQEMU: Codable {
case hasRTCLocalTime = "RTCLocalTime"
case hasPS2Controller = "PS2Controller"
case hasInterruptRemapping = "InterruptRemapping"
case hasMemoryLock = "MemoryLock"
case machinePropertyOverride = "MachinePropertyOverride"
case additionalArguments = "AdditionalArguments"
}
Expand All @@ -115,6 +118,7 @@ struct UTMQemuConfigurationQEMU: Codable {
hasRTCLocalTime = try values.decode(Bool.self, forKey: .hasRTCLocalTime)
hasPS2Controller = try values.decode(Bool.self, forKey: .hasPS2Controller)
hasInterruptRemapping = try values.decodeIfPresent(Bool.self, forKey: .hasInterruptRemapping) ?? true
hasMemoryLock = try values.decodeIfPresent(Bool.self, forKey: .hasMemoryLock) ?? true
machinePropertyOverride = try values.decodeIfPresent(String.self, forKey: .machinePropertyOverride)
additionalArguments = try values.decode([QEMUArgument].self, forKey: .additionalArguments)
if let dataURL = decoder.userInfo[.dataURL] as? URL {
Expand All @@ -136,6 +140,7 @@ struct UTMQemuConfigurationQEMU: Codable {
try container.encode(hasRTCLocalTime, forKey: .hasRTCLocalTime)
try container.encode(hasPS2Controller, forKey: .hasPS2Controller)
try container.encode(hasInterruptRemapping, forKey: .hasInterruptRemapping)
try container.encode(hasMemoryLock, forKey: .hasMemoryLock)
try container.encodeIfPresent(machinePropertyOverride, forKey: .machinePropertyOverride)
try container.encode(additionalArguments, forKey: .additionalArguments)
}
Expand Down
2 changes: 2 additions & 0 deletions Platform/Shared/VMConfigQEMUView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ struct VMConfigQEMUView: View {
if config.system.architecture == .x86_64 && config.qemu.hasHypervisor {
Toggle("Interrupt remapping", isOn: $config.qemu.hasInterruptRemapping)
.help("Lets the guest use faster interrupt handling, which reduces stutter and audio dropouts in Windows. Requires the Q35 machine.")
Toggle("Lock guest memory", isOn: $config.qemu.hasMemoryLock)
.help("Keeps the guest's memory resident so macOS does not compress or swap it. The Mac needs enough free memory for the whole guest.")
}
#endif
Toggle("Use local time for base clock", isOn: $config.qemu.hasRTCLocalTime)
Expand Down
Loading