test suite reviews and discussions
 help / color / mirror / Atom feed
* [dts] [PATCH] framework: enable AArch64 and add more options for libvirt
@ 2017-12-05  5:46 Herbert Guan
  2017-12-22  8:09 ` Liu, Yong
  2018-01-03  4:40 ` [dts] [PATCH v2] " Herbert Guan
  0 siblings, 2 replies; 6+ messages in thread
From: Herbert Guan @ 2017-12-05  5:46 UTC (permalink / raw)
  To: dts; +Cc: phil.yang, jianbo.liu, Herbert Guan

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@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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [dts] [PATCH] framework: enable AArch64 and add more options for libvirt
  2017-12-05  5:46 [dts] [PATCH] framework: enable AArch64 and add more options for libvirt Herbert Guan
@ 2017-12-22  8:09 ` Liu, Yong
  2017-12-22  9:53   ` Herbert Guan
  2018-01-03  4:40 ` [dts] [PATCH v2] " Herbert Guan
  1 sibling, 1 reply; 6+ messages in thread
From: Liu, Yong @ 2017-12-22  8:09 UTC (permalink / raw)
  To: Herbert Guan, dts; +Cc: phil.yang, jianbo.liu

Herbert, thanks for your patch.  I'm not very clear about what is must for AArch64 support and what is for enabling your environment.
Please separate them in different functions. 

Thanks,
Marvin 

> -----Original Message-----
> From: dts [mailto:dts-bounces@dpdk.org] On Behalf Of Herbert Guan
> Sent: Tuesday, December 05, 2017 1:46 PM
> To: dts@dpdk.org
> Cc: phil.yang@arm.com; jianbo.liu@arm.com; Herbert Guan
> <herbert.guan@arm.com>
> Subject: [dts] [PATCH] framework: enable AArch64 and add more options for
> libvirt
> 
> 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@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()

I'm not sure how much is the difference between x86 and AArch64 platform. Look like somethings are common for example graphic and control interface.
Could we separate arch related setting in separated function and keep those common in another function?

> 
>      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
> +

Herbert, libvirt status has been checked in function has_virtual_ability when initialize LibvirtKvm object. 
Why do this check again?

>          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']
> +

Where this function is called? 

> +
> +    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'})
> 

In qemu kvm module, we are using unix domain socket for serial device. Can you align to this?
Please let device type should be configurable, we plan to add more types later.

>      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

Previous check sentence is incorrect:) Should be "if pf >= len(self.host_dut.ports_info):". 
Most of suites are just using option "opt_host" to specify the pci address of device. So I'm planning to remove pf_idx option, what's your idea for that?

> +            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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [dts] [PATCH] framework: enable AArch64 and add more options for libvirt
  2017-12-22  8:09 ` Liu, Yong
@ 2017-12-22  9:53   ` Herbert Guan
  2018-01-02  2:21     ` Liu, Yong
  0 siblings, 1 reply; 6+ messages in thread
From: Herbert Guan @ 2017-12-22  9:53 UTC (permalink / raw)
  To: Liu, Yong, dts; +Cc: Phil Yang, Jianbo Liu, nd

Marvin,

> -----Original Message-----
> From: Liu, Yong [mailto:yong.liu@intel.com]
> Sent: Friday, December 22, 2017 16:10
> To: Herbert Guan <Herbert.Guan@arm.com>; dts@dpdk.org
> Cc: Phil Yang <Phil.Yang@arm.com>; Jianbo Liu <Jianbo.Liu@arm.com>
> Subject: RE: [dts] [PATCH] framework: enable AArch64 and add more options
> for libvirt
> 
> Herbert, thanks for your patch.  I'm not very clear about what is must for
> AArch64 support and what is for enabling your environment.
> Please separate them in different functions.

To make it more clear, are you requesting to split this patch into smaller ones (maybe around 6 patches)?

> 
> Thanks,
> Marvin
> 
> > -----Original Message-----
> > From: dts [mailto:dts-bounces@dpdk.org] On Behalf Of Herbert Guan
> > Sent: Tuesday, December 05, 2017 1:46 PM
> > To: dts@dpdk.org
> > Cc: phil.yang@arm.com; jianbo.liu@arm.com; Herbert Guan
> > <herbert.guan@arm.com>
> > Subject: [dts] [PATCH] framework: enable AArch64 and add more options
> > for libvirt
> >
> > 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@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()
> 
> I'm not sure how much is the difference between x86 and AArch64 platform.
> Look like somethings are common for example graphic and control interface.
> Could we separate arch related setting in separated function and keep those
> common in another function?
> 

