[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] vt-d: Detect and report failure to assign a pass-thru PCI device.
# HG changeset patch # User Keir Fraser <keir@xxxxxxxxxxxxx> # Date 1192782663 -3600 # Node ID bc4afcd4c612afcee7f2fa2fc0ca400c26758876 # Parent 3ad0080ad9b56a8eb19433c61f6e3c5644fb6f2e vt-d: Detect and report failure to assign a pass-thru PCI device. Signed-off-by: Weidong Han <weidong.han@xxxxxxxxx> --- tools/ioemu/hw/pass-through.c | 93 ++++++++++++++++---------------- tools/python/xen/lowlevel/xc/xc.c | 88 ++++++++++++++++++++++++++++++ tools/python/xen/xend/XendDomainInfo.py | 14 ++++ 3 files changed, 149 insertions(+), 46 deletions(-) diff -r 3ad0080ad9b5 -r bc4afcd4c612 tools/ioemu/hw/pass-through.c --- a/tools/ioemu/hw/pass-through.c Fri Oct 19 09:28:21 2007 +0100 +++ b/tools/ioemu/hw/pass-through.c Fri Oct 19 09:31:03 2007 +0100 @@ -28,40 +28,52 @@ #include "pci/pci.h" extern FILE *logfile; -char *token; - -int pci_devs(const char *direct_pci) -{ - int count = 0; - const char *c; - - /* skip first "[" character */ - c = direct_pci + 1; - while ((c = strchr(c, '[')) != NULL) { - c++; - count++; - } - return (count); -} - -int next_token(char *direct_pci) -{ - if (token == NULL) - token = strtok(direct_pci, ","); - else - token = strtok(NULL, ","); + +static int token_value(char *token) +{ token = strchr(token, 'x'); token = token + 1; + return ((int) strtol(token, NULL, 16)); } -void next_bdf(char *direct_pci, int *seg, - int *bus, int *dev, int *func) -{ - *seg = next_token(direct_pci); - *bus = next_token(direct_pci); - *dev = next_token(direct_pci); - *func = next_token(direct_pci); +static int first_bdf(char *pci_str, char **last, + int *seg, int *bus, int *dev, int *func) +{ + char *token; + + token = strtok_r(pci_str, ",", last); + if ( !token ) + return 0; + + *seg = token_value(token); + token = strtok_r(NULL, ",", last); + *bus = token_value(token); + token = strtok_r(NULL, ",", last); + *dev = token_value(token); + token = strtok_r(NULL, ",", last); + *func = token_value(token); + + return 1; +} + +static int next_bdf(char **last, int *seg, int *bus, int *dev, int *func) +{ + char *token; + + token = strtok_r(NULL, ",", last); + if ( !token ) + return 0; + + *seg = token_value(token); + token = strtok_r(NULL, ",", last); + *bus = token_value(token); + token = strtok_r(NULL, ",", last); + *dev = token_value(token); + token = strtok_r(NULL, ",", last); + *func = token_value(token); + + return 1; } uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap) @@ -333,7 +345,6 @@ struct pt_dev * register_real_device(PCI int rc, i; struct pt_dev *assigned_device = NULL; struct pci_dev *pci_dev; - struct pci_config_cf8 machine_bdf; uint8_t e_device, e_intx; PT_LOG("Assigning real physical device %02x:%02x.%x ...\n", @@ -367,15 +378,6 @@ struct pt_dev * register_real_device(PCI /* Issue PCIe FLR */ pdev_flr(pci_dev); - - /* Tell XEN vmm to change iommu settings */ - machine_bdf.reg = 0; - machine_bdf.bus = r_bus; - machine_bdf.dev = r_dev; - machine_bdf.func = r_func; - rc = xc_assign_device(xc_handle, domid, machine_bdf.value); - if ( rc < 0 ) - PT_LOG("Error: xc_domain_assign_device error %d\n", rc); /* Initialize virtualized PCI configuration (Extended 256 Bytes) */ for ( i = 0; i < PCI_CONFIG_SIZE; i++ ) @@ -417,11 +419,11 @@ struct pt_dev * register_real_device(PCI int pt_init(PCIBus *e_bus, char *direct_pci) { - int i; int seg, b, d, f; struct pt_dev *pt_dev; struct pci_access *pci_access; - int dev_count = pci_devs(direct_pci); + int get_bdf; + char *last = NULL; /* Initialize libpci */ pci_access = pci_alloc(); @@ -434,11 +436,10 @@ int pt_init(PCIBus *e_bus, char *direct_ pci_scan_bus(pci_access); /* Assign given devices to guest */ - for ( i = 0; i < dev_count; i++ ) - { - /* Get next device bdf (bus, device, function) */ - next_bdf(direct_pci, &seg, &b, &d, &f); - + for ( get_bdf = first_bdf(direct_pci, &last, &seg, &b, &d, &f); + get_bdf; + get_bdf = next_bdf(&last, &seg, &b, &d, &f) ) + { /* Register real device with the emulated bus */ pt_dev = register_real_device(e_bus, "DIRECT PCI", PT_VIRT_DEVFN_AUTO, b, d, f, PT_MACHINE_IRQ_AUTO, pci_access); diff -r 3ad0080ad9b5 -r bc4afcd4c612 tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Fri Oct 19 09:28:21 2007 +0100 +++ b/tools/python/xen/lowlevel/xc/xc.c Fri Oct 19 09:31:03 2007 +0100 @@ -529,6 +529,86 @@ static PyObject *pyxc_set_hvm_param(XcOb return zero; } +static int token_value(char *token) +{ + token = strchr(token, 'x'); + token = token + 1; + + return ((int) strtol(token, NULL, 16)); +} + +static int first_bdf(char *pci_str, char **last, + int *seg, int *bus, int *dev, int *func) +{ + char *token; + + token = strtok_r(pci_str, ",", last); + if ( !token ) + return 0; + + *seg = token_value(token); + token = strtok_r(NULL, ",", last); + *bus = token_value(token); + token = strtok_r(NULL, ",", last); + *dev = token_value(token); + token = strtok_r(NULL, ",", last); + *func = token_value(token); + + return 1; +} + +static int next_bdf(char **last, int *seg, int *bus, int *dev, int *func) +{ + char *token; + + token = strtok_r(NULL, ",", last); + if ( !token ) + return 0; + + *seg = token_value(token); + token = strtok_r(NULL, ",", last); + *bus = token_value(token); + token = strtok_r(NULL, ",", last); + *dev = token_value(token); + token = strtok_r(NULL, ",", last); + *func = token_value(token); + + return 1; +} + +static PyObject *pyxc_assign_device(XcObject *self, + PyObject *args, + PyObject *kwds) +{ + uint32_t dom; + char *pci_str; + uint32_t bdf = 0; + int seg, bus, dev, func; + int get_bdf; + char *last = NULL; + + static char *kwd_list[] = { "domid", "pci", NULL }; + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|s", kwd_list, + &dom, &pci_str) ) + return NULL; + + for ( get_bdf = first_bdf(pci_str, &last, &seg, &bus, &dev, &func); + get_bdf; + get_bdf = next_bdf(&last, &seg, &bus, &dev, &func) ) + { + bdf |= (bus & 0xff) << 16; + bdf |= (dev & 0x1f) << 11; + bdf |= (func & 0x7) << 8; + + if ( xc_assign_device(self->xc_handle, dom, bdf) != 0 ) + break; + + bdf = 0; + } + + return Py_BuildValue("i", bdf); +} + #ifdef __ia64__ static PyObject *pyxc_nvram_init(XcObject *self, PyObject *args) @@ -1349,6 +1429,14 @@ static PyMethodDef pyxc_methods[] = { " value [long]: Value of param.\n" "Returns: [int] 0 on success.\n" }, + { "assign_device", + (PyCFunction)pyxc_assign_device, + METH_VARARGS | METH_KEYWORDS, "\n" + "assign device with VT-d.\n" + " dom [int]: Identifier of domain to build into.\n" + " pci_str [str]: PCI devices.\n" + "Returns: [int] 0 on success, or device bdf that can't be assigned.\n" }, + { "sched_id_get", (PyCFunction)pyxc_sched_id_get, METH_NOARGS, "\n" diff -r 3ad0080ad9b5 -r bc4afcd4c612 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Fri Oct 19 09:28:21 2007 +0100 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Oct 19 09:31:03 2007 +0100 @@ -1586,6 +1586,20 @@ class XendDomainInfo: # Set maximum number of vcpus in domain xc.domain_max_vcpus(self.domid, int(self.info['VCPUs_max'])) + # Assign devices with VT-d + pci_str = str(self.info["platform"].get("pci")) + if hvm and pci_str: + bdf = xc.assign_device(self.domid, pci_str) + if bdf != 0: + bus = (bdf >> 16) & 0xff + devfn = (bdf >> 8) & 0xff + dev = (devfn >> 3) & 0x1f + func = devfn & 0x7 + raise VmError("Fail to assign device(%x:%x.%x): maybe VT-d is " + "not enabled, or the device is not exist, or it " + "has already been assigned to other domain" + % (bus, dev, func)) + # register the domain in the list from xen.xend import XendDomain XendDomain.instance().add_domain(self) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |