提交 c7cbbfa4 编写于 作者: D Daniel Veillard

* src/domain_conf.c src/qemu_conf.c: implement PCI passthrough

  for recent KVM versions in a similar way to USB, patch by
  Jason Krieg. Some cleanups and reformating too.
daniel
上级 d6eceb56
Wed Jan 7 13:54:05 CET 2009 Daniel Veillard <veillard@redhat.com>
* src/domain_conf.c src/qemu_conf.c: implement PCI passthrough
for recent KVM versions in a similar way to USB, patch by
Jason Krieg. Some cleanups and reformating too.
Wed Jan 7 11:54:06 CET 2009 Daniel Veillard <veillard@redhat.com>
* src/openvz_driver.c: fix the mac addresses generation for
......
......@@ -142,7 +142,7 @@ VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST,
"usb",
"pci")
#define virDomainReportError(conn, code, fmt...) \
#define virDomainReportError(conn, code, fmt...) \
virReportErrorHelper(conn, VIR_FROM_DOMAIN, code, __FILE__, \
__FUNCTION__, __LINE__, fmt)
......@@ -893,8 +893,8 @@ virDomainNetDefParseXML(virConnectPtr conn,
switch (def->type) {
case VIR_DOMAIN_NET_TYPE_NETWORK:
if (network == NULL) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("No <source> 'network' attribute specified with <interface type='network'/>"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("No <source> 'network' attribute specified with <interface type='network'/>"));
goto error;
}
def->data.network.name = network;
......@@ -919,8 +919,8 @@ virDomainNetDefParseXML(virConnectPtr conn,
case VIR_DOMAIN_NET_TYPE_BRIDGE:
if (bridge == NULL) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("No <source> 'dev' attribute specified with <interface type='bridge'/>"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("No <source> 'dev' attribute specified with <interface type='bridge'/>"));
goto error;
}
def->data.bridge.brname = bridge;
......@@ -931,21 +931,21 @@ virDomainNetDefParseXML(virConnectPtr conn,
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_MCAST:
if (port == NULL) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("No <source> 'port' attribute specified with socket interface"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("No <source> 'port' attribute specified with socket interface"));
goto error;
}
if (virStrToLong_i(port, NULL, 10, &def->data.socket.port) < 0) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("Cannot parse <source> 'port' attribute with socket interface"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot parse <source> 'port' attribute with socket interface"));
goto error;
}
if (address == NULL) {
if (def->type == VIR_DOMAIN_NET_TYPE_CLIENT ||
def->type == VIR_DOMAIN_NET_TYPE_MCAST) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("No <source> 'address' attribute specified with socket interface"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("No <source> 'address' attribute specified with socket interface"));
goto error;
}
} else {
......@@ -970,7 +970,7 @@ virDomainNetDefParseXML(virConnectPtr conn,
int char_ok = c_isalnum(model[i]) || model[i] == '_';
if (!char_ok) {
virDomainReportError (conn, VIR_ERR_INVALID_ARG, "%s",
_("Model name contains invalid characters"));
_("Model name contains invalid characters"));
goto error;
}
}
......@@ -1142,8 +1142,8 @@ virDomainChrDefParseXML(virConnectPtr conn,
case VIR_DOMAIN_CHR_TYPE_PIPE:
if (path == NULL &&
def->type != VIR_DOMAIN_CHR_TYPE_PTY) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("Missing source path attribute for char device"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing source path attribute for char device"));
goto error;
}
......@@ -1159,13 +1159,13 @@ virDomainChrDefParseXML(virConnectPtr conn,
if (mode == NULL ||
STREQ(mode, "connect")) {
if (connectHost == NULL) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("Missing source host attribute for char device"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing source host attribute for char device"));
goto error;
}
if (connectService == NULL) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("Missing source service attribute for char device"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing source service attribute for char device"));
goto error;
}
......@@ -1176,13 +1176,13 @@ virDomainChrDefParseXML(virConnectPtr conn,
def->data.tcp.listen = 0;
} else {
if (bindHost == NULL) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("Missing source host attribute for char device"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing source host attribute for char device"));
goto error;
}
if (bindService == NULL) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("Missing source service attribute for char device"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing source service attribute for char device"));
goto error;
}
......@@ -1201,8 +1201,8 @@ virDomainChrDefParseXML(virConnectPtr conn,
case VIR_DOMAIN_CHR_TYPE_UDP:
if (connectService == NULL) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("Missing source service attribute for char device"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing source service attribute for char device"));
goto error;
}
......@@ -1219,8 +1219,8 @@ virDomainChrDefParseXML(virConnectPtr conn,
case VIR_DOMAIN_CHR_TYPE_UNIX:
if (path == NULL) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("Missing source path attribute for char device"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing source path attribute for char device"));
goto error;
}
......@@ -1293,7 +1293,7 @@ virDomainInputDefParseXML(virConnectPtr conn,
if (def->bus == VIR_DOMAIN_INPUT_BUS_PS2 && /* Only allow mouse for ps2 */
def->type != VIR_DOMAIN_INPUT_TYPE_MOUSE) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("ps2 bus does not support %s input device"),
_("ps2 bus does not support %s input device"),
type);
goto error;
}
......@@ -1311,7 +1311,7 @@ virDomainInputDefParseXML(virConnectPtr conn,
}
if (def->type != VIR_DOMAIN_INPUT_TYPE_MOUSE) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("xen bus does not support %s input device"),
_("xen bus does not support %s input device"),
type);
goto error;
}
......@@ -1480,7 +1480,7 @@ virDomainHostdevSubsysUsbDefParseXML(virConnectPtr conn,
if (vendor) {
if (virStrToLong_ui(vendor, NULL, 0,
&def->source.subsys.u.usb.vendor) < 0) {
&def->source.subsys.u.usb.vendor) < 0) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("cannot parse vendor id %s"), vendor);
VIR_FREE(vendor);
......@@ -1499,7 +1499,8 @@ virDomainHostdevSubsysUsbDefParseXML(virConnectPtr conn,
if (virStrToLong_ui(product, NULL, 0,
&def->source.subsys.u.usb.product) < 0) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("cannot parse product %s"), product);
_("cannot parse product %s"),
product);
VIR_FREE(product);
goto out;
}
......@@ -1540,13 +1541,14 @@ virDomainHostdevSubsysUsbDefParseXML(virConnectPtr conn,
}
VIR_FREE(device);
} else {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("usb address needs device id"));
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("usb address needs device id"));
goto out;
}
} else {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("unknown usb source type '%s'"), cur->name);
_("unknown usb source type '%s'"),
cur->name);
goto out;
}
}
......@@ -1572,6 +1574,97 @@ out:
}
static int
virDomainHostdevSubsysPciDefParseXML(virConnectPtr conn,
const xmlNodePtr node,
virDomainHostdevDefPtr def) {
int ret = -1;
xmlNodePtr cur;
cur = node->children;
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE) {
if (xmlStrEqual(cur->name, BAD_CAST "address")) {
char *domain = virXMLPropString(cur, "domain");
if (domain) {
if (virStrToLong_ui(domain, NULL, 0,
&def->source.subsys.u.pci.domain) < 0) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("cannot parse domain %s"),
domain);
VIR_FREE(domain);
goto out;
}
VIR_FREE(domain);
}
char *bus = virXMLPropString(cur, "bus");
if (bus) {
if (virStrToLong_ui(bus, NULL, 0,
&def->source.subsys.u.pci.bus) < 0) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("cannot parse bus %s"), bus);
VIR_FREE(bus);
goto out;
}
VIR_FREE(bus);
} else {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("pci address needs bus id"));
goto out;
}
char *slot = virXMLPropString(cur, "slot");
if (slot) {
if (virStrToLong_ui(slot, NULL, 0,
&def->source.subsys.u.pci.slot) < 0) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("cannot parse slot %s"),
slot);
VIR_FREE(slot);
goto out;
}
VIR_FREE(slot);
} else {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("pci address needs slot id"));
goto out;
}
char *function = virXMLPropString(cur, "function");
if (function) {
if (virStrToLong_ui(function, NULL, 0,
&def->source.subsys.u.pci.function) < 0) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("cannot parse function %s"),
function);
VIR_FREE(function);
goto out;
}
VIR_FREE(function);
} else {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
_("pci address needs function id"));
goto out;
}
} else {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("unknown pci source type '%s'"),
cur->name);
goto out;
}
}
cur = cur->next;
}
ret = 0;
out:
return ret;
}
static virDomainHostdevDefPtr
virDomainHostdevDefParseXML(virConnectPtr conn,
const xmlNodePtr node) {
......@@ -1619,6 +1712,11 @@ virDomainHostdevDefParseXML(virConnectPtr conn,
if (virDomainHostdevSubsysUsbDefParseXML(conn, cur, def) < 0)
goto error;
}
if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
if (virDomainHostdevSubsysPciDefParseXML(conn, cur, def) < 0)
goto error;
}
} else {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("unknown node %s"), cur->name);
......@@ -2378,9 +2476,9 @@ cleanup:
#endif /* ! PROXY */
/************************************************************************
* *
* Parser and converter for the CPUset strings used in libvirt *
* *
* *
* Parser and converter for the CPUset strings used in libvirt *
* *
************************************************************************/
/**
* virDomainCpuNumberParse
......@@ -2995,7 +3093,7 @@ virDomainHostdevDefFormat(virConnectPtr conn,
}
type = virDomainHostdevSubsysTypeToString(def->source.subsys.type);
if (!type || def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
if (!type || (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB && def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) ) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("unexpected hostdev type %d"),
def->source.subsys.type);
......@@ -3005,15 +3103,24 @@ virDomainHostdevDefFormat(virConnectPtr conn,
virBufferVSprintf(buf, " <hostdev mode='%s' type='%s'>\n", mode, type);
virBufferAddLit(buf, " <source>\n");
if (def->source.subsys.u.usb.vendor) {
virBufferVSprintf(buf, " <vendor id='0x%.4x'/>\n",
def->source.subsys.u.usb.vendor);
virBufferVSprintf(buf, " <product id='0x%.4x'/>\n",
def->source.subsys.u.usb.product);
} else {
virBufferVSprintf(buf, " <address bus='%d' device='%d'/>\n",
def->source.subsys.u.usb.bus,
def->source.subsys.u.usb.device);
if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
if (def->source.subsys.u.usb.vendor) {
virBufferVSprintf(buf, " <vendor id='0x%.4x'/>\n",
def->source.subsys.u.usb.vendor);
virBufferVSprintf(buf, " <product id='0x%.4x'/>\n",
def->source.subsys.u.usb.product);
} else {
virBufferVSprintf(buf, " <address bus='%d' device='%d'/>\n",
def->source.subsys.u.usb.bus,
def->source.subsys.u.usb.device);
}
}
if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
virBufferVSprintf(buf, " <address domain='0x%.4x' bus='0x%.2x' slot='0x%.2x' function='0x%.1x'/>\n",
def->source.subsys.u.pci.domain,
def->source.subsys.u.pci.bus,
def->source.subsys.u.pci.slot,
def->source.subsys.u.pci.function);
}
virBufferAddLit(buf, " </source>\n");
......
......@@ -1203,8 +1203,10 @@ int qemudBuildCommandLine(virConnectPtr conn,
for (i = 0 ; i < vm->def->nhostdevs ; i++) {
int ret;
char* usbdev;
char* pcidev;
virDomainHostdevDefPtr hostdev = vm->def->hostdevs[i];
/* USB */
if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
if(hostdev->source.subsys.u.usb.vendor) {
......@@ -1224,6 +1226,23 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ARG_LIT(usbdev);
VIR_FREE(usbdev);
}
/* PCI */
if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
ret = virAsprintf(&pcidev, "host=%.2x:%.2x.%.1x",
hostdev->source.subsys.u.pci.bus,
hostdev->source.subsys.u.pci.slot,
hostdev->source.subsys.u.pci.function);
if (ret < 0) {
pcidev = NULL;
goto error;
}
ADD_ARG_LIT("-pcidevice");
ADD_ARG_LIT(pcidev);
VIR_FREE(pcidev);
}
}
if (migrateFrom) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册