Jelajahi Sumber

Merge pull request #4846 from utmapp/feature/backend-update

Update backend and rework rendering pipeline
osy 2 tahun lalu
induk
melakukan
a62ac55948

+ 373 - 30
Configuration/QEMUConstantGenerated.swift

@@ -26,6 +26,7 @@ enum QEMUArchitecture: String, CaseIterable, QEMUConstant {
     case cris
     case hppa
     case i386
+    case loongarch64
     case m68k
     case microblaze
     case microblazeel
@@ -59,6 +60,7 @@ enum QEMUArchitecture: String, CaseIterable, QEMUConstant {
         case .cris: return "CRIS"
         case .hppa: return "HPPA"
         case .i386: return "i386 (x86)"
+        case .loongarch64: return "LoongArch64"
         case .m68k: return "m68k"
         case .microblaze: return "Microblaze"
         case .microblazeel: return "Microblaze (Little Endian)"
@@ -201,6 +203,7 @@ enum QEMUCPU_aarch64: String, CaseIterable, QEMUCPU {
     case arm926
     case arm946
     case cortex_a15 = "cortex-a15"
+    case cortex_a35 = "cortex-a35"
     case cortex_a53 = "cortex-a53"
     case cortex_a57 = "cortex-a57"
     case cortex_a7 = "cortex-a7"
@@ -246,6 +249,7 @@ enum QEMUCPU_aarch64: String, CaseIterable, QEMUCPU {
         case .arm926: return "arm926"
         case .arm946: return "arm946"
         case .cortex_a15: return "cortex-a15"
+        case .cortex_a35: return "cortex-a35"
         case .cortex_a53: return "cortex-a53"
         case .cortex_a57: return "cortex-a57"
         case .cortex_a7: return "cortex-a7"
@@ -600,6 +604,16 @@ enum QEMUCPU_i386: String, CaseIterable, QEMUCPU {
     }
 }
 
+enum QEMUCPU_loongarch64: String, CaseIterable, QEMUCPU {
+    case `default` = "default"
+
+    var prettyValue: String {
+        switch self {
+        case .`default`: return NSLocalizedString("Default", comment: "QEMUConstantGenerated")
+        }
+    }
+}
+
 enum QEMUCPU_m68k: String, CaseIterable, QEMUCPU {
     case `default` = "default"
     case any
@@ -3822,6 +3836,8 @@ enum QEMUCPUFlag_i386: String, CaseIterable, QEMUCPUFlag {
     }
 }
 
+typealias QEMUCPUFlag_loongarch64 = AnyQEMUConstant
+
 typealias QEMUCPUFlag_m68k = AnyQEMUConstant
 
 typealias QEMUCPUFlag_microblaze = AnyQEMUConstant
@@ -4068,6 +4084,7 @@ enum QEMUCPUFlag_s390x: String, CaseIterable, QEMUCPUFlag {
     case nonqks
     case opc
     case pai
+    case paie
     case parseh
     case pcc_cmac_aes_128 = "pcc-cmac-aes-128"
     case pcc_cmac_aes_192 = "pcc-cmac-aes-192"
@@ -4400,6 +4417,7 @@ enum QEMUCPUFlag_s390x: String, CaseIterable, QEMUCPUFlag {
         case .nonqks: return "nonqks"
         case .opc: return "opc"
         case .pai: return "pai"
+        case .paie: return "paie"
         case .parseh: return "parseh"
         case .pcc_cmac_aes_128: return "pcc-cmac-aes-128"
         case .pcc_cmac_aes_192: return "pcc-cmac-aes-192"
@@ -5336,8 +5354,9 @@ enum QEMUTarget_arm: String, CaseIterable, QEMUTarget {
     case virt_6_1 = "virt-6.1"
     case virt_6_2 = "virt-6.2"
     case virt_7_0 = "virt-7.0"
-    case virt
     case virt_7_1 = "virt-7.1"
+    case virt
+    case virt_7_2 = "virt-7.2"
     case qcom_dc_scm_v1_bmc = "qcom-dc-scm-v1-bmc"
     case qcom_firework_bmc = "qcom-firework-bmc"
     case quanta_gbs_bmc = "quanta-gbs-bmc"
@@ -5447,8 +5466,9 @@ enum QEMUTarget_arm: String, CaseIterable, QEMUTarget {
         case .virt_6_1: return "QEMU 6.1 ARM Virtual Machine (virt-6.1)"
         case .virt_6_2: return "QEMU 6.2 ARM Virtual Machine (virt-6.2)"
         case .virt_7_0: return "QEMU 7.0 ARM Virtual Machine (virt-7.0)"
-        case .virt: return "QEMU 7.1 ARM Virtual Machine (alias of virt-7.1) (virt)"
         case .virt_7_1: return "QEMU 7.1 ARM Virtual Machine (virt-7.1)"
+        case .virt: return "QEMU 7.2 ARM Virtual Machine (alias of virt-7.2) (virt)"
+        case .virt_7_2: return "QEMU 7.2 ARM Virtual Machine (virt-7.2)"
         case .qcom_dc_scm_v1_bmc: return "Qualcomm DC-SCM V1 BMC (Cortex A7) (qcom-dc-scm-v1-bmc)"
         case .qcom_firework_bmc: return "Qualcomm DC-SCM V1/Firework BMC (Cortex A7) (qcom-firework-bmc)"
         case .quanta_gbs_bmc: return "Quanta GBS (Cortex-A9) (quanta-gbs-bmc)"
@@ -5557,8 +5577,9 @@ enum QEMUTarget_aarch64: String, CaseIterable, QEMUTarget {
     case virt_6_1 = "virt-6.1"
     case virt_6_2 = "virt-6.2"
     case virt_7_0 = "virt-7.0"
-    case virt
     case virt_7_1 = "virt-7.1"
+    case virt
+    case virt_7_2 = "virt-7.2"
     case qcom_dc_scm_v1_bmc = "qcom-dc-scm-v1-bmc"
     case qcom_firework_bmc = "qcom-firework-bmc"
     case quanta_gbs_bmc = "quanta-gbs-bmc"
@@ -5673,8 +5694,9 @@ enum QEMUTarget_aarch64: String, CaseIterable, QEMUTarget {
         case .virt_6_1: return "QEMU 6.1 ARM Virtual Machine (virt-6.1)"
         case .virt_6_2: return "QEMU 6.2 ARM Virtual Machine (virt-6.2)"
         case .virt_7_0: return "QEMU 7.0 ARM Virtual Machine (virt-7.0)"
-        case .virt: return "QEMU 7.1 ARM Virtual Machine (alias of virt-7.1) (virt)"
         case .virt_7_1: return "QEMU 7.1 ARM Virtual Machine (virt-7.1)"
+        case .virt: return "QEMU 7.2 ARM Virtual Machine (alias of virt-7.2) (virt)"
+        case .virt_7_2: return "QEMU 7.2 ARM Virtual Machine (virt-7.2)"
         case .qcom_dc_scm_v1_bmc: return "Qualcomm DC-SCM V1 BMC (Cortex A7) (qcom-dc-scm-v1-bmc)"
         case .qcom_firework_bmc: return "Qualcomm DC-SCM V1/Firework BMC (Cortex A7) (qcom-firework-bmc)"
         case .quanta_gbs_bmc: return "Quanta GBS (Cortex-A9) (quanta-gbs-bmc)"
@@ -5798,8 +5820,9 @@ enum QEMUTarget_i386: String, CaseIterable, QEMUTarget {
     case pc_q35_6_2 = "pc-q35-6.2"
     case pc_q35_7_0 = "pc-q35-7.0"
     case pc_q35_7_1 = "pc-q35-7.1"
+    case pc_q35_7_2 = "pc-q35-7.2"
     case pc
-    case pc_i440fx_7_1 = "pc-i440fx-7.1"
+    case pc_i440fx_7_2 = "pc-i440fx-7.2"
     case pc_i440fx_1_4 = "pc-i440fx-1.4"
     case pc_i440fx_1_5 = "pc-i440fx-1.5"
     case pc_i440fx_1_6 = "pc-i440fx-1.6"
@@ -5829,6 +5852,7 @@ enum QEMUTarget_i386: String, CaseIterable, QEMUTarget {
     case pc_i440fx_6_1 = "pc-i440fx-6.1"
     case pc_i440fx_6_2 = "pc-i440fx-6.2"
     case pc_i440fx_7_0 = "pc-i440fx-7.0"
+    case pc_i440fx_7_1 = "pc-i440fx-7.1"
     case none
     case microvm
 
@@ -5839,7 +5863,7 @@ enum QEMUTarget_i386: String, CaseIterable, QEMUTarget {
     var prettyValue: String {
         switch self {
         case .isapc: return "ISA-only PC (isapc)"
-        case .q35: return "Standard PC (Q35 + ICH9, 2009) (alias of pc-q35-7.1) (q35)"
+        case .q35: return "Standard PC (Q35 + ICH9, 2009) (alias of pc-q35-7.2) (q35)"
         case .pc_q35_2_10: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-2.10)"
         case .pc_q35_2_11: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-2.11)"
         case .pc_q35_2_12: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-2.12)"
@@ -5863,8 +5887,9 @@ enum QEMUTarget_i386: String, CaseIterable, QEMUTarget {
         case .pc_q35_6_2: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-6.2)"
         case .pc_q35_7_0: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-7.0)"
         case .pc_q35_7_1: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-7.1)"
-        case .pc: return "Standard PC (i440FX + PIIX, 1996) (alias of pc-i440fx-7.1) (pc)"
-        case .pc_i440fx_7_1: return "Standard PC (i440FX + PIIX, 1996) (default) (pc-i440fx-7.1)"
+        case .pc_q35_7_2: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-7.2)"
+        case .pc: return "Standard PC (i440FX + PIIX, 1996) (alias of pc-i440fx-7.2) (pc)"
+        case .pc_i440fx_7_2: return "Standard PC (i440FX + PIIX, 1996) (default) (pc-i440fx-7.2)"
         case .pc_i440fx_1_4: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-1.4)"
         case .pc_i440fx_1_5: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-1.5)"
         case .pc_i440fx_1_6: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-1.6)"
@@ -5894,12 +5919,29 @@ enum QEMUTarget_i386: String, CaseIterable, QEMUTarget {
         case .pc_i440fx_6_1: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-6.1)"
         case .pc_i440fx_6_2: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-6.2)"
         case .pc_i440fx_7_0: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-7.0)"
+        case .pc_i440fx_7_1: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-7.1)"
         case .none: return "empty machine (none)"
         case .microvm: return "microvm (i386) (microvm)"
         }
     }
 }
 
+enum QEMUTarget_loongarch64: String, CaseIterable, QEMUTarget {
+    case virt
+    case none
+
+    static var `default`: QEMUTarget_loongarch64 {
+        .virt
+    }
+
+    var prettyValue: String {
+        switch self {
+        case .virt: return "Loongson-3A5000 LS7A1000 machine (default) (virt)"
+        case .none: return "empty machine (none)"
+        }
+    }
+}
+
 enum QEMUTarget_m68k: String, CaseIterable, QEMUTarget {
     case an5206
     case mcf5208evb
@@ -5909,8 +5951,9 @@ enum QEMUTarget_m68k: String, CaseIterable, QEMUTarget {
     case virt_6_1 = "virt-6.1"
     case virt_6_2 = "virt-6.2"
     case virt_7_0 = "virt-7.0"
-    case virt
     case virt_7_1 = "virt-7.1"
+    case virt
+    case virt_7_2 = "virt-7.2"
     case none
 
     static var `default`: QEMUTarget_m68k {
@@ -5927,8 +5970,9 @@ enum QEMUTarget_m68k: String, CaseIterable, QEMUTarget {
         case .virt_6_1: return "QEMU 6.1 M68K Virtual Machine (virt-6.1)"
         case .virt_6_2: return "QEMU 6.2 M68K Virtual Machine (virt-6.2)"
         case .virt_7_0: return "QEMU 7.0 M68K Virtual Machine (virt-7.0)"
-        case .virt: return "QEMU 7.1 M68K Virtual Machine (alias of virt-7.1) (virt)"
         case .virt_7_1: return "QEMU 7.1 M68K Virtual Machine (virt-7.1)"
+        case .virt: return "QEMU 7.2 M68K Virtual Machine (alias of virt-7.2) (virt)"
+        case .virt_7_2: return "QEMU 7.2 M68K Virtual Machine (virt-7.2)"
         case .none: return "empty machine (none)"
         }
     }
@@ -6081,6 +6125,7 @@ enum QEMUTarget_nios2: String, CaseIterable, QEMUTarget {
 enum QEMUTarget_or1k: String, CaseIterable, QEMUTarget {
     case none
     case or1k_sim = "or1k-sim"
+    case virt
 
     static var `default`: QEMUTarget_or1k {
         .or1k_sim
@@ -6090,6 +6135,7 @@ enum QEMUTarget_or1k: String, CaseIterable, QEMUTarget {
         switch self {
         case .none: return "empty machine (none)"
         case .or1k_sim: return "or1k simulation (default) (or1k-sim)"
+        case .virt: return "or1k virtual machine (virt)"
         }
     }
 }
@@ -6106,7 +6152,6 @@ enum QEMUTarget_ppc: String, CaseIterable, QEMUTarget {
     case ppce500
     case mpc8544ds
     case ref405ep
-    case taihu
 
     static var `default`: QEMUTarget_ppc {
         .g3beige
@@ -6125,7 +6170,6 @@ enum QEMUTarget_ppc: String, CaseIterable, QEMUTarget {
         case .ppce500: return "generic paravirt e500 platform (ppce500)"
         case .mpc8544ds: return "mpc8544ds (mpc8544ds)"
         case .ref405ep: return "ref405ep (ref405ep)"
-        case .taihu: return "taihu (deprecated) (taihu)"
         }
     }
 }
@@ -6146,7 +6190,7 @@ enum QEMUTarget_ppc64: String, CaseIterable, QEMUTarget {
     case ppce500
     case mpc8544ds
     case pseries
-    case pseries_7_1 = "pseries-7.1"
+    case pseries_7_2 = "pseries-7.2"
     case pseries_2_1 = "pseries-2.1"
     case pseries_2_10 = "pseries-2.10"
     case pseries_2_11 = "pseries-2.11"
@@ -6172,11 +6216,11 @@ enum QEMUTarget_ppc64: String, CaseIterable, QEMUTarget {
     case pseries_6_1 = "pseries-6.1"
     case pseries_6_2 = "pseries-6.2"
     case pseries_7_0 = "pseries-7.0"
+    case pseries_7_1 = "pseries-7.1"
     case ref405ep
-    case taihu
 
     static var `default`: QEMUTarget_ppc64 {
-        .pseries_7_1
+        .pseries_7_2
     }
 
     var prettyValue: String {
@@ -6195,8 +6239,8 @@ enum QEMUTarget_ppc64: String, CaseIterable, QEMUTarget {
         case .none: return "empty machine (none)"
         case .ppce500: return "generic paravirt e500 platform (ppce500)"
         case .mpc8544ds: return "mpc8544ds (mpc8544ds)"
-        case .pseries: return "pSeries Logical Partition (PAPR compliant) (alias of pseries-7.1) (pseries)"
-        case .pseries_7_1: return "pSeries Logical Partition (PAPR compliant) (default) (pseries-7.1)"
+        case .pseries: return "pSeries Logical Partition (PAPR compliant) (alias of pseries-7.2) (pseries)"
+        case .pseries_7_2: return "pSeries Logical Partition (PAPR compliant) (default) (pseries-7.2)"
         case .pseries_2_1: return "pSeries Logical Partition (PAPR compliant) (pseries-2.1)"
         case .pseries_2_10: return "pSeries Logical Partition (PAPR compliant) (pseries-2.10)"
         case .pseries_2_11: return "pSeries Logical Partition (PAPR compliant) (pseries-2.11)"
@@ -6222,8 +6266,8 @@ enum QEMUTarget_ppc64: String, CaseIterable, QEMUTarget {
         case .pseries_6_1: return "pSeries Logical Partition (PAPR compliant) (pseries-6.1)"
         case .pseries_6_2: return "pSeries Logical Partition (PAPR compliant) (pseries-6.2)"
         case .pseries_7_0: return "pSeries Logical Partition (PAPR compliant) (pseries-7.0)"
+        case .pseries_7_1: return "pSeries Logical Partition (PAPR compliant) (pseries-7.1)"
         case .ref405ep: return "ref405ep (ref405ep)"
-        case .taihu: return "taihu (deprecated) (taihu)"
         }
     }
 }
@@ -6318,12 +6362,13 @@ enum QEMUTarget_s390x: String, CaseIterable, QEMUTarget {
     case s390_ccw_virtio_6_1 = "s390-ccw-virtio-6.1"
     case s390_ccw_virtio_6_2 = "s390-ccw-virtio-6.2"
     case s390_ccw_virtio_7_0 = "s390-ccw-virtio-7.0"
-    case s390_ccw_virtio = "s390-ccw-virtio"
     case s390_ccw_virtio_7_1 = "s390-ccw-virtio-7.1"
+    case s390_ccw_virtio = "s390-ccw-virtio"
+    case s390_ccw_virtio_7_2 = "s390-ccw-virtio-7.2"
     case none
 
     static var `default`: QEMUTarget_s390x {
-        .s390_ccw_virtio_7_1
+        .s390_ccw_virtio_7_2
     }
 
     var prettyValue: String {
@@ -6349,8 +6394,9 @@ enum QEMUTarget_s390x: String, CaseIterable, QEMUTarget {
         case .s390_ccw_virtio_6_1: return "Virtual s390x machine (version 6.1) (s390-ccw-virtio-6.1)"
         case .s390_ccw_virtio_6_2: return "Virtual s390x machine (version 6.2) (s390-ccw-virtio-6.2)"
         case .s390_ccw_virtio_7_0: return "Virtual s390x machine (version 7.0) (s390-ccw-virtio-7.0)"
-        case .s390_ccw_virtio: return "Virtual s390x machine (version 7.1) (alias of s390-ccw-virtio-7.1) (s390-ccw-virtio)"
-        case .s390_ccw_virtio_7_1: return "Virtual s390x machine (version 7.1) (default) (s390-ccw-virtio-7.1)"
+        case .s390_ccw_virtio_7_1: return "Virtual s390x machine (version 7.1) (s390-ccw-virtio-7.1)"
+        case .s390_ccw_virtio: return "Virtual s390x machine (version 7.2) (alias of s390-ccw-virtio-7.2) (s390-ccw-virtio)"
+        case .s390_ccw_virtio_7_2: return "Virtual s390x machine (version 7.2) (default) (s390-ccw-virtio-7.2)"
         case .none: return "empty machine (none)"
         }
     }
@@ -6490,8 +6536,9 @@ enum QEMUTarget_x86_64: String, CaseIterable, QEMUTarget {
     case pc_q35_6_2 = "pc-q35-6.2"
     case pc_q35_7_0 = "pc-q35-7.0"
     case pc_q35_7_1 = "pc-q35-7.1"
+    case pc_q35_7_2 = "pc-q35-7.2"
     case pc
-    case pc_i440fx_7_1 = "pc-i440fx-7.1"
+    case pc_i440fx_7_2 = "pc-i440fx-7.2"
     case pc_i440fx_1_4 = "pc-i440fx-1.4"
     case pc_i440fx_1_5 = "pc-i440fx-1.5"
     case pc_i440fx_1_6 = "pc-i440fx-1.6"
@@ -6521,6 +6568,7 @@ enum QEMUTarget_x86_64: String, CaseIterable, QEMUTarget {
     case pc_i440fx_6_1 = "pc-i440fx-6.1"
     case pc_i440fx_6_2 = "pc-i440fx-6.2"
     case pc_i440fx_7_0 = "pc-i440fx-7.0"
+    case pc_i440fx_7_1 = "pc-i440fx-7.1"
     case none
     case microvm
 
@@ -6531,7 +6579,7 @@ enum QEMUTarget_x86_64: String, CaseIterable, QEMUTarget {
     var prettyValue: String {
         switch self {
         case .isapc: return "ISA-only PC (isapc)"
-        case .q35: return "Standard PC (Q35 + ICH9, 2009) (alias of pc-q35-7.1) (q35)"
+        case .q35: return "Standard PC (Q35 + ICH9, 2009) (alias of pc-q35-7.2) (q35)"
         case .pc_q35_2_10: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-2.10)"
         case .pc_q35_2_11: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-2.11)"
         case .pc_q35_2_12: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-2.12)"
@@ -6555,8 +6603,9 @@ enum QEMUTarget_x86_64: String, CaseIterable, QEMUTarget {
         case .pc_q35_6_2: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-6.2)"
         case .pc_q35_7_0: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-7.0)"
         case .pc_q35_7_1: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-7.1)"
-        case .pc: return "Standard PC (i440FX + PIIX, 1996) (alias of pc-i440fx-7.1) (pc)"
-        case .pc_i440fx_7_1: return "Standard PC (i440FX + PIIX, 1996) (default) (pc-i440fx-7.1)"
+        case .pc_q35_7_2: return "Standard PC (Q35 + ICH9, 2009) (pc-q35-7.2)"
+        case .pc: return "Standard PC (i440FX + PIIX, 1996) (alias of pc-i440fx-7.2) (pc)"
+        case .pc_i440fx_7_2: return "Standard PC (i440FX + PIIX, 1996) (default) (pc-i440fx-7.2)"
         case .pc_i440fx_1_4: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-1.4)"
         case .pc_i440fx_1_5: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-1.5)"
         case .pc_i440fx_1_6: return "Standard PC (i440FX + PIIX, 1996) (deprecated) (pc-i440fx-1.6)"
@@ -6586,6 +6635,7 @@ enum QEMUTarget_x86_64: String, CaseIterable, QEMUTarget {
         case .pc_i440fx_6_1: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-6.1)"
         case .pc_i440fx_6_2: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-6.2)"
         case .pc_i440fx_7_0: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-7.0)"
+        case .pc_i440fx_7_1: return "Standard PC (i440FX + PIIX, 1996) (pc-i440fx-7.1)"
         case .none: return "empty machine (none)"
         case .microvm: return "microvm (i386) (microvm)"
         }
@@ -6848,6 +6898,44 @@ enum QEMUDisplayDevice_i386: String, CaseIterable, QEMUDisplayDevice {
     }
 }
 
+enum QEMUDisplayDevice_loongarch64: String, CaseIterable, QEMUDisplayDevice {
+    case cirrus_vga = "cirrus-vga"
+    case VGA
+    case ati_vga = "ati-vga"
+    case bochs_display = "bochs-display"
+    case ramfb
+    case secondary_vga = "secondary-vga"
+    case virtio_gpu_device = "virtio-gpu-device"
+    case virtio_gpu_gl_device = "virtio-gpu-gl-device"
+    case virtio_gpu_gl_pci = "virtio-gpu-gl-pci"
+    case virtio_gpu_pci = "virtio-gpu-pci"
+    case virtio_ramfb = "virtio-ramfb"
+    case virtio_ramfb_gl = "virtio-ramfb-gl"
+    case virtio_vga = "virtio-vga"
+    case virtio_vga_gl = "virtio-vga-gl"
+    case vmware_svga = "vmware-svga"
+
+    var prettyValue: String {
+        switch self {
+        case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)"
+        case .VGA: return "VGA"
+        case .ati_vga: return "ati-vga"
+        case .bochs_display: return "bochs-display"
+        case .ramfb: return "ram framebuffer standalone device (ramfb)"
+        case .secondary_vga: return "secondary-vga"
+        case .virtio_gpu_device: return "virtio-gpu-device"
+        case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)"
+        case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)"
+        case .virtio_gpu_pci: return "virtio-gpu-pci"
+        case .virtio_ramfb: return "virtio-ramfb"
+        case .virtio_ramfb_gl: return "virtio-ramfb-gl (GPU Supported)"
+        case .virtio_vga: return "virtio-vga"
+        case .virtio_vga_gl: return "virtio-vga-gl (GPU Supported)"
+        case .vmware_svga: return "vmware-svga"
+        }
+    }
+}
+
 enum QEMUDisplayDevice_m68k: String, CaseIterable, QEMUDisplayDevice {
     case nubus_macfb = "nubus-macfb"
     case virtio_gpu_device = "virtio-gpu-device"
@@ -7004,7 +7092,37 @@ enum QEMUDisplayDevice_mips64el: String, CaseIterable, QEMUDisplayDevice {
 
 typealias QEMUDisplayDevice_nios2 = AnyQEMUConstant
 
-typealias QEMUDisplayDevice_or1k = AnyQEMUConstant
+enum QEMUDisplayDevice_or1k: String, CaseIterable, QEMUDisplayDevice {
+    case cirrus_vga = "cirrus-vga"
+    case VGA
+    case ati_vga = "ati-vga"
+    case bochs_display = "bochs-display"
+    case secondary_vga = "secondary-vga"
+    case virtio_gpu_device = "virtio-gpu-device"
+    case virtio_gpu_gl_device = "virtio-gpu-gl-device"
+    case virtio_gpu_gl_pci = "virtio-gpu-gl-pci"
+    case virtio_gpu_pci = "virtio-gpu-pci"
+    case virtio_vga = "virtio-vga"
+    case virtio_vga_gl = "virtio-vga-gl"
+    case vmware_svga = "vmware-svga"
+
+    var prettyValue: String {
+        switch self {
+        case .cirrus_vga: return "Cirrus CLGD 54xx VGA (cirrus-vga)"
+        case .VGA: return "VGA"
+        case .ati_vga: return "ati-vga"
+        case .bochs_display: return "bochs-display"
+        case .secondary_vga: return "secondary-vga"
+        case .virtio_gpu_device: return "virtio-gpu-device"
+        case .virtio_gpu_gl_device: return "virtio-gpu-gl-device (GPU Supported)"
+        case .virtio_gpu_gl_pci: return "virtio-gpu-gl-pci (GPU Supported)"
+        case .virtio_gpu_pci: return "virtio-gpu-pci"
+        case .virtio_vga: return "virtio-vga"
+        case .virtio_vga_gl: return "virtio-vga-gl (GPU Supported)"
+        case .vmware_svga: return "vmware-svga"
+        }
+    }
+}
 
 enum QEMUDisplayDevice_ppc: String, CaseIterable, QEMUDisplayDevice {
     case cirrus_vga = "cirrus-vga"
@@ -7696,6 +7814,72 @@ enum QEMUNetworkDevice_i386: String, CaseIterable, QEMUNetworkDevice {
     }
 }
 
+enum QEMUNetworkDevice_loongarch64: String, CaseIterable, QEMUNetworkDevice {
+    case e1000e
+    case e1000
+    case e1000_82544gc = "e1000-82544gc"
+    case e1000_82545em = "e1000-82545em"
+    case i82550
+    case i82551
+    case i82557a
+    case i82557b
+    case i82557c
+    case i82558a
+    case i82558b
+    case i82559a
+    case i82559b
+    case i82559c
+    case i82559er
+    case i82562
+    case i82801
+    case rocker
+    case vmxnet3
+    case ne2k_isa
+    case ne2k_pci
+    case pcnet
+    case rtl8139
+    case tulip
+    case usb_net = "usb-net"
+    case virtio_net_device = "virtio-net-device"
+    case virtio_net_pci = "virtio-net-pci"
+    case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional"
+    case virtio_net_pci_transitional = "virtio-net-pci-transitional"
+
+    var prettyValue: String {
+        switch self {
+        case .e1000e: return "Intel 82574L GbE Controller (e1000e)"
+        case .e1000: return "Intel Gigabit Ethernet (e1000)"
+        case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)"
+        case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)"
+        case .i82550: return "Intel i82550 Ethernet (i82550)"
+        case .i82551: return "Intel i82551 Ethernet (i82551)"
+        case .i82557a: return "Intel i82557A Ethernet (i82557a)"
+        case .i82557b: return "Intel i82557B Ethernet (i82557b)"
+        case .i82557c: return "Intel i82557C Ethernet (i82557c)"
+        case .i82558a: return "Intel i82558A Ethernet (i82558a)"
+        case .i82558b: return "Intel i82558B Ethernet (i82558b)"
+        case .i82559a: return "Intel i82559A Ethernet (i82559a)"
+        case .i82559b: return "Intel i82559B Ethernet (i82559b)"
+        case .i82559c: return "Intel i82559C Ethernet (i82559c)"
+        case .i82559er: return "Intel i82559ER Ethernet (i82559er)"
+        case .i82562: return "Intel i82562 Ethernet (i82562)"
+        case .i82801: return "Intel i82801 Ethernet (i82801)"
+        case .rocker: return "Rocker Switch (rocker)"
+        case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)"
+        case .ne2k_isa: return "ne2k_isa"
+        case .ne2k_pci: return "ne2k_pci"
+        case .pcnet: return "pcnet"
+        case .rtl8139: return "rtl8139"
+        case .tulip: return "tulip"
+        case .usb_net: return "usb-net"
+        case .virtio_net_device: return "virtio-net-device"
+        case .virtio_net_pci: return "virtio-net-pci"
+        case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional"
+        case .virtio_net_pci_transitional: return "virtio-net-pci-transitional"
+        }
+    }
+}
+
 enum QEMUNetworkDevice_m68k: String, CaseIterable, QEMUNetworkDevice {
     case virtio_net_device = "virtio-net-device"
 
@@ -7964,7 +8148,65 @@ enum QEMUNetworkDevice_mips64el: String, CaseIterable, QEMUNetworkDevice {
 
 typealias QEMUNetworkDevice_nios2 = AnyQEMUConstant
 
-typealias QEMUNetworkDevice_or1k = AnyQEMUConstant
+enum QEMUNetworkDevice_or1k: String, CaseIterable, QEMUNetworkDevice {
+    case e1000
+    case e1000_82544gc = "e1000-82544gc"
+    case e1000_82545em = "e1000-82545em"
+    case i82550
+    case i82551
+    case i82557a
+    case i82557b
+    case i82557c
+    case i82558a
+    case i82558b
+    case i82559a
+    case i82559b
+    case i82559c
+    case i82559er
+    case i82562
+    case i82801
+    case vmxnet3
+    case ne2k_pci
+    case pcnet
+    case rtl8139
+    case tulip
+    case usb_net = "usb-net"
+    case virtio_net_device = "virtio-net-device"
+    case virtio_net_pci = "virtio-net-pci"
+    case virtio_net_pci_non_transitional = "virtio-net-pci-non-transitional"
+    case virtio_net_pci_transitional = "virtio-net-pci-transitional"
+
+    var prettyValue: String {
+        switch self {
+        case .e1000: return "Intel Gigabit Ethernet (e1000)"
+        case .e1000_82544gc: return "Intel Gigabit Ethernet (e1000-82544gc)"
+        case .e1000_82545em: return "Intel Gigabit Ethernet (e1000-82545em)"
+        case .i82550: return "Intel i82550 Ethernet (i82550)"
+        case .i82551: return "Intel i82551 Ethernet (i82551)"
+        case .i82557a: return "Intel i82557A Ethernet (i82557a)"
+        case .i82557b: return "Intel i82557B Ethernet (i82557b)"
+        case .i82557c: return "Intel i82557C Ethernet (i82557c)"
+        case .i82558a: return "Intel i82558A Ethernet (i82558a)"
+        case .i82558b: return "Intel i82558B Ethernet (i82558b)"
+        case .i82559a: return "Intel i82559A Ethernet (i82559a)"
+        case .i82559b: return "Intel i82559B Ethernet (i82559b)"
+        case .i82559c: return "Intel i82559C Ethernet (i82559c)"
+        case .i82559er: return "Intel i82559ER Ethernet (i82559er)"
+        case .i82562: return "Intel i82562 Ethernet (i82562)"
+        case .i82801: return "Intel i82801 Ethernet (i82801)"
+        case .vmxnet3: return "VMWare Paravirtualized Ethernet v3 (vmxnet3)"
+        case .ne2k_pci: return "ne2k_pci"
+        case .pcnet: return "pcnet"
+        case .rtl8139: return "rtl8139"
+        case .tulip: return "tulip"
+        case .usb_net: return "usb-net"
+        case .virtio_net_device: return "virtio-net-device"
+        case .virtio_net_pci: return "virtio-net-pci"
+        case .virtio_net_pci_non_transitional: return "virtio-net-pci-non-transitional"
+        case .virtio_net_pci_transitional: return "virtio-net-pci-transitional"
+        }
+    }
+}
 
 enum QEMUNetworkDevice_ppc: String, CaseIterable, QEMUNetworkDevice {
     case e1000e
@@ -8756,6 +8998,32 @@ enum QEMUSoundDevice_i386: String, CaseIterable, QEMUSoundDevice {
     }
 }
 
+enum QEMUSoundDevice_loongarch64: String, CaseIterable, QEMUSoundDevice {
+    case sb16
+    case cs4231a
+    case ES1370
+    case gus
+    case AC97
+    case intel_hda = "intel-hda"
+    case ich9_intel_hda = "ich9-intel-hda"
+    case adlib
+    case usb_audio = "usb-audio"
+
+    var prettyValue: String {
+        switch self {
+        case .sb16: return "Creative Sound Blaster 16 (sb16)"
+        case .cs4231a: return "Crystal Semiconductor CS4231A (cs4231a)"
+        case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)"
+        case .gus: return "Gravis Ultrasound GF1 (gus)"
+        case .AC97: return "Intel 82801AA AC97 Audio (AC97)"
+        case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)"
+        case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)"
+        case .adlib: return "Yamaha YM3812 (OPL2) (adlib)"
+        case .usb_audio: return "usb-audio"
+        }
+    }
+}
+
 typealias QEMUSoundDevice_m68k = AnyQEMUConstant
 
 typealias QEMUSoundDevice_microblaze = AnyQEMUConstant
@@ -8868,7 +9136,23 @@ enum QEMUSoundDevice_mips64el: String, CaseIterable, QEMUSoundDevice {
 
 typealias QEMUSoundDevice_nios2 = AnyQEMUConstant
 
-typealias QEMUSoundDevice_or1k = AnyQEMUConstant
+enum QEMUSoundDevice_or1k: String, CaseIterable, QEMUSoundDevice {
+    case ES1370
+    case AC97
+    case intel_hda = "intel-hda"
+    case ich9_intel_hda = "ich9-intel-hda"
+    case usb_audio = "usb-audio"
+
+    var prettyValue: String {
+        switch self {
+        case .ES1370: return "ENSONIQ AudioPCI ES1370 (ES1370)"
+        case .AC97: return "Intel 82801AA AC97 Audio (AC97)"
+        case .intel_hda: return "Intel HD Audio Controller (ich6) (intel-hda)"
+        case .ich9_intel_hda: return "Intel HD Audio Controller (ich9) (ich9-intel-hda)"
+        case .usb_audio: return "usb-audio"
+        }
+    }
+}
 
 enum QEMUSoundDevice_ppc: String, CaseIterable, QEMUSoundDevice {
     case sb16
@@ -9250,6 +9534,34 @@ enum QEMUSerialDevice_i386: String, CaseIterable, QEMUSerialDevice {
     }
 }
 
+enum QEMUSerialDevice_loongarch64: String, CaseIterable, QEMUSerialDevice {
+    case isa_serial = "isa-serial"
+    case pci_serial = "pci-serial"
+    case pci_serial_2x = "pci-serial-2x"
+    case pci_serial_4x = "pci-serial-4x"
+    case usb_serial = "usb-serial"
+    case virtio_serial_device = "virtio-serial-device"
+    case virtio_serial_pci = "virtio-serial-pci"
+    case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional"
+    case virtio_serial_pci_transitional = "virtio-serial-pci-transitional"
+    case virtserialport
+
+    var prettyValue: String {
+        switch self {
+        case .isa_serial: return "isa-serial"
+        case .pci_serial: return "pci-serial"
+        case .pci_serial_2x: return "pci-serial-2x"
+        case .pci_serial_4x: return "pci-serial-4x"
+        case .usb_serial: return "usb-serial"
+        case .virtio_serial_device: return "virtio-serial-device"
+        case .virtio_serial_pci: return "virtio-serial-pci"
+        case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional"
+        case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional"
+        case .virtserialport: return "virtserialport"
+        }
+    }
+}
+
 enum QEMUSerialDevice_m68k: String, CaseIterable, QEMUSerialDevice {
     case virtio_serial_device = "virtio-serial-device"
     case virtserialport
@@ -9380,7 +9692,31 @@ enum QEMUSerialDevice_mips64el: String, CaseIterable, QEMUSerialDevice {
 
 typealias QEMUSerialDevice_nios2 = AnyQEMUConstant
 
-typealias QEMUSerialDevice_or1k = AnyQEMUConstant
+enum QEMUSerialDevice_or1k: String, CaseIterable, QEMUSerialDevice {
+    case pci_serial = "pci-serial"
+    case pci_serial_2x = "pci-serial-2x"
+    case pci_serial_4x = "pci-serial-4x"
+    case usb_serial = "usb-serial"
+    case virtio_serial_device = "virtio-serial-device"
+    case virtio_serial_pci = "virtio-serial-pci"
+    case virtio_serial_pci_non_transitional = "virtio-serial-pci-non-transitional"
+    case virtio_serial_pci_transitional = "virtio-serial-pci-transitional"
+    case virtserialport
+
+    var prettyValue: String {
+        switch self {
+        case .pci_serial: return "pci-serial"
+        case .pci_serial_2x: return "pci-serial-2x"
+        case .pci_serial_4x: return "pci-serial-4x"
+        case .usb_serial: return "usb-serial"
+        case .virtio_serial_device: return "virtio-serial-device"
+        case .virtio_serial_pci: return "virtio-serial-pci"
+        case .virtio_serial_pci_non_transitional: return "virtio-serial-pci-non-transitional"
+        case .virtio_serial_pci_transitional: return "virtio-serial-pci-transitional"
+        case .virtserialport: return "virtserialport"
+        }
+    }
+}
 
 enum QEMUSerialDevice_ppc: String, CaseIterable, QEMUSerialDevice {
     case isa_serial = "isa-serial"
@@ -9690,6 +10026,7 @@ extension QEMUArchitecture {
         case .cris: return QEMUCPU_cris.self
         case .hppa: return QEMUCPU_hppa.self
         case .i386: return QEMUCPU_i386.self
+        case .loongarch64: return QEMUCPU_loongarch64.self
         case .m68k: return QEMUCPU_m68k.self
         case .microblaze: return QEMUCPU_microblaze.self
         case .microblazeel: return QEMUCPU_microblazeel.self
@@ -9725,6 +10062,7 @@ extension QEMUArchitecture {
         case .cris: return QEMUCPUFlag_cris.self
         case .hppa: return QEMUCPUFlag_hppa.self
         case .i386: return QEMUCPUFlag_i386.self
+        case .loongarch64: return QEMUCPUFlag_loongarch64.self
         case .m68k: return QEMUCPUFlag_m68k.self
         case .microblaze: return QEMUCPUFlag_microblaze.self
         case .microblazeel: return QEMUCPUFlag_microblazeel.self
@@ -9760,6 +10098,7 @@ extension QEMUArchitecture {
         case .cris: return QEMUTarget_cris.self
         case .hppa: return QEMUTarget_hppa.self
         case .i386: return QEMUTarget_i386.self
+        case .loongarch64: return QEMUTarget_loongarch64.self
         case .m68k: return QEMUTarget_m68k.self
         case .microblaze: return QEMUTarget_microblaze.self
         case .microblazeel: return QEMUTarget_microblazeel.self
@@ -9795,6 +10134,7 @@ extension QEMUArchitecture {
         case .cris: return QEMUDisplayDevice_cris.self
         case .hppa: return QEMUDisplayDevice_hppa.self
         case .i386: return QEMUDisplayDevice_i386.self
+        case .loongarch64: return QEMUDisplayDevice_loongarch64.self
         case .m68k: return QEMUDisplayDevice_m68k.self
         case .microblaze: return QEMUDisplayDevice_microblaze.self
         case .microblazeel: return QEMUDisplayDevice_microblazeel.self
@@ -9830,6 +10170,7 @@ extension QEMUArchitecture {
         case .cris: return QEMUNetworkDevice_cris.self
         case .hppa: return QEMUNetworkDevice_hppa.self
         case .i386: return QEMUNetworkDevice_i386.self
+        case .loongarch64: return QEMUNetworkDevice_loongarch64.self
         case .m68k: return QEMUNetworkDevice_m68k.self
         case .microblaze: return QEMUNetworkDevice_microblaze.self
         case .microblazeel: return QEMUNetworkDevice_microblazeel.self
@@ -9865,6 +10206,7 @@ extension QEMUArchitecture {
         case .cris: return QEMUSoundDevice_cris.self
         case .hppa: return QEMUSoundDevice_hppa.self
         case .i386: return QEMUSoundDevice_i386.self
+        case .loongarch64: return QEMUSoundDevice_loongarch64.self
         case .m68k: return QEMUSoundDevice_m68k.self
         case .microblaze: return QEMUSoundDevice_microblaze.self
         case .microblazeel: return QEMUSoundDevice_microblazeel.self
@@ -9900,6 +10242,7 @@ extension QEMUArchitecture {
         case .cris: return QEMUSerialDevice_cris.self
         case .hppa: return QEMUSerialDevice_hppa.self
         case .i386: return QEMUSerialDevice_i386.self
+        case .loongarch64: return QEMUSerialDevice_loongarch64.self
         case .m68k: return QEMUSerialDevice_m68k.self
         case .microblaze: return QEMUSerialDevice_microblaze.self
         case .microblazeel: return QEMUSerialDevice_microblazeel.self

+ 5 - 1
Managers/UTMQemuVirtualMachine.m

@@ -646,7 +646,11 @@ NSString *const kSuspendSnapshotName = @"suspend";
 #pragma mark - Screenshot
 
 - (void)updateScreenshot {
-    self.screenshot = [self.ioService screenshot];
+    [self.ioService screenshotWithCompletion:^(CSScreenshot * _Nullable screenshot) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            self.screenshot = screenshot;
+        });
+    }];
 }
 
 @end

+ 2 - 1
Managers/UTMSpiceIO.h

@@ -42,7 +42,6 @@ NS_ASSUME_NONNULL_BEGIN
 #endif
 @property (nonatomic, weak, nullable) id<UTMSpiceIODelegate> delegate;
 @property (nonatomic, readonly) BOOL isConnected;
-@property (nonatomic, readonly, nullable) CSScreenshot *screenshot;
 
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)initWithConfiguration:(UTMConfigurationWrapper *)configuration NS_DESIGNATED_INITIALIZER;
@@ -52,6 +51,8 @@ NS_ASSUME_NONNULL_BEGIN
 - (void)connectWithCompletion:(ioConnectCompletionHandler_t)block;
 - (void)disconnect;
 
+- (void)screenshotWithCompletion:(screenshotCallback_t)completion;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 2 - 2
Managers/UTMSpiceIO.m

@@ -153,8 +153,8 @@ extern NSString *const kUTMErrorDomain;
 #endif
 }
 
-- (CSScreenshot *)screenshot {
-    return [self.primaryDisplay screenshot];
+- (void)screenshotWithCompletion:(screenshotCallback_t)completion {
+    return [self.primaryDisplay screenshotWithCompletion:completion];
 }
 
 #pragma mark - CSConnectionDelegate

+ 24 - 0
UTM.xcodeproj/project.pbxproj

@@ -292,6 +292,16 @@
 		CE020BAC24AEE00000B44AB6 /* UTMLoggingSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE020BAA24AEE00000B44AB6 /* UTMLoggingSwift.swift */; };
 		CE020BB624B14F8400B44AB6 /* UTMVirtualMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE020BB524B14F8400B44AB6 /* UTMVirtualMachine.swift */; };
 		CE020BB724B14F8400B44AB6 /* UTMVirtualMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE020BB524B14F8400B44AB6 /* UTMVirtualMachine.swift */; };
+		CE02C8AA294EE4EB006DFE48 /* qemu-loongarch64-softmmu.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE02C8A8294EE4EA006DFE48 /* qemu-loongarch64-softmmu.framework */; };
+		CE02C8AB294EE4EB006DFE48 /* qemu-loongarch64-softmmu.framework in Embed Libraries */ = {isa = PBXBuildFile; fileRef = CE02C8A8294EE4EA006DFE48 /* qemu-loongarch64-softmmu.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+		CE02C8AC294EE4EC006DFE48 /* slirp.0.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE02C8A9294EE4EB006DFE48 /* slirp.0.framework */; };
+		CE02C8AD294EE4EC006DFE48 /* slirp.0.framework in Embed Libraries */ = {isa = PBXBuildFile; fileRef = CE02C8A9294EE4EB006DFE48 /* slirp.0.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+		CE02C8B1294EE58C006DFE48 /* slirp.0.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE02C8A9294EE4EB006DFE48 /* slirp.0.framework */; };
+		CE02C8B2294EE58C006DFE48 /* slirp.0.framework in Embed Libraries */ = {isa = PBXBuildFile; fileRef = CE02C8A9294EE4EB006DFE48 /* slirp.0.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+		CE02C8B3294EE59A006DFE48 /* slirp.0.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE02C8A9294EE4EB006DFE48 /* slirp.0.framework */; };
+		CE02C8B4294EE59A006DFE48 /* slirp.0.framework in Embed Libraries */ = {isa = PBXBuildFile; fileRef = CE02C8A9294EE4EB006DFE48 /* slirp.0.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+		CE02C8B5294EE59F006DFE48 /* qemu-loongarch64-softmmu.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE02C8A8294EE4EA006DFE48 /* qemu-loongarch64-softmmu.framework */; };
+		CE02C8B6294EE59F006DFE48 /* qemu-loongarch64-softmmu.framework in Embed Libraries */ = {isa = PBXBuildFile; fileRef = CE02C8A8294EE4EA006DFE48 /* qemu-loongarch64-softmmu.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
 		CE03D05224D90B4E00F76B84 /* UTMQemuSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = CE03D05024D90B4E00F76B84 /* UTMQemuSystem.m */; };
 		CE03D05324D90B4E00F76B84 /* UTMQemuSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = CE03D05024D90B4E00F76B84 /* UTMQemuSystem.m */; };
 		CE03D08624D90F0700F76B84 /* gmodule-2.0.0.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE2D63D822653C7300FC7E63 /* gmodule-2.0.0.framework */; };
@@ -1404,6 +1414,7 @@
 				CE0DF19625A83C1700A51894 /* qemu-arm-softmmu.framework in Embed Libraries */,
 				CE0DF19725A83C1700A51894 /* qemu-cris-softmmu.framework in Embed Libraries */,
 				CE0DF19825A83C1700A51894 /* qemu-hppa-softmmu.framework in Embed Libraries */,
+				CE02C8B4294EE59A006DFE48 /* slirp.0.framework in Embed Libraries */,
 				84937F0028960789003148F4 /* zstd.1.framework in Embed Libraries */,
 				CEA9054225F982C400801E7C /* usb-1.0.0.framework in Embed Libraries */,
 				CE0DF19925A83C1700A51894 /* qemu-i386-softmmu.framework in Embed Libraries */,
@@ -1422,6 +1433,7 @@
 				CE0DF1A725A83C1700A51894 /* qemu-riscv64-softmmu.framework in Embed Libraries */,
 				CE0DF1A825A83C1700A51894 /* qemu-s390x-softmmu.framework in Embed Libraries */,
 				CE0DF1A925A83C1700A51894 /* qemu-sh4-softmmu.framework in Embed Libraries */,
+				CE02C8B6294EE59F006DFE48 /* qemu-loongarch64-softmmu.framework in Embed Libraries */,
 				CE0DF1AA25A83C1700A51894 /* qemu-sh4eb-softmmu.framework in Embed Libraries */,
 				CE0DF1AB25A83C1700A51894 /* qemu-sparc-softmmu.framework in Embed Libraries */,
 				CE0DF1AC25A83C1700A51894 /* qemu-sparc64-softmmu.framework in Embed Libraries */,
@@ -1453,6 +1465,7 @@
 				CE2D937C24AD46670059923A /* ssl.1.1.framework in Embed Libraries */,
 				CEA9059125FC6A3300801E7C /* usbredirhost.1.framework in Embed Libraries */,
 				CE2D937D24AD46670059923A /* gio-2.0.0.framework in Embed Libraries */,
+				CE02C8AD294EE4EC006DFE48 /* slirp.0.framework in Embed Libraries */,
 				CE2D937E24AD46670059923A /* png16.16.framework in Embed Libraries */,
 				CE2D937F24AD46670059923A /* gstnet-1.0.0.framework in Embed Libraries */,
 				CE2D938024AD46670059923A /* qemu-cris-softmmu.framework in Embed Libraries */,
@@ -1506,6 +1519,7 @@
 				CE2D93AB24AD46670059923A /* opus.0.framework in Embed Libraries */,
 				CE2D93AD24AD46670059923A /* gstsdp-1.0.0.framework in Embed Libraries */,
 				CE2D93AE24AD46670059923A /* qemu-nios2-softmmu.framework in Embed Libraries */,
+				CE02C8AB294EE4EB006DFE48 /* qemu-loongarch64-softmmu.framework in Embed Libraries */,
 				CE2D93B024AD46670059923A /* gstaudio-1.0.0.framework in Embed Libraries */,
 				CE2D93B124AD46670059923A /* gstcheck-1.0.0.framework in Embed Libraries */,
 				CE2D93B224AD46670059923A /* qemu-xtensa-softmmu.framework in Embed Libraries */,
@@ -1576,6 +1590,7 @@
 				CEA45FA8263519B5002FA97D /* spice-client-glib-2.0.8.framework in Embed Libraries */,
 				CEA45FA9263519B5002FA97D /* opus.0.framework in Embed Libraries */,
 				CEA45FAA263519B5002FA97D /* gstsdp-1.0.0.framework in Embed Libraries */,
+				CE02C8B2294EE58C006DFE48 /* slirp.0.framework in Embed Libraries */,
 				CEA45FAC263519B5002FA97D /* gstaudio-1.0.0.framework in Embed Libraries */,
 				CEA45FAD263519B5002FA97D /* gstcheck-1.0.0.framework in Embed Libraries */,
 				CEA45FAF263519B5002FA97D /* iconv.2.framework in Embed Libraries */,
@@ -1792,6 +1807,8 @@
 		CE020BA224AEDC7C00B44AB6 /* UTMData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMData.swift; sourceTree = "<group>"; };
 		CE020BAA24AEE00000B44AB6 /* UTMLoggingSwift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMLoggingSwift.swift; sourceTree = "<group>"; };
 		CE020BB524B14F8400B44AB6 /* UTMVirtualMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMVirtualMachine.swift; sourceTree = "<group>"; };
+		CE02C8A8294EE4EA006DFE48 /* qemu-loongarch64-softmmu.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "qemu-loongarch64-softmmu.framework"; path = "$(SYSROOT_DIR)/Frameworks/qemu-loongarch64-softmmu.framework"; sourceTree = "<group>"; };
+		CE02C8A9294EE4EB006DFE48 /* slirp.0.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = slirp.0.framework; path = "$(SYSROOT_DIR)/Frameworks/slirp.0.framework"; sourceTree = "<group>"; };
 		CE03D05024D90B4E00F76B84 /* UTMQemuSystem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UTMQemuSystem.m; sourceTree = "<group>"; };
 		CE03D05424D90BE000F76B84 /* UTMQemuSystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UTMQemuSystem.h; sourceTree = "<group>"; };
 		CE03D0D024D9A62B00F76B84 /* QEMUHelper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = QEMUHelper.entitlements; sourceTree = "<group>"; };
@@ -2358,6 +2375,7 @@
 				CE2D933A24AD46670059923A /* libgstaudiorate.a in Frameworks */,
 				B3DDF57226E9BBA300CE47F0 /* AltKit in Frameworks */,
 				CE2D933B24AD46670059923A /* libgstvideofilter.a in Frameworks */,
+				CE02C8AA294EE4EB006DFE48 /* qemu-loongarch64-softmmu.framework in Frameworks */,
 				84018695288B66370050AC51 /* SwiftUIVisualEffects in Frameworks */,
 				84937F1D289767EC003148F4 /* zstd.1.framework in Frameworks */,
 				CE2D933C24AD46670059923A /* libgstapp.a in Frameworks */,
@@ -2383,6 +2401,7 @@
 				CE2D934E24AD46670059923A /* gstbase-1.0.0.framework in Frameworks */,
 				CE020BA724AEDEF000B44AB6 /* Logging in Frameworks */,
 				8401865A2887AFD50050AC51 /* SwiftTerm in Frameworks */,
+				CE02C8AC294EE4EC006DFE48 /* slirp.0.framework in Frameworks */,
 				CE2D934F24AD46670059923A /* phodav-2.0.0.framework in Frameworks */,
 				CEA9059025FC6A1700801E7C /* usbredirparser.1.framework in Frameworks */,
 				CE0E9B87252FD06B0026E02B /* SwiftUI.framework in Frameworks */,
@@ -2427,6 +2446,7 @@
 				CE0B6EF024AD677200FE012D /* gstcontroller-1.0.0.framework in Frameworks */,
 				CE0B6EE024AD677200FE012D /* libgstosxaudio.a in Frameworks */,
 				CE0B6F0D24AD677200FE012D /* libgstadder.a in Frameworks */,
+				CE02C8B3294EE59A006DFE48 /* slirp.0.framework in Frameworks */,
 				CE0B6EF224AD677200FE012D /* gstallocators-1.0.0.framework in Frameworks */,
 				CE03D08B24D90F2900F76B84 /* jpeg.62.framework in Frameworks */,
 				CE0B6EBC24AD677200FE012D /* gstpbutils-1.0.0.framework in Frameworks */,
@@ -2469,6 +2489,7 @@
 				CE0B6EE724AD677200FE012D /* libgstvideotestsrc.a in Frameworks */,
 				CE0B6EBB24AD677200FE012D /* libgstgio.a in Frameworks */,
 				84937EFF28960789003148F4 /* zstd.1.framework in Frameworks */,
+				CE02C8B5294EE59F006DFE48 /* qemu-loongarch64-softmmu.framework in Frameworks */,
 				CE0B6EE224AD677200FE012D /* gstnet-1.0.0.framework in Frameworks */,
 				CE03D08624D90F0700F76B84 /* gmodule-2.0.0.framework in Frameworks */,
 				CE03D0CA24D9142000F76B84 /* ssl.1.1.framework in Frameworks */,
@@ -2515,6 +2536,7 @@
 				CEA45F2F263519B5002FA97D /* libgstaudioresample.a in Frameworks */,
 				CEA45F30263519B5002FA97D /* libgstplayback.a in Frameworks */,
 				CEA45F31263519B5002FA97D /* libgstadder.a in Frameworks */,
+				CE02C8B1294EE58C006DFE48 /* slirp.0.framework in Frameworks */,
 				CEA45F32263519B5002FA97D /* libgstaudiorate.a in Frameworks */,
 				CEA45F33263519B5002FA97D /* libgstvideofilter.a in Frameworks */,
 				CEA45F34263519B5002FA97D /* libgstapp.a in Frameworks */,
@@ -2637,6 +2659,8 @@
 		CE2D63D622653C7300FC7E63 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				CE02C8A8294EE4EA006DFE48 /* qemu-loongarch64-softmmu.framework */,
+				CE02C8A9294EE4EB006DFE48 /* slirp.0.framework */,
 				84C5068528CA5702007CE8FF /* Hypervisor.framework */,
 				84818C0B2898A07A009EDB67 /* AVFAudio.framework */,
 				84937EFE28960789003148F4 /* zstd.1.framework */,

+ 1 - 1
UTM.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

@@ -15,7 +15,7 @@
       "location" : "https://github.com/utmapp/CocoaSpice.git",
       "state" : {
         "branch" : "main",
-        "revision" : "33f9e8e7cee801137238d33b793b92392d7a9854"
+        "revision" : "89fabc654b65568fae5192c1547023cfe333c2df"
       }
     },
     {

+ 0 - 0
patches/data/qemu-7.1.0-utm/pc-bios/edk2-aarch64-code.fd.bz2 → patches/data/qemu-7.2.0-utm/pc-bios/edk2-aarch64-code.fd.bz2


+ 0 - 0
patches/data/qemu-7.1.0-utm/pc-bios/edk2-arm-vars.fd.bz2 → patches/data/qemu-7.2.0-utm/pc-bios/edk2-arm-vars.fd.bz2


+ 0 - 0
patches/data/qemu-7.1.0-utm/pc-bios/edk2-i386-code.fd.bz2 → patches/data/qemu-7.2.0-utm/pc-bios/edk2-i386-code.fd.bz2


+ 0 - 0
patches/data/qemu-7.1.0-utm/pc-bios/edk2-i386-vars.fd.bz2 → patches/data/qemu-7.2.0-utm/pc-bios/edk2-i386-vars.fd.bz2


+ 0 - 0
patches/data/qemu-7.1.0-utm/pc-bios/edk2-x86_64-code.fd.bz2 → patches/data/qemu-7.2.0-utm/pc-bios/edk2-x86_64-code.fd.bz2


+ 0 - 0
patches/data/qemu-7.1.0-utm/pc-bios/openbios-ppc → patches/data/qemu-7.2.0-utm/pc-bios/openbios-ppc


+ 24 - 0
patches/gst-plugins-good-1.19.1.patch

@@ -0,0 +1,24 @@
+diff -Naur a/sys/osxaudio/gstosxcoreaudiocommon.c b/sys/osxaudio/gstosxcoreaudiocommon.c
+--- a/sys/osxaudio/gstosxcoreaudiocommon.c	2021-05-31 16:11:47.000000000 -0700
++++ b/sys/osxaudio/gstosxcoreaudiocommon.c	2022-12-24 23:00:48.000000000 -0800
+@@ -137,15 +137,16 @@
+       "osx ring buffer stop ioproc: %p device_id %lu",
+       core_audio->element->io_proc, (gulong) core_audio->device_id);
+ 
++  // ###: why is it okay to directly remove from here but not from pause() ?
++  if (core_audio->io_proc_active) {
++    gst_core_audio_remove_render_callback (core_audio);
++  }
++
+   status = AudioOutputUnitStop (core_audio->audiounit);
+   if (status) {
+     GST_WARNING_OBJECT (core_audio->osxbuf,
+         "AudioOutputUnitStop failed: %d", (int) status);
+   }
+-  // ###: why is it okay to directly remove from here but not from pause() ?
+-  if (core_audio->io_proc_active) {
+-    gst_core_audio_remove_render_callback (core_audio);
+-  }
+   return TRUE;
+ }
+ 

+ 25 - 0
patches/libslirp-v4.7.0.patch

@@ -0,0 +1,25 @@
+From 23019cdeb76de066cf3f05a599817e2ac6306747 Mon Sep 17 00:00:00 2001
+From: osy <osy@turing.llc>
+Date: Sat, 17 Dec 2022 20:10:22 -0800
+Subject: [PATCH] meson: add libresolv for iOS builds
+
+---
+ meson.build | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/meson.build b/meson.build
+index 5605dc9..f6d128e 100644
+--- a/meson.build
++++ b/meson.build
+@@ -62,7 +62,7 @@ if host_system == 'windows'
+     cc.find_library('ws2_32'),
+     cc.find_library('iphlpapi')
+   ]
+-elif host_system == 'darwin'
++elif host_system == 'darwin' or host_system == 'ios'
+   platform_deps += [
+     cc.find_library('resolv')
+   ]
+-- 
+2.28.0
+

+ 324 - 0
patches/qemu-7.2.0-utm.patch

@@ -0,0 +1,324 @@
+From bb5c41eb13130dada2f3cd766da9a537ef466a4b Mon Sep 17 00:00:00 2001
+From: osy <50960678+osy@users.noreply.github.com>
+Date: Tue, 20 Dec 2022 15:56:07 -0800
+Subject: [PATCH 1/3] spice-display: fix memory leak issues
+
+1) Some of the error cases did not free GL memory.
+2) Remove some unneeded logic and simplify the code.
+3) Add a `eglMakeCurrent` to `spice_iosurface_destroy` to make sure we are
+   freeing objects in the right context.
+---
+ ui/egl-helpers.c   |  1 +
+ ui/spice-display.c | 29 ++++++-----------------------
+ 2 files changed, 7 insertions(+), 23 deletions(-)
+
+diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
+index 0df9dd8fd5..a636e5f2f2 100644
+--- a/ui/egl-helpers.c
++++ b/ui/egl-helpers.c
+@@ -389,6 +389,7 @@ EGLSurface qemu_egl_init_buffer_surface(EGLContext ectx,
+     b = eglMakeCurrent(qemu_egl_display, esurface, esurface, ectx);
+     if (b == EGL_FALSE) {
+         error_report("egl: eglMakeCurrent failed");
++        qemu_egl_destroy_surface(esurface);
+         return NULL;
+     }
+ 
+diff --git a/ui/spice-display.c b/ui/spice-display.c
+index 4e4791484c..c1d2a66fc5 100644
+--- a/ui/spice-display.c
++++ b/ui/spice-display.c
+@@ -847,7 +847,7 @@ static int spice_iosurface_create(SimpleSpiceDisplay *ssd, int width, int height
+                            EGL_BIND_TO_TEXTURE_TARGET_ANGLE,
+                            &target) != EGL_TRUE) {
+         error_report("spice_iosurface_create: eglGetConfigAttrib failed");
+-        return 0;
++        goto gl_error;
+     }
+     if (target == EGL_TEXTURE_2D) {
+         tex_target = GL_TEXTURE_2D;
+@@ -855,7 +855,7 @@ static int spice_iosurface_create(SimpleSpiceDisplay *ssd, int width, int height
+         tex_target = GL_TEXTURE_RECTANGLE_ANGLE;
+     } else {
+         error_report("spice_iosurface_create: unsupported texture target");
+-        return 0;
++        goto gl_error;
+     }
+ 
+     const EGLint attribs[] = {
+@@ -880,6 +880,8 @@ static int spice_iosurface_create(SimpleSpiceDisplay *ssd, int width, int height
+ 
+     egl_fb_setup_new_tex_target(&ssd->iosurface_fb, width, height, tex_target);
+ 
++    eglBindTexImage(qemu_egl_display, ssd->esurface, EGL_BACK_BUFFER);
++
+     return 1;
+ gl_error:
+     CFRelease(ssd->iosurface);
+@@ -897,6 +899,8 @@ static void spice_iosurface_destroy(SimpleSpiceDisplay *ssd)
+         return;
+     }
+ #if defined(CONFIG_ANGLE)
++    eglMakeCurrent(qemu_egl_display, ssd->esurface, ssd->esurface, spice_gl_ctx);
++    eglReleaseTexImage(qemu_egl_display, ssd->esurface, EGL_BACK_BUFFER);
+     egl_fb_destroy(&ssd->iosurface_fb);
+     qemu_egl_destroy_surface(ssd->esurface);
+     ssd->esurface = EGL_NO_SURFACE;
+@@ -963,23 +967,10 @@ static void spice_iosurface_blit(SimpleSpiceDisplay *ssd, GLuint src_texture, bo
+ #if defined(CONFIG_ANGLE)
+     eglMakeCurrent(qemu_egl_display, ssd->esurface, ssd->esurface, spice_gl_ctx);
+     glBindTexture(ssd->iosurface_fb.texture_target, ssd->iosurface_fb.texture);
+-    eglBindTexImage(qemu_egl_display, ssd->esurface, EGL_BACK_BUFFER);
+     egl_texture_blit(ssd->gls, &ssd->iosurface_fb, &tmp_fb, flip, swap);
+ #endif
+ }
+ 
+-static void spice_iosurface_flush(SimpleSpiceDisplay *ssd)
+-{
+-    if (!ssd->iosurface) {
+-        return;
+-    }
+-
+-#if defined(CONFIG_ANGLE)
+-    eglMakeCurrent(qemu_egl_display, ssd->esurface, ssd->esurface, spice_gl_ctx);
+-    eglReleaseTexImage(qemu_egl_display, ssd->esurface, EGL_BACK_BUFFER);
+-#endif
+-}
+-
+ #endif
+ 
+ static void qemu_spice_gl_monitor_config(SimpleSpiceDisplay *ssd,
+@@ -1043,9 +1034,6 @@ static void spice_gl_refresh(DisplayChangeListener *dcl)
+     graphic_hw_update(dcl->con);
+     if (ssd->gl_updates && ssd->have_surface) {
+         qemu_spice_gl_block(ssd, true);
+-#if defined(CONFIG_IOSURFACE)
+-        spice_iosurface_flush(ssd);
+-#endif
+         glFlush();
+         cookie = (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_GL_DRAW_DONE, 0);
+         spice_qxl_gl_draw_async(&ssd->qxl, 0, 0,
+@@ -1079,10 +1067,6 @@ static void spice_gl_switch(DisplayChangeListener *dcl,
+     int width = 0, height = 0;
+ 
+     if (ssd->ds) {
+-#if defined(CONFIG_IOSURFACE)
+-        // need to release texture from surface before destorying it
+-        spice_iosurface_flush(ssd);
+-#endif
+         surface_gl_destroy_texture(ssd->gls, ssd->ds);
+     }
+     ssd->ds = new_surface;
+@@ -1346,7 +1330,6 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl,
+     GLuint tex_id = ssd->backing_borrow(ssd->backing_id, &y_0_top,
+                                         NULL, NULL);
+     spice_iosurface_blit(ssd, tex_id, !y_0_top, false);
+-    spice_iosurface_flush(ssd);
+     //TODO: cursor stuff
+ #endif
+ 
+-- 
+2.28.0
+
+From 34b035535eee0f8497a1492ae1d9478dc9c7e7a0 Mon Sep 17 00:00:00 2001
+From: osy <50960678+osy@users.noreply.github.com>
+Date: Sat, 24 Dec 2022 17:08:52 -0800
+Subject: [PATCH 2/3] spice-display: remove redundant glBindTexture
+
+---
+ ui/spice-display.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/ui/spice-display.c b/ui/spice-display.c
+index c1d2a66fc5..610edaa089 100644
+--- a/ui/spice-display.c
++++ b/ui/spice-display.c
+@@ -966,7 +966,6 @@ static void spice_iosurface_blit(SimpleSpiceDisplay *ssd, GLuint src_texture, bo
+ 
+ #if defined(CONFIG_ANGLE)
+     eglMakeCurrent(qemu_egl_display, ssd->esurface, ssd->esurface, spice_gl_ctx);
+-    glBindTexture(ssd->iosurface_fb.texture_target, ssd->iosurface_fb.texture);
+     egl_texture_blit(ssd->gls, &ssd->iosurface_fb, &tmp_fb, flip, swap);
+ #endif
+ }
+-- 
+2.28.0
+
+From bbc1efd4ca66d0892f2bced95fc6150192585a12 Mon Sep 17 00:00:00 2001
+From: osy <50960678+osy@users.noreply.github.com>
+Date: Sun, 25 Dec 2022 00:46:42 -0800
+Subject: [PATCH 3/3] Revert "virtio-blk: use BDRV_REQ_REGISTERED_BUF
+ optimization hint"
+
+This reverts commit baf422684d73c7bf38e2c18815e18d44fcf395b6.
+---
+ hw/block/virtio-blk.c          | 39 ++++++++++++----------------------
+ include/hw/virtio/virtio-blk.h |  2 --
+ 2 files changed, 14 insertions(+), 27 deletions(-)
+
+diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
+index f717550fdc..8131ec2dbc 100644
+--- a/hw/block/virtio-blk.c
++++ b/hw/block/virtio-blk.c
+@@ -21,7 +21,6 @@
+ #include "hw/block/block.h"
+ #include "hw/qdev-properties.h"
+ #include "sysemu/blockdev.h"
+-#include "sysemu/block-ram-registrar.h"
+ #include "sysemu/sysemu.h"
+ #include "sysemu/runstate.h"
+ #include "hw/virtio/virtio-blk.h"
+@@ -363,14 +362,12 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
+     }
+ }
+ 
+-static inline void submit_requests(VirtIOBlock *s, MultiReqBuffer *mrb,
++static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb,
+                                    int start, int num_reqs, int niov)
+ {
+-    BlockBackend *blk = s->blk;
+     QEMUIOVector *qiov = &mrb->reqs[start]->qiov;
+     int64_t sector_num = mrb->reqs[start]->sector_num;
+     bool is_write = mrb->is_write;
+-    BdrvRequestFlags flags = 0;
+ 
+     if (num_reqs > 1) {
+         int i;
+@@ -401,18 +398,12 @@ static inline void submit_requests(VirtIOBlock *s, MultiReqBuffer *mrb,
+                               num_reqs - 1);
+     }
+ 
+-    if (blk_ram_registrar_ok(&s->blk_ram_registrar)) {
+-        flags |= BDRV_REQ_REGISTERED_BUF;
+-    }
+-
+     if (is_write) {
+-        blk_aio_pwritev(blk, sector_num << BDRV_SECTOR_BITS, qiov,
+-                        flags, virtio_blk_rw_complete,
+-                        mrb->reqs[start]);
++        blk_aio_pwritev(blk, sector_num << BDRV_SECTOR_BITS, qiov, 0,
++                        virtio_blk_rw_complete, mrb->reqs[start]);
+     } else {
+-        blk_aio_preadv(blk, sector_num << BDRV_SECTOR_BITS, qiov,
+-                       flags, virtio_blk_rw_complete,
+-                       mrb->reqs[start]);
++        blk_aio_preadv(blk, sector_num << BDRV_SECTOR_BITS, qiov, 0,
++                       virtio_blk_rw_complete, mrb->reqs[start]);
+     }
+ }
+ 
+@@ -434,14 +425,14 @@ static int multireq_compare(const void *a, const void *b)
+     }
+ }
+ 
+-static void virtio_blk_submit_multireq(VirtIOBlock *s, MultiReqBuffer *mrb)
++static void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
+ {
+     int i = 0, start = 0, num_reqs = 0, niov = 0, nb_sectors = 0;
+     uint32_t max_transfer;
+     int64_t sector_num = 0;
+ 
+     if (mrb->num_reqs == 1) {
+-        submit_requests(s, mrb, 0, 1, -1);
++        submit_requests(blk, mrb, 0, 1, -1);
+         mrb->num_reqs = 0;
+         return;
+     }
+@@ -461,11 +452,11 @@ static void virtio_blk_submit_multireq(VirtIOBlock *s, MultiReqBuffer *mrb)
+              * 3. merge would exceed maximum transfer length of backend device
+              */
+             if (sector_num + nb_sectors != req->sector_num ||
+-                niov > blk_get_max_iov(s->blk) - req->qiov.niov ||
++                niov > blk_get_max_iov(blk) - req->qiov.niov ||
+                 req->qiov.size > max_transfer ||
+                 nb_sectors > (max_transfer -
+                               req->qiov.size) / BDRV_SECTOR_SIZE) {
+-                submit_requests(s, mrb, start, num_reqs, niov);
++                submit_requests(blk, mrb, start, num_reqs, niov);
+                 num_reqs = 0;
+             }
+         }
+@@ -481,7 +472,7 @@ static void virtio_blk_submit_multireq(VirtIOBlock *s, MultiReqBuffer *mrb)
+         num_reqs++;
+     }
+ 
+-    submit_requests(s, mrb, start, num_reqs, niov);
++    submit_requests(blk, mrb, start, num_reqs, niov);
+     mrb->num_reqs = 0;
+ }
+ 
+@@ -496,7 +487,7 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
+      * Make sure all outstanding writes are posted to the backing device.
+      */
+     if (mrb->is_write && mrb->num_reqs > 0) {
+-        virtio_blk_submit_multireq(s, mrb);
++        virtio_blk_submit_multireq(s->blk, mrb);
+     }
+     blk_aio_flush(s->blk, virtio_blk_flush_complete, req);
+ }
+@@ -676,7 +667,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
+         if (mrb->num_reqs > 0 && (mrb->num_reqs == VIRTIO_BLK_MAX_MERGE_REQS ||
+                                   is_write != mrb->is_write ||
+                                   !s->conf.request_merging)) {
+-            virtio_blk_submit_multireq(s, mrb);
++            virtio_blk_submit_multireq(s->blk, mrb);
+         }
+ 
+         assert(mrb->num_reqs < VIRTIO_BLK_MAX_MERGE_REQS);
+@@ -783,7 +774,7 @@ void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
+     } while (!virtio_queue_empty(vq));
+ 
+     if (mrb.num_reqs) {
+-        virtio_blk_submit_multireq(s, &mrb);
++        virtio_blk_submit_multireq(s->blk, &mrb);
+     }
+ 
+     blk_io_unplug(s->blk);
+@@ -832,7 +823,7 @@ void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh)
+     }
+ 
+     if (mrb.num_reqs) {
+-        virtio_blk_submit_multireq(s, &mrb);
++        virtio_blk_submit_multireq(s->blk, &mrb);
+     }
+     if (is_bh) {
+         blk_dec_in_flight(s->conf.conf.blk);
+@@ -1214,7 +1205,6 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
+     }
+ 
+     s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
+-    blk_ram_registrar_init(&s->blk_ram_registrar, s->blk);
+     blk_set_dev_ops(s->blk, &virtio_block_ops, s);
+ 
+     blk_iostatus_enable(s->blk);
+@@ -1240,7 +1230,6 @@ static void virtio_blk_device_unrealize(DeviceState *dev)
+         virtio_del_queue(vdev, i);
+     }
+     qemu_coroutine_dec_pool_size(conf->num_queues * conf->queue_size / 2);
+-    blk_ram_registrar_destroy(&s->blk_ram_registrar);
+     qemu_del_vm_change_state_handler(s->change);
+     blockdev_mark_auto_del(s->blk);
+     virtio_cleanup(vdev);
+diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
+index 7f589b4146..d311c57cca 100644
+--- a/include/hw/virtio/virtio-blk.h
++++ b/include/hw/virtio/virtio-blk.h
+@@ -19,7 +19,6 @@
+ #include "hw/block/block.h"
+ #include "sysemu/iothread.h"
+ #include "sysemu/block-backend.h"
+-#include "sysemu/block-ram-registrar.h"
+ #include "qom/object.h"
+ 
+ #define TYPE_VIRTIO_BLK "virtio-blk-device"
+@@ -65,7 +64,6 @@ struct VirtIOBlock {
+     struct VirtIOBlockDataPlane *dataplane;
+     uint64_t host_features;
+     size_t config_size;
+-    BlockRAMRegistrar blk_ram_registrar;
+ };
+ 
+ typedef struct VirtIOBlockReq {
+-- 
+2.28.0
+

+ 5 - 4
patches/sources

@@ -19,8 +19,9 @@ ZSTD_SRC="https://github.com/facebook/zstd/releases/download/v1.5.2/zstd-1.5.2.t
 SPICE_PROTOCOL_SRC="https://www.spice-space.org/download/releases/spice-protocol-0.14.4.tar.xz"
 SPICE_SERVER_SRC="https://www.spice-space.org/download/releases/spice-server/spice-0.14.3.tar.bz2"
 USB_SRC="https://github.com/libusb/libusb/releases/download/v1.0.25/libusb-1.0.25.tar.bz2"
-USBREDIR_SRC="https://www.spice-space.org/download/usbredir/usbredir-0.12.0.tar.xz"
-QEMU_SRC="https://github.com/utmapp/qemu/releases/download/v7.1.0-utm/qemu-7.1.0-utm.tar.bz2"
+USBREDIR_SRC="https://www.spice-space.org/download/usbredir/usbredir-0.13.0.tar.xz"
+SLIRP_SRC="https://gitlab.freedesktop.org/slirp/libslirp/-/archive/v4.7.0/libslirp-v4.7.0.tar.gz"
+QEMU_SRC="https://github.com/utmapp/qemu/releases/download/v7.2.0-utm/qemu-7.2.0-utm.tar.bz2"
 
 # Source files for spice-client
 JSON_GLIB_SRC="https://download.gnome.org/sources/json-glib/1.6/json-glib-1.6.6.tar.xz"
@@ -36,11 +37,11 @@ SPICE_CLIENT_SRC="https://www.spice-space.org/download/gtk/spice-gtk-0.40.tar.xz
 DEPOT_TOOLS_REPO="https://chromium.googlesource.com/chromium/tools/depot_tools.git"
 DEPOT_TOOLS_COMMIT="5da65ec20db9b17b03420d928240092e5955a769"
 ANGLE_REPO="https://github.com/utmapp/angle.git"
-ANGLE_COMMIT="b9b67fbf749b7a5402593e54d01386c0cd96c42a"
+ANGLE_COMMIT="70e456bebd831c3c015c3fcca8b7e0e1ec9e04ef"
 EPOXY_REPO="https://github.com/utmapp/libepoxy.git"
 EPOXY_COMMIT="266d2290a437c655f7419e85af06bfbb73a720c4"
 VIRGLRENDERER_REPO="https://github.com/utmapp/virglrenderer.git"
-VIRGLRENDERER_COMMIT="2415ce6e2d66d2892bf214daf123b6d7bb2af9dc"
+VIRGLRENDERER_COMMIT="d46413cf4797a33cfbe1c9f14e6d22ce563ef700"
 
 # Decompiled Hypervisor for iOS
 HYPERVISOR_REPO="https://github.com/utmapp/Hypervisor.git"

+ 55 - 20
patches/spice-0.14.3.patch

@@ -1,7 +1,7 @@
 From c74ae160e3ac6d726fd312ba36f5ca4bfed0eb9c Mon Sep 17 00:00:00 2001
 From: Frediano Ziglio <fziglio@redhat.com>
 Date: Wed, 15 Apr 2020 13:36:13 +0100
-Subject: [PATCH 01/10] Fix compatibility with MSG_NOSIGNAL and Darwin
+Subject: [PATCH 01/11] Fix compatibility with MSG_NOSIGNAL and Darwin
 
 Darwin does not have MSG_NOSIGNAL but allows to set a SO_NOSIGPIPE
 option to disable sending SIGPIPE writing to closed socket.
@@ -74,12 +74,12 @@ index 3a3b7878..2935cfb5 100644
 +
  #endif // RED_SYS_SOCKET_H_
 -- 
-2.32.0 (Apple Git-132)
+2.28.0
 
 From c3ca9e8db128fb8e9fa033f8f1aabb96514f6f94 Mon Sep 17 00:00:00 2001
 From: Frediano Ziglio <fziglio@redhat.com>
 Date: Wed, 15 Apr 2020 14:30:37 +0100
-Subject: [PATCH 02/10] Fix compatibility with pthread_setname_np and Darwin
+Subject: [PATCH 02/11] Fix compatibility with pthread_setname_np and Darwin
 
 On Darwin pthread_setname_np accepts only an argument and
 set current thread name.
@@ -114,12 +114,12 @@ index 12a8e739..2f07337e 100644
      return r == 0;
  }
 -- 
-2.32.0 (Apple Git-132)
+2.28.0
 
 From d728111a51c8c08806e78c3b0d46d92a048b865a Mon Sep 17 00:00:00 2001
 From: Frediano Ziglio <fziglio@redhat.com>
 Date: Wed, 15 Apr 2020 14:35:10 +0100
-Subject: [PATCH 03/10] Fix compatibility with mremap and Darwin
+Subject: [PATCH 03/11] Fix compatibility with mremap and Darwin
 
 Darwin does not have mremap. Use munmap+mmap instead.
 That code is not in a hot path, number of nodes do not change very
@@ -158,12 +158,12 @@ index deffec1b..7d35c45b 100644
              }
              reds_nodes = (SpiceStatNode *)((char *) reds_stat + header_size);
 -- 
-2.32.0 (Apple Git-132)
+2.28.0
 
 From 20e058fd9ba28892adffc8d2ade809b698577756 Mon Sep 17 00:00:00 2001
 From: Frediano Ziglio <fziglio@redhat.com>
 Date: Wed, 15 Apr 2020 20:47:05 +0100
-Subject: [PATCH 04/10] Fix compatibility with TCP_KEEPIDLE and Darwin
+Subject: [PATCH 04/11] Fix compatibility with TCP_KEEPIDLE and Darwin
 
 Darwin uses for the same setting the TCP_KEEPALIVE option.
 Use TCP_KEEPALIVE instead of TCP_KEEPIDLE for Darwin.
@@ -198,12 +198,12 @@ index 78b94886..32ceb3b8 100644
          if (errno != ENOTSUP) {
              g_warning("setsockopt for keepalive timeout failed, %s", strerror(errno));
 -- 
-2.32.0 (Apple Git-132)
+2.28.0
 
 From eb21efe8e5d6fa2cc893b1f7fec356fd06834d30 Mon Sep 17 00:00:00 2001
 From: Frediano Ziglio <fziglio@redhat.com>
 Date: Wed, 15 Apr 2020 20:50:56 +0100
-Subject: [PATCH 05/10] Fix compatibility with ENOTSUP and Darwin
+Subject: [PATCH 05/11] Fix compatibility with ENOTSUP and Darwin
 
 Darwin uses also the constant EOPNOTSUPP for the same reasons.
 In some versions EOPNOTSUPP is defined as ENOTSUP.
@@ -259,12 +259,12 @@ index 32ceb3b8..f0aecc3d 100644
              return false;
          }
 -- 
-2.32.0 (Apple Git-132)
+2.28.0
 
 From f93264cb497ea3ab45d35ab3e03546d1cdaa1600 Mon Sep 17 00:00:00 2001
 From: Frediano Ziglio <fziglio@redhat.com>
 Date: Wed, 15 Apr 2020 21:15:34 +0100
-Subject: [PATCH 06/10] Fix compatibility with TCP sockets and Darwin
+Subject: [PATCH 06/11] Fix compatibility with TCP sockets and Darwin
 
 Using socket pairs and trying to set a TCP level option on the
 socket setsockopt returns EINVAL error and not ENOTSUP as
@@ -335,12 +335,12 @@ index f0aecc3d..e9778e73 100644
              return false;
          }
 -- 
-2.32.0 (Apple Git-132)
+2.28.0
 
 From 2e6271dbbab76e3868a6cee1c9a800d87ccd30a1 Mon Sep 17 00:00:00 2001
 From: osy <osy@turing.llc>
 Date: Fri, 4 Mar 2022 19:17:58 -0800
-Subject: [PATCH 07/10] red-stream: disable socket_set_cork() on Darwin
+Subject: [PATCH 07/11] red-stream: disable socket_set_cork() on Darwin
 
 TCP_NOPUSH is broken and cannot be used.
 ---
@@ -371,12 +371,12 @@ index 2c13aa2f..77d44c9a 100644
   * Set TCP_CORK on socket
   */
 -- 
-2.32.0 (Apple Git-132)
+2.28.0
 
 From 740fb04a95ff2a5aebd67f488e7d6f19b62fe3c1 Mon Sep 17 00:00:00 2001
 From: osy <osy@turing.llc>
 Date: Fri, 4 Mar 2022 19:20:06 -0800
