
on 2014/06/09 23:14, Sheldon wrote:
On 06/09/2014 05:28 PM, Zhou Zheng Sheng wrote:
+def _is_pci_qualified(pci_dev): + # PCI class such as bridge and storage controller are not suitable to + # passthrough to VM, so we make a whitelist and only passthrough PCI + # class in the list. + + whitelist_pci_classes = { + # Refer to Linux Kernel code include/linux/pci_ids.h + 0x000000: { # Old PCI devices + 0x000100: None}, # Old VGA devices looks strange?
So the problem you think here is?
+ 0x020000: None, # Network controller + 0x030000: None, # Display controller + 0x040000: None, # Multimedia device + 0x090000: None, # Inupt device + 0x0d0000: None, # Wireless controller + 0x0f0000: None, # Satellite communication controller + 0x100000: None, # Cryption controller + 0x110000: None, # Signal Processing controller + } + + with open(os.path.join(pci_dev['path'], 'class')) as f: + pci_class = int(f.read(), 16) + + try: + subclass = whitelist_pci_classes[pci_class & 0xff0000] + except KeyError: + return False + + if subclass is None: + return True + + if pci_class & 0xffff00 in subclass: + return True + + return False + + +def get_passthrough_dev_infos(): + ''' Get devices eligible to be passed through to VM. ''' + + dev_infos = _get_all_host_dev_infos() + devs = dict([(dev_info['name'], dev_info) for dev_info in dev_infos]) + + for dev in dev_infos: + if dev['device_type'] in ('pci', 'usb_device', 'scsi'): + _strip_parents(devs, dev) + + def is_eligible(dev): + if dev['device_type'] not in ('pci', 'usb_device', 'scsi'): + return False + if dev['device_type'] == 'pci': + return _is_pci_qualified(dev) + return True + + return [dev for dev in devs.itervalues() if is_eligible(dev)] + + +def get_affected_passthrough_devices(passthrough_dev): + devs = dict([(dev['name'], dev) for dev in _get_all_host_dev_infos()]) + + def get_iommu_group(dev_info): + try: + return int(dev_info['iommuGroup']) + except KeyError: + pass + + parent = dev_info['parent'] + while parent is not None: + try: + iommuGroup = int(devs[parent]['iommuGroup']) + except KeyError: + pass + else: + return iommuGroup + parent = devs[parent]['parent'] + + return -1 + + iommu_group = get_iommu_group(passthrough_dev) + + return [dev for dev in get_passthrough_dev_infos() + if dev['name'] != passthrough_dev['name'] and + get_iommu_group(dev) == iommu_group] does this means dev['name'] and passthrough_dev['name'] in same IOMMU group ?
Yes.