6d3351
From 5832f82195c2b4144841645f90467cfb11d8d2a4 Mon Sep 17 00:00:00 2001
6d3351
Message-Id: <5832f82195c2b4144841645f90467cfb11d8d2a4@dist-git>
6d3351
From: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com>
6d3351
Date: Thu, 3 Aug 2017 10:11:48 +0200
6d3351
Subject: [PATCH] qemu: Enable NUMA node tag in pci-root for PPC64
6d3351
6d3351
This patch addresses the same aspects on PPC the bug 1103314 addressed
6d3351
on x86.
6d3351
6d3351
PCI expander bus creates multiple primary PCI busses, where each of these
6d3351
busses can be assigned a specific NUMA affinity, which, on x86 is
6d3351
advertised through ACPI on a per-bus basis.
6d3351
6d3351
For SPAPR, a PHB's NUMA affinities are assigned on a per-PHB basis, and
6d3351
there is no mechanism for advertising NUMA affinities to a guest on a
6d3351
per-bus basis. So, even if qemu-ppc manages to get some sort of multi-bus
6d3351
topology working using PXB, there is no way to expose the affinities
6d3351
of these busses to the guest. It can only be exposed on a per-PHB/per-domain
6d3351
basis.
6d3351
6d3351
So patch enables NUMA node tag in pci-root controller on PPC.
6d3351
6d3351
The way to set the NUMA node is through the numa_node option of
6d3351
spapr-pci-host-bridge device. However for the implicit PHB, the only way
6d3351
to set the numa_node is from the -global option. The -global option applies
6d3351
to all the PHBs unless explicitly specified with the option on the
6d3351
respective PHB of CLI. The default PHB has the emulated devices only, so
6d3351
the patch prevents setting the NUMA node for the default PHB.
6d3351
6d3351
Signed-off-by: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com>
6d3351
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
6d3351
(cherry picked from commit e5a0579996b96e74d12dd348cb73b6a0947f9a20)
6d3351
6d3351
Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1474327
6d3351
6d3351
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
6d3351
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
6d3351
---
6d3351
 docs/formatdomain.html.in                          |  5 ++-
6d3351
 src/conf/domain_conf.c                             |  9 +++-
6d3351
 src/qemu/qemu_command.c                            | 10 +++++
6d3351
 src/qemu/qemu_domain.c                             | 13 +++---
6d3351
 .../qemuxml2argv-pseries-default-phb-numa-node.xml | 29 ++++++++++++
6d3351
 .../qemuxml2argv-pseries-phb-numa-node.args        | 28 ++++++++++++
6d3351
 .../qemuxml2argv-pseries-phb-numa-node.xml         | 41 +++++++++++++++++
6d3351
 tests/qemuxml2argvtest.c                           |  6 +++
6d3351
 .../qemuxml2xmlout-pseries-phb-numa-node.xml       | 52 ++++++++++++++++++++++
6d3351
 tests/qemuxml2xmltest.c                            |  4 ++
6d3351
 10 files changed, 188 insertions(+), 9 deletions(-)
6d3351
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-default-phb-numa-node.xml
6d3351
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-numa-node.args
6d3351
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-numa-node.xml
6d3351
 create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-numa-node.xml
6d3351
6d3351
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
6d3351
index bc67a53408..5e747542fc 100644
6d3351
--- a/docs/formatdomain.html.in
6d3351
+++ b/docs/formatdomain.html.in
6d3351
@@ -3751,7 +3751,10 @@
6d3351
       
6d3351
       
node
6d3351
       
6d3351
-        pci-expander-bus controllers can have an
6d3351
+        Some PCI controllers (pci-expander-bus for the pc
6d3351
+        machine type, pcie-expander-bus for the q35 machine
6d3351
+        type and, since 3.6.0,
6d3351
+        pci-root for the pseries machine type) can have an
6d3351
         optional <node> subelement within
6d3351
         the <target> subelement, which is used to
6d3351
         set the NUMA node reported to the guest OS for that bus - the
6d3351
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
6d3351
index 5941a3a4c4..7ba2bc01ca 100644
6d3351
--- a/src/conf/domain_conf.c
6d3351
+++ b/src/conf/domain_conf.c
6d3351
@@ -9314,8 +9314,15 @@ virDomainControllerDefParseXML(xmlNodePtr node,
6d3351
                 goto error;
6d3351
             }
6d3351
         }
