📄 pci.py
字号:
for pci_names in pci_list: devs = [] for pci in pci_names: devs = devs + [pci_dev_dict[pci]] result = result + [devs] return resultdef check_mmio_bar(devs_list): result = [] for dev_list in devs_list: non_aligned_bar_found = False for dev in dev_list: if dev.has_non_page_aligned_bar: non_aligned_bar_found = True break if not non_aligned_bar_found: result = result + [dev_list] return resultclass PciDeviceNotFoundError(Exception): def __init__(self,domain,bus,slot,func): self.domain = domain self.bus = bus self.slot = slot self.func = func self.name = PCI_DEV_FORMAT_STR %(domain, bus, slot, func) def __str__(self): return ('PCI Device %s Not Found' % (self.name))class PciDeviceParseError(Exception): def __init__(self,msg): self.message = msg def __str__(self): return 'Error Parsing PCI Device Info: '+self.messageclass PciDeviceAssignmentError(Exception): def __init__(self,msg): self.message = msg def __str__(self): return 'pci: impproper device assignment spcified: ' + \ self.messageclass PciDevice: def __init__(self, domain, bus, slot, func): self.domain = domain self.bus = bus self.slot = slot self.func = func self.name = PCI_DEV_FORMAT_STR % (domain, bus, slot, func) self.cfg_space_path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ \ self.name + SYSFS_PCI_DEV_CONFIG_PATH self.irq = 0 self.iomem = [] self.ioports = [] self.driver = None self.vendor = None self.device = None self.subvendor = None self.subdevice = None self.msix = 0 self.msix_iomem = [] self.revision = 0 self.classcode = None self.vendorname = "" self.devicename = "" self.classname = "" self.subvendorname = "" self.subdevicename = "" self.dev_type = None self.has_non_page_aligned_bar = False self.pcie_flr = False self.pci_af_flr = False self.detect_dev_info() self.get_info_from_sysfs() self.get_info_from_lspci() def find_parent(self): # i.e., /sys/bus/pci/devices/0000:00:19.0 or # /sys/bus/pci/devices/0000:03:04.0 path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ self.name # i.e., ../../../devices/pci0000:00/0000:00:19.0 # ../../../devices/pci0000:00/0000:00:02.0/0000:01:00.2/0000:03:04.0 try: target = os.readlink(path) lst = target.split('/') parent = lst[len(lst)-2] if parent[0:3] == 'pci': parent = parent[3:] lst = parent.split(':') dom = int(lst[0], 16) bus = int(lst[1], 16) dev = 0 func = 0 else: lst = parent.split(':') dom = int(lst[0], 16) bus = int(lst[1], 16) lst = lst[2] lst = lst.split('.') dev = int(lst[0], 16) func = int(lst[1], 16) return (dom, bus, dev, func) except OSError, (errno, strerr): raise PciDeviceParseError('Can not locate the parent of %s', self.name) def find_the_uppermost_pci_bridge(self): # Find the uppermost PCI/PCI-X bridge (dom, b, d, f) = self.find_parent() dev = dev_parent = PciDevice(dom, b, d, f) while dev_parent.dev_type != DEV_TYPE_PCIe_BRIDGE: (dom, b, d, f) = dev_parent.find_parent() dev = dev_parent dev_parent = PciDevice(dom, b, d, f) return dev def find_all_devices_behind_the_bridge(self, ignore_bridge): sysfs_mnt = find_sysfs_mnt() self_path = sysfs_mnt + SYSFS_PCI_DEVS_PATH + '/' + self.name pci_names = os.popen('ls ' + self_path).read() dev_list = re.findall(PCI_DEV_REG_EXPRESS_STR, pci_names) list = [self.name] for pci_str in dev_list: (dom, b, d, f) = parse_pci_name(pci_str) dev = PciDevice(dom, b, d, f) if dev.dev_type == DEV_TYPE_PCI_BRIDGE or \ dev.dev_type == DEV_TYPE_PCIe_BRIDGE: sub_list_including_self = \ dev.find_all_devices_behind_the_bridge(ignore_bridge) if ignore_bridge: del sub_list_including_self[0] list = list + [sub_list_including_self] else: list = list + [dev.name] return list def find_coassigned_devices(self, ignore_bridge = True): ''' Here'self' is a PCI device, we need find the uppermost PCI/PCI-X bridge, and all devices behind it must be co-assigned to the same guest. Parameter: [ignore_bridge]: if set, the returned result doesn't include any bridge behind the uppermost PCI/PCI-X bridge. Note: The first element of the return value is the uppermost PCI/PCI-X bridge. If the caller doesn't need the first element, the caller itself can remove it explicitly. ''' dev = self.find_the_uppermost_pci_bridge() dev_list = dev.find_all_devices_behind_the_bridge(ignore_bridge) dev_list = re.findall(PCI_DEV_REG_EXPRESS_STR, '%s' % dev_list) return dev_list def do_secondary_bus_reset(self, target_bus, devs): # Save the config spaces of all the devices behind the bus. (pci_list, cfg_list) = save_pci_conf_space(devs) #Do the Secondary Bus Reset sysfs_mnt = find_sysfs_mnt() parent_path = sysfs_mnt + SYSFS_PCI_DEVS_PATH + '/' + \ target_bus + SYSFS_PCI_DEV_CONFIG_PATH fd = os.open(parent_path, os.O_WRONLY) # Assert Secondary Bus Reset os.lseek(fd, PCI_CB_BRIDGE_CONTROL, 0) os.write(fd, struct.pack('I', PCI_BRIDGE_CTL_BUS_RESET)) time.sleep(0.200) # De-assert Secondary Bus Reset os.lseek(fd, 0x3e, 0) os.write(fd, struct.pack('I', 0x00)) time.sleep(0.200) os.close(fd) # Restore the config spaces restore_pci_conf_space((pci_list, cfg_list)) def do_Dstate_transition(self): pos = self.find_cap_offset(PCI_CAP_ID_PM) if pos == 0: return (pci_list, cfg_list) = save_pci_conf_space([self.name]) # Enter D3hot without soft reset pm_ctl = self.pci_conf_read32(pos + PCI_PM_CTRL) pm_ctl |= PCI_PM_CTRL_NO_SOFT_RESET pm_ctl &= ~PCI_PM_CTRL_STATE_MASK pm_ctl |= PCI_D3hot self.pci_conf_write32(pos + PCI_PM_CTRL, pm_ctl) time.sleep(0.010) # From D3hot to D0 self.pci_conf_write32(pos + PCI_PM_CTRL, 0) time.sleep(0.010) restore_pci_conf_space((pci_list, cfg_list)) def find_all_the_multi_functions(self): sysfs_mnt = find_sysfs_mnt() pci_names = os.popen('ls ' + sysfs_mnt + SYSFS_PCI_DEVS_PATH).read() p = self.name p = p[0 : p.rfind('.')] + '.[0-7]' funcs = re.findall(p, pci_names) return funcs def find_cap_offset(self, cap): path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ \ self.name+SYSFS_PCI_DEV_CONFIG_PATH pos = PCI_CAPABILITY_LIST try: fd = os.open(path, os.O_RDONLY) os.lseek(fd, PCI_STATUS, 0) status = struct.unpack('H', os.read(fd, 2))[0] if (status & 0x10) == 0: # The device doesn't support PCI_STATUS_CAP_LIST return 0 max_cap = 48 while max_cap > 0: os.lseek(fd, pos, 0) pos = ord(os.read(fd, 1)) if pos < 0x40: pos = 0 break; os.lseek(fd, pos + 0, 0) id = ord(os.read(fd, 1)) if id == 0xff: pos = 0 break; # Found the capability if id == cap: break; # Test the next one pos = pos + 1 max_cap = max_cap - 1; os.close(fd) except OSError, (errno, strerr): raise PciDeviceParseError(('Error when accessing sysfs: %s (%d)' % (strerr, errno))) return pos def pci_conf_read8(self, pos): fd = os.open(self.cfg_space_path, os.O_RDONLY) os.lseek(fd, pos, 0) str = os.read(fd, 1) os.close(fd) val = struct.unpack('B', str)[0] return val def pci_conf_read16(self, pos): fd = os.open(self.cfg_space_path, os.O_RDONLY) os.lseek(fd, pos, 0) str = os.read(fd, 2) os.close(fd) val = struct.unpack('H', str)[0] return val def pci_conf_read32(self, pos): fd = os.open(self.cfg_space_path, os.O_RDONLY) os.lseek(fd, pos, 0) str = os.read(fd, 4) os.close(fd) val = struct.unpack('I', str)[0] return val def pci_conf_write8(self, pos, val): str = struct.pack('B', val) fd = os.open(self.cfg_space_path, os.O_WRONLY) os.lseek(fd, pos, 0) os.write(fd, str) os.close(fd) def pci_conf_write16(self, pos, val): str = struct.pack('H', val) fd = os.open(self.cfg_space_path, os.O_WRONLY) os.lseek(fd, pos, 0) os.write(fd, str) os.close(fd) def pci_conf_write32(self, pos, val): str = struct.pack('I', val) fd = os.open(self.cfg_space_path, os.O_WRONLY) os.lseek(fd, pos, 0) os.write(fd, str) os.close(fd) def detect_dev_info(self): class_dev = self.pci_conf_read16(PCI_CLASS_DEVICE) pos = self.find_cap_offset(PCI_CAP_ID_EXP) if class_dev == PCI_CLASS_BRIDGE_PCI: if pos == 0: self.dev_type = DEV_TYPE_PCI_BRIDGE else: creg = self.pci_conf_read16(pos + PCI_EXP_FLAGS) if ((creg & PCI_EXP_TYPE_PCI_BRIDGE) >> 4) == \ PCI_EXP_TYPE_PCI_BRIDGE: self.dev_type = DEV_TYPE_PCI_BRIDGE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -