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

📄 pass-through.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
        }        reg_grp_offset = 0;    }out:    return err;}/* delete all emulate register */static void pt_config_delete(struct pt_dev *ptdev){    struct pt_reg_grp_tbl *reg_grp_entry = NULL;    struct pt_reg_tbl *reg_entry = NULL;    /* free MSI/MSI-X info table */    if (ptdev->msix)        pt_msix_delete(ptdev);    if (ptdev->msi)        free(ptdev->msi);    /* free all register group entry */    while ((reg_grp_entry = ptdev->reg_grp_tbl_head.lh_first) != NULL)    {        /* free all register entry */        while ((reg_entry = reg_grp_entry->reg_tbl_head.lh_first) != NULL)        {            LIST_REMOVE(reg_entry, entries);            qemu_free(reg_entry);        }        LIST_REMOVE(reg_grp_entry, entries);        qemu_free(reg_grp_entry);    }}/* initialize common register value */static uint32_t pt_common_reg_init(struct pt_dev *ptdev,        struct pt_reg_info_tbl *reg, uint32_t real_offset){    return reg->init_val;}/* initialize Capabilities Pointer or Next Pointer register */static uint32_t pt_ptr_reg_init(struct pt_dev *ptdev,        struct pt_reg_info_tbl *reg, uint32_t real_offset){    uint32_t reg_field = (uint32_t)ptdev->dev.config[real_offset];    int i;    /* find capability offset */    while (reg_field)    {        for (i=0; pt_emu_reg_grp_tbl[i].grp_size != 0; i++)        {            /* check whether the next capability              * should be exported to guest or not              */            if (pt_emu_reg_grp_tbl[i].grp_id == ptdev->dev.config[reg_field])            {                if (pt_emu_reg_grp_tbl[i].grp_type == GRP_TYPE_EMU)                    goto out;                /* ignore the 0 hardwired capability, find next one */                break;            }        }        /* next capability */        reg_field = (uint32_t)ptdev->dev.config[reg_field + 1];    }out:    return reg_field;}/* initialize Status register */static uint32_t pt_status_reg_init(struct pt_dev *ptdev,        struct pt_reg_info_tbl *reg, uint32_t real_offset){    struct pt_reg_grp_tbl *reg_grp_entry = NULL;    struct pt_reg_tbl *reg_entry = NULL;    int reg_field = 0;    /* find Header register group */    reg_grp_entry = pt_find_reg_grp(ptdev, PCI_CAPABILITY_LIST);    if (reg_grp_entry)    {        /* find Capabilities Pointer register */        reg_entry = pt_find_reg(reg_grp_entry, PCI_CAPABILITY_LIST);        if (reg_entry)        {            /* check Capabilities Pointer register */            if (reg_entry->data)                reg_field |= PCI_STATUS_CAP_LIST;            else                reg_field &= ~PCI_STATUS_CAP_LIST;        }        else        {            /* exit I/O emulator */            PT_LOG("Internal error: Couldn't find pt_reg_tbl for "                "Capabilities Pointer register. I/O emulator exit.\n");            exit(1);        }    }    else    {        /* exit I/O emulator */        PT_LOG("Internal error: Couldn't find pt_reg_grp_tbl for Header. "            "I/O emulator exit.\n");        exit(1);    }    return reg_field;}/* initialize Interrupt Pin register */static uint32_t pt_irqpin_reg_init(struct pt_dev *ptdev,        struct pt_reg_info_tbl *reg, uint32_t real_offset){    int reg_field = 0;    /* set Interrupt Pin register to use INTA# if it has */    if (ptdev->dev.config[real_offset])        reg_field = 0x01;    return reg_field;}/* initialize BAR */static uint32_t pt_bar_reg_init(struct pt_dev *ptdev,        struct pt_reg_info_tbl *reg, uint32_t real_offset){    int reg_field = 0;    int index;    /* get BAR index */    index = pt_bar_offset_to_index(reg->offset);    if (index < 0)    {        /* exit I/O emulator */        PT_LOG("Internal error: Invalid BAR index[%d]. "            "I/O emulator exit.\n", index);        exit(1);    }    /* set initial guest physical base address to -1 */    ptdev->bases[index].e_physbase = -1;    /* set BAR flag */    ptdev->bases[index].bar_flag = pt_bar_reg_parse(ptdev, reg);    if (ptdev->bases[index].bar_flag == PT_BAR_FLAG_UNUSED)        reg_field = PT_INVALID_REG;    return reg_field;}/* initialize Link Control 2 register */static uint32_t pt_linkctrl2_reg_init(struct pt_dev *ptdev,        struct pt_reg_info_tbl *reg, uint32_t real_offset){    int reg_field = 0;    /* set Supported Link Speed */    reg_field |=         (0x0F &          ptdev->dev.config[(real_offset - reg->offset) + PCI_EXP_LNKCAP]);    return reg_field;}/* initialize Message Control register */static uint32_t pt_msgctrl_reg_init(struct pt_dev *ptdev,        struct pt_reg_info_tbl *reg, uint32_t real_offset){    PCIDevice *d = (struct PCIDevice *)ptdev;    struct pci_dev *pdev = ptdev->pci_dev;    uint32_t reg_field = 0;        /* use I/O device register's value as initial value */    reg_field |= *((uint16_t*)(d->config + real_offset));        if (reg_field & PCI_MSI_FLAGS_ENABLE)    {        PT_LOG("MSI enabled already, disable first\n");        pci_write_word(pdev, real_offset, reg_field & ~PCI_MSI_FLAGS_ENABLE);    }    ptdev->msi->flags |= (reg_field | MSI_FLAG_UNINIT);        /* All register is 0 after reset, except first 4 byte */    reg_field &= reg->ro_mask;        return reg_field;}/* initialize Message Address register */static uint32_t pt_msgaddr32_reg_init(struct pt_dev *ptdev,        struct pt_reg_info_tbl *reg, uint32_t real_offset){    PCIDevice *d = (struct PCIDevice *)ptdev;    uint32_t reg_field = 0;        /* use I/O device register's value as initial value */    reg_field |= *((uint32_t*)(d->config + real_offset));        return reg_field;}/* initialize Message Upper Address register */static uint32_t pt_msgaddr64_reg_init(struct pt_dev *ptdev,        struct pt_reg_info_tbl *reg, uint32_t real_offset){    PCIDevice *d = (struct PCIDevice *)ptdev;    uint32_t reg_field = 0;        /* no need to initialize in case of 32 bit type */    if (!(ptdev->msi->flags & PCI_MSI_FLAGS_64BIT))        return PT_INVALID_REG;        /* use I/O device register's value as initial value */    reg_field |= *((uint32_t*)(d->config + real_offset));        return reg_field;}/* this function will be called twice (for 32 bit and 64 bit type) *//* initialize Message Data register */static uint32_t pt_msgdata_reg_init(struct pt_dev *ptdev,        struct pt_reg_info_tbl *reg, uint32_t real_offset){    PCIDevice *d = (struct PCIDevice *)ptdev;    uint32_t flags = ptdev->msi->flags;    uint32_t offset = reg->offset;        /* check the offset whether matches the type or not */    if (((offset == PCI_MSI_DATA_64) &&  (flags & PCI_MSI_FLAGS_64BIT)) ||        ((offset == PCI_MSI_DATA_32) && !(flags & PCI_MSI_FLAGS_64BIT)))        return *((uint16_t*)(d->config + real_offset));    else        return PT_INVALID_REG;}/* initialize Message Control register for MSI-X */static uint32_t pt_msixctrl_reg_init(struct pt_dev *ptdev,        struct pt_reg_info_tbl *reg, uint32_t real_offset){    PCIDevice *d = (struct PCIDevice *)ptdev;    struct pci_dev *pdev = ptdev->pci_dev;    uint16_t reg_field = 0;        /* use I/O device register's value as initial value */    reg_field |= *((uint16_t*)(d->config + real_offset));        if (reg_field & PCI_MSIX_ENABLE)    {        PT_LOG("MSIX enabled already, disable first\n");        pci_write_word(pdev, real_offset, reg_field & ~PCI_MSIX_ENABLE);        reg_field &= ~(PCI_MSIX_ENABLE | PCI_MSIX_MASK);    }        return reg_field;}/* get register group size */static uint8_t pt_reg_grp_size_init(struct pt_dev *ptdev,        struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset){    return grp_reg->grp_size;}/* get MSI Capability Structure register group size */static uint8_t pt_msi_size_init(struct pt_dev *ptdev,        struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset){    PCIDevice *d = &ptdev->dev;    uint16_t msg_ctrl = 0;    uint8_t msi_size = 0xa;    msg_ctrl = *((uint16_t*)(d->config + (base_offset + PCI_MSI_FLAGS)));    /* check 64 bit address capable & Per-vector masking capable */    if (msg_ctrl & PCI_MSI_FLAGS_64BIT)        msi_size += 4;    if (msg_ctrl & PCI_MSI_FLAGS_MASK_BIT)        msi_size += 10;    ptdev->msi = malloc(sizeof(struct pt_msi_info));    if ( !ptdev->msi )    {        /* exit I/O emulator */        PT_LOG("error allocation pt_msi_info. I/O emulator exit.\n");        exit(1);    }    memset(ptdev->msi, 0, sizeof(struct pt_msi_info));        return msi_size;}/* get MSI-X Capability Structure register group size */static uint8_t pt_msix_size_init(struct pt_dev *ptdev,        struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset){    int ret = 0;    ret = pt_msix_init(ptdev, base_offset);    if (ret == -1)    {        /* exit I/O emulator */        PT_LOG("Internal error: Invalid pt_msix_init return value[%d]. "            "I/O emulator exit.\n", ret);        exit(1);    }    return grp_reg->grp_size;}/* get Vendor Specific Capability Structure register group size */static uint8_t pt_vendor_size_init(struct pt_dev *ptdev,        struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset){    return ptdev->dev.config[base_offset + 0x02];}/* read byte size emulate register */static int pt_byte_reg_read(struct pt_dev *ptdev,        struct pt_reg_tbl *cfg_entry,        uint8_t *value, uint8_t valid_mask){    struct pt_reg_info_tbl *reg = cfg_entry->reg;    uint8_t valid_emu_mask = 0;    /* emulate byte register */    valid_emu_mask = reg->emu_mask & valid_mask;    *value = ((*value & ~valid_emu_mask) |               (cfg_entry->data & valid_emu_mask));    return 0;}/* read word size emulate register */static int pt_word_reg_read(struct pt_dev *ptdev,        struct pt_reg_tbl *cfg_entry,        uint16_t *value, uint16_t valid_mask){    struct pt_reg_info_tbl *reg = cfg_entry->reg;    uint16_t valid_emu_mask = 0;    /* emulate word register */    valid_emu_mask = reg->emu_mask & valid_mask;    *value = ((*value & ~valid_emu_mask) |               (cfg_entry->data & valid_emu_mask));    return 0;}/* read long size emulate register */static int pt_long_reg_read(struct pt_dev *ptdev,        struct pt_reg_tbl *cfg_entry,        uint32_t *value, uint32_t valid_mask){    struct pt_reg_info_tbl *reg = cfg_entry->reg;    uint32_t valid_emu_mask = 0;    /* emulate long register */    valid_emu_mask = reg->emu_mask & valid_mask;    *value = ((*value & ~valid_emu_mask) |               (cfg_entry->data & valid_emu_mask));   return 0;}/* read BAR */static int pt_bar_reg_read(struct pt_dev *ptdev,        struct pt_reg_tbl *cfg_entry,        uint32_t *value, uint32_t valid_mask){    struct pt_reg_info_tbl *reg = cfg_entry->reg;    uint32_t valid_emu_mask = 0;    uint32_t bar_emu_mask = 0;    int index;    /* get BAR index */    index = pt_bar_offset_to_index(reg->offset);    if (index < 0)    {        /* exit I/O emulator */        PT_LOG("Internal error: Invalid BAR index[%d]. "            "I/O emulator exit.\n", index);        exit(1);    }    /* set emulate mask depend on BAR flag */    switch (ptdev->bases[index].bar_flag)    {    case PT_BAR_FLAG_MEM:        bar_emu_mask = PT_BAR_MEM_EMU_MASK;        break;    case PT_BAR_FLAG_IO:        bar_emu_mask = PT_BAR_IO_EMU_MASK;        break;    case PT_BAR_FLAG_UPPER:        bar_emu_mask = PT_BAR_ALLF;        break;    default:        break;    }    /* emulate BAR */    valid_emu_mask = bar_emu_mask & valid_mask;    *value = ((*value & ~valid_emu_mask) |               (cfg_entry->data & valid_emu_mask));   return 0;}/* write byte size emulate register */static int pt_byte_reg_write(struct pt_dev *ptdev,         struct pt_reg_tbl *cfg_entry,         uint8_t *value, uint8_t dev_value, uint8_t valid_mask){    struct pt_reg_info_tbl *reg = cfg_entry->reg;    uint8_t writable_mask = 0;    uint8_t throughable_mask = 0;    /* modify emulate register */    writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;    cfg_entry->data = ((*val

⌨️ 快捷键说明

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