# HG changeset patch
# User Sharad Mishra <snmishra(a)us.ibm.com>
# Date 1318954618 25200
# Node ID d07f99a0279030e62046bbdc3ac378f9dc6473af
# Parent fb09136deb494008eb3aacee420ad74da7d7c294
<Incomplete> SROV support in libvirt-cim
This patch is the patch to add SRIOV support in libvirt-cim.
This patch is not complete. Work on it was halted since the
exploiter of this feature is not ready to consume it. And there
are other features that need to be added which are in demand in
near future.
SRIOV support adds Enumeration of node devices to see what is
available. Then it adds Virtual Functions (VFs), removes VFs and
modifies VFs. It also adds support to detach a node. This link
shows the steps -
http://docs.fedoraproject.org/en-US/Fedora/13/html/
Virtualization_Guide/sect-Para-virtualized_Windows_Drivers_Guide-
How_SR_IOV_Libvirt_Works.html
Step 6 above is for enum node devices.
Step 8 is detach VF.
Step 9 is add VF to guest.
Similar to step 9 will be removeVF and modifyVF.
So far, we have "sorta" implemented enum node device.
Signed-off-by: Sharad Mishra <snmishra(a)us.ibm.com>
diff -r fb09136deb49 -r d07f99a02790 Makefile.am
--- a/Makefile.am Tue Aug 30 08:48:36 2011 -0700
+++ b/Makefile.am Tue Oct 18 09:16:58 2011 -0700
@@ -29,6 +29,7 @@
schema/ComputerSystemIndication.mof \
schema/ResourceAllocationSettingDataIndication.mof \
schema/SwitchService.mof \
+ schema/VirtualSystemPCIDevice.mof \
schema/ComputerSystemMigrationIndication.mof \
schema/Virt_ResourceAllocationSettingData.mof \
schema/ResourceAllocationSettingData.mof \
@@ -116,6 +117,7 @@
schema/ComputerSystemIndication.registration \
schema/ResourceAllocationSettingDataIndication.registration \
schema/SwitchService.registration \
+ schema/VirtualSystemPCIDevice.registration \
schema/ComputerSystemMigrationIndication.registration \
schema/ResourceAllocationSettingData.registration \
schema/ResourcePoolConfigurationService.registration \
diff -r fb09136deb49 -r d07f99a02790 libxkutil/Makefile.am
--- a/libxkutil/Makefile.am Tue Aug 30 08:48:36 2011 -0700
+++ b/libxkutil/Makefile.am Tue Oct 18 09:16:58 2011 -0700
@@ -5,12 +5,14 @@
-DLIBVIRTCIM_CONF=\"@sysconfdir@/@PACKAGE@.conf\"
noinst_HEADERS = cs_util.h misc_util.h device_parsing.h xmlgen.h
infostore.h \
- pool_parsing.h acl_parsing.h
+ pool_parsing.h acl_parsing.h node_parsing.h
lib_LTLIBRARIES = libxkutil.la
libxkutil_la_SOURCES = cs_util_instance.c misc_util.c device_parsing.c \
- xmlgen.c infostore.c pool_parsing.c acl_parsing.c
+ xmlgen.c infostore.c pool_parsing.c acl_parsing.c
\
+ node_parsing.c
+
libxkutil_la_LDFLAGS = -version-info @VERSION_INFO@
libxkutil_la_LIBADD = @LIBVIRT_LIBS@ \
@LIBUUID_LIBS@
diff -r fb09136deb49 -r d07f99a02790 libxkutil/node_parsing.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libxkutil/node_parsing.c Tue Oct 18 09:16:58 2011 -0700
@@ -0,0 +1,184 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Sharad Mishra <snmishra(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include "misc_util.h"
+
+#include <libcmpiutil/libcmpiutil.h>
+
+#include "node_parsing.h"
+
+static void cleanup_pci_device(struct pci_device pci) {
+
+ free(pci.product);
+ free(pci.vendor);
+}
+
+void cleanup_node_device(struct node_device **node)
+{
+ struct node_device *_node = *node;
+
+ if ((node == NULL) || (*node == NULL))
+ return;
+
+ if (XSTREQ(_node->capability, "pci"))
+ cleanup_pci_device(_node->device_info.pci);
+
+ free(_node->name);
+ free(_node->parent);
+ free(_node->capability);
+ free(_node);
+
+ *node = NULL;
+}
+
+CMPIStatus get_node_from_xml(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ virConnectPtr conn,
+ char *xml,
+ CMPIInstance **_inst)
+{
+ int len;
+ xmlDoc *xmldoc;
+ xmlXPathContext *xpathctx;
+ xmlXPathObject *xpathobj;
+ const xmlChar *xpathstr = (xmlChar *)"/device";
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *inst = NULL;
+ char *val = NULL;
+ char *tmpstr = NULL;
+ xmlNode **nodes = NULL;
+ xmlNode *child;
+ uint8_t ival;
+
+ CU_DEBUG("Node XML : %s", xml);
+ len = strlen(xml) + 1;
+
+ inst = get_typed_instance(broker,
+ pfx_from_conn(conn),
+ "VirtualSystemPCIDevice",
+ NAMESPACE(reference));
+ if (inst == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to init VirtualSystemPCIDevice
instance");
+ goto err1;
+ }
+
+
+ if ((xmldoc = xmlParseMemory(xml, len)) == NULL) {
+ CU_DEBUG("xmlParseMemory failed");
+ goto err1;
+ }
+
+ if ((xpathctx = xmlXPathNewContext(xmldoc)) == NULL) {
+ CU_DEBUG("xmlXPathNewContext failed");
+ goto err2;
+ }
+
+ if ((xpathobj = xmlXPathEvalExpression(xpathstr, xpathctx))==
NULL) {
+ CU_DEBUG("xmlXPathEvalExpression
failed");
+ goto err3;
+ }
+
+ nodes = xpathobj->nodesetval->nodeTab;
+
+ for (child = nodes[0]->children; child != NULL; child =
child->next) {
+ if (XSTREQ(child->name, "name")) {
+ val = get_node_content(child);
+CU_DEBUG("val is %s", val);
+ if (val != NULL)
+ s = CMSetProperty(inst, "Name",
+ (CMPIValue *)val,
+ CMPI_chars);
+ } else if (XSTREQ(child->name, "capability")) {
+ child = child->children;
+CU_DEBUG("found capabi s.rc is %d, s.msg is %s", s.rc, s.msg);
+ continue;
+ } else if (XSTREQ(child->name, "bus")) {
+CU_DEBUG("found bus");
+ val = get_node_content(child);
+CU_DEBUG("val is %s", val);
+ival = atoi(val);
+CU_DEBUG("len is %d", ival);
+ s = CMSetProperty(inst, "BusNumber",
+ (CMPIValue *)&ival,
+ CMPI_uint8);
+ } else if (XSTREQ(child->name, "slot")) {
+CU_DEBUG("found slot rs is %d msg is %s", s.rc, s.msg);
+ val = get_node_content(child);
+CU_DEBUG("val is %s", val);
+ival = atoi(val);
+CU_DEBUG("len is %d", ival);
+ s = CMSetProperty(inst, "DeviceNumber",
+ (CMPIValue *)&ival,
+ CMPI_uint8);
+ } else if (XSTREQ(child->name, "function")) {
+CU_DEBUG("found function rc is %d, msg is %s", s.rc, s.msg);
+ val = get_node_content(child);
+CU_DEBUG("val is %s", val);
+ival = atoi(val);
+CU_DEBUG("len_16 is %d", ival);
+ s = CMSetProperty(inst, "FunctionNumber",
+ (CMPIValue *)&ival,
+ CMPI_uint8);
+ } else if (XSTREQ(child->name, "vendor")) {
+CU_DEBUG("found vendor rc is %d msg is %s", s.rc, s.msg);
+ val = get_attr_value(child, "id");
+CU_DEBUG("val is %s", val);
+sprintf(tmpstr, "%*2s", val);
+CU_DEBUG("tmpstr is %s", tmpstr);
+uint16_t val16 = atoi(tmpstr);
+CU_DEBUG("len is %d", val16);
+ s = CMSetProperty(inst, "VendorID",
+ (CMPIValue *)&val16,
+ CMPI_uint16);
+ }
+ }
+
+ *_inst = inst;
+
+ xmlXPathFreeObject(xpathobj);
+ err3:
+ xmlXPathFreeContext(xpathctx);
+ err2:
+ xmlFreeDoc(xmldoc);
+ err1:
+ return s;
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -r fb09136deb49 -r d07f99a02790 libxkutil/node_parsing.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libxkutil/node_parsing.h Tue Oct 18 09:16:58 2011 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Sharad Mishra <snmishra(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+
+
+#include "cmpidt.h"
+#include "cmpift.h"
+#include "cmpimacs.h"
+#include "device_parsing.h"
+
+struct pci_device {
+ int domain;
+ int bus;
+ int slot;
+ int function;
+ char *product;
+ char *vendor;
+};
+
+/* USB and other node devices can be added later. */
+struct node_device {
+ char *name;
+ char *parent;
+ char *capability;
+ union {
+ struct pci_device pci;
+ } device_info;
+};
+
+void cleanup_node_device(struct node_device **node);
+CMPIStatus get_node_from_xml(const CMPIBroker *broker,
+ const CMPIObjectPath *reference,
+ virConnectPtr conn,
+ char *xml,
+ CMPIInstance **_inst);
+
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r fb09136deb49 -r d07f99a02790 schema/VirtualSystemPCIDevice.mof
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/schema/VirtualSystemPCIDevice.mof Tue Oct 18 09:16:58 2011 -0700
@@ -0,0 +1,14 @@
+// Copyright IBM Corp. 2011
+
+[Provider("cmpi::Virt_VirtualSystemPCIDevice")]
+class Xen_VirtualSystemPCIDevice : CIM_PCIDevice {
+};
+
+[Provider("cmpi::Virt_VirtualSystemPCIDevice")]
+class KVM_VirtualSystemPCIDevice : CIM_PCIDevice {
+};
+
+[Provider("cmpi::Virt_VirtualSystemPCIDevice")]
+class LXC_VirtualSystemPCIDevice : CIM_PCIDevice {
+};
+
diff -r fb09136deb49 -r d07f99a02790 schema/
VirtualSystemPCIDevice.registration
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/schema/VirtualSystemPCIDevice.registration Tue Oct 18 09:16:
58 2011 -0700
@@ -0,0 +1,5 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+Xen_VirtualSystemPCIDevice root/virt Virt_VirtualSystemPCIDevice
Virt_VirtualSystemPCIDevice instance method
+KVM_VirtualSystemPCIDevice root/virt Virt_VirtualSystemPCIDevice
Virt_VirtualSystemPCIDevice instance method
+LXC_VirtualSystemPCIDevice root/virt Virt_VirtualSystemPCIDevice
Virt_VirtualSystemPCIDevice instance method
diff -r fb09136deb49 -r d07f99a02790 src/Makefile.am
--- a/src/Makefile.am Tue Aug 30 08:48:36 2011 -0700
+++ b/src/Makefile.am Tue Oct 18 09:16:58 2011 -0700
@@ -17,6 +17,7 @@
Virt_VSSD.h \
Virt_VSMigrationCapabilities.h \
Virt_VSMigrationService.h \
+ Virt_VirtualSystemPCIDevice.h \
Virt_AllocationCapabilities.h \
Virt_VirtualSystemSnapshotService.h \
Virt_VirtualSystemSnapshotServiceCapabilities.h \
@@ -53,6 +54,7 @@
libVirt_ComputerSystemIndication.la \
libVirt_ResourceAllocationSettingDataIndication.la \
libVirt_SwitchService.la \
+ libVirt_VirtualSystemPCIDevice.la \
libVirt_ComputerSystemMigrationIndication.la \
libVirt_VirtualSystemManagementCapabilities.la \
libVirt_AllocationCapabilities.la \
@@ -105,6 +107,9 @@
libVirt_SwitchService_la_SOURCES = Virt_SwitchService.c
libVirt_SwitchService_la_LIBADD = -lVirt_ComputerSystem
+libVirt_VirtualSystemPCIDevice = libVirt_ComputerSystem.la
+libVirt_VirtualSystemPCIDevice_la_SOURCES =
Virt_VirtualSystemPCIDevice.c
+
libVirt_ComputerSystemMigrationIndication_la_DEPENDENCIES =
libVirt_ComputerSystem.la
libVirt_ComputerSystemMigrationIndication_la_SOURCES =
Virt_ComputerSystemMigrationIndication.c
libVirt_ComputerSystemMigrationIndication_la_LIBADD =
-lVirt_ComputerSystem
diff -r fb09136deb49 -r d07f99a02790
src/Virt_VirtualSystemPCIDevice.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Virt_VirtualSystemPCIDevice.c Tue Oct 18 09:16:58 2011 -0700
@@ -0,0 +1,295 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Sharad Mishra <snmishra(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include <uuid.h>
+
+#include <libvirt/libvirt.h>
+
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include "misc_util.h"
+#include "node_parsing.h"
+#include <libcmpiutil/std_instance.h>
+#include <libcmpiutil/std_invokemethod.h>
+#include <libcmpiutil/std_indication.h>
+
+#include "Virt_VSMigrationService.h"
+#include "Virt_HostSystem.h"
+#include "Virt_ComputerSystem.h"
+#include "Virt_VSMigrationSettingData.h"
+#include "svpc_types.h"
+#include "libxkutil/infostore.h"
+
+#include "config.h"
+
+#include "Virt_VirtualSystemPCIDevice.h"
+
+const static CMPIBroker *_BROKER;
+
+static CMPIStatus add_sriov_vf(CMPIMethodMI *self,
+ const CMPIContext *ctx,
+ const CMPIResult *results,
+ const CMPIObjectPath *ref,
+ const CMPIArgs *argsin,
+ CMPIArgs *argsout)
+{
+
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+
+ return s;
+}
+
+static CMPIStatus remove_sriov_vf(CMPIMethodMI *self,
+ const CMPIContext *ctx,
+ const CMPIResult *results,
+ const CMPIObjectPath *ref,
+ const CMPIArgs *argsin,
+ CMPIArgs *argsout)
+{
+
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+
+ return s;
+}
+
+static CMPIStatus modify_sriov_vf(CMPIMethodMI *self,
+ const CMPIContext *ctx,
+ const CMPIResult *results,
+ const CMPIObjectPath *ref,
+ const CMPIArgs *argsin,
+ CMPIArgs *argsout)
+{
+
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+
+ return s;
+}
+
+static struct method_handler AddSriovVf = {
+ .name = "AddSriovVf",
+ .handler = add_sriov_vf,
+ .args = {{"ComputerSystem", CMPI_ref, false},
+ {"DestinationSystem", CMPI_ref, false},
+ {"MigrationSettingData", CMPI_instance, true},
+ {"NewSystemSettingData", CMPI_instance, true},
+ {"NewResourceSettingData", CMPI_instanceA, true},
+ ARG_END
+ }
+};
+
+static struct method_handler RemoveSriovVf = {
+ .name = "RemoveSriovVf",
+ .handler = remove_sriov_vf,
+ .args = {{"ComputerSystem", CMPI_ref, false},
+ {"DestinationHost", CMPI_string, false},
+ {"MigrationSettingData", CMPI_instance, true},
+ {"NewSystemSettingData", CMPI_instance, true},
+ {"NewResourceSettingData", CMPI_instanceA, true},
+ ARG_END
+ }
+};
+
+static struct method_handler ModifySriovVf = {
+ .name = "ModifySriovVf",
+ .handler = modify_sriov_vf,
+ .args = {{"ComputerSystem", CMPI_ref, false},
+ {"DestinationSystem", CMPI_ref, false},
+ {"MigrationSettingData", CMPI_instance, true},
+ {"NewSystemSettingData", CMPI_instance, true},
+ {"NewResourceSettingData", CMPI_instanceA, true},
+ ARG_END
+ }
+};
+
+static struct method_handler *my_handlers[] = {
+ &AddSriovVf,
+ &RemoveSriovVf,
+ &ModifySriovVf,
+ NULL
+};
+
+STDIM_MethodMIStub(, Virt_VSMigrationService, _BROKER,
+ libvirt_cim_init(), my_handlers);
+
+
+static CMPIStatus enum_pci(const CMPIBroker *broker,
+ const CMPIObjectPath *ref,
+ struct inst_list *instlist)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ virConnectPtr conn = NULL;
+ char **names = NULL;
+ char *nodeXML;
+ int count;
+ int i;
+
+ conn = connect_by_classname(broker, CLASSNAME(ref), &s);
+ if (conn == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Failed to connect to Hypervisor");
+ goto out;
+ }
+
+ count = virNodeNumOfDevices(conn, "pci", 0);
+ if (count < 1) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Failed to find a PCI device");
+ goto out;
+ }
+
+ names = calloc(count, sizeof(char *));
+ if (names == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Failed to allocate memory");
+ goto out;
+ }
+
+
+ i = virNodeListDevices(conn, "pci", names, count, 0);
+ if (i == -1) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Failed to get PCI devices");
+ goto out;
+ }
+
+ for (i=0; i < count; i++) {
+ CMPIInstance *inst = NULL;
+
+ virNodeDevicePtr nptr = virNodeDeviceLookupByName(conn,
+ names
[i]);
+ if (nptr == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Failed to lookup PCI device by
name");
+ continue;
+ }
+
+ nodeXML = virNodeDeviceGetXMLDesc(nptr, 0);
+ if (nodeXML == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Failed to get PCI Device XML
Description");
+ continue;
+ }
+
+ CU_DEBUG("PCI Device node xml is %s", nodeXML);
+
+ CMPIStatus stat = get_node_from_xml(broker, ref, conn,
+ nodeXML, &inst);
+ if (stat.rc != CMPI_RC_OK)
+ continue;
+
+ inst_list_add(instlist, inst);
+ }
+
+ out:
+ virConnectClose(conn);
+
+ return s;
+}
+
+static CMPIStatus return_pci(const CMPIContext *context,
+ const CMPIObjectPath *ref,
+ const CMPIResult *results,
+ bool name_only,
+ bool is_get_inst)
+{
+ struct inst_list list;
+ CMPIStatus s;
+
+ inst_list_init(&list);
+ s = enum_pci(_BROKER, ref, &list);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ if (name_only)
+ cu_return_instance_names(results, &list);
+ else
+ cu_return_instances(results, &list);
+ out:
+ inst_list_free(&list);
+ return s;
+}
+
+static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *ref)
+{
+ return return_pci(context, ref, results, true, false);
+}
+
+static CMPIStatus EnumInstances(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *ref,
+ const char **properties)
+{
+
+ return return_pci(context, ref, results, false, false);
+}
+
+
+static CMPIStatus GetInstance(CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *ref,
+ const char **properties)
+{
+ return return_pci(context, ref, results, false, true);
+}
+
+DEFAULT_CI();
+DEFAULT_MI();
+DEFAULT_DI();
+DEFAULT_EQ();
+DEFAULT_INST_CLEANUP();
+
+STD_InstanceMIStub(,
+ Virt_VirtualSystemPCIDevice,
+ _BROKER,
+ libvirt_cim_init());
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */