Beispiel #1
0
/* default write_config function for PCI-to-PCI bridge */
void pci_bridge_write_config(PCIDevice *d,
                             uint32_t address, uint32_t val, int len)
{
    PCIBridge *s = container_of(d, PCIBridge, dev);
    uint16_t oldctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
    uint16_t newctl;

    pci_default_write_config(d, address, val, len);

    if (ranges_overlap(address, len, PCI_COMMAND, 2) ||

        /* io base/limit */
        ranges_overlap(address, len, PCI_IO_BASE, 2) ||

        /* memory base/limit, prefetchable base/limit and
           io base/limit upper 16 */
        ranges_overlap(address, len, PCI_MEMORY_BASE, 20)) {
        pci_bridge_update_mappings(s);
    }

    newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
    if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) {
        /* Trigger hot reset on 0->1 transition. */
        pci_bus_reset(&s->sec_bus);
    }
}
Beispiel #2
0
static void pm_write_config(PCIDevice *d,
                            uint32_t address, uint32_t val, int len)
{
    pci_default_write_config(d, address, val, len);
    if (range_covers_byte(address, len, 0x80))
        pm_io_space_update((PIIX4PMState *)d);
}
Beispiel #3
0
static void xilinx_pcie_root_config_write(PCIDevice *d, uint32_t address,
                                          uint32_t val, int len)
{
    XilinxPCIEHost *s = XILINX_PCIE_HOST(OBJECT(d)->parent);
    switch (address) {
    case ROOTCFG_INTDEC:
        xilinx_pcie_update_intr(s, 0, val);
        break;
    case ROOTCFG_INTMASK:
        s->intr_mask = val;
        xilinx_pcie_update_intr(s, 0, 0);
        break;
    case ROOTCFG_RPSCR:
        s->rpscr &= ~ROOTCFG_RPSCR_BRIDGEEN;
        s->rpscr |= val & ROOTCFG_RPSCR_BRIDGEEN;
        memory_region_set_enabled(&s->mmio, val & ROOTCFG_RPSCR_BRIDGEEN);

        if (val & ROOTCFG_INTMASK_INTX) {
            s->rpscr &= ~ROOTCFG_INTMASK_INTX;
        }
        break;
    case ROOTCFG_RPIFR1:
    case ROOTCFG_RPIFR2:
        if (s->intr_fifo_w == s->intr_fifo_r) {
            /* FIFO empty */
            return;
        } else {
            s->intr_fifo_r = (s->intr_fifo_r + 1) % ARRAY_SIZE(s->intr_fifo);
        }
        break;
    default:
        pci_default_write_config(d, address, val, len);
        break;
    }
}
static void i6300esb_config_write(PCIDevice *dev, uint32_t addr,
                                  uint32_t data, int len)
{
    I6300State *d = DO_UPCAST(I6300State, dev, dev);
    int old;

    i6300esb_debug("addr = %x, data = %x, len = %d\n", addr, data, len);

    if (addr == ESB_CONFIG_REG && len == 2) {
        d->reboot_enabled = (data & ESB_WDT_REBOOT) == 0;
        d->clock_scale =
            (data & ESB_WDT_FREQ) != 0 ? CLOCK_SCALE_1MHZ : CLOCK_SCALE_1KHZ;
        d->int_type = (data & ESB_WDT_INTTYPE);
    } else if (addr == ESB_LOCK_REG && len == 1) {
        if (!d->locked) {
            d->locked = (data & ESB_WDT_LOCK) != 0;
            d->free_run = (data & ESB_WDT_FUNC) != 0;
            old = d->enabled;
            d->enabled = (data & ESB_WDT_ENABLE) != 0;
            if (!old && d->enabled) /* Enabled transitioned from 0 -> 1 */
                i6300esb_restart_timer(d, 1);
            else if (!d->enabled)
                i6300esb_disable_timer(d);
        }
    } else {
        pci_default_write_config(dev, addr, data, len);
    }
}
static void assigned_dev_pci_write_config(PCIDevice *d, uint32_t address,
                                          uint32_t val, int len)
{
    int fd;
    ssize_t ret;
    AssignedDevice *pci_dev = container_of(d, AssignedDevice, dev);

    DEBUG("(%x.%x): address=%04x val=0x%08x len=%d\n",
          ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),
          (uint16_t) address, val, len);

    if (address == 0x4) {
        pci_default_write_config(d, address, val, len);
        /* Continue to program the card */
    }

    if ((address >= 0x10 && address <= 0x24) || address == 0x34 ||
        address == 0x3c || address == 0x3d ||
        pci_access_cap_config(d, address, len)) {
        /* used for update-mappings (BAR emulation) */
        pci_default_write_config(d, address, val, len);
        return;
    }

    DEBUG("NON BAR (%x.%x): address=%04x val=0x%08x len=%d\n",
          ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7),
          (uint16_t) address, val, len);

    fd = pci_dev->real_device.config_fd;

again:
    ret = pwrite(fd, &val, len, address);
    if (ret != len) {
	if ((ret < 0) && (errno == EINTR || errno == EAGAIN))
	    goto again;

	fprintf(stderr, "%s: pwrite failed, ret = %zd errno = %d\n",
		__func__, ret, errno);

	exit(1);
    }
}
Beispiel #6
0
void igd_pci_write(PCIDevice *pci_dev, uint32_t config_addr, uint32_t val, int len)
{
    assert(pci_dev->devfn == 0x00);
    if ( !igd_passthru ) {
        pci_default_write_config(pci_dev, config_addr, val, len);
        return;
    }

    switch (config_addr)
    {
        case 0x58:        // PAVPC Offset
            pt_pci_host_write(0, 0, 0, config_addr, val, len);
            PT_LOG("pci_config_write: %x:%x.%x: addr=%x len=%x val=%x\n",
                   pci_bus_num(pci_dev->bus), PCI_SLOT(pci_dev->devfn),
                   PCI_FUNC(pci_dev->devfn), config_addr, len, val);
            break;
        default:
            pci_default_write_config(pci_dev, config_addr, val, len);
    }
}
Beispiel #7
0
static void e1000e_write_config(PCIDevice *pci_dev, uint32_t address,
                                uint32_t val, int len)
{
    E1000EState *s = E1000E(pci_dev);

    pci_default_write_config(pci_dev, address, val, len);

    if (range_covers_byte(address, len, PCI_COMMAND) &&
        (pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
        e1000e_start_recv(&s->core);
    }
}
Beispiel #8
0
static void e1000e_write_config(PCIDevice *pci_dev, uint32_t address,
                                uint32_t val, int len)
{
    E1000EState *s = E1000E(pci_dev);

    pci_default_write_config(pci_dev, address, val, len);

    if (range_covers_byte(address, len, PCI_COMMAND) &&
        (pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
        qemu_flush_queued_packets(qemu_get_queue(s->nic));
    }
}
Beispiel #9
0
static void pm_write_config(PCIDevice *d,
                            uint32_t address, uint32_t val, int len)
{
    pci_default_write_config(d, address, val, len);
    if (range_covers_byte(address, len, 0x80) ||
        ranges_overlap(address, len, 0x40, 4)) {
        pm_io_space_update((PIIX4PMState *)d);
    }
    if (range_covers_byte(address, len, 0xd2) ||
        ranges_overlap(address, len, 0x90, 4)) {
        smbus_io_space_update((PIIX4PMState *)d);
    }
}
Beispiel #10
0
static void usb_ehci_pci_write_config(PCIDevice *dev, uint32_t addr,
                                      uint32_t val, int l)
{
    EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev);
    bool busmaster;

    pci_default_write_config(dev, addr, val, l);

    if (!range_covers_byte(addr, l, PCI_COMMAND)) {
        return;
    }
    busmaster = pci_get_word(dev->config + PCI_COMMAND) & PCI_COMMAND_MASTER;
    i->ehci.dma = busmaster ? pci_dma_context(dev) : NULL;
}
Beispiel #11
0
static void ivshmem_write_config(PCIDevice *pdev, uint32_t address,
                                 uint32_t val, int len)
{
    IVShmemState *s = IVSHMEM_COMMON(pdev);
    int is_enabled, was_enabled = msix_enabled(pdev);

    pci_default_write_config(pdev, address, val, len);
    is_enabled = msix_enabled(pdev);

    if (kvm_msi_via_irqfd_enabled()) {
        if (!was_enabled && is_enabled) {
            ivshmem_enable_irqfd(s);
        } else if (was_enabled && !is_enabled) {
            ivshmem_disable_irqfd(s);
        }
    }
}
Beispiel #12
0
static void mch_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
{
    MCHPCIState *mch = MCH_PCI_DEVICE(d);

    pci_default_write_config(d, address, val, len);

    if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PAM0,
                       MCH_HOST_BRIDGE_PAM_SIZE)) {
        mch_update_pam(mch);
    }

    if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PCIEXBAR,
                       MCH_HOST_BRIDGE_PCIEXBAR_SIZE)) {
        mch_update_pciexbar(mch);
    }

    if (ranges_overlap(address, len, MCH_HOST_BRIDGE_SMRAM,
                       MCH_HOST_BRIDGE_SMRAM_SIZE)) {
        mch_update_smram(mch);
    }
}
Beispiel #13
0
static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address,
				 uint32_t val, int len)
{
    pci_default_write_config(pci_dev, address, val, len);
    msix_write_config(pci_dev, address, val, len);
}
Beispiel #14
0
static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
                                    uint32_t val, int len)
{
    XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d);
    int index = 0;
    XenPTRegGroup *reg_grp_entry = NULL;
    int rc = 0;
    uint32_t read_val = 0;
    int emul_len = 0;
    XenPTReg *reg_entry = NULL;
    uint32_t find_addr = addr;
    XenPTRegInfo *reg = NULL;

    if (xen_pt_pci_config_access_check(d, addr, len)) {
        return;
    }

    XEN_PT_LOG_CONFIG(d, addr, val, len);

    /* check unused BAR register */
    index = xen_pt_bar_offset_to_index(addr);
    if ((index >= 0) && (val > 0 && val < XEN_PT_BAR_ALLF) &&
        (s->bases[index].bar_flag == XEN_PT_BAR_FLAG_UNUSED)) {
        XEN_PT_WARN(d, "Guest attempt to set address to unused Base Address "
                    "Register. (addr: 0x%02x, len: %d)\n", addr, len);
    }

    /* find register group entry */
    reg_grp_entry = xen_pt_find_reg_grp(s, addr);
    if (reg_grp_entry) {
        /* check 0-Hardwired register group */
        if (reg_grp_entry->reg_grp->grp_type == XEN_PT_GRP_TYPE_HARDWIRED) {
            /* ignore silently */
            XEN_PT_WARN(d, "Access to 0-Hardwired register. "
                        "(addr: 0x%02x, len: %d)\n", addr, len);
            return;
        }
    }

    rc = xen_host_pci_get_block(&s->real_device, addr,
                                (uint8_t *)&read_val, len);
    if (rc < 0) {
        XEN_PT_ERR(d, "pci_read_block failed. return value: %d.\n", rc);
        memset(&read_val, 0xff, len);
    }

    /* pass directly to the real device for passthrough type register group */
    if (reg_grp_entry == NULL) {
        goto out;
    }

    memory_region_transaction_begin();
    pci_default_write_config(d, addr, val, len);

    /* adjust the read and write value to appropriate CFC-CFF window */
    read_val <<= (addr & 3) << 3;
    val <<= (addr & 3) << 3;
    emul_len = len;

    /* loop around the guest requested size */
    while (emul_len > 0) {
        /* find register entry to be emulated */
        reg_entry = xen_pt_find_reg(reg_grp_entry, find_addr);
        if (reg_entry) {
            reg = reg_entry->reg;
            uint32_t real_offset = reg_grp_entry->base_offset + reg->offset;
            uint32_t valid_mask = 0xFFFFFFFF >> ((4 - emul_len) << 3);
            uint8_t *ptr_val = NULL;

            valid_mask <<= (find_addr - real_offset) << 3;
            ptr_val = (uint8_t *)&val + (real_offset & 3);

            /* do emulation based on register size */
            switch (reg->size) {
            case 1:
                if (reg->u.b.write) {
                    rc = reg->u.b.write(s, reg_entry, ptr_val,
                                        read_val >> ((real_offset & 3) << 3),
                                        valid_mask);
                }
                break;
            case 2:
                if (reg->u.w.write) {
                    rc = reg->u.w.write(s, reg_entry, (uint16_t *)ptr_val,
                                        (read_val >> ((real_offset & 3) << 3)),
                                        valid_mask);
                }
                break;
            case 4:
                if (reg->u.dw.write) {
                    rc = reg->u.dw.write(s, reg_entry, (uint32_t *)ptr_val,
                                         (read_val >> ((real_offset & 3) << 3)),
                                         valid_mask);
                }
                break;
            }
Beispiel #15
0
static void pci_ich9_write_config(PCIDevice *pci, uint32_t addr,
                                  uint32_t val, int len)
{
    pci_default_write_config(pci, addr, val, len);
    msi_write_config(pci, addr, val, len);
}