X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fpci.c;h=ab1442248a820916b1aa286702f6afcd5b0ecbcb;hb=d22c11cec4e8c3390bfe6bf16ed07f5d073f0d4a;hp=3eadbc5768210368f3b0a672f697fb359204d594;hpb=91a4db3c4b06db6a44aa0daeaab750df666d5d79;p=palacios.git diff --git a/palacios/src/devices/pci.c b/palacios/src/devices/pci.c index 3eadbc5..ab14422 100644 --- a/palacios/src/devices/pci.c +++ b/palacios/src/devices/pci.c @@ -170,19 +170,19 @@ static void pci_dump_state(struct pci_internal * pci_state) { struct rb_node * node = v3_rb_first(&(pci_state->bus_list[0].devices)); struct pci_device * tmp_dev = NULL; - PrintDebug("===PCI: Dumping state Begin ==========\n"); + PrintDebug(VM_NONE, VCORE_NONE, "===PCI: Dumping state Begin ==========\n"); do { tmp_dev = rb_entry(node, struct pci_device, dev_tree_node); - PrintDebug("PCI Device Number: %d (%s):\n", tmp_dev->dev_num, tmp_dev->name); - PrintDebug("irq = %d\n", tmp_dev->config_header.intr_line); - PrintDebug("Vend ID: 0x%x\n", tmp_dev->config_header.vendor_id); - PrintDebug("Device ID: 0x%x\n", tmp_dev->config_header.device_id); + PrintDebug(VM_NONE, VCORE_NONE, "PCI Device Number: %d (%s):\n", tmp_dev->dev_num, tmp_dev->name); + PrintDebug(VM_NONE, VCORE_NONE, "irq = %d\n", tmp_dev->config_header.intr_line); + PrintDebug(VM_NONE, VCORE_NONE, "Vend ID: 0x%x\n", tmp_dev->config_header.vendor_id); + PrintDebug(VM_NONE, VCORE_NONE, "Device ID: 0x%x\n", tmp_dev->config_header.device_id); } while ((node = v3_rb_next(node))); - PrintDebug("====PCI: Dumping state End==========\n"); + PrintDebug(VM_NONE, VCORE_NONE, "====PCI: Dumping state End==========\n"); } #endif @@ -195,11 +195,11 @@ static int get_free_dev_num(struct pci_bus * bus) { int i, j; for (i = 0; i < sizeof(bus->dev_map); i++) { - PrintDebug("i=%d\n", i); + PrintDebug(VM_NONE, VCORE_NONE, "i=%d\n", i); if (bus->dev_map[i] != 0xff) { // availability for (j = 0; j < 8; j++) { - PrintDebug("\tj=%d\n", j); + PrintDebug(VM_NONE, VCORE_NONE, "\tj=%d\n", j); if (!(bus->dev_map[i] & (0x1 << j))) { return ((i * 8) + j); } @@ -312,14 +312,14 @@ int v3_pci_hook_config_range(struct pci_device * pci, if (find_cfg_range_hook(pci, start, length)) { - PrintError("Tried to hook an already hooked config region\n"); + PrintError(VM_NONE, VCORE_NONE, "Tried to hook an already hooked config region\n"); return -1; } hook = V3_Malloc(sizeof(struct cfg_range_hook)); if (!hook) { - PrintError("Could not allocate range hook\n"); + PrintError(VM_NONE, VCORE_NONE, "Could not allocate range hook\n"); return -1; } @@ -427,7 +427,7 @@ int cap_write(struct pci_device * pci, uint32_t offset, void * src, uint_t lengt int msix_was_enabled = 0; - V3_Print("CAP write trapped (val=%x, cfg_offset=%d, write_offset=%d)\n", *(uint32_t *)src, offset, write_offset); + V3_Print(VM_NONE, VCORE_NONE, "CAP write trapped (val=%x, cfg_offset=%d, write_offset=%d)\n", *(uint32_t *)src, offset, write_offset); if (cap_type == PCI_CAP_MSI) { struct msi_msg_ctrl * msg_ctrl = cap_ptr; @@ -449,10 +449,10 @@ int cap_write(struct pci_device * pci, uint32_t offset, void * src, uint_t lengt if (cap_type == PCI_CAP_MSI) { struct msi_msg_ctrl * msg_ctrl = cap_ptr; - V3_Print("MSI Cap Ctrl=%x\n", *(uint16_t *)pci->msi_cap); - V3_Print("MSI ADDR=%x\n", *(uint32_t *)(cap_ptr + 2)); - V3_Print("MSI HI ADDR=%x\n", *(uint32_t *)(cap_ptr + 6)); - V3_Print("MSI Data=%x\n", *(uint16_t *)(cap_ptr + 10)); + V3_Print(VM_NONE, VCORE_NONE, "MSI Cap Ctrl=%x\n", *(uint16_t *)pci->msi_cap); + V3_Print(VM_NONE, VCORE_NONE, "MSI ADDR=%x\n", *(uint32_t *)(cap_ptr + 2)); + V3_Print(VM_NONE, VCORE_NONE, "MSI HI ADDR=%x\n", *(uint32_t *)(cap_ptr + 6)); + V3_Print(VM_NONE, VCORE_NONE, "MSI Data=%x\n", *(uint16_t *)(cap_ptr + 10)); if (msg_ctrl->cap_64bit) { if (msg_ctrl->per_vect_mask) { @@ -492,7 +492,7 @@ int cap_write(struct pci_device * pci, uint32_t offset, void * src, uint_t lengt if (cap_type == PCI_CAP_MSI) { struct msi_msg_ctrl * msg_ctrl = cap_ptr; - V3_Print("msi_was_enabled=%d, msi_is_enabled=%d\n", msi_was_enabled, msg_ctrl->msi_enable); + V3_Print(VM_NONE, VCORE_NONE, "msi_was_enabled=%d, msi_is_enabled=%d\n", msi_was_enabled, msg_ctrl->msi_enable); if ((msg_ctrl->msi_enable == 1) && (msi_was_enabled == 0)) { pci->irq_type = IRQ_MSI; @@ -577,19 +577,19 @@ static int init_pci_cap(struct pci_device * pci, pci_cap_type_t cap_type, uint_t static int scan_pci_caps(struct pci_device * pci) { uint_t cap_offset = pci->config_header.cap_ptr; - V3_Print("Scanning for Capabilities (cap_offset=%d)\n", cap_offset); + V3_Print(VM_NONE, VCORE_NONE, "Scanning for Capabilities (cap_offset=%d)\n", cap_offset); while (cap_offset != 0) { uint8_t id = pci->config_space[cap_offset]; uint8_t next = pci->config_space[cap_offset + 1]; - V3_Print("Found Capability 0x%x at offset %d (0x%x)\n", + V3_Print(VM_NONE, VCORE_NONE, "Found Capability 0x%x at offset %d (0x%x)\n", id, cap_offset, cap_offset); struct pci_cap * cap = V3_Malloc(sizeof(struct pci_cap)); if (!cap) { - PrintError("Error allocating PCI CAP info\n"); + PrintError(VM_NONE, VCORE_NONE, "Error allocating PCI CAP info\n"); return -1; } memset(cap, 0, sizeof(struct pci_cap)); @@ -613,7 +613,7 @@ static int scan_pci_caps(struct pci_device * pci) { // Hook Cap pointer to return cached config space value if (v3_pci_hook_config_range(pci, 0x34, 1, NULL, NULL, NULL) == -1) { - PrintError("Could not hook cap pointer\n"); + PrintError(VM_NONE, VCORE_NONE, "Could not hook cap pointer\n"); return -1; } @@ -651,7 +651,7 @@ int v3_pci_enable_capability(struct pci_device * pci, pci_cap_type_t cap_type) { } - V3_Print("Found Capability %x at %x (%d)\n", cap_type, cap->offset, cap->offset); + V3_Print(VM_NONE, VCORE_NONE, "Found Capability %x at %x (%d)\n", cap_type, cap->offset, cap->offset); // found the capability @@ -698,11 +698,11 @@ int v3_pci_enable_capability(struct pci_device * pci, pci_cap_type_t cap_type) { } - V3_Print("Hooking capability range (offset=%d, size=%d)\n", cap->offset, size); + V3_Print(VM_NONE, VCORE_NONE, "Hooking capability range (offset=%d, size=%d)\n", cap->offset, size); if (v3_pci_hook_config_range(pci, cap->offset, size + 2, cap_write, NULL, cap) == -1) { - PrintError("Could not hook config range (start=%d, size=%d)\n", + PrintError(VM_NONE, VCORE_NONE, "Could not hook config range (start=%d, size=%d)\n", cap->offset + 2, size); return -1; } @@ -724,10 +724,10 @@ static int addr_port_read(struct guest_info * core, ushort_t port, void * dst, u int reg_offset = port & 0x3; uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset; - PrintDebug("Reading PCI Address Port (%x): %x len=%d\n", port, pci_state->addr_reg.val, length); + PrintDebug(core->vm_info, core, "Reading PCI Address Port (%x): %x len=%d\n", port, pci_state->addr_reg.val, length); if (reg_offset + length > 4) { - PrintError("Invalid Address port write\n"); + PrintError(core->vm_info, core, "Invalid Address port write\n"); return -1; } @@ -743,14 +743,14 @@ static int addr_port_write(struct guest_info * core, ushort_t port, void * src, uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset; if (reg_offset + length > 4) { - PrintError("Invalid Address port write\n"); + PrintError(core->vm_info, core, "Invalid Address port write\n"); return -1; } // Set address register memcpy(reg_addr, src, length); - PrintDebug("Writing PCI Address Port(%x): AddrReg=%x (op_val = %x, len=%d) \n", port, pci_state->addr_reg.val, *(uint32_t *)src, length); + PrintDebug(core->vm_info, core, "Writing PCI Address Port(%x): AddrReg=%x (op_val = %x, len=%d) \n", port, pci_state->addr_reg.val, *(uint32_t *)src, length); return length; } @@ -770,13 +770,14 @@ 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); return length; } - PrintDebug("Reading PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (%x), cfg_reg = %x\n", + PrintDebug(core->vm_info, core, "Reading PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (%x), cfg_reg = %x\n", pci_state->addr_reg.bus_num, pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num, @@ -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("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--; @@ -812,7 +819,7 @@ static int data_port_read(struct guest_info * core, uint16_t port, void * dst, u memcpy(dst, &(pci_dev->config_space[reg_num]), length); - PrintDebug("\tVal=%x, len=%d\n", *(uint32_t *)dst, length); + PrintDebug(core->vm_info, core, "\tVal=%x, len=%d\n", *(uint32_t *)dst, length); return length; } @@ -826,15 +833,15 @@ 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("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); if (bar->type == PCI_BAR_PASSTHROUGH) { if (bar->bar_write(bar_num, (void *)(pci_dev->config_space + bar_offset), bar->private_data) == -1) { - PrintError("Error in Passthrough bar write operation\n"); + PrintError(VM_NONE, VCORE_NONE, "Error in Passthrough bar write operation\n"); return -1; } @@ -845,22 +852,27 @@ 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; - PrintDebug("\tRehooking %d IO ports from base 0x%x to 0x%x for %d ports\n", + 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("PCI Device IO space not enabled\n"); - } for (i = 0; i < bar->num_ports; i++) { - PrintDebug("Rehooking PCI IO port (old port=%u) (new port=%u)\n", + PrintDebug(VM_NONE, VCORE_NONE, "Rehooking PCI IO port (old port=%u) (new port=%u)\n", PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i); v3_unhook_io_port(pci_dev->vm, PCI_IO_BASE(bar->val) + i); @@ -869,9 +881,9 @@ static int bar_update(struct pci_device * pci_dev, uint32_t offset, bar->io_read, bar->io_write, bar->private_data) == -1) { - PrintError("Could not hook PCI IO port (old port=%u) (new port=%u)\n", + 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; } } @@ -888,7 +900,7 @@ static int bar_update(struct pci_device * pci_dev, uint32_t offset, PCI_MEM32_BASE(new_val) + (bar->num_pages * PAGE_SIZE_4KB), bar->mem_read, bar->mem_write, pci_dev->priv_data); } else { - PrintError("Write hooks not supported for PCI\n"); + PrintError(VM_NONE, VCORE_NONE, "Write hooks not supported for PCI\n"); return -1; } @@ -897,12 +909,12 @@ static int bar_update(struct pci_device * pci_dev, uint32_t offset, break; } case PCI_BAR_NONE: { - PrintDebug("Reprogramming an unsupported BAR register (Dev=%s) (bar=%d) (val=%x)\n", + PrintDebug(VM_NONE, VCORE_NONE, "Reprogramming an unsupported BAR register (Dev=%s) (bar=%d) (val=%x)\n", pci_dev->name, bar_num, new_val); break; } default: - PrintError("Invalid Bar Reg updated (bar=%d)\n", bar_num); + PrintError(VM_NONE, VCORE_NONE, "Invalid Bar Reg updated (bar=%d)\n", bar_num); return -1; } @@ -921,7 +933,7 @@ static int data_port_write(struct guest_info * core, uint16_t port, void * src, return length; } - PrintDebug("Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (0x%x) addr_reg = 0x%x (val=0x%x, len=%d)\n", + PrintDebug(VM_NONE, VCORE_NONE, "Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (0x%x) addr_reg = 0x%x (val=0x%x, len=%d)\n", pci_state->addr_reg.bus_num, pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num, @@ -933,7 +945,7 @@ static int data_port_write(struct guest_info * core, uint16_t port, void * src, 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) { - PrintError("Writing configuration space for non-present device (dev_num=%d)\n", + PrintError(VM_NONE, VCORE_NONE, "Writing configuration space for non-present device (dev_num=%d)\n", pci_state->addr_reg.dev_num); return -1; } @@ -950,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; @@ -987,13 +999,17 @@ 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); return 0; } - PrintError("Expansion ROM update not handled. Will appear to not Exist\n"); + PrintError(VM_NONE, VCORE_NONE, "Expansion ROM update not handled. Will appear to not Exist\n"); return 0; } @@ -1002,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++) { @@ -1018,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; @@ -1100,87 +1120,150 @@ static int pci_free(struct pci_internal * pci_state) { #include -static int pci_save(struct v3_chkpt_ctx * ctx, void * private_data) { +static int pci_save_extended(struct v3_chkpt *chkpt, char *id, void * private_data) { struct pci_internal * pci = (struct pci_internal *)private_data; + struct v3_chkpt_ctx *ctx=0; char buf[128]; int i = 0; - - v3_chkpt_save_32(ctx, "ADDR_REG", &(pci->addr_reg.val)); - v3_chkpt_save_16(ctx, "IO_BASE", &(pci->dev_io_base)); + + ctx = v3_chkpt_open_ctx(chkpt,id); + + if (!ctx) { + PrintError(VM_NONE, VCORE_NONE, "Unable to open base context on save\n"); + goto savefailout; + } + + V3_CHKPT_SAVE(ctx, "ADDR_REG", pci->addr_reg.val, savefailout); + V3_CHKPT_SAVE(ctx, "IO_BASE", pci->dev_io_base, savefailout); + + v3_chkpt_close_ctx(ctx); ctx=0; for (i = 0; i < PCI_BUS_COUNT; i++) { struct pci_bus * bus = &(pci->bus_list[i]); struct rb_node * node = v3_rb_first(&(bus->devices)); struct pci_device * dev = NULL; - struct v3_chkpt_ctx * bus_ctx = NULL; - snprintf(buf, 128, "pci-%d", i); + snprintf(buf, 128, "%s-%d", id, i); + + ctx = v3_chkpt_open_ctx(chkpt, buf); - bus_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf); + if (!ctx) { + PrintError(VM_NONE, VCORE_NONE, "Failed to open context for %s\n", buf); + goto savefailout; + } + + // nothing actually saved on the bus context... (later expansion) + + v3_chkpt_close_ctx(ctx); ctx=0; while (node) { - struct v3_chkpt_ctx * dev_ctx = NULL; int bar_idx = 0; dev = rb_entry(node, struct pci_device, dev_tree_node); - snprintf(buf, 128, "pci-%d.%d-%d", i, dev->dev_num, dev->fn_num); - dev_ctx = v3_chkpt_open_ctx(bus_ctx->chkpt, bus_ctx, buf); + snprintf(buf, 128, "%s-%d.%d-%d", id, i, dev->dev_num, dev->fn_num); + + ctx = v3_chkpt_open_ctx(chkpt, buf); + + if (!ctx) { + PrintError(VM_NONE, VCORE_NONE, "Failed to open context for device\n"); + goto savefailout; + } - v3_chkpt_save(dev_ctx, "CONFIG_SPACE", 256, dev->config_space); + V3_CHKPT_SAVE(ctx, "CONFIG_SPACE", dev->config_space, savefailout); for (bar_idx = 0; bar_idx < 6; bar_idx++) { snprintf(buf, 128, "BAR-%d", bar_idx); - v3_chkpt_save_32(dev_ctx, buf, &(dev->bar[bar_idx].val)); + V3_CHKPT_SAVE(ctx, buf, dev->bar[bar_idx].val, savefailout); } + + v3_chkpt_close_ctx(ctx); ctx=0; node = v3_rb_next(node); } } +// goodout: return 0; + + savefailout: + PrintError(VM_NONE, VCORE_NONE, "Failed to save PCI\n"); + if (ctx) { v3_chkpt_close_ctx(ctx); } + return -1; + } -static int pci_load(struct v3_chkpt_ctx * ctx, void * private_data) { +static int pci_load_extended(struct v3_chkpt *chkpt, char *id, void * private_data) { struct pci_internal * pci = (struct pci_internal *)private_data; + struct v3_chkpt_ctx *ctx=0; char buf[128]; int i = 0; - v3_chkpt_load_32(ctx, "ADDR_REG", &(pci->addr_reg.val)); - v3_chkpt_load_16(ctx, "IO_BASE", &(pci->dev_io_base)); + ctx = v3_chkpt_open_ctx(chkpt,id); + + if (!ctx) { + PrintError(VM_NONE, VCORE_NONE, "Unable to open base context on load\n"); + goto loadfailout; + } + + V3_CHKPT_LOAD(ctx, "ADDR_REG", pci->addr_reg.val, loadfailout); + V3_CHKPT_LOAD(ctx, "IO_BASE", pci->dev_io_base, loadfailout); + + v3_chkpt_close_ctx(ctx); ctx=0; for (i = 0; i < PCI_BUS_COUNT; i++) { struct pci_bus * bus = &(pci->bus_list[i]); struct rb_node * node = v3_rb_first(&(bus->devices)); struct pci_device * dev = NULL; - struct v3_chkpt_ctx * bus_ctx = NULL; snprintf(buf, 128, "pci-%d", i); - bus_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf); + ctx = v3_chkpt_open_ctx(chkpt, buf); + + if (!ctx) { + PrintError(VM_NONE, VCORE_NONE, "Failed to open context for %s\n", buf); + goto loadfailout; + } + + // nothing actually saved on the bus context... (later expansion) + + v3_chkpt_close_ctx(ctx); ctx=0; while (node) { - struct v3_chkpt_ctx * dev_ctx = NULL; int bar_idx = 0; dev = rb_entry(node, struct pci_device, dev_tree_node); snprintf(buf, 128, "pci-%d.%d-%d", i, dev->dev_num, dev->fn_num); - dev_ctx = v3_chkpt_open_ctx(bus_ctx->chkpt, bus_ctx, buf); + + ctx = v3_chkpt_open_ctx(chkpt, buf); - v3_chkpt_load(dev_ctx, "CONFIG_SPACE", 256, dev->config_space); + if (!ctx) { + PrintError(VM_NONE, VCORE_NONE, "Failed to open context for device\n"); + goto loadfailout; + } + + V3_CHKPT_LOAD(ctx, "CONFIG_SPACE", dev->config_space, loadfailout); for (bar_idx = 0; bar_idx < 6; bar_idx++) { snprintf(buf, 128, "BAR-%d", bar_idx); - v3_chkpt_load_32(dev_ctx, buf, &(dev->bar[bar_idx].val)); + V3_CHKPT_LOAD(ctx, buf, dev->bar[bar_idx].val, loadfailout); } + v3_chkpt_close_ctx(ctx); ctx=0; + node = v3_rb_next(node); } } - +// goodout: return 0; + + loadfailout: + PrintError(VM_NONE, VCORE_NONE, "Failed to load PCI\n"); + if (ctx) { v3_chkpt_close_ctx(ctx); } + return -1; + } @@ -1192,8 +1275,8 @@ static int pci_load(struct v3_chkpt_ctx * ctx, void * private_data) { static struct v3_device_ops dev_ops = { .free = (int (*)(void *))pci_free, #ifdef V3_CONFIG_CHECKPOINT - .save = pci_save, - .load = pci_load + .save_extended = pci_save_extended, + .load_extended = pci_load_extended #endif }; @@ -1202,16 +1285,22 @@ static struct v3_device_ops dev_ops = { static int pci_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal)); + + if (!pci_state) { + PrintError(vm, VCORE_NONE, "Cannot allocate in init\n"); + return -1; + } + int i = 0; char * dev_id = v3_cfg_val(cfg, "ID"); int ret = 0; - PrintDebug("PCI internal at %p\n",(void *)pci_state); + PrintDebug(vm, VCORE_NONE, "PCI internal at %p\n",(void *)pci_state); struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, pci_state); if (dev == NULL) { - PrintError("Could not attach device %s\n", dev_id); + PrintError(vm, VCORE_NONE, "Could not attach device %s\n", dev_id); V3_Free(pci_state); return -1; } @@ -1222,7 +1311,7 @@ static int pci_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { init_pci_busses(pci_state); - PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header)); + PrintDebug(vm, VCORE_NONE, "Sizeof config header=%d\n", (int)sizeof(struct pci_config_header)); for (i = 0; i < 4; i++) { ret |= v3_dev_hook_io(dev, CONFIG_ADDR_PORT + i, &addr_port_read, &addr_port_write); @@ -1230,7 +1319,7 @@ static int pci_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { } if (ret != 0) { - PrintError("Error hooking PCI IO ports\n"); + PrintError(vm, VCORE_NONE, "Error hooking PCI IO ports\n"); v3_remove_device(dev); return -1; } @@ -1267,7 +1356,7 @@ static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev) if (v3_hook_io_port(vm, bar->default_base_port + j, bar->io_read, bar->io_write, bar->private_data) == -1) { - PrintError("Could not hook default io port %x\n", bar->default_base_port + j); + PrintError(vm, VCORE_NONE, "Could not hook default io port %x\n", bar->default_base_port + j); return -1; } } @@ -1279,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 { @@ -1293,7 +1383,7 @@ static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev) bar->mem_read, bar->mem_write, pci_dev->priv_data); } else if (bar->mem_write) { // write hook - PrintError("Write hooks not supported for PCI devices\n"); + PrintError(vm, VCORE_NONE, "Write hooks not supported for PCI devices\n"); return -1; /* v3_hook_write_mem(pci_dev->vm_dev->vm, bar->default_base_addr, @@ -1309,7 +1399,7 @@ static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev) *(uint32_t *)(pci_dev->config_space + bar_offset) = bar->val; } else if (bar->type == PCI_BAR_MEM24) { - PrintError("16 Bit memory ranges not supported (reg: %d)\n", i); + PrintError(vm, VCORE_NONE, "16 Bit memory ranges not supported (reg: %d)\n", i); return -1; } else if (bar->type == PCI_BAR_NONE) { bar->val = 0x00000000; @@ -1320,8 +1410,11 @@ static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev) // Call the bar init function to get the local cached value bar->bar_init(i, &(bar->val), bar->private_data); + // Copy back changes it made + *(uint32_t *)(pci_dev->config_space + bar_offset) = bar->val; + } else { - PrintError("Invalid BAR type for bar #%d\n", i); + PrintError(vm, VCORE_NONE, "Invalid BAR type for bar #%d\n", i); return -1; } @@ -1418,7 +1511,7 @@ int v3_pci_raise_acked_irq(struct vm_device * pci_bus, struct pci_device * dev, struct msi_data * data = NULL; if (dev->bar[bar_idx].type != PCI_BAR_MEM32) { - PrintError("Non 32bit MSIX BAR registers are not supported\n"); + PrintError(VM_NONE, VCORE_NONE, "Non 32bit MSIX BAR registers are not supported\n"); return -1; } @@ -1426,7 +1519,7 @@ int v3_pci_raise_acked_irq(struct vm_device * pci_bus, struct pci_device * dev, msix_table_gpa += dev->msix_cap->table_offset; if (v3_gpa_to_hva(&(dev->vm->cores[0]), msix_table_gpa, (void *)&(msix_table)) != 0) { - PrintError("Could not translate MSIX Table GPA (%p)\n", (void *)msix_table_gpa); + PrintError(VM_NONE, VCORE_NONE, "Could not translate MSIX Table GPA (%p)\n", (void *)msix_table_gpa); return -1; } @@ -1445,7 +1538,7 @@ int v3_pci_raise_acked_irq(struct vm_device * pci_bus, struct pci_device * dev, - V3_Print("Decode MSIX\n"); + V3_Print(VM_NONE, VCORE_NONE, "Decode MSIX\n"); v3_apic_send_ipi(dev->vm, &ipi, dev->apic_dev); @@ -1491,22 +1584,23 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, int i; if (dev_num > MAX_BUS_DEVICES) { - PrintError("Requested Invalid device number (%d)\n", dev_num); + PrintError(VM_NONE, VCORE_NONE, "Requested Invalid device number (%d)\n", dev_num); return NULL; } if (dev_num == PCI_AUTO_DEV_NUM) { - PrintDebug("Searching for free device number\n"); + PrintDebug(VM_NONE, VCORE_NONE, "Searching for free device number\n"); if ((dev_num = get_free_dev_num(bus)) == -1) { - PrintError("No more available PCI slots on bus %d\n", bus->bus_num); + 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("Checking for PCI Device\n"); + PrintDebug(VM_NONE, VCORE_NONE, "Checking for PCI Device\n"); if (get_device(bus, dev_num, fn_num) != NULL) { - PrintError("PCI Device already registered at slot %d on bus %d\n", + PrintError(VM_NONE, VCORE_NONE, "PCI Device already registered at slot %d on bus %d\n", dev_num, bus->bus_num); return NULL; } @@ -1515,7 +1609,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device)); if (pci_dev == NULL) { - PrintError("Could not allocate pci device\n"); + PrintError(VM_NONE, VCORE_NONE, "Could not allocate pci device\n"); return NULL; } @@ -1532,7 +1626,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, pci_dev->config_header.header_type = 0x80; break; default: - PrintError("Unhandled PCI Device Type: %d\n", dev_type); + PrintError(VM_NONE, VCORE_NONE, "Unhandled PCI Device Type: %d\n", dev_type); return NULL; } @@ -1543,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; @@ -1572,14 +1667,14 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, } } - V3_Print("Scanning for Capabilities\n"); + V3_Print(VM_NONE, VCORE_NONE, "Scanning for Capabilities\n"); // scan for caps scan_pci_caps(pci_dev); pci_dev->irq_type = IRQ_INTX; - V3_Print("Caps scanned\n"); + V3_Print(VM_NONE, VCORE_NONE, "Caps scanned\n"); // hook important regions v3_pci_hook_config_range(pci_dev, 0x30, 4, exp_rom_write, NULL, NULL); // ExpRom @@ -1626,7 +1721,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, } if (init_bars(pci->vm, pci_dev) == -1) { - PrintError("could not initialize bar registers\n"); + PrintError(VM_NONE, VCORE_NONE, "could not initialize bar registers\n"); return NULL; }