iommu: Handle sibling device assignment correctly

Domctl interface is extended to allow libxc retrieve device group
information from hypervisor. Vendor-specific iommu_ops is also
extended by adding a new operation "get_device_group_id()", which is
currently a null pointer but could be implemented later for vt-d.

Error will be raised from tools side when user trying to assign PCI
device with a sibling device being driven by dom0. User will keep
being prompted until he has hidden the entire device group (at least,
the sibling devices driven by dom0) in dom0 kernel
parameter. Hopefully this framework could be flexible enough to
support both amd iommu and vt-d.

The following 2 cases are not covered by this patch, but should be
easy to handle.
* Checking for hot-plug devices (maybe we can delay calling
ImageHandler.signalDeviceModel() until all checks are done?)
* Checking for splitted device group between different passthru
domains

Signed-off-by: Wei Wang <wei.wang2@amd.com>
This commit is contained in:
Keir Fraser committed 2008-05-28 14:41:23 +01:00
1 parent 32c028cd83
commit 491c0ade25
10 files changed
+246

No files matched your search

+73
View File
@@ -646,6 +646,68 @@ static PyObject *pyxc_deassign_device(XcObject *self,
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)
@@ -1584,6 +1646,17 @@ static PyMethodDef pyxc_methods[] = {
" 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,
METH_VARARGS | METH_KEYWORDS, "\n"
+35
View File
@@ -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
"""
@@ -245,6 +278,8 @@ class PciController(DevController):
"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)
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.