config: detect support for various features

Unify the code for generating default settings with the code for generating
QEMU arguments. The list of supported archs/targets is incomplete and
should be filled out with more testing.

Also addresses the issue where "virtio-serial" device is generated for
SPARC virtual machines.

Fixes #4575
This commit is contained in:
osy
2022-11-23 17:44:33 -08:00
parent c7a34605ef
commit 82b4ad4e99
6 changed files with 73 additions and 42 deletions
+48
View File
@@ -390,3 +390,51 @@ enum QEMUPackageFileName: String {
case debugLog = "debug.log"
case efiVariables = "efi_vars.fd"
}
// MARK: Supported features
extension QEMUArchitecture {
var hasAgentSupport: Bool {
switch self {
case .sparc, .sparc64: return false
default: return true
}
}
var hasSharingSupport: Bool {
switch self {
case .sparc, .sparc64: return false
default: return true
}
}
var hasUsbSupport: Bool {
switch self {
case .s390x: return false
case .sparc, .sparc64: return false
default: return true
}
}
var hasHypervisorSupport: Bool {
guard jb_has_hypervisor() else {
return false
}
#if arch(arm64)
return self == .aarch64
#elseif arch(x86_64)
return self == .x86_64
#else
return false
#endif
}
}
extension QEMUTarget {
var hasUsbSupport: Bool {
switch self.rawValue {
case "isapc": return false
default: return true
}
}
}
@@ -269,38 +269,12 @@ import Foundation
#endif
}
private var isHypervisorSupported: Bool {
guard jb_has_hypervisor() else {
return false
}
#if arch(arm64)
return system.architecture == .aarch64
#elseif arch(x86_64)
return system.architecture == .x86_64
#else
return false
#endif
}
private var isHypervisorUsed: Bool {
isHypervisorSupported && qemu.hasHypervisor
}
private var isUsbSupported: Bool {
if system.target.rawValue == QEMUTarget_x86_64.isapc.rawValue {
return false
}
if system.architecture == .s390x {
return false
}
if system.architecture == .sparc || system.architecture == .sparc64 {
return false
}
return true
system.architecture.hasHypervisorSupport && qemu.hasHypervisor
}
private var isUsbUsed: Bool {
isUsbSupported && input.usbBusSupport != .disabled
system.architecture.hasUsbSupport && system.target.hasUsbSupport && input.usbBusSupport != .disabled
}
@QEMUArgumentBuilder private var machineArguments: [QEMUArgument] {
@@ -721,8 +695,15 @@ import Foundation
}
}
private var isAgentUsed: Bool {
guard system.architecture.hasAgentSupport else {
return false
}
return sharing.hasClipboardSharing || sharing.directoryShareMode == .webdav || displays.contains(where: { $0.isDynamicResolution })
}
@QEMUArgumentBuilder private var sharingArguments: [QEMUArgument] {
if sharing.hasClipboardSharing || sharing.directoryShareMode == .webdav || displays.contains(where: { $0.isDynamicResolution }) {
if isAgentUsed {
f("-device")
f("virtio-serial")
f("-device")
@@ -736,7 +717,7 @@ import Foundation
f("spiceport,name=org.spice-space.webdav.0,id=charchannel1")
}
}
if sharing.directoryShareMode == .virtfs, let url = sharing.directoryShareUrl {
if system.architecture.hasSharingSupport && sharing.directoryShareMode == .virtfs, let url = sharing.directoryShareUrl {
f("-fsdev")
"local"
"id=virtfs0"
@@ -76,6 +76,9 @@ struct UTMQemuConfigurationDisplay: Codable, Identifiable {
extension UTMQemuConfigurationDisplay {
init?(forArchitecture architecture: QEMUArchitecture, target: any QEMUTarget) {
self.init()
if !architecture.hasAgentSupport {
isDynamicResolution = false
}
let rawTarget = target.rawValue
if rawTarget.hasPrefix("pc") || rawTarget.hasPrefix("q35") {
hardware = QEMUDisplayDevice_x86_64.virtio_vga
@@ -57,12 +57,12 @@ extension UTMQemuConfigurationInput {
init(forArchitecture architecture: QEMUArchitecture, target: any QEMUTarget) {
self.init()
let rawTarget = target.rawValue
if rawTarget.hasPrefix("pc") || rawTarget.hasPrefix("q35") {
if !architecture.hasUsbSupport || !target.hasUsbSupport {
usbBusSupport = .disabled
} else if rawTarget.hasPrefix("pc") || rawTarget.hasPrefix("q35") {
usbBusSupport = .usb3_0
} else if (architecture == .arm || architecture == .aarch64) && (rawTarget.hasPrefix("virt-") || rawTarget == "virt") {
usbBusSupport = .usb3_0
} else if rawTarget == "isapc" {
usbBusSupport = .disabled
}
}
}
+1 -9
View File
@@ -122,15 +122,7 @@ extension UTMQemuConfigurationQEMU {
hasUefiBoot = true
hasRNGDevice = true
}
#if arch(arm64)
if architecture == .aarch64 {
hasHypervisor = jb_has_hypervisor()
}
#elseif arch(x86_64)
if architecture == .x86_64 {
hasHypervisor = jb_has_hypervisor()
}
#endif
hasHypervisor = architecture.hasHypervisorSupport
}
}
@@ -60,6 +60,13 @@ extension UTMQemuConfigurationSharing {
init(forArchitecture architecture: QEMUArchitecture, target: any QEMUTarget) {
self.init()
let rawTarget = target.rawValue
if !architecture.hasAgentSupport {
hasClipboardSharing = false
}
if !architecture.hasSharingSupport {
directoryShareMode = .none
}
// overrides for specific configurations
if rawTarget.hasPrefix("pc") || rawTarget.hasPrefix("q35") {
directoryShareMode = .webdav
hasClipboardSharing = true