From 870dc69df0bee7309430a5f0cc3219e5ebdc4a47 Mon Sep 17 00:00:00 2001
From: yangchenguang <yangchenguang@kylinsec.com.cn>
Date: Tue, 6 Jun 2023 19:53:32 +0800
Subject: [PATCH] Add loongarch64 support

Signed-off-by: yangchenguang <yangchenguang@kylinsec.com.cn>
---
 virtManager/create.py        |  4 ++++
 virtinst/devices/disk.py     |  2 ++
 virtinst/devices/graphics.py |  2 +-
 virtinst/devices/video.py    |  2 ++
 virtinst/domain/cpu.py       |  5 +++++
 virtinst/domain/os.py        |  2 ++
 virtinst/domcapabilities.py  |  4 ++++
 virtinst/guest.py            | 14 ++++++++++----
 8 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/virtManager/create.py b/virtManager/create.py
index e7ddd0c..2afd400 100644
--- a/virtManager/create.py
+++ b/virtManager/create.py
@@ -428,6 +428,7 @@ class vmmCreate(vmmGObjectUI):
         installable_arch = bool(guest.os.is_x86() or
                 guest.os.is_ppc64() or
                 guest.os.is_sw_64() or
+                guest.os.is_loongarch() or
                 guest.os.is_s390x())
 
         if guest.prefers_uefi():
@@ -823,6 +824,9 @@ class vmmCreate(vmmGObjectUI):
         machines.sort()
 
         defmachine = None
+
+        if self._capsinfo.arch in ["loongarch64"]:
+            defmachine = "loongson7a"
         prios = []
         recommended_machine = virtinst.Guest.get_recommended_machine(
                 self._capsinfo)
diff --git a/virtinst/devices/disk.py b/virtinst/devices/disk.py
index 533631e..ac20f08 100644
--- a/virtinst/devices/disk.py
+++ b/virtinst/devices/disk.py
@@ -963,6 +963,8 @@ class DeviceDisk(Device):
             return "sata"
         if self.is_cdrom() and guest.os.is_s390x():
             return "scsi"
+        if self.is_cdrom() and guest.os.is_loongarch():
+            return "scsi"
         return "ide"
 
     def set_defaults(self, guest):
diff --git a/virtinst/devices/graphics.py b/virtinst/devices/graphics.py
index dafae06..fa0b9e1 100644
--- a/virtinst/devices/graphics.py
+++ b/virtinst/devices/graphics.py
@@ -203,7 +203,7 @@ class DeviceGraphics(Device):
         if not self.conn.is_qemu() and not self.conn.is_test():
             return False
         # Spice has issues on some host arches, like ppc, so whitelist it
-        if self.conn.caps.host.cpu.arch not in ["i686", "x86_64"]:
+        if self.conn.caps.host.cpu.arch not in ["i686", "x86_64", "loongarch64"]:
             return False
         return True
 
diff --git a/virtinst/devices/video.py b/virtinst/devices/video.py
index 785d412..5e459bb 100644
--- a/virtinst/devices/video.py
+++ b/virtinst/devices/video.py
@@ -47,6 +47,8 @@ class DeviceVideo(Device):
             return "virtio"
         if guest.conn.is_qemu() and guest.os.is_s390x():
             return "virtio"
+        if guest.os.is_loongarch():
+            return "virtio"
         if guest.has_spice() and guest.os.is_x86():
             if guest.has_gl():
                 return "virtio"
diff --git a/virtinst/domain/cpu.py b/virtinst/domain/cpu.py
index 3548acd..7d35a11 100644
--- a/virtinst/domain/cpu.py
+++ b/virtinst/domain/cpu.py
@@ -274,6 +274,11 @@ class DomainCpu(XMLBuilder):
             # -M virt defaults to a 32bit CPU, even if using aarch64
             self.model = "cortex-a57"
 
+        elif guest.os.is_loongarch() and guest.type == "kvm":
+            if guest.os.arch != self.conn.caps.host.cpu.arch:
+                return
+            self.set_special_mode(guest, guest.loongarch_cpu_default)
+
         elif guest.os.is_x86() and guest.type == "kvm":
             self._set_cpu_x86_kvm_default(guest)
 
diff --git a/virtinst/domain/os.py b/virtinst/domain/os.py
index fdcaa19..fe46dd2 100644
--- a/virtinst/domain/os.py
+++ b/virtinst/domain/os.py
@@ -48,6 +48,8 @@ class DomainOs(XMLBuilder):
         return self.arch == "aarch64"
     def is_sw_64(self):
         return self.arch == "sw_64"
+    def is_loongarch(self):
+        return self.arch == "loongarch64"
     def is_arm(self):
         return self.is_arm32() or self.is_arm64()
     def is_arm_vexpress(self):
diff --git a/virtinst/domcapabilities.py b/virtinst/domcapabilities.py
index 4cbb7f2..1fbb3d0 100644
--- a/virtinst/domcapabilities.py
+++ b/virtinst/domcapabilities.py
@@ -177,6 +177,10 @@ class DomainCapabilities(XMLBuilder):
         "armv7l": [
             r".*arm/QEMU_EFI.*",  # fedora, gerd's firmware repo
         ],
+        "loongarch64": [
+            ".*loongarch_bios.bin",  # loongarch
+            ".*loongarch_bios.bin",  # gerd's firmware repo
+        ],
     }
 
     def find_uefi_path_for_arch(self):
diff --git a/virtinst/guest.py b/virtinst/guest.py
index c0471cd..c539276 100644
--- a/virtinst/guest.py
+++ b/virtinst/guest.py
@@ -162,6 +162,7 @@ class Guest(XMLBuilder):
         self.skip_default_graphics = False
         self.skip_default_rng = False
         self.x86_cpu_default = self.cpu.SPECIAL_MODE_APP_DEFAULT
+        self.loongarch_cpu_default = self.cpu.SPECIAL_MODE_HOST_MODEL_ONLY
 
         self.__osinfo = None
         self._capsinfo = None
@@ -283,6 +284,7 @@ class Guest(XMLBuilder):
         # These _only_ support virtio so don't check the OS
         if (self.os.is_arm_machvirt() or
             self.os.is_s390x() or
+            self.os.is_loongarch() or
             self.os.is_pseries()):
             return True
 
@@ -318,7 +320,7 @@ class Guest(XMLBuilder):
         arm+machvirt prefers UEFI since it's required for traditional
         install methods
         """
-        return self.os.is_arm_machvirt()
+        return (self.os.is_arm_machvirt() or self.os.is_loongarch())
 
     def get_uefi_path(self):
         """
@@ -350,6 +352,8 @@ class Guest(XMLBuilder):
         """
         self.os.loader_ro = True
         self.os.loader_type = "pflash"
+        if self.os.is_loongarch():
+            self.os.loader_type = "rom"
         self.os.loader = path
 
         # If the firmware name contains "secboot" it is probably build
@@ -573,7 +577,7 @@ class Guest(XMLBuilder):
         usb_keyboard = False
         if self.os.is_x86() and not self.os.is_xenpv():
             usb_tablet = self.osinfo.supports_usbtablet()
-        if self.os.is_arm_machvirt():
+        if (self.os.is_arm_machvirt() or self.os.is_loongarch()):
             usb_tablet = True
             usb_keyboard = True
 
@@ -665,7 +669,7 @@ class Guest(XMLBuilder):
             return
         if self.os.is_container() and not self.conn.is_vz():
             return
-        if self.os.arch not in ["x86_64", "i686", "ppc64", "ppc64le"]:
+        if self.os.arch not in ["x86_64", "i686", "ppc64", "ppc64le", "loongarch64"]:
             return
         self.add_device(DeviceGraphics(self.conn))
 
@@ -711,7 +715,7 @@ class Guest(XMLBuilder):
                     break
 
         # Add virtio-scsi controller if needed
-        if ((self.os.is_arm_machvirt() or self.os.is_pseries()) and
+        if ((self.os.is_arm_machvirt() or self.os.is_pseries() or self.os.is_loongarch()) and
             not has_any_scsi and
             not has_virtio_scsi):
             for dev in self.devices.disk:
@@ -753,6 +757,8 @@ class Guest(XMLBuilder):
         self.add_device(dev)
 
     def _add_spice_usbredir(self):
+        if self.os.is_loongarch():
+            return
         if self.skip_default_usbredir:
             return
         if self.devices.redirdev:
-- 
2.33.0

