From: Michael Ellerman <michael(a)ellerman.id.au>
Date: Tue, 29 Nov 2011 13:48:09 +0530
Subject: [PATCH 5/5] Add address-type "spapr-vio" for devices based on
the same bus.
For QEMU PPC64 we have a machine type ("pseries") which
has a virtual bus called "spapr-vio". We need to be
able to create devices on this bus, and as such need a
way to specify the address for those devices.
This patch adds a new address type "spapr-vio", which achieves this.
The addressing is specified with a "reg" property in the address
definition. The reg is optional, if it is not specified QEMU will
auto-assign an address for the device.
Additionally, this patch forces an "spapr-vscsi" controller to be
selected for a guest running on architecture 'ppc64' and platform
'pseries'.
Signed-off-by: Michael Ellerman <michael(a)ellerman.id.au>
Signed-off-by: Prerna Saxena <prerna(a)linux.vnet.ibm.com>
---
src/conf/domain_conf.c | 42 +++++++++++++++++++++++++++++++++++++++++-
src/conf/domain_conf.h | 9 +++++++++
src/qemu/qemu_command.c | 18 ++++++++++++++----
src/qemu/qemu_command.h | 3 ++-
src/qemu/qemu_hotplug.c | 2 +-
5 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3ea99f7..5c3809e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -139,7 +139,8 @@ VIR_ENUM_IMPL(virDomainDeviceAddress,
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
"drive",
"virtio-serial",
"ccid",
- "usb")
+ "usb",
+ "spapr-vio")
VIR_ENUM_IMPL(virDomainDeviceAddressPciMulti,
VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_LAST,
@@ -1844,6 +1845,11 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
info->addr.usb.port);
break;
+ case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO:
+ if (info->addr.spaprvio.has_reg)
+ virBufferAsprintf(buf, " reg='%#llx'",
info->addr.spaprvio.reg);
+ break;
+
default:
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("unknown address type '%d'"),
info->type);
@@ -2103,6 +2109,34 @@ cleanup:
}
static int
+virDomainDeviceSpaprVioAddressParseXML(xmlNodePtr node,
+ virDomainDeviceSpaprVioAddressPtr addr)
+{
+ char *reg;
+ int ret;
+
+ memset(addr, 0, sizeof(*addr));
+ addr->has_reg = false;
+
+ reg = virXMLPropString(node, "reg");
+ if (reg) {
+ if (virStrToLong_ull(reg, NULL, 16, &addr->reg) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot parse <address> 'reg'
attribute"));
+ ret = -1;
+ goto cleanup;
+ }
+
+ addr->has_reg = true;
+ }
+
+ ret = 0;
+cleanup:
+ VIR_FREE(reg);
+ return ret;
+}
+
+static int
virDomainDeviceUSBMasterParseXML(xmlNodePtr node,
virDomainDeviceUSBMasterPtr master)
{
@@ -2215,6 +2249,11 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
goto cleanup;
break;
+ case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO:
+ if (virDomainDeviceSpaprVioAddressParseXML(address, &info->addr.spaprvio)
< 0)
+ goto cleanup;
+ break;
+
default:
/* Should not happen */
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@@ -3048,6 +3087,7 @@ virDomainControllerDefParseXML(xmlNodePtr node,
}
if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+ def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO &&
def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Controllers must use the 'pci' address
type"));
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 4439f55..b1f9260 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -69,6 +69,7 @@ enum virDomainDeviceAddressType {
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL,
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID,
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB,
+ VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO,
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST
};
@@ -121,6 +122,13 @@ struct _virDomainDeviceUSBAddress {
char *port;
};
+typedef struct _virDomainDeviceSpaprVioAddress virDomainDeviceSpaprVioAddress;
+typedef virDomainDeviceSpaprVioAddress *virDomainDeviceSpaprVioAddressPtr;
+struct _virDomainDeviceSpaprVioAddress {
+ unsigned long long reg;
+ bool has_reg;
+};
+
enum virDomainControllerMaster {
VIR_DOMAIN_CONTROLLER_MASTER_NONE,
VIR_DOMAIN_CONTROLLER_MASTER_USB,
@@ -145,6 +153,7 @@ struct _virDomainDeviceInfo {
virDomainDeviceVirtioSerialAddress vioserial;
virDomainDeviceCcidAddress ccid;
virDomainDeviceUSBAddress usb;
+ virDomainDeviceSpaprVioAddress spaprvio;
} addr;
int mastertype;
union {
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 57b25d6..0d03fbc 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1253,6 +1253,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
qemuDomainPCIAddressSetPtr addrs)
def->controllers[i]->idx == 0)
continue;
+ if (def->controllers[i]->info.type ==
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO)
+ continue;
if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
continue;
if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info)
< 0)
@@ -1403,6 +1405,9 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
virBufferAsprintf(buf, ",bus=");
qemuUsbId(buf, info->addr.usb.bus);
virBufferAsprintf(buf, ".0,port=%s", info->addr.usb.port);
+ } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO) {
+ if (info->addr.spaprvio.has_reg)
+ virBufferAsprintf(buf, ",reg=%#llx", info->addr.spaprvio.reg);
}
return 0;
@@ -2087,7 +2092,8 @@ qemuBuildUSBControllerDevStr(virDomainControllerDefPtr def,
}
char *
-qemuBuildControllerDevStr(virDomainControllerDefPtr def,
+qemuBuildControllerDevStr(virDomainDefPtr domainDef,
+ virDomainControllerDefPtr def,
virBitmapPtr qemuCaps,
int *nusbcontroller)
{
@@ -2095,7 +2101,11 @@ qemuBuildControllerDevStr(virDomainControllerDefPtr def,
switch (def->type) {
case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
- virBufferAddLit(&buf, "lsi");
+ if (STREQ(domainDef->os.arch, "ppc64") &&
STREQ(domainDef->os.machine, "pseries")) {
+ virBufferAddLit(&buf, "spapr-vscsi");
+ } else {
+ virBufferAddLit(&buf, "lsi");
+ }
virBufferAsprintf(&buf, ",id=scsi%d", def->idx);
break;
@@ -4009,7 +4019,7 @@ qemuBuildCommandLine(virConnectPtr conn,
char *devstr;
virCommandAddArg(cmd, "-device");
- if (!(devstr = qemuBuildControllerDevStr(cont, qemuCaps, NULL)))
+ if (!(devstr = qemuBuildControllerDevStr(def, cont, qemuCaps,
NULL)))
goto error;
virCommandAddArg(cmd, devstr);
@@ -4028,7 +4038,7 @@ qemuBuildCommandLine(virConnectPtr conn,
virCommandAddArg(cmd, "-device");
char *devstr;
- if (!(devstr = qemuBuildControllerDevStr(def->controllers[i],
qemuCaps,
+ if (!(devstr = qemuBuildControllerDevStr(def, def->controllers[i],
qemuCaps,
&usbcontroller)))
goto error;
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 1fe0394..3978b2b 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -95,7 +95,8 @@ char * qemuBuildDriveDevStr(virDomainDiskDefPtr disk,
char * qemuBuildFSDevStr(virDomainFSDefPtr fs,
virBitmapPtr qemuCaps);
/* Current, best practice */
-char * qemuBuildControllerDevStr(virDomainControllerDefPtr def,
+char * qemuBuildControllerDevStr(virDomainDefPtr domainDef,
+ virDomainControllerDefPtr def,
virBitmapPtr qemuCaps,
int *nusbcontroller);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 96c0070..eabfeaa 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -329,7 +329,7 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver,
goto cleanup;
}
- if (!(devstr = qemuBuildControllerDevStr(controller, priv->qemuCaps, NULL)))
{
+ if (!(devstr = qemuBuildControllerDevStr(vm->def, controller,
priv->qemuCaps, NULL))) {
goto cleanup;
}
}
--
1.7.7
--
Prerna Saxena
Linux Technology Centre,
IBM Systems and Technology Lab,
Bangalore, India