[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] Rudimentary (basic) s390x architecture functions for libvirt



Am 26.01.2011 13:41, schrieb Daniel P. Berrange:
>> On Tue, Jan 25, 2011 at 08:34:03PM +0100, Patrick Siegl wrote:
>>> A few more details for s390x: why you can't set param '-S' and need
>>> '-chardev vc,id=cons -device virtio-serial-s390 -device
>>> virtconsole,chardev=cons' on s390x:
>>>
>>> 1) qemu-system-s390x -M s390-virtio -vnc :0 -enable-kvm -smp 1 -m 1024
>>> -k de  -kernel /boot/image-2.6.34-tue01 -initrd
>>> /boot/initrd-2.6.34-tue01_GUEST -drive file=/data/sle11.img -append
>>> "root=/dev/vda1 rw"
>>>
>>> => screenshot 1
>>>
>>> 2) qemu-system-s390x -S -M s390-virtio -vnc :0 -enable-kvm -smp 1 -m
>>> 1024 -k de  -kernel /boot/image-2.6.34-tue01 -initrd
>>> /boot/initrd-2.6.34-tue01_GUEST -drive file=/data/sle11.img -append
>>> "root=/dev/vda1 rw"
>>>
>>> => screenshot 2
>>> 3) qemu-system-s390x -M s390-virtio -vnc :0 -enable-kvm -smp 1 -m 1024
>>> -k de  -kernel /boot/image-2.6.34-tue01 -initrd
>>> /boot/initrd-2.6.34-tue01_GUEST -drive file=/data/sle11.img -append
>>> "root=/dev/vda1 rw" -chardev vc,id=cons -device virtio-serial-s390
>>> -device virtconsole,chardev=cons
>>>
>>>  => RUN
>>>
>>> 4) qemu-system-s390x -S -M s390-virtio -vnc :0 -enable-kvm -smp 1 -m
>>> 1024 -k de  -kernel /boot/image-2.6.34-tue01 -initrd
>>> /boot/initrd-2.6.34-tue01_GUEST -drive file=/data/sle11.img -append
>>> "root=/dev/vda1 rw" -chardev vc,id=cons -device virtio-serial-s390
>>> -device virtconsole,chardev=cons
>>>
>>> => screenshot 4
>> These screenshots are all showing the same thing, but for different
>> reasons.
>>
>> IIUC, there is no 'VGA' graphics adapter in s390 world, hence
>> you need some form of text console. This is what virtio-serial-s390
>> is providing for you. This does not need to be hardcoded in the
>> QEMU arg generator. You can set this in the XML
>>
>>   <console type='vc'>
>>     <target type='virtio'/>
>>   </console>
>>
>> When you add the '-S' argument this tells QEMU to launch the binary
>> but *NOT* run the guest. When libvirt uses '-S', it launches QEMU
>> runs some monitor commands, and then runs 'cont' to start the
>> guest running. When you're running QEMU manually in your demo
>> above, I assume you never told QEMU to start the CPUs, hence you
>> see the screenshot 4. If you had issued 'cont' on the monitor it
>> would run normally as per example 3.
>>
>> Regards,
>> Daniel
> --
> libvir-list mailing list
> libvir-list redhat com
> https://www.redhat.com/mailman/listinfo/libvir-list

I have overhauled my last patch (for libvirt KVM support on s390x). You
will find the new one as attachment.
There is only one problem, which I can't get fixed. You wrote following:

"This is expected change, since s390 isn't PCI based, but what
addressing scheme is used for s390 devices to uniquely and
stablly identify them. 

eg, we need to make sure that

    qemu -drive AAA -drive BBB -drive CCC
    (monitor) drive_del BBB

results except same guest visible ABI as

    qemu -drive AAA -drive CCC"

This is a small problem under s390x, because if you try to add ',addr='
to a device, qemu prints: "Property '<device>.addr' not found".

There are a few more details:
- netdev isn't supported, because netdev needs param 'bus='. If you try
to run this with BUS s390-virtio, netdev prints, that this is not supported.
  (everything should work with virtio, so if you enable '<model
type="virtio"/>', it works fine)
- You have to set 'ports' for the controller. If you don't do this, the
virtual machine doesn't find VDA and so you can't start it. Maybe this
is because of the flags '-nodefconfig' and '-nodefaults'. The maximum
count of ports is 31 (the qemu implementation kills everything which is
higher than 32).
- Also 'vectors' aren't supported for the controller. If you therefor
try to set a value, the virtual machine doesn't start.
- It is not very nice within the libvirt implementation
('qemu_command.c') when every device gets PCI as address type (the only
way to fix this in a relative moderat time, is to overwrite it with
s390-virtio, if it runs on s390x).
- The last point is that I haven't found a way for parsing the cpu MHz
count. Within the patch there is some comment about it.

Everything which I recognized for building an virtual machine on s390x
is written into the XML file.

Regards,
Patrick Siegl
<domain type='kvm'>
	<name>TestVM</name>
	<uuid></uuid>
	<memory>1024000</memory>
	<currentMemory>1024000</currentMemory>
	<cpu>
    		<topology sockets='1' cores='1' threads='1'/>
  	</cpu>

	<os>
		<type arch="s390x" machine='s390'>hvm</type>
		<kernel>/boot/image-2.6.34-tue01</kernel>
    		<initrd>/boot/initrd-2.6.34-tue01_GUEST</initrd>
		<cmdline>"root=/dev/vda1 rw"</cmdline>
		<boot dev='hd'/>
	</os>
	<devices>
		<graphics type='vnc' port='5903' listen='' keymap='de'/>

		<!-- without this console a vm kills hisself on s390x, when connecting VNC to it -->
		<console type='vc'>  
  			<target type='virtio' name='virtio.serial'/>
		</console>

		<disk type='file' device='disk'>
  			<source file='/data/sle11.img'/>
  			<target dev='vda' bus='virtio'/>
  			<driver name='qemu' type='qcow2' cache='writeback'/>
  			<!--<address type='s390-virtio'/>--> <!-- not really needed, but possible -->
		</disk>

		<interface type='ethernet'>
			<target dev='tap0'/>
			<script path='/data/qemu-ifup-siegl'/>
			<mac address='00:17:31:88:AC:86'/>
			<ip address='134.2.14.241'/>
			<model type='virtio'/> <!-- http://wiki.libvirt.org/page/Virtio#Network_driver -->
    		</interface>

		<!-- It is highly recommended to enable ports and disable (not set) vectors! -->
		<!-- Without ports a vm will not start under s390x. Vectors aren't supported on s390x and will not work -->
		<!-- Minimum of ports is 1 (for 1 HDD), Maximum is 31 (qemu implementation => s390-virtio-bus.c); 16 works on z9 university tuebingen -->
		<controller type='virtio-serial' index='0' ports='16'/>

		<memballoon model='none'/> <!-- Deactivate Ballon Support; it doesn't work on z9 university tuebingen -->
	</devices>
</domain>

diff --git a/libvirt.orig/src/nodeinfo.c b/libvirt/src/nodeinfo.c
index 22d53e5..126bf7a 100644
--- a/libvirt.orig/src/nodeinfo.c
+++ b/libvirt/src/nodeinfo.c
@@ -164,7 +164,11 @@ cleanup:
 
 static int parse_socket(unsigned int cpu)
 {
+# if defined __s390x__ || defined __s390__  
+    return 0; /* s390 does not implement physical_package_id by now */
+# else
     return get_cpu_value(cpu, "topology/physical_package_id", false);
+# endif
 }
 
 int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
@@ -195,6 +199,50 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
      * has no knowledge of NUMA nodes */
 
     /* NOTE: hyperthreads are ignored here; they are parsed out of /sys */
+# if defined __s390x__ || defined __s390__ 
+/* cat /proc/cpuinfo under s390x:
+vendor_id       : IBM/S390
+# processors    : 2
+bogomips per cpu: 5681.00
+features	: esan3 zarch stfle msa ldisp eimm dfp etf3eh highgprs 
+processor 0: version = 00,  identification = 08A750,  machine = 2096
+processor 1: version = 00,  identification = 08A750,  machine = 2096
+*/
+    while (fgets(line, sizeof(line), cpuinfo) != NULL) {
+        char *buf = line;
+        if (STRPREFIX(buf, "# processors")) { /* Number of processors */
+            char *p;
+            unsigned int id;
+            buf += 12;
+            while (*buf && c_isspace(*buf))
+                buf++;
+            if (*buf != ':' || !buf[1]) {
+                nodeReportError(VIR_ERR_INTERNAL_ERROR,
+                        "parsing cpuinfo cpu count %c", *buf);
+                return -1;
+            }
+            if (virStrToLong_ui(buf+1, &p, 10, &id) == 0
+                    && (*p == '\0' || c_isspace(*p))
+                    && id > nodeinfo->cores) {
+                nodeinfo->cpus  = id;
+                //nodeinfo->cores = 1; // is already set.
+                nodeinfo->mhz   = 1400; /* z9 BC */
+            }
+        }
+    }
+
+// I searched for parsing the CPU MHz value, but I am not sure if this is the correct path:
+// cat /sys/devices/system/cpu/cpu0/capabilities => 1760
+
+/* lscpu shows following:
+Architecture:          s390x
+CPU(s):                2
+Thread(s) per core:    1
+Core(s) per socket:    64
+CPU socket(s):         0
+Vendor ID:             IBM/S390*
+*/
+# else /* no s390 */
     while (fgets(line, sizeof(line), cpuinfo) != NULL) {
         char *buf = line;
         if (STRPREFIX(buf, "processor")) { /* aka a single logical CPU */
@@ -239,6 +287,7 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
                 nodeinfo->cores = id;
         }
     }
+# endif /* s390 */
 
     if (!nodeinfo->cpus) {
         nodeReportError(VIR_ERR_INTERNAL_ERROR,
diff --git a/libvirt.orig/src/qemu/qemu_command.c b/libvirt/src/qemu/qemu_command.c
index a0f86a3..a49069f 100644
--- a/libvirt.orig/src/qemu/qemu_command.c
+++ b/libvirt/src/qemu/qemu_command.c
@@ -857,7 +857,12 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
             return -1;
         }
 
+// well this is not the best way, but overwriting all 'dev->type' with 'pci' is also not a good solution ...
+# if ! ( defined __s390x__ || defined __s390__ )
         dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+# else
+        dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390;
+# endif
         dev->addr.pci = maybe.addr.pci;
 
         addrs->nextslot = i + 1;
@@ -1090,7 +1095,8 @@ static int
 qemuBuildDeviceAddressStr(virBufferPtr buf,
                           virDomainDeviceInfoPtr info)
 {
-    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+    switch(info->type){
+      case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
         if (info->addr.pci.domain != 0) {
             qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                             _("Only PCI device addresses with domain=0 are supported"));
@@ -1114,6 +1120,13 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
          * to pciNN.0  where NN is the domain number
          */
         virBufferVSprintf(buf, ",bus=pci.0,addr=0x%x", info->addr.pci.slot);
+        break;
+    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390:
+        // if you try to add 'addr=' to an Device, qemu-system-s390x prints: "Property '*.addr' not found"
+
+        // there is also no way to make an difference with a dot and a number for more than one bus ...
+        // if you try to do so, qemu will crash with following: "Bus 's390-virtio.0' not found"
+        virBufferVSprintf(buf, ",bus=s390-virtio");
     }
     return 0;
 }
@@ -1382,7 +1395,11 @@ qemuBuildDriveDevStr(virDomainDiskDefPtr disk,
                           disk->info.addr.drive.unit);
         break;
     case VIR_DOMAIN_DISK_BUS_VIRTIO:
+# if ( defined __s390x__  || defined __s390__ )
+        virBufferAddLit(&opt, "virtio-blk-s390");
+# else
         virBufferAddLit(&opt, "virtio-blk-pci");
+# endif
         qemuBuildDeviceAddressStr(&opt, &disk->info);
         break;
     case VIR_DOMAIN_DISK_BUS_USB:
@@ -1488,9 +1505,17 @@ qemuBuildControllerDevStr(virDomainControllerDefPtr def)
         break;
 
     case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
-        if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+
+        switch(def->info.type){
+        case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
             virBufferAddLit(&buf, "virtio-serial-pci");
-        } else {
+            break;
+
+        case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390:
+            virBufferAddLit(&buf, "virtio-serial-s390");
+            break;
+
+        default:
             virBufferAddLit(&buf, "virtio-serial");
         }
         virBufferVSprintf(&buf, ",id=" QEMU_VIRTIO_SERIAL_PREFIX "%d",
@@ -1566,7 +1591,11 @@ qemuBuildNicDevStr(virDomainNetDefPtr net,
     if (!net->model) {
         nic = "rtl8139";
     } else if (STREQ(net->model, "virtio")) {
+# if defined __s390x__  || defined __s390__
+        nic = "virtio-net-s390";
+# else
         nic = "virtio-net-pci";
+# endif
     } else {
         nic = net->model;
     }
@@ -2952,8 +2981,10 @@ qemuBuildCommandLine(virConnectPtr conn,
         def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART)
         virCommandAddArg(cmd, "-no-reboot");
 
+# if ! ( defined __s390x__  || defined __s390__ )
     if (!(def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
         virCommandAddArg(cmd, "-no-acpi");
+# endif
 
     if (!def->os.bootloader) {
         for (i = 0 ; i < def->os.nBootDevs ; i++) {
diff --git a/libvirt.orig/src/conf/domain_conf.c b/libvirt/src/conf/domain_conf.c
index b1cc6c8..a2675a6 100644
--- a/libvirt.orig/src/conf/domain_conf.c
+++ b/libvirt/src/conf/domain_conf.c
@@ -108,6 +108,7 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
 VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
               "none",
               "pci",
+              "s390-virtio",
               "drive",
               "virtio-serial")
 
@@ -1109,6 +1110,9 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
         return virDomainDevicePCIAddressIsValid(&info->addr.pci);
 
+    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390:
+        return 1;
+
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
         return virDomainDeviceDriveAddressIsValid(&info->addr.drive);
     }
@@ -1271,6 +1275,9 @@ static int virDomainDeviceInfoFormat(virBufferPtr buf,
                           info->addr.pci.function);
         break;
 
+    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390:
+        break;
+
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
         virBufferVSprintf(buf, " controller='%d' bus='%d' unit='%d'",
                           info->addr.drive.controller,
@@ -1515,6 +1522,9 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
             goto cleanup;
         break;
 
+    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390:
+        break;
+
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
         if (virDomainDeviceDriveAddressParseXML(address, &info->addr.drive) < 0)
             goto cleanup;
@@ -1948,7 +1958,12 @@ virDomainDiskDefParseXML(virCapsPtr caps,
                                  devaddr);
             goto error;
         }
+// well this is not the best way, but overwriting all 'dev->info.type' with 'pci' is also not a good solution ...
+# if ( defined __s390x__ || defined __s390__ )
+        def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390;
+# else
         def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+# endif
     } else {
         if (virDomainDeviceInfoParseXML(node, &def->info, flags) < 0)
             goto error;
@@ -2106,9 +2121,10 @@ virDomainControllerDefParseXML(xmlNodePtr node,
     }
 
     if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
-        def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+        def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
+        def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390) {
         virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                             _("Controllers must use the 'pci' address type"));
+                             _("Controllers must use the 'pci' or 's390-virtio' address type"));
         goto error;
     }
 
@@ -2512,7 +2528,12 @@ virDomainNetDefParseXML(virCapsPtr caps,
                                  devaddr);
             goto error;
         }
+// well this is not the best way, but overwriting all 'dev->info.type' with 'pci' is also not a good solution ...
+# if ( defined __s390x__ || defined __s390__ )
+        def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390;
+# else
         def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+# endif
     } else {
         if (virDomainDeviceInfoParseXML(node, &def->info, flags) < 0)
             goto error;
@@ -2521,7 +2542,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
     /* XXX what about ISA/USB based NIC models - once we support
      * them we should make sure address type is correct */
     if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
-        def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+        def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
+        def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390) {
         virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                              _("Network interfaces must use 'pci' address type"));
         goto error;
@@ -4228,7 +4250,12 @@ virDomainHostdevSubsysPciDefParseXML(const xmlNodePtr node,
                     VIR_FREE(devaddr);
                     goto out;
                 }
+// well this is not the best way, but overwriting all 'dev->info.type' with 'pci' is also not a good solution ...
+# if ( defined __s390x__ || defined __s390__ )
+                def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390;
+# else
                 def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+# endif
             } else {
                 virDomainReportError(VIR_ERR_INTERNAL_ERROR,
                                      _("unknown pci source type '%s'"),
@@ -4325,9 +4352,10 @@ virDomainHostdevDefParseXML(const xmlNodePtr node,
         switch (def->source.subsys.type) {
         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
             if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
-                def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+                def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
+                def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390) {
                 virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                     _("PCI host devices must use 'pci' address type"));
+                                     _("PCI host devices must use 'pci' or 's390-virtio' address type"));
                 goto error;
             }
             break;
diff --git a/libvirt.orig/src/conf/domain_conf.h b/libvirt/src/conf/domain_conf.h
index 871fa9a..5db6c55 100644
--- a/libvirt.orig/src/conf/domain_conf.h
+++ b/libvirt/src/conf/domain_conf.h
@@ -71,6 +71,7 @@ enum virDomainVirtType {
 enum virDomainDeviceAddressType {
     VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE,
     VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI,
+    VIR_DOMAIN_DEVICE_ADDRESS_TYPE_S390,
     VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE,
     VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL,
 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]