def _open_device(self): self.cfgfd = os.open(self.dd + "/config", os.O_RDWR) try: self.barfd = os.open(self.dd + "/resource0_wc", os.O_RDWR) except: self.barfd = os.open(self.dd + "/resource0", os.O_RDWR) bar0 = c.mmap(0, 64 * 1024, c.PROT_READ | c.PROT_WRITE, c.MAP_SHARED | c.MAP_LOCKED, self.barfd, 0) if -1 == bar0: raise Exception("failed to mmap bar 0") self.bar0 = bar0 try: self.barfd2 = os.open(self.dd + "/resource2_wc", os.O_RDWR) self.bar2 = c.mmap(0, 64 * 1024, c.PROT_READ | c.PROT_WRITE, c.MAP_SHARED | c.MAP_LOCKED, self.barfd2, 0) except: pass
def _open_device(self): with file(self.dd + "/enable", "w") as f: f.write('1') self.cfgfd = os.open(self.dd + "/config", os.O_RDWR) try: self.barfd = os.open(self.dd + "/resource0_wc", os.O_RDWR) except: self.barfd = os.open(self.dd + "/resource0", os.O_RDWR) bar0 = c.mmap(0, 64 * 1024, c.PROT_READ | c.PROT_WRITE, c.MAP_SHARED | c.MAP_LOCKED, self.barfd, 0) if -1 == bar0: raise Exception("failed to mmap bar 0") self.bar0 = bar0 try: self.barfd2 = os.open(self.dd + "/resource2_wc", os.O_RDWR) self.bar2 = c.mmap(0, 64 * 1024, c.PROT_READ | c.PROT_WRITE, c.MAP_SHARED | c.MAP_LOCKED, self.barfd2, 0) except: pass
def __attempt_hugetlb(self): flags = c.MAP_ANONYMOUS | c.MAP_PRIVATE | c.MAP_LOCKED | c.MAP_HUGETLB flags |= (21 << c.MAP_HUGE_SHIFT) prot = c.PROT_READ | c.PROT_WRITE sz = 2048 * 1024 a = c.mmap(0, sz, prot, flags, -1, 0) if a != c.MAP_FAILED: print "[+] huge pages available" c.munmap(a, sz) self._hugetlb_available = True self._hugetlb_pgsz = sz else: print "[-] huge pages unavailable" self._hugetlb_available = False
def show_regions(self): print "[+] enumerating vfio device regions" self.regions = [] for i in range(self.device_info.num_regions - 1): r = c.vfio_region_info() r.argsz = c.sizeof(c.vfio_region_info) r.index = i ioctl(self.device, c.VFIO_DEVICE_GET_REGION_INFO, r) if r.size == 0: continue self.regions += [r] flags = "" if r.flags & c.VFIO_REGION_INFO_FLAG_READ: flags += "R" if r.flags & c.VFIO_REGION_INFO_FLAG_WRITE: flags += "W" if r.flags & c.VFIO_REGION_INFO_FLAG_MMAP: flags += "M" if r.flags & c.VFIO_REGION_INFO_FLAG_CAPS: flags += "*" t = "region %d" % r.index if i == c.VFIO_PCI_BAR0_REGION_INDEX: bar0 = c.mmap(0, r.size, c.PROT_READ | c.PROT_WRITE, c.MAP_SHARED | c.MAP_LOCKED, self.device, r.offset) self.bar0 = bar0 self.bar0_sz = r.size t = "pci bar 0" elif i == c.VFIO_PCI_BAR2_REGION_INDEX: bar2 = c.mmap64(0, r.size, c.PROT_READ | c.PROT_WRITE, c.MAP_PRIVATE, self.device, r.offset) if 0xffffffffffffffff != bar2: self.bar2 = bar2 self.bar2_sz = r.size t = "pci bar 2" elif i == c.VFIO_PCI_CONFIG_REGION_INDEX: self.config_offset = r.offset t = "pci config" elif i == c.VFIO_PCI_ROM_REGION_INDEX: t = "rom bar" else: t += " (type 0x%x)" % i print "[*] %s [%s]: size %04x, ofs %x" % (t, flags, r.size, r.offset)
def __attempt_hugetlb(self): try: with open("/proc/sys/vm/nr_hugepages", "r+") as hp: a = int(hp.read()) if a < 20: hp.seek(0) hp.write('20') except: pass flags = c.MAP_ANONYMOUS | c.MAP_PRIVATE | c.MAP_LOCKED | c.MAP_HUGETLB | c.MAP_32BIT flags |= (21 << c.MAP_HUGE_SHIFT) prot = c.PROT_READ | c.PROT_WRITE sz = 2048 * 1024 a = c.mmap(0, sz, prot, flags, -1, 0) if a != c.MAP_FAILED: print "[+] huge pages available" c.munmap(a, sz) self._hugetlb_available = True self._hugetlb_pgsz = sz else: print "[-] huge pages unavailable" self._hugetlb_available = False
def get_page(self): if self._hugetlb_available: assert self.page_sz == self._hugetlb_pgsz prot = c.PROT_READ | c.PROT_WRITE flags = c.MAP_ANONYMOUS | c.MAP_PRIVATE | c.MAP_LOCKED | c.MAP_HUGETLB | c.MAP_32BIT flags |= (21 << c.MAP_HUGE_SHIFT) sz = self._hugetlb_pgsz page = c.mmap(0, sz, prot, flags, -1, 0) if c.MAP_FAILED == page: e = c.errno.value raise Exception("mmap: 0x%x" % e) else: assert self.page_sz == self._page_sz page = c.valloc(self._page_sz) if 0 == page: raise Exception("valloc") if -1 == c.mlock(page, self._page_sz): raise Exception("mlock") c.memset(page, 0xFF, self.page_sz) self.locked_pages += [page] return (page, self.page_sz)
def get_page(self): if self._hugetlb_available: assert self.page_sz == self._hugetlb_pgsz prot = c.PROT_READ | c.PROT_WRITE flags = c.MAP_ANONYMOUS | c.MAP_PRIVATE | c.MAP_LOCKED | c.MAP_HUGETLB flags |= (21 << c.MAP_HUGE_SHIFT) sz = self._hugetlb_pgsz page = c.mmap(0, sz, prot, flags, -1, 0) if c.MAP_FAILED == page: e = c.errno.value raise Exception("mmap: 0x%x" % e) else: assert self.page_sz == self._page_sz page = c.valloc(self._page_sz) if 0 == page: raise Exception("valloc") if -1 == c.mlock(page, self._page_sz): raise Exception("mlock") c.memset(page, 0xFF, self.page_sz) self.locked_pages += [page] return (page, self.page_sz)
def _dev_open(self): print "[+] opening vfio group" group = os.open("/dev/vfio/%d" % self.groupno, os.O_RDWR) group_status = c.vfio_group_status() group_status.argsz = c.sizeof(c.vfio_group_status) ioctl(group, c.VFIO_GROUP_GET_STATUS, group_status) if not (group_status.flags & c.VFIO_GROUP_FLAGS_VIABLE): raise Exception("vfio group %d is not viable" % self.groupno) self.group = group ioctl(group, c.VFIO_GROUP_SET_CONTAINER, struct.pack("I", self.container)) ioctl(self.container, c.VFIO_SET_IOMMU, c.VFIO_TYPE1_IOMMU) iommu_info = c.vfio_iommu_type1_info() iommu_info.argsz = c.sizeof(c.vfio_iommu_type1_info) ioctl(self.container, c.VFIO_IOMMU_GET_INFO, iommu_info) self.iommu_info = iommu_info print "[+] opening vfio device" device = c.ioctl(group, c.VFIO_GROUP_GET_DEVICE_FD, self.bdf) self.device = device device_info = c.vfio_device_info() device_info.argsz = c.sizeof(c.vfio_device_info) ioctl(device, c.VFIO_DEVICE_GET_INFO, device_info) print "[+] enumerating vfio device regions" self.regions = [] for i in range(device_info.num_regions - 1): r = c.vfio_region_info() r.argsz = c.sizeof(c.vfio_region_info) r.index = i ioctl(device, c.VFIO_DEVICE_GET_REGION_INFO, r) self.regions += [r] flags = "" if r.flags & c.VFIO_REGION_INFO_FLAG_READ: flags += "R" if r.flags & c.VFIO_REGION_INFO_FLAG_WRITE: flags += "W" if r.flags & c.VFIO_REGION_INFO_FLAG_MMAP: flags += "M" t = "region %d" % r.index if i == c.VFIO_PCI_BAR0_REGION_INDEX: bar0 = c.mmap(0, r.size, c.PROT_READ | c.PROT_WRITE, c.MAP_SHARED | c.MAP_LOCKED, device, r.offset) self.bar0 = bar0 self.bar0_sz = r.size t = "pci bar 0" elif i == c.VFIO_PCI_BAR2_REGION_INDEX: bar2 = c.mmap64(0, r.size, c.PROT_READ | c.PROT_WRITE, c.MAP_PRIVATE, device, r.offset) if 0xffffffffffffffff != bar2: self.bar2 = bar2 self.bar2_sz = r.size t = "pci bar 2" elif i == c.VFIO_PCI_CONFIG_REGION_INDEX: self.config_offset = r.offset t = "pci config" print "[*] %s [%s]: size %04x, ofs %x, resv %x" % (t, flags, r.size, r.offset, r.resv) self.show_irqs() print "[+] enabling msi-x" irq_set = c.vfio_irq_set() c.resize(irq_set, c.sizeof(c.vfio_irq_set) + c.sizeof(c.c_uint)) irq_set.argsz = c.sizeof(c.vfio_irq_set) + c.sizeof(c.c_uint) irq_set.index = c.VFIO_PCI_MSIX_IRQ_INDEX irq_set.start = 0 irq_set.count = 1 irq_set.flags = c.VFIO_IRQ_SET_DATA_EVENTFD | c.VFIO_IRQ_SET_ACTION_TRIGGER self.eventfd = c.eventfd(0, 0) c.cast(c.addressof(irq_set.data), c.POINTER(c.c_uint))[0] = self.eventfd ioctl(self.device, c.VFIO_DEVICE_SET_IRQS, irq_set)