⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pass-through.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* map only valid guest address */    if (e_phys != -1)    {        /* Create new mapping */        ret = xc_domain_memory_mapping(xc_handle, domid,                assigned_device->bases[i].e_physbase >> XC_PAGE_SHIFT,                assigned_device->bases[i].access.maddr >> XC_PAGE_SHIFT,                (e_size+XC_PAGE_SIZE-1) >> XC_PAGE_SHIFT,                DPCI_ADD_MAPPING);        if ( ret != 0 )        {            PT_LOG("Error: create new mapping failed!\n");        }                ret = remove_msix_mapping(assigned_device, i);        if ( ret != 0 )            PT_LOG("Error: remove MSI-X mmio mapping failed!\n");    }}/* Being called each time a pio region has been updated */void pt_ioport_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=%04x pio_base=%04x len=%d index=%d first_map=%d\n",        (uint16_t)e_phys, (uint16_t)assigned_device->bases[i].access.pio_base,        (uint16_t)e_size, i, first_map);    if ( e_size == 0 )        return;    if ( !first_map && old_ebase != -1 )    {        /* Remove old mapping */        ret = xc_domain_ioport_mapping(xc_handle, domid, old_ebase,                    assigned_device->bases[i].access.pio_base, e_size,                    DPCI_REMOVE_MAPPING);        if ( ret != 0 )        {            PT_LOG("Error: remove old mapping failed!\n");            return;        }    }    /* map only valid guest address (include 0) */    if (e_phys != -1)    {        /* Create new mapping */        ret = xc_domain_ioport_mapping(xc_handle, domid, e_phys,                    assigned_device->bases[i].access.pio_base, e_size,                    DPCI_ADD_MAPPING);        if ( ret != 0 )        {            PT_LOG("Error: create new mapping failed!\n");        }    }}/* find emulate register group entry */struct pt_reg_grp_tbl* pt_find_reg_grp(        struct pt_dev *ptdev, uint32_t address){    struct pt_reg_grp_tbl* reg_grp_entry = NULL;    /* find register group entry */    for (reg_grp_entry = ptdev->reg_grp_tbl_head.lh_first; reg_grp_entry;        reg_grp_entry = reg_grp_entry->entries.le_next)    {        /* check address */        if ((reg_grp_entry->base_offset <= address) &&            ((reg_grp_entry->base_offset + reg_grp_entry->size) > address))            goto out;    }    /* group entry not found */    reg_grp_entry = NULL;out:    return reg_grp_entry;}/* find emulate register entry */struct pt_reg_tbl* pt_find_reg(        struct pt_reg_grp_tbl* reg_grp, uint32_t address){    struct pt_reg_tbl* reg_entry = NULL;    struct pt_reg_info_tbl* reg = NULL;    uint32_t real_offset = 0;    /* find register entry */    for (reg_entry = reg_grp->reg_tbl_head.lh_first; reg_entry;        reg_entry = reg_entry->entries.le_next)    {        reg = reg_entry->reg;        real_offset = (reg_grp->base_offset + reg->offset);        /* check address */        if ((real_offset <= address) && ((real_offset + reg->size) > address))            goto out;    }    /* register entry not found */    reg_entry = NULL;out:    return reg_entry;}/* get BAR index */static int pt_bar_offset_to_index(uint32_t offset){    int index = 0;    /* check Exp ROM BAR */    if (offset == PCI_ROM_ADDRESS)    {        index = PCI_ROM_SLOT;        goto out;    }    /* calculate BAR index */    index = ((offset - PCI_BASE_ADDRESS_0) >> 2);    if (index >= PCI_NUM_REGIONS)        index = -1;out:    return index;}static void pt_pci_write_config(PCIDevice *d, uint32_t address, uint32_t val,                                int len){    struct pt_dev *assigned_device = (struct pt_dev *)d;    struct pci_dev *pci_dev = assigned_device->pci_dev;    struct pt_reg_grp_tbl *reg_grp_entry = NULL;    struct pt_reg_grp_info_tbl *reg_grp = NULL;    struct pt_reg_tbl *reg_entry = NULL;    struct pt_reg_info_tbl *reg = NULL;    uint32_t find_addr = address;    uint32_t real_offset = 0;    uint32_t valid_mask = 0xFFFFFFFF;    uint32_t read_val = 0;    uint8_t *ptr_val = NULL;    int emul_len = 0;    int index = 0;    int ret = 0;#ifdef PT_DEBUG_PCI_CONFIG_ACCESS    PT_LOG("[%02x:%02x.%x]: address=%04x val=0x%08x len=%d\n",       pci_bus_num(d->bus), (d->devfn >> 3) & 0x1F, (d->devfn & 0x7),       address, val, len);#endif    /* check offset range */    if (address >= 0xFF)    {        PT_LOG("Failed to write register with offset exceeding FFh. "            "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",            pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),            address, len);        goto exit;    }    /* check write size */    if ((len != 1) && (len != 2) && (len != 4))    {        PT_LOG("Failed to write register with invalid access length. "            "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",            pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),            address, len);        goto exit;    }    /* check offset alignment */    if (address & (len-1))    {        PT_LOG("Failed to write register with invalid access size alignment. "            "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",            pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),            address, len);        goto exit;    }    /* check unused BAR register */    index = pt_bar_offset_to_index(address);    if ((index >= 0) && (val > 0 && val < PT_BAR_ALLF) &&        (assigned_device->bases[index].bar_flag == PT_BAR_FLAG_UNUSED))    {        PT_LOG("Guest attempt to set address to unused Base Address Register. "            "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",            pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F),             (d->devfn & 0x7), address, len);    }    /* find register group entry */    reg_grp_entry = pt_find_reg_grp(assigned_device, address);    if (reg_grp_entry)    {        reg_grp = reg_grp_entry->reg_grp;        /* check 0 Hardwired register group */        if (reg_grp->grp_type == GRP_TYPE_HARDWIRED)        {            /* ignore silently */            PT_LOG("Access to 0 Hardwired register. "                "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",                pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F),                 (d->devfn & 0x7), address, len);            goto exit;        }    }    /* read I/O device register value */    switch (len) {    case 1:        read_val = pci_read_byte(pci_dev, address);        break;    case 2:        read_val = pci_read_word(pci_dev, address);        break;    case 4:        read_val = pci_read_long(pci_dev, address);        break;    }    /* check libpci result */    valid_mask = (0xFFFFFFFF >> ((4 - len) << 3));    if ((read_val & valid_mask) == valid_mask)    {        PT_LOG("Warning: Return ALL F from libpci read. "            "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",            pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),            address, len);    }        /* pass directly to libpci for passthrough type register group */    if (reg_grp_entry == NULL)        goto out;    /* adjust the read and write value to appropriate CFC-CFF window */    read_val <<= ((address & 3) << 3);    val <<= ((address & 3) << 3);    emul_len = len;    /* loop Guest request size */    while (0 < emul_len)    {        /* find register entry to be emulated */        reg_entry = pt_find_reg(reg_grp_entry, find_addr);        if (reg_entry)        {            reg = reg_entry->reg;            real_offset = (reg_grp_entry->base_offset + reg->offset);            valid_mask = (0xFFFFFFFF >> ((4 - emul_len) << 3));            valid_mask <<= ((find_addr - real_offset) << 3);            ptr_val = ((uint8_t *)&val + (real_offset & 3));            /* do emulation depend on register size */            switch (reg->size) {            case 1:                /* emulate write to byte register */                if (reg->u.b.write)                    ret = reg->u.b.write(assigned_device, reg_entry,                               (uint8_t *)ptr_val,                                (uint8_t)(read_val >> ((real_offset & 3) << 3)),                               (uint8_t)valid_mask);                break;            case 2:                /* emulate write to word register */                if (reg->u.w.write)                    ret = reg->u.w.write(assigned_device, reg_entry,                               (uint16_t *)ptr_val,                                (uint16_t)(read_val >> ((real_offset & 3) << 3)),                               (uint16_t)valid_mask);                break;            case 4:                /* emulate write to double word register */                if (reg->u.dw.write)                    ret = reg->u.dw.write(assigned_device, reg_entry,                               (uint32_t *)ptr_val,                                (uint32_t)(read_val >> ((real_offset & 3) << 3)),                               (uint32_t)valid_mask);                break;            }            /* write emulation error */            if (ret < 0)            {                /* exit I/O emulator */                PT_LOG("Internal error: Invalid write emulation "                    "return value[%d]. I/O emulator exit.\n", ret);                exit(1);            }            /* calculate next address to find */            emul_len -= reg->size;            if (emul_len > 0)                find_addr = real_offset + reg->size;        }        else        {            /* nothing to do with passthrough type register,              * continue to find next byte              */            emul_len--;            find_addr++;        }    }        /* need to shift back before passing them to libpci */    val >>= ((address & 3) << 3);out:    switch (len){    case 1:        pci_write_byte(pci_dev, address, val);        break;    case 2:        pci_write_word(pci_dev, address, val);        break;    case 4:        pci_write_long(pci_dev, address, val);        break;    }exit:    return;}static uint32_t pt_pci_read_config(PCIDevice *d, uint32_t address, int len){    struct pt_dev *assigned_device = (struct pt_dev *)d;    struct pci_dev *pci_dev = assigned_device->pci_dev;    uint32_t val = 0xFFFFFFFF;    struct pt_reg_grp_tbl *reg_grp_entry = NULL;    struct pt_reg_grp_info_tbl *reg_grp = NULL;    struct pt_reg_tbl *reg_entry = NULL;    struct pt_reg_info_tbl *reg = NULL;    uint32_t find_addr = address;    uint32_t real_offset = 0;    uint32_t valid_mask = 0xFFFFFFFF;    uint8_t *ptr_val = NULL;    int emul_len = 0;    int ret = 0;    /* check offset range */    if (address >= 0xFF)    {        PT_LOG("Failed to read register with offset exceeding FFh. "            "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",            pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),            address, len);        goto exit;    }    /* check read size */    if ((len != 1) && (len != 2) && (len != 4))    {        PT_LOG("Failed to read register with invalid access length. "            "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",            pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),            address, len);        goto exit;    }    /* check offset alignment */    if (address & (len-1))    {        PT_LOG("Failed to read register with invalid access size alignment. "            "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",            pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),            address, len);        goto exit;    }    /* find register group entry */    reg_grp_entry = pt_find_reg_grp(assigned_device, address);    if (reg_grp_entry)    {        reg_grp = reg_grp_entry->reg_grp;        /* check 0 Hardwired register group */        if (reg_grp->grp_type == GRP_TYPE_HARDWIRED)        {            /* no need to emulate, just return 0 */            val = 0;            goto exit;        }    }    /* read I/O device register value */    switch (len) {    case 1:        val = pci_read_byte(pci_dev, address);        break;    case 2:        val = pci_read_word(pci_dev, address);        break;    case 4:        val = pci_read_long(pci_dev, address);        break;    }    /* check libpci result */    valid_mask = (0xFFFFFFFF >> ((4 - len) << 3));    if ((val & valid_mask) == valid_mask)    {        PT_LOG("Warning: Return ALL F from libpci read. "            "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n",            pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),            address, len);    }    /* just return the I/O device register value for      * passthrough type register group      */    if (reg_grp_entry == NULL)        goto exit;    /* adjust the read value to appropriate CFC-CFF window */    val <<= ((address & 3) << 3);    emul_len = len;    /* loop Guest request size */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -