[dts] [PATCH] framework: enable AArch64 and add more options for libvirt

Herbert Guan herbert.guan at arm.com
Tue Dec 5 06:46:17 CET 2017


1) Add the libvirt support on AArch64 platforms
2) Add 'loader' and 'nvram' option support in 'os' section
3) Add 'opt_bus', 'opt_dev' and 'opt_controller' option support in
   'disk' section.  Change 'type' to 'opt_format' to get aligined
   with option naming in qemu_kvm.
4) Add serial 'serial_option' option support for serial console
5) Add domain parsing in __parse_pci()
6) Function add_vm_device() supports both VF (new) and PF devices now

Signed-off-by: Herbert Guan <herbert.guan at arm.com>
---
 conf/vm_power_manager.cfg |   4 +-
 framework/qemu_libvirt.py | 152 ++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 128 insertions(+), 28 deletions(-)
 mode change 100644 => 100755 conf/vm_power_manager.cfg
 mode change 100644 => 100755 framework/qemu_libvirt.py

diff --git a/conf/vm_power_manager.cfg b/conf/vm_power_manager.cfg
old mode 100644
new mode 100755
index 9c8f87a..7d5d9b6
--- a/conf/vm_power_manager.cfg
+++ b/conf/vm_power_manager.cfg
@@ -7,7 +7,7 @@
 #   size: 4096
 # disk
 #   file: absolute path to disk image
-#   type: disk image format
+#   opt_format: [ raw | qcow2 | ... ]  #disk image format
 # login
 #   user: user name to login into VM
 #   password: passwork to login into VM
@@ -25,7 +25,7 @@ cpu =
 mem =
     size=4096;
 disk =
-    file=/storage/vm-image/vm0.img,type=raw;
+    file=/storage/vm-image/vm0.img,opt_format=raw;
 login =
     user=root,password=tester;
 [vm1]
diff --git a/framework/qemu_libvirt.py b/framework/qemu_libvirt.py
old mode 100644
new mode 100755
index ed8e0e6..18dcd8b
--- a/framework/qemu_libvirt.py
+++ b/framework/qemu_libvirt.py
@@ -57,6 +57,7 @@ class LibvirtKvm(VirtBase):
 
         # disk and pci device default index
         self.diskindex = 'a'
+        self.controllerindex = 0
         self.pciindex = 10
 
         # configure root element
@@ -82,7 +83,12 @@ class LibvirtKvm(VirtBase):
 
         # set some default values for vm,
         # if there is not the values of the specified options
-        self.set_vm_default()
+        arch = self.host_session.send_expect('uname -m', '# ')
+        set_default_func = getattr(self, 'set_vm_default_' + arch)
+        if callable(set_default_func):
+            set_default_func()
+        else:
+            self.set_vm_default()
 
     def get_qemu_emulator(self):
         """
@@ -98,6 +104,13 @@ class LibvirtKvm(VirtBase):
         """
         check and setup host virtual ability
         """
+        arch = self.host_session.send_expect('uname -m', '# ')
+        if arch == 'aarch64':
+            out = self.host_session.send_expect('service libvirtd status', "# ")
+            if 'active (running)' not in out:
+                return False
+            return True
+
         out = self.host_session.send_expect('cat /proc/cpuinfo | grep flags',
                                             '# ')
         rgx = re.search(' vmx ', out)
@@ -201,6 +214,47 @@ class LibvirtKvm(VirtBase):
                                 ',name=org.qemu.guest_agent.0'})
         self.qga_sock_path = '/tmp/%s_qga0.sock' % self.vm_name
 
+    def add_vm_os(self, **options):
+        os = self.domain.find('os')
+        if 'loader' in options.keys():
+            loader = ET.SubElement(
+            os, 'loader', {'readonly': 'yes', 'type': 'pflash'})
+            loader.text = options['loader']
+        if 'nvram' in options.keys():
+            nvram = ET.SubElement(os, 'nvram')
+            nvram.text = options['nvram']
+
+
+    def set_vm_default_aarch64(self):
+        os = ET.SubElement(self.domain, 'os')
+        type = ET.SubElement(
+            os, 'type', {'arch': 'aarch64', 'machine': 'virt'})
+        type.text = 'hvm'
+        ET.SubElement(os, 'boot', {'dev': 'hd'})
+
+        features = ET.SubElement(self.domain, 'features')
+        ET.SubElement(features, 'acpi')
+        ET.SubElement(features, 'gic', {'version': '3'})
+
+        ET.SubElement(self.domain, 'cpu',
+            {'mode': 'host-passthrough', 'check': 'none'})
+
+        # qemu-kvm for emulator
+        device = ET.SubElement(self.domain, 'devices')
+        ET.SubElement(device, 'emulator').text = self.qemu_emulator
+
+        # graphic device
+        #ET.SubElement(device, 'graphics', {
+        #              'type': 'vnc', 'port': '-1', 'autoport': 'yes'})
+        # qemu guest agent
+        self.add_vm_qga(None)
+
+        # add default control interface
+        if not self.__default_nic:
+            def_nic = {'type': 'nic', 'opt_hostfwd': ''}
+            self.add_vm_net(**def_nic)
+            self.__default_nic = True
+
     def set_vm_default(self):
         os = ET.SubElement(self.domain, 'os')
         type = ET.SubElement(
@@ -273,17 +327,44 @@ class LibvirtKvm(VirtBase):
             return False
 
         ET.SubElement(disk, 'source', {'file': options['file']})
-        if 'type' not in options:
+        if 'opt_format' not in options:
             disk_type = 'raw'
         else:
-            disk_type = options['type']
+            disk_type = options['opt_format']
 
         ET.SubElement(disk, 'driver', {'name': 'qemu', 'type': disk_type})
 
+        if 'opt_bus' not in options:
+            bus = 'virtio'
+        else:
+            bus = options['opt_bus']
+        if 'opt_dev' not in options:
+            dev = 'vd%c' % self.diskindex
+            self.diskindex = chr(ord(self.diskindex) + 1)
+        else:
+            dev = options['opt_dev']
         ET.SubElement(
-            disk, 'target', {'dev': 'vd%c' % self.diskindex, 'bus': 'virtio'})
+            disk, 'target', {'dev': dev, 'bus': bus})
+
+        if 'opt_controller' in options:
+            controller = ET.SubElement(devices, 'controller',
+                {'type': bus,
+                'index': hex(self.controllerindex)[2:],
+                'model': options['opt_controller']})
+            self.controllerindex += 1
+            ET.SubElement(controller, 'address',
+                {'type': 'pci', 'domain': '0x0000', 'bus': hex(self.pciindex),
+                'slot': '0x00', 'function': '0x00'})
+            self.pciindex += 1
 
-        self.diskindex = chr(ord(self.diskindex) + 1)
+    def add_vm_serial_port(self, **options):
+        if 'enable' in options.keys():
+            if options['enable'].lower() == 'yes':
+                devices = self.domain.find('devices')
+                serial = ET.SubElement(devices, 'serial', {'type': 'pty'})
+                ET.SubElement(serial, 'target', {'port': '0'})
+                console = ET.SubElement(devices, 'console', {'type': 'pty'})
+                ET.SubElement(console, 'target', {'type': 'serial', 'port': '0'})
 
     def add_vm_login(self, **options):
         """
@@ -305,14 +386,23 @@ class LibvirtKvm(VirtBase):
     def __parse_pci(self, pci_address):
         pci_regex = r"([0-9a-fA-F]{1,2}):([0-9a-fA-F]{1,2})" + \
             ".([0-9a-fA-F]{1,2})"
+        pci_regex_domain = r"([0-9a-fA-F]{1,4}):([0-9a-fA-F]{1,2}):" + \
+            "([0-9a-fA-F]{1,2}).([0-9a-fA-F]{1,2})"
         m = re.match(pci_regex, pci_address)
-        if m is None:
-            return None
-        bus = m.group(1)
-        slot = m.group(2)
-        func = m.group(3)
-
-        return (bus, slot, func)
+        if m is not None:
+            bus = m.group(1)
+            slot = m.group(2)
+            func = m.group(3)
+            dom  = '0'
+            return (bus, slot, func, dom)
+        m = re.match(pci_regex_domain, pci_address)
+        if m is not None:
+            bus = m.group(2)
+            slot = m.group(3)
+            func = m.group(4)
+            dom  = m.group(1)
+            return (bus, slot, func, dom)
+        return None
 
     def add_vm_device(self, **options):
         """
@@ -325,35 +415,45 @@ class LibvirtKvm(VirtBase):
                                    'mode': 'subsystem', 'type': 'pci',
                                    'managed': 'yes'})
 
-        if 'pf_idx' not in options.keys():
-            print utils.RED("Missing device index for device option!!!")
-            return False
-
-        pf = int(options['pf_idx'])
-        if pf > len(self.host_dut.ports_info):
-            print utils.RED("PF device index over size!!!")
+        if 'pf_idx' in options.keys():
+            pf = int(options['pf_idx'])
+            if pf > len(self.host_dut.ports_info):
+                print utils.RED("PF device index over size!!!")
+                return False
+            pci_addr = self.host_dut.ports_info[pf]['pci']
+        elif 'vf_idx' in options.keys():
+            vf = int(options['vf_idx'])
+            if vf > len(self.host_dut.ports_info):
+                print utils.RED("VF device index over size!!!")
+                return False
+            if 'vf_id' in options.keys():
+                vf_id = int(options['vf_id'])
+            else:
+                vf_id = 0
+            pci_addr = self.host_dut.ports_info[vf]['sriov_vfs_pci'][vf_id]
+        else:
+            print utils.RED("Missing pf/vf device index for device option!!!")
             return False
 
-        pci_addr = self.host_dut.ports_info[pf]['pci']
 
         pci = self.__parse_pci(pci_addr)
         if pci is None:
             return False
-        bus, slot, func = pci
+        bus, slot, func, dom = pci
 
         source = ET.SubElement(hostdevice, 'source')
         ET.SubElement(source, 'address', {
-                      'domain': '0x0', 'bus': '0x%s' % bus,
+                      'domain': '0x%s' % dom, 'bus': '0x%s' % bus,
                       'slot': '0x%s' % slot,
                       'function': '0x%s' % func})
         if 'guestpci' in options.keys():
             pci = self.__parse_pci(options['guestpci'])
             if pci is None:
                 return False
-            bus, slot, func = pci
+            bus, slot, func, dom = pci
             ET.SubElement(hostdevice, 'address', {
-                          'type': 'pci', 'domain': '0x0', 'bus': '0x%s' % bus,
-                          'slot': '0x%s' % slot, 'function': '0x%s' % func})
+                  'type': 'pci', 'domain': '0x%s' % dom, 'bus': '0x%s' % bus,
+                  'slot': '0x%s' % slot, 'function': '0x%s' % func})
             # save host and guest pci address mapping
             pci_map = {}
             pci_map['hostpci'] = pci_addr
@@ -397,7 +497,7 @@ class LibvirtKvm(VirtBase):
             pci = self.__parse_pci(options['opt_addr'])
             if pci is None:
                 return False
-            bus, slot, func = pci
+            bus, slot, func, dom = pci
             ET.SubElement(qemu, 'qemu:arg',
                           {'value': 'nic,model=e1000,addr=0x%s' % slot})
         else:
-- 
1.8.3.1



More information about the dts mailing list