-Subject: [PATCH 08/10] meson: fix build on Darwin
+Subject: [PATCH 08/11] meson: fix build on Darwin
 
 ---
  meson.build              | 4 +++-
@@ -428,12 +428,12 @@ index 8ec2cc91..4962f63d 100644
               install : false,
               include_directories : spice_server_include,
 -- 
-2.32.0 (Apple Git-132)
+2.28.0
 
 From a411fbcb321347356a78126e923bd49aa91381df Mon Sep 17 00:00:00 2001
 From: osy <osy@turing.llc>
 Date: Fri, 4 Mar 2022 19:23:44 -0800
-Subject: [PATCH 09/10] reds: always send monitors config
+Subject: [PATCH 09/11] reds: always send monitors config
 
 When the Windows VDagent sees a new monitor config, it will trigger a
 refresh of the display resolution. This is needed when the device driver
@@ -457,12 +457,12 @@ index d91b32b0..9513b5cf 100644
          red_channel_client_shutdown(RED_CHANNEL_CLIENT(mcc));
          return;
 -- 
-2.32.0 (Apple Git-132)
+2.28.0
 
 From e32a7ea61569b7771f0ef655fba86f6d23d53d31 Mon Sep 17 00:00:00 2001
 From: osy <osy@turing.llc>
 Date: Fri, 4 Mar 2022 20:09:34 -0800
-Subject: [PATCH 10/10] gstreamer-encoder: work without Orc
+Subject: [PATCH 10/11] gstreamer-encoder: work without Orc
 
 If Orc is missing, GStreamer will still work.
 ---
@@ -525,7 +525,41 @@ index 3ca04d7a..238463f2 100644
  VideoEncoder *gstreamer_encoder_new(SpiceVideoCodecType codec_type,
                                      uint64_t starting_bit_rate,
 -- 
-2.32.0 (Apple Git-132)
+2.28.0
+
+From 02cae4922d55c488cce790835ee2fccd61e34dbd Mon Sep 17 00:00:00 2001
+From: osy <osy@turing.llc>
+Date: Sun, 18 Dec 2022 23:20:48 -0800
+Subject: [PATCH 11/11] red-qxl: remove cookie assertion on scanout
+
+The original check ensures we do not have an outstanding GL_DRAW. However,
+in QEMU, there is no guarantee that a scanout cannot happen while the async
+GL_DRAW has not returned a result yet. This introduces a race where if a
+scanout is called while there is an outstanding GL_DRAW, QEMU will crash.
+
+The removal of this check enforces a new contract with the SPICE client.
+Every GL_DRAW must be matched with a GL_DONE (i.e. with a call to
+`spice_display_channel_gl_draw_done()` in the client) even if the render
+context is no longer valid. Otherwise, the assertion crash will happen in
+the next call to `spice_qxl_gl_draw_async()`.
+---
+ server/red-qxl.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/server/red-qxl.c b/server/red-qxl.c
+index dbfcd440..8cdf86f5 100644
+--- a/server/red-qxl.c
++++ b/server/red-qxl.c
+@@ -703,7 +703,6 @@ void spice_qxl_gl_scanout(QXLInstance *qxl,
+     spice_return_if_fail(qxl != NULL);
+ 
+     QXLState *qxl_state = qxl->st;
+-    spice_return_if_fail(qxl_state->gl_draw_cookie == GL_DRAW_COOKIE_INVALID);
+ 
+     pthread_mutex_lock(&qxl_state->scanout_mutex);
+ 
+-- 
+2.28.0
 
 --- a/subprojects/spice-common/meson.build	2022-03-04 19:26:32.000000000 -0800
 +++ b/subprojects/spice-common/meson.build	2022-03-04 19:26:03.000000000 -0800
@@ -549,3 +583,4 @@ index 3ca04d7a..238463f2 100644
      if cmd.returncode() != 0
        error('Python module @0@ not found'.format(module))
      endif
+

+ 3 - 1
scripts/build_dependencies.sh

@@ -149,6 +149,7 @@ download_all () {
     download $PHODAV_SRC
     download $SPICE_CLIENT_SRC
     download $ZSTD_SRC
+    download $SLIRP_SRC
     download $QEMU_SRC
     if [ -z "$SKIP_USB_BUILD" ]; then
         download $USB_SRC
@@ -491,6 +492,7 @@ build_qemu_dependencies () {
     meson_build $GST_GOOD_SRC -Dtests=disabled -Ddefault_library=both
     meson_build $SPICE_PROTOCOL_SRC
     meson_build $SPICE_SERVER_SRC -Dlz4=false -Dsasl=false
+    meson_build $SLIRP_SRC
     # USB support
     if [ -z "$SKIP_USB_BUILD" ]; then
         build $USB_SRC
@@ -499,7 +501,7 @@ build_qemu_dependencies () {
     # GPU support
     build_angle
     meson_build $EPOXY_REPO -Dtests=false -Dglx=no -Degl=yes
-    meson_build $VIRGLRENDERER_REPO -Dtests=false
+    meson_build $VIRGLRENDERER_REPO -Dtests=false -Dcheck-gl-errors=false
     # Hypervisor for iOS
     if [ "$PLATFORM" == "ios" ]; then
         build_hypervisor

+ 1 - 0
scripts/const-gen.py

@@ -20,6 +20,7 @@ TARGETS = [
     Name("cris", "CRIS"),
     Name("hppa", "HPPA"),
     Name("i386", "i386 (x86)"),
+    Name("loongarch64", "LoongArch64"),
     Name("m68k", "m68k"),
     Name("microblaze", "Microblaze"),
     Name("microblazeel", "Microblaze (Little Endian)"),