X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fpci.c;h=ab1442248a820916b1aa286702f6afcd5b0ecbcb;hb=d22c11cec4e8c3390bfe6bf16ed07f5d073f0d4a;hp=f9c7d1aee87041d5d1f3f84f4175c72f277b9abc;hpb=95a09f3e974f23d8e3d20b3a333f5c07631be17d;p=palacios.git diff --git a/palacios/src/devices/pci.c b/palacios/src/devices/pci.c index f9c7d1a..ab14422 100644 --- a/palacios/src/devices/pci.c +++ b/palacios/src/devices/pci.c @@ -770,6 +770,7 @@ static int data_port_read(struct guest_info * core, uint16_t port, void * dst, u pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num); + if (pci_dev == NULL) { memset(dst, 0xff, length); @@ -794,15 +795,21 @@ static int data_port_read(struct guest_info * core, uint16_t port, void * dst, u if (cfg_hook->read) { cfg_hook->read(pci_dev, reg_num + i, cfg_dst, range_len, cfg_hook->private_data); - } + } else { + if (pci_dev->config_read) { + if (pci_dev->config_read(pci_dev, reg_num + i, cfg_dst, range_len, pci_dev->priv_data) != 0) { + PrintError(core->vm_info, core, "Error in config_read from PCI device (%s)\n", pci_dev->name); + } + } + } bytes_left -= range_len; i += range_len; } else { if (pci_dev->config_read) { - if (pci_dev->config_read(pci_dev, reg_num + i, cfg_dst, 1, pci_dev->priv_data) != 0) { - PrintError(core->vm_info, core, "Error in config_read from PCI device (%s)\n", pci_dev->name); - } + if (pci_dev->config_read(pci_dev, reg_num + i, cfg_dst, 1, pci_dev->priv_data) != 0) { + PrintError(core->vm_info, core, "Error in config_read from PCI device (%s)\n", pci_dev->name); + } } bytes_left--; @@ -826,8 +833,8 @@ static int bar_update(struct pci_device * pci_dev, uint32_t offset, int bar_num = (bar_offset - 0x10) / 4; uint32_t new_val = *(uint32_t *)src; - PrintDebug(VM_NONE, VCORE_NONE, "Updating BAR Register (Dev=%s) (bar=%d) (old_val=0x%x) (new_val=0x%x)\n", - pci_dev->name, bar_num, bar->val, new_val); + PrintDebug(VM_NONE, VCORE_NONE, "Updating BAR Register (Dev=%s) (bar=%d) (old_val=0x%x) (new_val=0x%x) (length=%d)\n", + pci_dev->name, bar_num, bar->val, new_val, length); // Cache the changes locally memcpy(&(pci_dev->config_space[offset]), src, length); @@ -845,6 +852,16 @@ static int bar_update(struct pci_device * pci_dev, uint32_t offset, *(uint32_t *)(pci_dev->config_space + offset) &= bar->mask; + // Handle buggy code that discards the freaking I/O bit... + if (bar->type == PCI_BAR_IO && !(new_val & 0x1) ) { + PrintError(VM_NONE,VCORE_NONE,"Buggy guest: Updating BAR %d of device %s discards the I/O bit...\n", bar_num, pci_dev->name); + *(uint32_t *)(pci_dev->config_space + offset) |= 0x1; + new_val |= 0x1; + } + + + // V3_Print(VM_NONE, VCORE_NONE,"mask=%x written val=%x\n", bar->mask, *(uint32_t *)(pci_dev->config_space + offset)); + switch (bar->type) { case PCI_BAR_IO: { int i = 0; @@ -852,12 +869,6 @@ static int bar_update(struct pci_device * pci_dev, uint32_t offset, PrintDebug(VM_NONE, VCORE_NONE, "\tRehooking %d IO ports from base 0x%x to 0x%x for %d ports\n", bar->num_ports, PCI_IO_BASE(bar->val), PCI_IO_BASE(new_val), bar->num_ports); - - // only do this if pci device is enabled.... - if (!(pci_dev->config_header.status & 0x1)) { - PrintError(VM_NONE, VCORE_NONE, "PCI Device IO space not enabled\n"); - break; - } for (i = 0; i < bar->num_ports; i++) { @@ -872,7 +883,7 @@ static int bar_update(struct pci_device * pci_dev, uint32_t offset, PrintError(VM_NONE, VCORE_NONE, "Could not hook PCI IO port (old port=%u) (new port=%u)\n", PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i); - v3_print_io_map(pci_dev->vm); + //v3_print_io_map(pci_dev->vm); return -1; } } @@ -951,7 +962,7 @@ static int data_port_write(struct guest_info * core, uint16_t port, void * src, if (cfg_hook->write) { cfg_hook->write(pci_dev, reg_num + i, (void *)(src + i), range_len, cfg_hook->private_data); - } + } length -= range_len; i += range_len; @@ -988,6 +999,10 @@ static int exp_rom_write(struct pci_device * pci_dev, uint32_t offset, void * src, uint_t length, void * private_data) { int bar_offset = offset & ~0x03; + if (pci_dev->config_write) { + pci_dev->config_write(pci_dev, offset, src, length, pci_dev->priv_data); + } + if (pci_dev->exp_rom_update) { pci_dev->exp_rom_update(pci_dev, (void *)(pci_dev->config_space + bar_offset), pci_dev->priv_data); @@ -1003,10 +1018,15 @@ static int exp_rom_write(struct pci_device * pci_dev, uint32_t offset, static int cmd_write(struct pci_device * pci_dev, uint32_t offset, void * src, uint_t length, void * private_data) { + PrintDebug(VM_NONE, VCORE_NONE, "PCI command update!\n"); + int i = 0; struct pci_cmd_reg old_cmd; struct pci_cmd_reg new_cmd; + if (pci_dev->config_write) { + pci_dev->config_write(pci_dev, offset, src, length, pci_dev->priv_data); + } old_cmd.val = pci_dev->config_header.command; for (i = 0; i < length; i++) { @@ -1019,22 +1039,21 @@ static int cmd_write(struct pci_device * pci_dev, uint32_t offset, new_cmd.val = pci_dev->config_header.command; - if (pci_dev->cmd_update) { - if ((new_cmd.intx_disable == 1) && (old_cmd.intx_disable == 0)) { - pci_dev->irq_type = IRQ_NONE; - pci_dev->cmd_update(pci_dev, PCI_CMD_INTX_DISABLE, 0, pci_dev->priv_data); - } else if ((new_cmd.intx_disable == 0) && (old_cmd.intx_disable == 1)) { - pci_dev->irq_type = IRQ_INTX; - pci_dev->cmd_update(pci_dev, PCI_CMD_INTX_ENABLE, 0, pci_dev->priv_data); - } - - - if ((new_cmd.dma_enable == 1) && (old_cmd.dma_enable == 0)) { - pci_dev->cmd_update(pci_dev, PCI_CMD_DMA_ENABLE, 0, pci_dev->priv_data); - } else if ((new_cmd.dma_enable == 0) && (old_cmd.dma_enable == 1)) { - pci_dev->cmd_update(pci_dev, PCI_CMD_DMA_DISABLE, 0, pci_dev->priv_data); - } + if ((new_cmd.intx_disable == 1) && (old_cmd.intx_disable == 0)) { + pci_dev->irq_type = IRQ_NONE; + pci_dev->cmd_update(pci_dev, PCI_CMD_INTX_DISABLE, 0, pci_dev->priv_data); + } else if ((new_cmd.intx_disable == 0) && (old_cmd.intx_disable == 1)) { + pci_dev->irq_type = IRQ_INTX; + pci_dev->cmd_update(pci_dev, PCI_CMD_INTX_ENABLE, 0, pci_dev->priv_data); + } + + + if ((new_cmd.dma_enable == 1) && (old_cmd.dma_enable == 0)) { + pci_dev->cmd_update(pci_dev, PCI_CMD_DMA_ENABLE, 0, pci_dev->priv_data); + } else if ((new_cmd.dma_enable == 0) && (old_cmd.dma_enable == 1)) { + pci_dev->cmd_update(pci_dev, PCI_CMD_DMA_DISABLE, 0, pci_dev->priv_data); + } } return 0; @@ -1349,6 +1368,7 @@ static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev) bar->mask = ~((bar->num_pages << 12) - 1); bar->mask |= 0xf; // preserve the configuration flags + if (bar->default_base_addr != 0xffffffff) { bar->val = bar->default_base_addr & bar->mask; } else { @@ -1574,6 +1594,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, PrintError(VM_NONE, VCORE_NONE, "No more available PCI slots on bus %d\n", bus->bus_num); return NULL; } + V3_Print(VM_NONE, VCORE_NONE,"assigning dev num %d to device (%s, busnum=%d,fnnum=%d)\n", dev_num, name, bus->bus_num, fn_num); } PrintDebug(VM_NONE, VCORE_NONE, "Checking for PCI Device\n"); @@ -1616,6 +1637,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, pci_dev->fn_num = fn_num; strncpy(pci_dev->name, name, sizeof(pci_dev->name)); + pci_dev->name[sizeof(pci_dev->name)-1] = 0; pci_dev->vm = pci->vm; pci_dev->priv_data = priv_data;