How about this: call into common function set_vm_default() first, and then call arch specific function set_vm_default_'x86_64/aarch64/...'()?  

> >
> >      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
> > +
> 
> Herbert, libvirt status has been checked in function has_virtual_ability when
> initialize LibvirtKvm object.
> Why do this check again?
> 

This is not double check but just modifying the logic of "has_virtual_ability ".  It defines the specific checking logic for arm platforms.  And if it's not 'aarch64' platform, will go with the original logic. 

> >          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']
> > +
> 
> Where this function is called?

It's called by load_local_config() in virt_base.py.  There'll be an entry added in case config file, such as:
os =
    loader=/usr/share/AAVMF/AAVMF_CODE.fd,nvram=/var/lib/libvirt/qemu/nvram/vm0_VARS.fd;

> 
> > +
> > +    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'})
> >
> 
> In qemu kvm module, we are using unix domain socket for serial device. Can
> you align to this?
> Please let device type should be configurable, we plan to add more types
> later.

OK, I'll add the unix socket support and make type configurable in the new version.

> 
> >      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
> 
> Previous check sentence is incorrect:) Should be "if pf >=
> len(self.host_dut.ports_info):".
> Most of suites are just using option "opt_host" to specify the pci address of
> device. So I'm planning to remove pf_idx option, what's your idea for that?
> 
Fully agree switching to "opt_host" to specify the PCI address.  This can match the function name "add_vm_device" better, not limited to pf/vf NIC devices.  'vf_idx' was added just because it only support pf before, but this is quite complex and not aligned with vf_xx suites.  I can make such change if decided to go.  Could you confirm that?

> > +            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

Thanks,
Herbert

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [dts] [PATCH] framework: enable AArch64 and add more options for libvirt
  2017-12-22  9:53   ` Herbert Guan
@ 2018-01-02  2:21     ` Liu, Yong
  0 siblings, 0 replies; 6+ messages in thread
From: Liu, Yong @ 2018-01-02  2:21 UTC (permalink / raw)
  To: Herbert Guan, dts; +Cc: Phil Yang, Jianbo Liu, nd, Mo, YufengX

Herber,
Sorry for late response, I was on vacation last week. For my previous comments, I just want to separated arch specified stuffs. 
Some common things like disk/graphic should be done in independent functions like add_vm_disk. 


You can change the previous functions, I think below is the specified things for x86_64.

    def set_vm_default_x86(self):
        os = ET.SubElement(self.domain, 'os')
        type = ET.SubElement(
            os, 'type', {'arch': 'x86_64', 'machine': 'pc-i440fx-1.6'})
        type.text = 'hvm'
        features = ET.SubElement(self.domain, 'features')
        ET.SubElement(features, 'acpi')
        ET.SubElement(features, 'apic')
        ET.SubElement(features, 'pae')
        ET.SubElement(self.domain, 'cpu', {'mode': 'host-passthrough'})

Thanks,
Marvin

> -----Original Message-----
> From: Herbert Guan [mailto:Herbert.Guan@arm.com]
> Sent: Friday, December 22, 2017 5:53 PM
> To: Liu, Yong <yong.liu@intel.com>; dts@dpdk.org
> Cc: Phil Yang <Phil.Yang@arm.com>; Jianbo Liu <Jianbo.Liu@arm.com>; nd
> <nd@arm.com>
> Subject: RE: [dts] [PATCH] framework: enable AArch64 and add more options
> for libvirt
> 
> Marvin,
> 
> > -----Original Message-----
> > From: Liu, Yong [mailto:yong.liu@intel.com]
> > Sent: Friday, December 22, 2017 16:10
> > To: Herbert Guan <Herbert.Guan@arm.com>; dts@dpdk.org
> > Cc: Phil Yang <Phil.Yang@arm.com>; Jianbo Liu <Jianbo.Liu@arm.com>
> > Subject: RE: [dts] [PATCH] framework: enable AArch64 and add more
> options
> > for libvirt
> >
> > Herbert, thanks for your patch.  I'm not very clear about what is must
> for
> > AArch64 support and what is for enabling your environment.
> > Please separate them in different functions.
> 
> To make it more clear, are you requesting to split this patch into smaller
> ones (maybe around 6 patches)?
> 
> >
> > Thanks,
> > Marvin
> >
> > > -----Original Message-----
> > > From: dts [mailto:dts-bounces@dpdk.org] On Behalf Of Herbert Guan
> > > Sent: Tuesday, December 05, 2017 1:46 PM
> > > To: dts@dpdk.org
> > > Cc: phil.yang@arm.com; jianbo.liu@arm.com; Herbert Guan
> > > <herbert.guan@arm.com>
> > > Subject: [dts] [PATCH] framework: enable AArch64 and add more options
> > > for libvirt
> > >
> > > 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@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()
> >
> > I'm not sure how much is the difference between x86 and AArch64 platform.
> > Look like somethings are common for example graphic and control
> interface.
> > Could we separate arch related setting in separated function and keep
> those
> > common in another function?
> >
> 
> How about this: call into common function set_vm_default() first, and then
> call arch specific function set_vm_default_'x86_64/aarch64/...'()?
> 
> > >
> > >      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
> > > +
> >
> > Herbert, libvirt status has been checked in function has_virtual_ability
> when
> > initialize LibvirtKvm object.
> > Why do this check again?
> >
> 
> This is not double check but just modifying the logic of
> "has_virtual_ability ".  It defines the specific checking logic for arm
> platforms.  And if it's not 'aarch64' platform, will go with the original
> logic.
> 
> > >          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']
> > > +
> >
> > Where this function is called?
> 
> It's called by load_local_config() in virt_base.py.  There'll be an entry
> added in case config file, such as:
> os =
> 
> loader=/usr/share/AAVMF/AAVMF_CODE.fd,nvram=/var/lib/libvirt/qemu/nvram/vm
> 0_VARS.fd;
> 
> >
> > > +
> > > +    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'})
> > >
> >
> > In qemu kvm module, we are using unix domain socket for serial device.
> Can
> > you align to this?
> > Please let device type should be configurable, we plan to add more types
> > later.
> 
> OK, I'll add the unix socket support and make type configurable in the new
> version.
> 
> >
> > >      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
> >
> > Previous check sentence is incorrect:) Should be "if pf >=
> > len(self.host_dut.ports_info):".
> > Most of suites are just using option "opt_host" to specify the pci
> address of
> > device. So I'm planning to remove pf_idx option, what's your idea for
> that?
> >
> Fully agree switching to "opt_host" to specify the PCI address.  This can
> match the function name "add_vm_device" better, not limited to pf/vf NIC
> devices.  'vf_idx' was added just because it only support pf before, but
> this is quite complex and not aligned with vf_xx suites.  I can make such
> change if decided to go.  Could you confirm that?
> 
> > > +            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
> 
> Thanks,
> Herbert

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [dts] [PATCH v2] framework: enable AArch64 and add more options for libvirt
  2017-12-05  5:46 [dts] [PATCH] framework: enable AArch64 and add more options for libvirt Herbert Guan
  2017-12-22  8:09 ` Liu, Yong
@ 2018-01-03  4:40 ` Herbert Guan
  2018-01-03 16:44   ` Liu, Yong
  1 sibling, 1 reply; 6+ messages in thread
From: Herbert Guan @ 2018-01-03  4:40 UTC (permalink / raw)
  To: dts; +Cc: yong.liu, phil.yang, jianbo.liu, Herbert Guan

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() uses 'opt_host' to specify PCI address

Signed-off-by: Herbert Guan <herbert.guan@arm.com>
---
 conf/vm_power_manager.cfg |  11 +++-
 framework/qemu_libvirt.py | 144 +++++++++++++++++++++++++++++++++++++---------
 2 files changed, 125 insertions(+), 30 deletions(-)

diff --git a/conf/vm_power_manager.cfg b/conf/vm_power_manager.cfg
index 9c8f87a..e2c8fc7 100644
--- a/conf/vm_power_manager.cfg
+++ b/conf/vm_power_manager.cfg
@@ -1,5 +1,8 @@
 # libvirtd options:
 # [VM name] section value is the name for VM
+# os
+#   loader:  /path/to/loader/file.fd
+#   nvram:   /path/to/nvram/file.fd
 # cpu       # hard code type to host-passthrough
 #   number: number of vcpus
 #   cpupin: host cpu list
@@ -7,7 +10,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
@@ -20,18 +23,20 @@
 
 # vm configuration for vm power management case
 [vm0]
+#os =
+#    loader=/usr/share/AAVMF/AAVMF_CODE.fd,nvram=/var/lib/libvirt/qemu/nvram/vm0_VARS.fd;
 cpu =
     number=4,cpupin=5 6 7 8;
 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]
 mem =
     size=4096;
 disk =
-    file=/storage/vm-image/vm1.img,type=raw;
+    file=/storage/vm-image/vm1.img,opt_format=raw;
 login =
     user=root,password=tester;
diff --git a/framework/qemu_libvirt.py b/framework/qemu_libvirt.py
index ed8e0e6..59a0c9e 100644
--- 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
@@ -79,6 +80,7 @@ class LibvirtKvm(VirtBase):
 
         # internal variable to track whether default nic has been added
         self.__default_nic = False
+        self.__default_nic_pci = ''
 
         # set some default values for vm,
         # if there is not the values of the specified options
@@ -98,6 +100,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,7 +210,31 @@ class LibvirtKvm(VirtBase):
                                 ',name=org.qemu.guest_agent.0'})
         self.qga_sock_path = '/tmp/%s_qga0.sock' % self.vm_name
 
-    def set_vm_default(self):
+    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'})
+
+    def set_vm_default_x86_64(self):
         os = ET.SubElement(self.domain, 'os')
         type = ET.SubElement(
             os, 'type', {'arch': 'x86_64', 'machine': 'pc-i440fx-1.6'})
@@ -213,6 +246,14 @@ class LibvirtKvm(VirtBase):
         ET.SubElement(features, 'pae')
 
         ET.SubElement(self.domain, 'cpu', {'mode': 'host-passthrough'})
+        self.__default_nic_pci = '00:1f.0'
+
+    def set_vm_default(self):
+        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()
+            
 
         # qemu-kvm for emulator
         device = ET.SubElement(self.domain, 'devices')
@@ -226,7 +267,11 @@ class LibvirtKvm(VirtBase):
 
         # add default control interface
         if not self.__default_nic:
-            def_nic = {'type': 'nic', 'opt_hostfwd': '', 'opt_addr': '00:1f.0'}
+            if len(self.__default_nic_pci) > 0:
+                def_nic = {'type': 'nic', 'opt_hostfwd': '',
+                           'opt_addr': self.__default_nic_pci}
+            else:
+                def_nic = {'type': 'nic', 'opt_hostfwd': ''}
             self.add_vm_net(**def_nic)
             self.__default_nic = True
 
@@ -273,17 +318,57 @@ 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')
+                if 'opt_type' in options.keys():
+                    serial_type = options['opt_type']
+                else:
+                    serial_type = 'unix'
+                if serial_type == 'pty':
+                    serial = ET.SubElement(devices, 'serial', {'type': serial_type})
+                    ET.SubElement(serial, 'target', {'port': '0'})
+                elif serial_type == 'unix':
+                    serial = ET.SubElement(devices, 'serial', {'type': serial_type})
+                    self.serial_path = "/tmp/%s_serial.sock" % self.vm_name
+                    ET.SubElement(serial, 'source', {'mode': 'bind', 'path': self.serial_path})
+                    ET.SubElement(serial, 'target', {'port': '0'})
+                else:
+                    print utils.RED("Serial type %s is not supported!" % serial_type)
+                    return False
+                console = ET.SubElement(devices, 'console', {'type': serial_type})
+                ET.SubElement(console, 'target', {'type': 'serial', 'port': '0'})
 
     def add_vm_login(self, **options):
         """
@@ -305,14 +390,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 +419,31 @@ 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 'opt_host' in options.keys():
+            pci_addr = options['opt_host']
+        else:
+            print utils.RED("Missing opt_host 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 +487,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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [dts] [PATCH v2] framework: enable AArch64 and add more options for libvirt
  2018-01-03  4:40 ` [dts] [PATCH v2] " Herbert Guan
@ 2018-01-03 16:44   ` Liu, Yong
  0 siblings, 0 replies; 6+ messages in thread
From: Liu, Yong @ 2018-01-03 16:44 UTC (permalink / raw)
  To: Herbert Guan, dts; +Cc: phil.yang, jianbo.liu

Thanks Herbert. Applied.

On 01/03/2018 12:40 PM, Herbert Guan wrote:
> 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() uses 'opt_host' to specify PCI address
>
> Signed-off-by: Herbert Guan<herbert.guan@arm.com>
> ---
>   conf/vm_power_manager.cfg |  11 +++-
>   framework/qemu_libvirt.py | 144 +++++++++++++++++++++++++++++++++++++---------
>   2 files changed, 125 insertions(+), 30 deletions(-)

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-01-03  8:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-05  5:46 [dts] [PATCH] framework: enable AArch64 and add more options for libvirt Herbert Guan
2017-12-22  8:09 ` Liu, Yong
2017-12-22  9:53   ` Herbert Guan
2018-01-02  2:21     ` Liu, Yong
2018-01-03  4:40 ` [dts] [PATCH v2] " Herbert Guan
2018-01-03 16:44   ` Liu, Yong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).