📄 pass-through.c
字号:
.init = pt_common_reg_init, .u.w.read = pt_word_reg_read, .u.w.write = pt_devctrl_reg_write, }, /* Link Control reg */ { .offset = PCI_EXP_LNKCTL, .size = 2, .init_val = 0x0000, .ro_mask = 0x0000, .emu_mask = 0xFFFF, .init = pt_common_reg_init, .u.w.read = pt_word_reg_read, .u.w.write = pt_linkctrl_reg_write, }, /* Device Control 2 reg */ { .offset = 0x28, .size = 2, .init_val = 0x0000, .ro_mask = 0x0000, .emu_mask = 0xFFFF, .init = pt_common_reg_init, .u.w.read = pt_word_reg_read, .u.w.write = pt_devctrl2_reg_write, }, /* Link Control 2 reg */ { .offset = 0x30, .size = 2, .init_val = 0x0000, .ro_mask = 0x0000, .emu_mask = 0xFFFF, .init = pt_linkctrl2_reg_init, .u.w.read = pt_word_reg_read, .u.w.write = pt_linkctrl2_reg_write, }, { .size = 0, }, };/* MSI Capability Structure reg static infomation table */static struct pt_reg_info_tbl pt_emu_reg_msi_tbl[] = { /* Next Pointer reg */ { .offset = PCI_CAP_LIST_NEXT, .size = 1, .init_val = 0x00, .ro_mask = 0xFF, .emu_mask = 0xFF, .init = pt_ptr_reg_init, .u.b.read = pt_byte_reg_read, .u.b.write = pt_byte_reg_write, }, /* Message Control reg */ { .offset = PCI_MSI_FLAGS, // 2 .size = 2, .init_val = 0x0000, .ro_mask = 0x018E, .emu_mask = 0xFFFE, .init = pt_msgctrl_reg_init, .u.w.read = pt_word_reg_read, .u.w.write = pt_msgctrl_reg_write, }, /* Message Address reg */ { .offset = PCI_MSI_ADDRESS_LO, // 4 .size = 4, .init_val = 0x00000000, .ro_mask = 0x00000FF0, /* bit 4~11 is reserved for MSI in x86 */ .emu_mask = 0xFFFFFFFF, .init = pt_msgaddr32_reg_init, .u.dw.read = pt_long_reg_read, .u.dw.write = pt_msgaddr32_reg_write, }, /* Message Upper Address reg (if PCI_MSI_FLAGS_64BIT set) */ { .offset = PCI_MSI_ADDRESS_HI, // 8 .size = 4, .init_val = 0x00000000, .ro_mask = 0x00000000, .emu_mask = 0xFFFFFFFF, .init = pt_msgaddr64_reg_init, .u.dw.read = pt_long_reg_read, .u.dw.write = pt_msgaddr64_reg_write, }, /* Message Data reg (16 bits of data for 32-bit devices) */ { .offset = PCI_MSI_DATA_32, // 8 .size = 2, .init_val = 0x0000, .ro_mask = 0x3800, .emu_mask = 0xFFFF, .init = pt_msgdata_reg_init, .u.w.read = pt_word_reg_read, .u.w.write = pt_msgdata_reg_write, }, /* Message Data reg (16 bits of data for 64-bit devices) */ { .offset = PCI_MSI_DATA_64, // 12 .size = 2, .init_val = 0x0000, .ro_mask = 0x3800, .emu_mask = 0xFFFF, .init = pt_msgdata_reg_init, .u.w.read = pt_word_reg_read, .u.w.write = pt_msgdata_reg_write, }, { .size = 0, }, };/* MSI-X Capability Structure reg static infomation table */static struct pt_reg_info_tbl pt_emu_reg_msix_tbl[] = { /* Next Pointer reg */ { .offset = PCI_CAP_LIST_NEXT, .size = 1, .init_val = 0x00, .ro_mask = 0xFF, .emu_mask = 0xFF, .init = pt_ptr_reg_init, .u.b.read = pt_byte_reg_read, .u.b.write = pt_byte_reg_write, }, /* Message Control reg */ { .offset = PCI_MSI_FLAGS, // 2 .size = 2, .init_val = 0x0000, .ro_mask = 0x3FFF, .emu_mask = 0x0000, .init = pt_msixctrl_reg_init, .u.w.read = pt_word_reg_read, .u.w.write = pt_msixctrl_reg_write, }, { .size = 0, }, };/* pt_reg_grp_info_tbl declaration * - only for emulated or zero-hardwired register group. * - for register group with dynamic size, just set grp_size to 0xFF and * specify size_init func properly. * - no need to specify emu_reg_tbl for zero-hardwired type. *//* emul reg group static infomation table */static const struct pt_reg_grp_info_tbl pt_emu_reg_grp_tbl[] = { /* Header Type0 reg group */ { .grp_id = 0xFF, .grp_type = GRP_TYPE_EMU, .grp_size = 0x40, .size_init = pt_reg_grp_size_init, .emu_reg_tbl= pt_emu_reg_header0_tbl, }, /* PCI PowerManagement Capability reg group */ { .grp_id = PCI_CAP_ID_PM, .grp_type = GRP_TYPE_EMU, .grp_size = PCI_PM_SIZEOF, .size_init = pt_reg_grp_size_init, .emu_reg_tbl= pt_emu_reg_pm_tbl, }, /* AGP Capability Structure reg group */ { .grp_id = PCI_CAP_ID_AGP, .grp_type = GRP_TYPE_HARDWIRED, .grp_size = 0x30, .size_init = pt_reg_grp_size_init, }, /* Vital Product Data Capability Structure reg group */ { .grp_id = PCI_CAP_ID_VPD, .grp_type = GRP_TYPE_EMU, .grp_size = 0x08, .size_init = pt_reg_grp_size_init, .emu_reg_tbl= pt_emu_reg_vpd_tbl, }, /* Slot Identification reg group */ { .grp_id = PCI_CAP_ID_SLOTID, .grp_type = GRP_TYPE_HARDWIRED, .grp_size = 0x04, .size_init = pt_reg_grp_size_init, }, /* MSI Capability Structure reg group */ { .grp_id = PCI_CAP_ID_MSI, .grp_type = GRP_TYPE_EMU, .grp_size = 0xFF, .size_init = pt_msi_size_init, .emu_reg_tbl= pt_emu_reg_msi_tbl, }, /* PCI-X Capabilities List Item reg group */ { .grp_id = PCI_CAP_ID_PCIX, .grp_type = GRP_TYPE_HARDWIRED, .grp_size = 0x18, .size_init = pt_reg_grp_size_init, }, /* Vendor Specific Capability Structure reg group */ { .grp_id = PCI_CAP_ID_VNDR, .grp_type = GRP_TYPE_EMU, .grp_size = 0xFF, .size_init = pt_vendor_size_init, .emu_reg_tbl= pt_emu_reg_vendor_tbl, }, /* SHPC Capability List Item reg group */ { .grp_id = PCI_CAP_ID_HOTPLUG, .grp_type = GRP_TYPE_HARDWIRED, .grp_size = 0x08, .size_init = pt_reg_grp_size_init, }, /* Subsystem ID and Subsystem Vendor ID Capability List Item reg group */ { .grp_id = PCI_CAP_ID_SSVID, .grp_type = GRP_TYPE_HARDWIRED, .grp_size = 0x08, .size_init = pt_reg_grp_size_init, }, /* AGP 8x Capability Structure reg group */ { .grp_id = PCI_CAP_ID_AGP3, .grp_type = GRP_TYPE_HARDWIRED, .grp_size = 0x30, .size_init = pt_reg_grp_size_init, }, /* PCI Express Capability Structure reg group */ { .grp_id = PCI_CAP_ID_EXP, .grp_type = GRP_TYPE_EMU, .grp_size = 0x3C, .size_init = pt_reg_grp_size_init, .emu_reg_tbl= pt_emu_reg_pcie_tbl, }, /* MSI-X Capability Structure reg group */ { .grp_id = PCI_CAP_ID_MSIX, .grp_type = GRP_TYPE_EMU, .grp_size = 0x0C, .size_init = pt_msix_size_init, .emu_reg_tbl= pt_emu_reg_msix_tbl, }, { .grp_size = 0, }, };static int token_value(char *token){ return strtol(token, NULL, 16);}static int next_bdf(char **str, int *seg, int *bus, int *dev, int *func){ char *token, *delim = ":.-"; if ( !(*str) || ( !strchr(*str, ':') && !strchr(*str, '.')) ) return 0; token = strsep(str, delim); *seg = token_value(token); token = strsep(str, delim); *bus = token_value(token); token = strsep(str, delim); *dev = token_value(token); token = strsep(str, delim); *func = token_value(token); return 1;}/* Insert a new pass-through device into a specific pci slot. * input dom:bus:dev.func@slot, chose free one if slot == 0 * return -1: required slot not available * 0: no free hotplug slots, but normal slot should okay * >0: the new hotplug slot */static int __insert_to_pci_slot(int bus, int dev, int func, int slot){ int i, php_slot; /* preferred virt pci slot */ if ( slot >= PHP_SLOT_START && slot < PHP_SLOT_END ) { php_slot = PCI_TO_PHP_SLOT(slot); if ( !dpci_infos.php_devs[php_slot].valid ) { goto found; } else return -1; } if ( slot != 0 ) return -1; /* slot == 0, pick up a free one */ for ( i = 0; i < PHP_SLOT_LEN; i++ ) { if ( !dpci_infos.php_devs[i].valid ) { php_slot = i; goto found; } } /* not found */ return 0;found: dpci_infos.php_devs[php_slot].valid = 1; dpci_infos.php_devs[php_slot].r_bus = bus; dpci_infos.php_devs[php_slot].r_dev = dev; dpci_infos.php_devs[php_slot].r_func = func; return PHP_TO_PCI_SLOT(php_slot);}/* Insert a new pass-through device into a specific pci slot. * input dom:bus:dev.func@slot */int insert_to_pci_slot(char *bdf_slt){ int seg, bus, dev, func, slot; char *bdf_str, *slt_str, *delim="@"; bdf_str = strsep(&bdf_slt, delim); slt_str = bdf_slt; slot = token_value(slt_str); if ( !next_bdf(&bdf_str, &seg, &bus, &dev, &func)) { return -1; } return __insert_to_pci_slot(bus, dev, func, slot);}/* Test if a pci slot has a device * 1: present * 0: not present * -1: invalide pci slot input */int test_pci_slot(int slot){ int php_slot; if ( slot < PHP_SLOT_START || slot >= PHP_SLOT_END ) return -1; php_slot = PCI_TO_PHP_SLOT(slot); if ( dpci_infos.php_devs[php_slot].valid ) return 1; else return 0;}/* find the pci slot for pass-through dev with specified BDF */int bdf_to_slot(char *bdf_str){ int seg, bus, dev, func, i; if ( !next_bdf(&bdf_str, &seg, &bus, &dev, &func)) { return -1; } /* locate the virtual pci slot for this VTd device */ for ( i = 0; i < PHP_SLOT_LEN; i++ ) { if ( dpci_infos.php_devs[i].valid && dpci_infos.php_devs[i].r_bus == bus && dpci_infos.php_devs[i].r_dev == dev && dpci_infos.php_devs[i].r_func == func ) { return PHP_TO_PCI_SLOT(i); } } return -1;}/* Being called each time a mmio region has been updated */void pt_iomem_map(PCIDevice *d, int i, uint32_t e_phys, uint32_t e_size, int type){ struct pt_dev *assigned_device = (struct pt_dev *)d; uint32_t old_ebase = assigned_device->bases[i].e_physbase; int first_map = ( assigned_device->bases[i].e_size == 0 ); int ret = 0; assigned_device->bases[i].e_physbase = e_phys; assigned_device->bases[i].e_size= e_size; PT_LOG("e_phys=%08x maddr=%lx type=%d len=%d index=%d first_map=%d\n", e_phys, (unsigned long)assigned_device->bases[i].access.maddr, type, e_size, i, first_map); if ( e_size == 0 ) return; if ( !first_map && old_ebase != -1 ) { add_msix_mapping(assigned_device, i); /* Remove old mapping */ ret = xc_domain_memory_mapping(xc_handle, domid, old_ebase >> XC_PAGE_SHIFT, assigned_device->bases[i].access.maddr >> XC_PAGE_SHIFT, (e_size+XC_PAGE_SIZE-1) >> XC_PAGE_SHIFT, DPCI_REMOVE_MAPPING); if ( ret != 0 ) { PT_LOG("Error: remove old mapping failed!\n"); return; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -