[libvirt] [RFC v3 PATCH 5/5] PowerPC : Add address-type "spapr-vio"

Michael Ellerman michael at ellerman.id.au
Fri Dec 2 07:34:23 UTC 2011


On Thu, 2011-12-01 at 09:52 +0000, Daniel P. Berrange wrote:
> On Thu, Dec 01, 2011 at 05:38:31PM +1100, Michael Ellerman wrote:
> > But if it's a hard requirement in your view then I'll do it.
> 
> It is the only way to ensure stable device addresses every time the
> guest is started.
> 
> eg, consider what happens if you don't assign addresses
> 
>    qemu -drive foo  -drive bar
> 
> QEMU assigns  foo reg=1,  bar reg=2. Now delete hotunplug a device
> 
>   (qemu) drive_del foo
> 
> Now migrate QEMU to a new host, which means it'll be started with
> 
>    qemu -drive bar
> 
> So QEMU will assign bar reg=1, whereas the guest OS currently
> thinks it has reg=2.
> 
> libvirt *must* define addresses for every single device it passes to
> QEMU at all times. Even if we ignore hotplug, and just consider that
> we cold unpluged 'foo', we still want 'bar' to have the same address,
> in case the guest OS had configured something based on address, or
> worse yet done an OS license/activation check based on hardware config.

OK. Currently I don't think either of those examples actually apply to
us, but I can see that it is liable to bite us in the future if we don't
assign addresses.

Below is a first cut at a patch to do this. It seems to work but it has
a few problems.

Firstly there are calls in qemuDomainUpdateDeviceConfig()
to qemuDomainAssignPCIAddresses(), I'm not sure if I need to also add
calls to qemuAssignSpaprVIOAddresses() in there. Can you explain to me
when qemuDomainUpdateDeviceConfig() is called and what it is doing?

Secondly, and this is a real problem, if the user specifies a serial
with no address type, we don't see it, because it doesn't have a
spapr-vio address, and so we don't take it into account in the address
allocation. But then because it ends becoming a spapr-vty in
qemuBuildChrDeviceStr() (which Prerna added), it clashes with the other
serial we created.

Example config is:

 <serial type="pty"/>
 <serial type="pty">
   <address type="spapr-vio"/>
 </serial>

So we need some way of knowing that the first serial will end up on the
spapr-vio bus, so we can take it into account in the address allocation.
I haven't thought of a good way to fix that yet. We could just say that
it's unsupported for pseries, ie. you MUST specify the address type, but
that would be a pity.

cheers


diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index eceae35..dfd92ad 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -684,6 +684,63 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virBitmapPtr qemuCaps)
     return -1;
 }
 
+static int qemuSpaprVIOFindByReg(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                                 virDomainDeviceInfoPtr info, void *opaque)
+{
+    virDomainDeviceInfoPtr target = (virDomainDeviceInfoPtr)opaque;
+
+    if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO)
+        return 0;
+
+    /* Match a dev that has a reg, is not us, and has a matching reg */
+    if (info->addr.spaprvio.has_reg && info != target &&
+        info->addr.spaprvio.reg == target->addr.spaprvio.reg)
+        /* Has to be < 0 so virDomainDeviceInfoIterate() will exit */
+        return -1;
+
+    return 0;
+}
+
+static void qemuAssignSpaprVIOAddress(virDomainDefPtr def,
+                                      virDomainDeviceInfoPtr info,
+                                      unsigned long long default_reg)
+{
+    int rc;
+
+    if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO)
+        return;
+
+    if (info->addr.spaprvio.has_reg)
+        return;
+
+    info->addr.spaprvio.has_reg = true;
+    info->addr.spaprvio.reg = default_reg;
+
+    rc = virDomainDeviceInfoIterate(def, qemuSpaprVIOFindByReg, info);
+    while (rc != 0) {
+        /* We hit another device, move along by 4K and search again */
+        info->addr.spaprvio.reg += 0x1000;
+        rc = virDomainDeviceInfoIterate(def, qemuSpaprVIOFindByReg, info);
+    }
+}
+
+int qemuAssignSpaprVIOAddresses(virDomainDefPtr def)
+{
+    int i;
+
+    for (i = 0 ; i < def->nnets; i++)
+        qemuAssignSpaprVIOAddress(def, &def->nets[i]->info, 0x1000ul);
+
+    for (i = 0 ; i < def->ncontrollers; i++)
+        qemuAssignSpaprVIOAddress(def, &def->controllers[i]->info, 0x2000ul);
+
+    for (i = 0 ; i < def->nserials; i++)
+        qemuAssignSpaprVIOAddress(def, &def->serials[i]->info, 0x30000000ul);
+
+    /* No other devices are currently supported on spapr-vio */
+
+    return 0;
+}
 
 #define QEMU_PCI_ADDRESS_LAST_SLOT 31
 #define QEMU_PCI_ADDRESS_LAST_FUNCTION 8
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 8b51ef3..f748c2b 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -203,6 +203,8 @@ int qemuAssignDeviceHostdevAlias(virDomainDefPtr def, virDomainHostdevDefPtr hos
 int qemuAssignDeviceControllerAlias(virDomainControllerDefPtr controller);
 int qemuAssignDeviceRedirdevAlias(virDomainDefPtr def, virDomainRedirdevDefPtr redirdev, int idx);
 
+int qemuAssignSpaprVIOAddresses(virDomainDefPtr def);
+
 int
 qemuParseKeywords(const char *str,
                   char ***retkeywords,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 105bdde..6c47516 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1317,6 +1317,8 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
     if (qemuDomainAssignPCIAddresses(def) < 0)
         goto cleanup;
 
+    qemuAssignSpaprVIOAddresses(def);
+
     if (!(vm = virDomainAssignDef(driver->caps,
                                   &driver->domains,
                                   def, false)))
@@ -4903,6 +4905,8 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
     if (qemuDomainAssignPCIAddresses(def) < 0)
         goto cleanup;
 
+    qemuAssignSpaprVIOAddresses(def);
+
     if (!(vm = virDomainAssignDef(driver->caps,
                                   &driver->domains,
                                   def, false))) {
@@ -10748,6 +10752,8 @@ static virDomainPtr qemuDomainAttach(virConnectPtr conn,
     if (qemuDomainAssignPCIAddresses(def) < 0)
         goto cleanup;
 
+    qemuAssignSpaprVIOAddresses(def);
+
     if (!(vm = virDomainAssignDef(driver->caps,
                                   &driver->domains,
                                   def, false)))
-- 
1.7.7.3






More information about the libvir-list mailing list