6d3351
-        if (numaNode >= 0)
6d3351
+        if (numaNode >= 0) {
6d3351
+            if (def->idx == 0) {
6d3351
+                virReportError(VIR_ERR_XML_ERROR, "%s",
6d3351
+                               _("The PCI controller with index=0 can't "
6d3351
+                                 "be associated with a NUMA node"));
6d3351
+                goto error;
6d3351
+            }
6d3351
             def->opts.pciopts.numaNode = numaNode;
6d3351
+        }
6d3351
         break;
6d3351
 
6d3351
     default:
6d3351
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
6d3351
index cb0eac4668..0437db0ba2 100644
6d3351
--- a/src/qemu/qemu_command.c
6d3351
+++ b/src/qemu/qemu_command.c
6d3351
@@ -3191,6 +3191,16 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef,
6d3351
             virBufferAsprintf(&buf, "%s,index=%d,id=%s",
6d3351
                               modelName, def->opts.pciopts.targetIndex,
6d3351
                               def->info.alias);
6d3351
+
6d3351
+            if (def->opts.pciopts.numaNode != -1) {
6d3351
+                if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPAPR_PCI_HOST_BRIDGE_NUMA_NODE)) {
6d3351
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6d3351
+                                   _("the spapr-pci-host-bridge controller "
6d3351
+                                     "doesn't support numa_node on this QEMU binary"));
6d3351
+                    goto error;
6d3351
+                }
6d3351
+                virBufferAsprintf(&buf, ",numa_node=%d", def->opts.pciopts.numaNode);
6d3351
+            }
6d3351
             break;
6d3351
         case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
6d3351
         case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
6d3351
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
6d3351
index 916358ea1e..ff7efa609e 100644
6d3351
--- a/src/qemu/qemu_domain.c
6d3351
+++ b/src/qemu/qemu_domain.c
6d3351
@@ -3406,15 +3406,14 @@ qemuDomainControllerDefPostParse(virDomainControllerDefPtr cont,
6d3351
             return -1;
6d3351
         }
6d3351
 
6d3351
-        /* if a PCI expander bus has a NUMA node set, make sure
6d3351
-         * that NUMA node is configured in the guest <cpu><numa>
6d3351
-         * array. NUMA cell id's in this array are numbered
6d3351
+        /* if a PCI expander bus or pci-root on Pseries has a NUMA node
6d3351
+         * set, make sure that NUMA node is configured in the guest
6d3351
+         * <cpu><numa> array. NUMA cell id's in this array are numbered
6d3351
          * from 0 .. size-1.
6d3351
          */
6d3351
-        if ((cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS ||
6d3351
-             cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS) &&
6d3351
-            (int) virDomainNumaGetNodeCount(def->numa)
6d3351
-            <= cont->opts.pciopts.numaNode) {
6d3351
+        if (cont->opts.pciopts.numaNode >= 0 &&
6d3351
+            cont->opts.pciopts.numaNode >=
6d3351
+            (int) virDomainNumaGetNodeCount(def->numa)) {
6d3351
             virReportError(VIR_ERR_XML_ERROR,
6d3351
                            _("%s with index %d is "
6d3351
                              "configured for a NUMA node (%d) "
6d3351
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-default-phb-numa-node.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-default-phb-numa-node.xml
6d3351
new file mode 100644
6d3351
index 0000000000..12d277aaf8
6d3351
--- /dev/null
6d3351
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-default-phb-numa-node.xml
6d3351
@@ -0,0 +1,29 @@
6d3351
+<domain type='qemu'>
6d3351
+  <name>QEMUGuest1</name>
6d3351
+  <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid>
6d3351
+  <memory unit='KiB'>1048576</memory>
6d3351
+  <vcpu placement='static'>24</vcpu>
6d3351
+  <numatune>
6d3351
+    <memnode cellid="0" mode="strict" nodeset="1"/>
6d3351
+  </numatune>
6d3351
+  <cpu>
6d3351
+    <topology sockets='3' cores='1' threads='8'/>
6d3351
+    <numa>
6d3351
+      <cell id='0' cpus='0-23' memory='1048576' unit='KiB'/>
6d3351
+    </numa>
6d3351
+  </cpu>
6d3351
+  <os>
6d3351
+    <type arch='ppc64' machine='pseries'>hvm</type>
6d3351
+  </os>
6d3351
+  <devices>
6d3351
+    <emulator>/usr/bin/qemu-system-ppc64</emulator>
6d3351
+    
6d3351
+    <controller type='pci' index='0' model='pci-root'>
6d3351
+      <target index='0'>
6d3351
+        <node>0</node>
6d3351
+      </target>
6d3351
+    </controller>
6d3351
+    <controller type='usb' model='none'/>
6d3351
+    <memballoon model='none'/>
6d3351
+  </devices>
6d3351
+</domain>
6d3351
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-numa-node.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-numa-node.args
6d3351
new file mode 100644
6d3351
index 0000000000..e69ff16d0e
6d3351
--- /dev/null
6d3351
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-numa-node.args
6d3351
@@ -0,0 +1,28 @@
6d3351
+LC_ALL=C \
6d3351
+PATH=/bin \
6d3351
+HOME=/home/test \
6d3351
+USER=test \
6d3351
+LOGNAME=test \
6d3351
+QEMU_AUDIO_DRV=none \
6d3351
+/usr/bin/qemu-system-ppc64 \
6d3351
+-name QEMUGuest1 \
6d3351
+-S \
6d3351
+-M pseries \
6d3351
+-m 2048 \
6d3351
+-smp 8,sockets=2,cores=1,threads=4 \
6d3351
+-object memory-backend-ram,id=ram-node0,size=1073741824,host-nodes=1,\
6d3351
+policy=bind \
6d3351
+-numa node,nodeid=0,cpus=0-3,memdev=ram-node0 \
6d3351
+-object memory-backend-ram,id=ram-node1,size=1073741824,host-nodes=2,\
6d3351
+policy=bind \
6d3351
+-numa node,nodeid=1,cpus=4-7,memdev=ram-node1 \
6d3351
+-uuid 87eedafe-eedc-4336-8130-ed9fe5dc90c8 \
6d3351
+-nographic \
6d3351
+-nodefaults \
6d3351
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
6d3351
+server,nowait \
6d3351
+-mon chardev=charmonitor,id=monitor,mode=readline \
6d3351
+-boot c \
6d3351
+-device spapr-pci-host-bridge,index=1,id=pci.1,numa_node=1 \
6d3351
+-device spapr-pci-host-bridge,index=2,id=pci.2 \
6d3351
+-device spapr-pci-host-bridge,index=3,id=pci.3,numa_node=0
6d3351
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-numa-node.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-numa-node.xml
6d3351
new file mode 100644
6d3351
index 0000000000..aeccb14dfb
6d3351
--- /dev/null
6d3351
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-phb-numa-node.xml
6d3351
@@ -0,0 +1,41 @@
6d3351
+<domain type='qemu'>
6d3351
+  <name>QEMUGuest1</name>
6d3351
+  <uuid>87eedafe-eedc-4336-8130-ed9fe5dc90c8</uuid>
6d3351
+  <memory unit='KiB'>2097152</memory>
6d3351
+  <vcpu placement='static'>8</vcpu>
6d3351
+  <numatune>
6d3351
+    <memnode cellid="0" mode="strict" nodeset="1"/>
6d3351
+    <memnode cellid="1" mode="strict" nodeset="2"/>
6d3351
+  </numatune>
6d3351
+  <cpu>
6d3351
+    <topology sockets='2' cores='1' threads='4'/>
6d3351
+    <numa>
6d3351
+      <cell id='0' cpus='0-3' memory='1048576' unit='KiB'/>
6d3351
+      <cell id='1' cpus='4-7' memory='1048576' unit='KiB'/>
6d3351
+    </numa>
6d3351
+  </cpu>
6d3351
+  <os>
6d3351
+    <type arch='ppc64' machine='pseries'>hvm</type>
6d3351
+  </os>
6d3351
+  <devices>
6d3351
+    <emulator>/usr/bin/qemu-system-ppc64</emulator>
6d3351
+    <controller type='usb' model='none' index='0'/>
6d3351
+    <controller type='pci' index='0' model='pci-root'>
6d3351
+      <target index='0'/>
6d3351
+    </controller>
6d3351
+    <controller type='pci' index='1' model='pci-root'>
6d3351
+      <target index='1'>
6d3351
+        <node>1</node>
6d3351
+      </target>
6d3351
+    </controller>
6d3351
+    <controller type='pci' index='2' model='pci-root'>
6d3351
+      <target index='2'/>
6d3351
+    </controller>
6d3351
+    <controller type='pci' index='3' model='pci-root'>
6d3351
+      <target index='3'>
6d3351
+        <node>0</node>
6d3351
+      </target>
6d3351
+    </controller>
6d3351
+    <memballoon model='none'/>
6d3351
+  </devices>
6d3351
+</domain>
6d3351
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
6d3351
index 2b9421cb7a..ee62e26309 100644
6d3351
--- a/tests/qemuxml2argvtest.c
6d3351
+++ b/tests/qemuxml2argvtest.c
6d3351
@@ -1761,6 +1761,12 @@ mymain(void)
6d3351
             QEMU_CAPS_NODEFCONFIG,
6d3351
             QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE);
6d3351
     DO_TEST_PARSE_ERROR("pseries-phb-wrong-target-index", NONE);
6d3351
+    DO_TEST("pseries-phb-numa-node",
6d3351
+            QEMU_CAPS_NUMA,
6d3351
+            QEMU_CAPS_OBJECT_MEMORY_RAM,
6d3351
+            QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE,
6d3351
+            QEMU_CAPS_SPAPR_PCI_HOST_BRIDGE_NUMA_NODE);
6d3351
+    DO_TEST_PARSE_ERROR("pseries-default-phb-numa-node", NONE);
6d3351
 
6d3351
     DO_TEST("pseries-many-devices",
6d3351
             QEMU_CAPS_NODEFCONFIG,
6d3351
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-numa-node.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-numa-node.xml
6d3351
new file mode 100644
6d3351
index 0000000000..80b771e89d
6d3351
--- /dev/null
6d3351
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pseries-phb-numa-node.xml
6d3351
@@ -0,0 +1,52 @@
6d3351
+<domain type='qemu'>
6d3351
+  <name>QEMUGuest1</name>
6d3351
+  <uuid>87eedafe-eedc-4336-8130-ed9fe5dc90c8</uuid>
6d3351
+  <memory unit='KiB'>2097152</memory>
6d3351
+  <currentMemory unit='KiB'>2097152</currentMemory>
6d3351
+  <vcpu placement='static'>8</vcpu>
6d3351
+  <numatune>
6d3351
+    <memnode cellid='0' mode='strict' nodeset='1'/>
6d3351
+    <memnode cellid='1' mode='strict' nodeset='2'/>
6d3351
+  </numatune>
6d3351
+  <os>
6d3351
+    <type arch='ppc64' machine='pseries'>hvm</type>
6d3351
+    <boot dev='hd'/>
6d3351
+  </os>
6d3351
+  <cpu>
6d3351
+    <topology sockets='2' cores='1' threads='4'/>
6d3351
+    <numa>
6d3351
+      <cell id='0' cpus='0-3' memory='1048576' unit='KiB'/>
6d3351
+      <cell id='1' cpus='4-7' memory='1048576' unit='KiB'/>
6d3351
+    </numa>
6d3351
+  </cpu>
6d3351
+  <clock offset='utc'/>
6d3351
+  <on_poweroff>destroy</on_poweroff>
6d3351
+  <on_reboot>restart</on_reboot>
6d3351
+  <on_crash>destroy</on_crash>
6d3351
+  <devices>
6d3351
+    <emulator>/usr/bin/qemu-system-ppc64</emulator>
6d3351
+    <controller type='usb' index='0' model='none'/>
6d3351
+    <controller type='pci' index='0' model='pci-root'>
6d3351
+      <model name='spapr-pci-host-bridge'/>
6d3351
+      <target index='0'/>
6d3351
+    </controller>
6d3351
+    <controller type='pci' index='1' model='pci-root'>
6d3351
+      <model name='spapr-pci-host-bridge'/>
6d3351
+      <target index='1'>
6d3351
+        <node>1</node>
6d3351
+      </target>
6d3351
+    </controller>
6d3351
+    <controller type='pci' index='2' model='pci-root'>
6d3351
+      <model name='spapr-pci-host-bridge'/>
6d3351
+      <target index='2'/>
6d3351
+    </controller>
6d3351
+    <controller type='pci' index='3' model='pci-root'>
6d3351
+      <model name='spapr-pci-host-bridge'/>
6d3351
+      <target index='3'>
6d3351
+        <node>0</node>
6d3351
+      </target>
6d3351
+    </controller>
6d3351
+    <memballoon model='none'/>
6d3351
+    <panic model='pseries'/>
6d3351
+  </devices>
6d3351
+</domain>
6d3351
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
6d3351
index 6762145470..564da08707 100644
6d3351
--- a/tests/qemuxml2xmltest.c
6d3351
+++ b/tests/qemuxml2xmltest.c
6d3351
@@ -672,6 +672,10 @@ mymain(void)
6d3351
     DO_TEST("pseries-phb-default-missing",
6d3351
             QEMU_CAPS_NODEFCONFIG,
6d3351
             QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE);
6d3351
+    DO_TEST("pseries-phb-numa-node",
6d3351
+            QEMU_CAPS_NUMA,
6d3351
+            QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE,
6d3351
+            QEMU_CAPS_SPAPR_PCI_HOST_BRIDGE_NUMA_NODE);
6d3351
 
6d3351
     DO_TEST("pseries-many-devices",
6d3351
             QEMU_CAPS_NODEFCONFIG,
6d3351
-- 
6d3351
2.13.3
6d3351