diff -r 28083093cc5d tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Sat May 24 09:45:37 2008 +0100 +++ b/tools/libxc/xc_domain.c Tue May 27 16:14:33 2008 +0200 @@ -767,6 +767,37 @@ int xc_assign_device( return do_domctl(xc_handle, &domctl); } +int xc_get_device_group( + int xc_handle, + uint32_t domid, + uint32_t machine_bdf, + uint32_t max_sdevs, + uint32_t *num_sdevs, + uint32_t *sdev_array) +{ + int rc; + DECLARE_DOMCTL; + + domctl.cmd = XEN_DOMCTL_get_device_group; + domctl.domain = (domid_t)domid; + + domctl.u.get_device_group.machine_bdf = machine_bdf; + domctl.u.get_device_group.max_sdevs = max_sdevs; + + set_xen_guest_handle(domctl.u.get_device_group.sdev_array, sdev_array); + + if ( lock_pages(sdev_array, max_sdevs * sizeof(*sdev_array)) != 0 ) + { + PERROR("Could not lock memory for xc_get_device_group\n"); + return -ENOMEM; + } + rc = do_domctl(xc_handle, &domctl); + unlock_pages(sdev_array, max_sdevs * sizeof(*sdev_array)); + + *num_sdevs = domctl.u.get_device_group.num_sdevs; + return rc; +} + int xc_test_assign_device( int xc_handle, uint32_t domid, diff -r 28083093cc5d tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Sat May 24 09:45:37 2008 +0100 +++ b/tools/libxc/xenctrl.h Tue May 27 16:14:33 2008 +0200 @@ -955,6 +955,13 @@ int xc_assign_device(int xc_handle, uint32_t domid, uint32_t machine_bdf); +int xc_get_device_group(int xc_handle, + uint32_t domid, + uint32_t machine_bdf, + uint32_t max_sdevs, + uint32_t *num_sdevs, + uint32_t *sdev_array); + int xc_test_assign_device(int xc_handle, uint32_t domid, uint32_t machine_bdf); diff -r 28083093cc5d tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Sat May 24 09:45:37 2008 +0100 +++ b/tools/python/xen/lowlevel/xc/xc.c Tue May 27 16:14:33 2008 +0200 @@ -646,6 +646,68 @@ static PyObject *pyxc_deassign_device(Xc return Py_BuildValue("i", bdf); } +static PyObject *pyxc_get_device_group(XcObject *self, + PyObject *args) +{ + domid_t domid; + uint32_t bdf = 0; + uint32_t max_sdevs, num_sdevs; + int seg, bus, dev, func, rc, i; + PyObject *Pystr; + char *group_str; + char dev_str[9]; + uint32_t *sdev_array; + + if ( !PyArg_ParseTuple(args, "iiiii", &domid, &seg, &bus, &dev, &func) ) + return NULL; + + /* Maximum allowed siblings device number per group */ + max_sdevs = 1024; + + if ( (sdev_array = malloc(max_sdevs * sizeof(*sdev_array))) == NULL ) + return PyErr_NoMemory(); + memset(sdev_array, 0, max_sdevs * sizeof(*sdev_array)); + + bdf |= (bus & 0xff) << 16; + bdf |= (dev & 0x1f) << 11; + bdf |= (func & 0x7) << 8; + + rc = xc_get_device_group(self->xc_handle, + domid, bdf, max_sdevs, &num_sdevs, sdev_array); + + if ( rc < 0 ) + { + free(sdev_array); + return pyxc_error_to_exception(); + } + + if ( !num_sdevs ) + { + free(sdev_array); + return Py_BuildValue("s", ""); + } + + if ( (group_str = malloc(num_sdevs * sizeof(dev_str))) == NULL ) + return PyErr_NoMemory(); + memset(group_str, '\0', num_sdevs * sizeof(dev_str)); + + for ( i = 0; i < num_sdevs; i++ ) + { + bus = (sdev_array[i] >> 16) & 0xff; + dev = (sdev_array[i] >> 11) & 0x1f; + func = (sdev_array[i] >> 8) & 0x7; + sprintf(dev_str, "%02x:%02x.%x,", bus, dev, func); + strcat(group_str, dev_str); + } + + Pystr = Py_BuildValue("s", group_str); + + free(sdev_array); + free(group_str); + + return Pystr; +} + #ifdef __ia64__ static PyObject *pyxc_nvram_init(XcObject *self, PyObject *args) @@ -1583,6 +1645,17 @@ static PyMethodDef pyxc_methods[] = { " param [int]: No. of HVM param.\n" " value [long]: Value of param.\n" "Returns: [int] 0 on success.\n" }, + + { "get_device_group", + (PyCFunction)pyxc_get_device_group, + METH_VARARGS, "\n" + "get sibling devices infomation.\n" + " dom [int]: Domain to assign device to.\n" + " seg [int]: PCI segment.\n" + " bus [int]: PCI bus.\n" + " dev [int]: PCI dev.\n" + " func [int]: PCI func.\n" + "Returns: [string]: Sibling devices \n" }, { "test_assign_device", (PyCFunction)pyxc_test_assign_device, diff -r 28083093cc5d tools/python/xen/xend/server/pciif.py --- a/tools/python/xen/xend/server/pciif.py Sat May 24 09:45:37 2008 +0100 +++ b/tools/python/xen/xend/server/pciif.py Tue May 27 16:14:33 2008 +0200 @@ -226,6 +226,39 @@ class PciController(DevController): return sxpr + def CheckSiblingDevices(self, domid, dev): + """ Check if all sibling devices of dev are owned by pciback + """ + if not self.vm.info.is_hvm(): + return + + group_str = xc.get_device_group(domid, dev.domain, dev.bus, dev.slot, dev.func) + if group_str == "": + return + + #group string format xx:xx.x,xx:xx.x, + devstr_len = group_str.find(',') + for i in range(0, len(group_str), devstr_len + 1): + (bus, slotfunc) = group_str[i:i + devstr_len].split(':') + (slot, func) = slotfunc.split('.') + b = parse_hex(bus) + d = parse_hex(slot) + f = parse_hex(func) + try: + sdev = PciDevice(dev.domain, b, d, f) + except Exception, e: + #no dom0 drivers bound to sdev + continue + + if sdev.driver!='pciback': + raise VmError(("pci: PCI Backend does not own\n "+ \ + "sibling device %s of device %s\n"+ \ + "See the pciback.hide kernel "+ \ + "command-line parameter or\n"+ \ + "bind your slot/device to the PCI backend using sysfs" \ + )%(sdev.name, dev.name)) + return + def setupOneDevice(self, domain, bus, slot, func): """ Attach I/O resources for device to frontend domain """ @@ -244,6 +277,8 @@ class PciController(DevController): "command-line parameter or\n"+ \ "bind your slot/device to the PCI backend using sysfs" \ )%(dev.name)) + + self.CheckSiblingDevices(fe_domid, dev) PCIQuirk(dev.vendor, dev.device, dev.subvendor, dev.subdevice, domain, bus, slot, func)