X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fpci_passthrough.c;h=5792535032029597e8368207ec2bf91ff6d87ab4;hb=d22c11cec4e8c3390bfe6bf16ed07f5d073f0d4a;hp=89b4e8487c48a6e158833df3e83aab28d95e5b8f;hpb=3cab540e9e47ce3562dae4c03b20d84b24d8f1f7;p=palacios.git diff --git a/palacios/src/devices/pci_passthrough.c b/palacios/src/devices/pci_passthrough.c index 89b4e84..5792535 100644 --- a/palacios/src/devices/pci_passthrough.c +++ b/palacios/src/devices/pci_passthrough.c @@ -36,12 +36,11 @@ #include #include #include // must include this to avoid dependency issue -#include +#include #include #include - // Hardcoded... Are these standard?? #define PCI_CFG_ADDR 0xcf8 #define PCI_CFG_DATA 0xcfc @@ -75,17 +74,26 @@ typedef enum { PT_BAR_NONE, PT_BAR_IO, PT_BAR_MEM32, PT_BAR_MEM24, - PT_BAR_MEM64_LOW, - PT_BAR_MEM64_HIGH } pt_bar_type_t; + PT_BAR_MEM64_LO, + PT_BAR_MEM64_HI, + PT_EXP_ROM } pt_bar_type_t; struct pt_bar { uint32_t size; pt_bar_type_t type; - uint32_t addr; + + /* We store 64 bit memory bar addresses in the high BAR + * because they are the last to be updated + * This means that the addr field must be 64 bits + */ + uint64_t addr; uint32_t val; }; + + + struct pt_dev_state { union { uint8_t config_space[256]; @@ -95,7 +103,9 @@ struct pt_dev_state { struct pt_bar phys_bars[6]; struct pt_bar virt_bars[6]; - + struct pt_bar phys_exp_rom; + struct pt_bar virt_exp_rom; + struct vm_device * pci_bus; struct pci_device * pci_dev; @@ -146,8 +156,77 @@ static inline void pci_cfg_write8(uint32_t addr, uint8_t val) { } + +static int pci_exp_rom_init(struct vm_device * dev, struct pt_dev_state * state) { + struct pci_device * pci_dev = state->pci_dev; + const uint32_t exp_rom_base_reg = 12; + union pci_addr_reg pci_addr = {state->phys_pci_addr.value}; + uint32_t max_val = 0; + uint32_t rom_val = 0; + struct pt_bar * prom = &(state->phys_exp_rom); + struct pt_bar * vrom = &(state->virt_exp_rom); + + // should read from cached header + pci_addr.reg = exp_rom_base_reg; + + rom_val = pci_cfg_read32(pci_addr.value); + + prom->val = rom_val; + prom->type = PT_EXP_ROM; + + max_val = rom_val | PCI_EXP_ROM_MASK; + + // Cycle the physical bar, to determine the actual size + // Disable irqs, to try to prevent accesses to the space via a interrupt handler + // This is not SMP safe!! + // What we probably want to do is write a 0 to the command register + //irq_state = v3_irq_save(); + + pci_cfg_write32(pci_addr.value, max_val); + max_val = pci_cfg_read32(pci_addr.value); + pci_cfg_write32(pci_addr.value, rom_val); + + //v3_irq_restore(irq_state); + + prom->type = PT_EXP_ROM; + prom->addr = PCI_EXP_ROM_BASE(rom_val); + prom->size = ~PCI_EXP_ROM_BASE(max_val) + 1; + + PrintDebug(VM_NONE, VCORE_NONE, "Adding 32 bit PCI mem region: start=%p, end=%p\n", + (void *)(addr_t)prom->addr, + (void *)(addr_t)(prom->addr + prom->size)); + + if ((prom->val & 0x1) == 0x1) { + // only map shadow memory if the ROM is enabled + + v3_add_shadow_mem(dev->vm, V3_MEM_CORE_ANY, + prom->addr, + prom->addr + prom->size - 1, + prom->addr); + } + + // Initially the virtual location matches the physical ones + memcpy(&(state->virt_exp_rom), &(state->phys_exp_rom), sizeof(struct pt_bar)); + + PrintDebug(VM_NONE, VCORE_NONE, "exp_rom_val=0x%x\n", rom_val); + + PrintDebug(VM_NONE, VCORE_NONE, "phys exp_rom: addr=%p, size=%u\n", + (void *)(addr_t)prom->addr, + prom->size); + + PrintDebug(VM_NONE, VCORE_NONE, "virt exp_rom: addr=%p, size=%u\n", + (void *)(addr_t)vrom->addr, + vrom->size); + + // Update the pci subsystem versions + pci_dev->config_header.expansion_rom_address = rom_val; + + return 0; +} + + // We initialize this -static int pci_bar_init(int bar_num, uint32_t * dst,void * private_data) { +static int pci_bar_init(int bar_num, uint32_t * dst, void * private_data) { struct vm_device * dev = (struct vm_device *)private_data; struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data; const uint32_t bar_base_reg = 4; @@ -157,16 +236,48 @@ static int pci_bar_init(int bar_num, uint32_t * dst,void * private_data) { //addr_t irq_state = 0; struct pt_bar * pbar = &(state->phys_bars[bar_num]); - // should read from cached header pci_addr.reg = bar_base_reg + bar_num; - PrintDebug("PCI Address = 0x%x\n", pci_addr.value); + PrintDebug(VM_NONE, VCORE_NONE, "PCI Address = 0x%x\n", pci_addr.value); bar_val = pci_cfg_read32(pci_addr.value); - pbar->val = bar_val; + pbar->val = bar_val; + + // We preset this type when we encounter a MEM64 Low BAR + if (pbar->type == PT_BAR_MEM64_HI) { + struct pt_bar * lo_pbar = &(state->phys_bars[bar_num - 1]); + + max_val = PCI_MEM64_MASK_HI; + + pci_cfg_write32(pci_addr.value, max_val); + max_val = pci_cfg_read32(pci_addr.value); + pci_cfg_write32(pci_addr.value, bar_val); + + pbar->addr = PCI_MEM64_BASE_HI(bar_val); + pbar->addr <<= 32; + pbar->addr |= lo_pbar->addr; + + // Executive Decision: We will not support devices with memory mapped regions over 4GB + // The right way to do this would be to change 'size' to the order (power of 2) of the region + pbar->size += lo_pbar->size; + + PrintDebug(VM_NONE, VCORE_NONE, "Adding 64 bit PCI mem region: start=0x%p, end=0x%p\n", + (void *)(addr_t)pbar->addr, + (void *)(addr_t)(pbar->addr + pbar->size)); + + + if (v3_add_shadow_mem(dev->vm, V3_MEM_CORE_ANY, pbar->addr, + pbar->addr + pbar->size - 1, pbar->addr) == -1) { + + PrintError(VM_NONE, VCORE_NONE, "Fail to insert shadow region (0x%p, 0x%p) -> 0x%p\n", + (void *)(addr_t)pbar->addr, + (void *)(addr_t)(pbar->addr + pbar->size - 1), + (void *)(addr_t)pbar->addr); + return -1; + } - if ((bar_val & 0x3) == 0x1) { + } else if ((bar_val & 0x3) == 0x1) { int i = 0; // IO bar @@ -187,9 +298,13 @@ static int pci_bar_init(int bar_num, uint32_t * dst,void * private_data) { //v3_irq_restore(irq_state); - pbar->size = ~PCI_IO_BASE(max_val) + 1; + V3_Print(VM_NONE, VCORE_NONE, "max_val = %x\n", max_val); + + pbar->size = (uint16_t)~PCI_IO_BASE(max_val) + 1; + V3_Print(VM_NONE, VCORE_NONE, "IO Bar with %d (%x) ports %x->%x\n", pbar->size, pbar->size, + (uint32_t)pbar->addr, (uint32_t)pbar->addr + pbar->size); // setup a set of null io hooks // This allows the guest to do passthrough IO to these ports // While still reserving them in the IO map @@ -228,10 +343,11 @@ static int pci_bar_init(int bar_num, uint32_t * dst,void * private_data) { pbar->addr = PCI_MEM32_BASE(bar_val); pbar->size = ~PCI_MEM32_BASE(max_val) + 1; - PrintDebug("Adding 32 bit PCI mem region: start=0x%x, end=0x%x\n", - pbar->addr, pbar->addr + pbar->size); + PrintDebug(VM_NONE, VCORE_NONE, "Adding 32 bit PCI mem region: start=%p, end=%p\n", + (void *)(addr_t)pbar->addr, + (void *)(addr_t)(pbar->addr + pbar->size)); - v3_add_shadow_mem(dev->vm, + v3_add_shadow_mem(dev->vm, V3_MEM_CORE_ANY, pbar->addr, pbar->addr + pbar->size - 1, pbar->addr); @@ -242,48 +358,50 @@ static int pci_bar_init(int bar_num, uint32_t * dst,void * private_data) { pbar->addr = PCI_MEM24_BASE(bar_val); pbar->size = ~PCI_MEM24_BASE(max_val) + 1; - v3_add_shadow_mem(dev->vm, + v3_add_shadow_mem(dev->vm, V3_MEM_CORE_ANY, pbar->addr, pbar->addr + pbar->size - 1, pbar->addr); } else if ((bar_val & 0x6) == 0x4) { - // Mem 64 - PrintError("64 Bit PCI bars not supported\n"); - return -1; + struct pt_bar * hi_pbar = &(state->phys_bars[bar_num + 1]); + + pbar->type = PT_BAR_MEM64_LO; + hi_pbar->type = PT_BAR_MEM64_HI; + + // Set the low bits, only for temporary storage until we calculate the high BAR + pbar->addr = PCI_MEM64_BASE_LO(bar_val); + pbar->size = ~PCI_MEM64_BASE_LO(max_val) + 1; + } else { - PrintError("Invalid Memory bar type\n"); + PrintError(VM_NONE, VCORE_NONE, "Invalid Memory bar type\n"); return -1; } } } - - // Initially the virtual bars match the physical ones memcpy(&(state->virt_bars[bar_num]), &(state->phys_bars[bar_num]), sizeof(struct pt_bar)); - PrintDebug("bar_num=%d, bar_val=0x%x\n", bar_num, bar_val); + PrintDebug(VM_NONE, VCORE_NONE, "bar_num=%d, bar_val=0x%x\n", bar_num, bar_val); - PrintDebug("phys bar type=%d, addr=0x%x, size=%d\n", - pbar->type, pbar->addr, + PrintDebug(VM_NONE, VCORE_NONE, "phys bar type=%d, addr=%p, size=%d\n", + pbar->type, (void *)(addr_t)pbar->addr, pbar->size); - PrintDebug("virt bar type=%d, addr=0x%x, size=%d\n", - state->virt_bars[bar_num].type, state->virt_bars[bar_num].addr, + PrintDebug(VM_NONE, VCORE_NONE, "virt bar type=%d, addr=%p, size=%d\n", + state->virt_bars[bar_num].type, (void *)(addr_t)state->virt_bars[bar_num].addr, state->virt_bars[bar_num].size); - - // Update the pci subsystem versions *dst = bar_val; return 0; } -static int pt_io_read(uint16_t port, void * dst, uint_t length, void * priv_data) { +static int pt_io_read(struct guest_info * core, uint16_t port, void * dst, uint_t length, void * priv_data) { struct pt_bar * pbar = (struct pt_bar *)priv_data; int port_offset = port % pbar->size; @@ -294,7 +412,7 @@ static int pt_io_read(uint16_t port, void * dst, uint_t length, void * priv_data } else if (length == 4) { *(uint32_t *)dst = v3_indw(pbar->addr + port_offset); } else { - PrintError("Invalid PCI passthrough IO Redirection size read\n"); + PrintError(core->vm_info, core, "Invalid PCI passthrough IO Redirection size read\n"); return -1; } @@ -302,7 +420,7 @@ static int pt_io_read(uint16_t port, void * dst, uint_t length, void * priv_data } -static int pt_io_write(uint16_t port, void * src, uint_t length, void * priv_data) { +static int pt_io_write(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data) { struct pt_bar * pbar = (struct pt_bar *)priv_data; int port_offset = port % pbar->size; @@ -313,7 +431,7 @@ static int pt_io_write(uint16_t port, void * src, uint_t length, void * priv_dat } else if (length == 4) { v3_outdw(pbar->addr + port_offset, *(uint32_t *)src); } else { - PrintError("Invalid PCI passthrough IO Redirection size write\n"); + PrintError(core->vm_info, core, "Invalid PCI passthrough IO Redirection size write\n"); return -1; } @@ -332,7 +450,13 @@ static int pci_bar_write(int bar_num, uint32_t * src, void * private_data) { struct pt_bar * pbar = &(state->phys_bars[bar_num]); struct pt_bar * vbar = &(state->virt_bars[bar_num]); - PrintDebug("Bar update src=0x%x\n", *src); + PrintDebug(VM_NONE, VCORE_NONE, "Bar update: bar_num=%d, src=0x%x\n", bar_num, *src); + PrintDebug(VM_NONE, VCORE_NONE, "vbar is size=%u, type=%d, addr=%p, val=0x%x\n", + vbar->size, vbar->type, (void *)(addr_t)vbar->addr, vbar->val); + PrintDebug(VM_NONE, VCORE_NONE, "pbar is size=%u, type=%d, addr=%p, val=0x%x\n", + pbar->size, pbar->type, (void *)(addr_t)pbar->addr, pbar->val); + + if (vbar->type == PT_BAR_NONE) { return 0; @@ -342,13 +466,13 @@ static int pci_bar_write(int bar_num, uint32_t * src, void * private_data) { // unhook old ports for (i = 0; i < vbar->size; i++) { if (v3_unhook_io_port(dev->vm, vbar->addr + i) == -1) { - PrintError("Could not unhook previously hooked port.... %d (0x%x)\n", - vbar->addr + i, vbar->addr + i); + PrintError(VM_NONE, VCORE_NONE, "Could not unhook previously hooked port.... %d (0x%x)\n", + (uint32_t)vbar->addr + i, (uint32_t)vbar->addr + i); return -1; } } - PrintDebug("Setting IO Port range size=%d\n", pbar->size); + PrintDebug(VM_NONE, VCORE_NONE, "Setting IO Port range size=%d\n", pbar->size); // clear the low bits to match the size *src &= ~(pbar->size - 1); @@ -358,10 +482,10 @@ static int pci_bar_write(int bar_num, uint32_t * src, void * private_data) { vbar->addr = PCI_IO_BASE(*src); - PrintDebug("Cooked src=0x%x\n", *src); + PrintDebug(VM_NONE, VCORE_NONE, "Cooked src=0x%x\n", *src); - PrintDebug("Rehooking passthrough IO ports starting at %d (0x%x)\n", - vbar->addr, vbar->addr); + PrintDebug(VM_NONE, VCORE_NONE, "Rehooking passthrough IO ports starting at %d (0x%x)\n", + (uint32_t)vbar->addr, (uint32_t)vbar->addr); if (vbar->addr == pbar->addr) { // Map the io ports as passthrough @@ -376,15 +500,15 @@ static int pci_bar_write(int bar_num, uint32_t * src, void * private_data) { } } else if (vbar->type == PT_BAR_MEM32) { // remove old mapping - struct v3_shadow_region * old_reg = v3_get_shadow_region(dev->vm, vbar->addr); + struct v3_mem_region * old_reg = v3_get_mem_region(dev->vm, V3_MEM_CORE_ANY, vbar->addr); if (old_reg == NULL) { // uh oh... - PrintError("Could not find PCI Passthrough memory redirection region (addr=0x%x)\n", vbar->addr); + PrintError(VM_NONE, VCORE_NONE, "Could not find PCI Passthrough memory redirection region (addr=0x%x)\n", (uint32_t)vbar->addr); return -1; } - v3_delete_shadow_region(dev->vm, old_reg); + v3_delete_mem_region(dev->vm, old_reg); // clear the low bits to match the size *src &= ~(pbar->size - 1); @@ -392,37 +516,84 @@ static int pci_bar_write(int bar_num, uint32_t * src, void * private_data) { // Set reserved bits *src |= (pbar->val & ~PCI_MEM_MASK); - PrintDebug("Cooked src=0x%x\n", *src); + PrintDebug(VM_NONE, VCORE_NONE, "Cooked src=0x%x\n", *src); vbar->addr = PCI_MEM32_BASE(*src); - PrintDebug("Adding pci Passthrough remapping: start=0x%x, size=%d, end=0x%x\n", - vbar->addr, vbar->size, vbar->addr + vbar->size); + PrintDebug(VM_NONE, VCORE_NONE, "Adding pci Passthrough remapping: start=0x%x, size=%d, end=0x%x\n", + (uint32_t)vbar->addr, vbar->size, (uint32_t)vbar->addr + vbar->size); - v3_add_shadow_mem(dev->vm, + v3_add_shadow_mem(dev->vm, V3_MEM_CORE_ANY, vbar->addr, vbar->addr + vbar->size - 1, pbar->addr); + + } else if (vbar->type == PT_BAR_MEM64_LO) { + // We only store the written values here, the actual reconfig comes when the high BAR is updated + + // clear the low bits to match the size + *src &= ~(pbar->size - 1); + + // Set reserved bits + *src |= (pbar->val & ~PCI_MEM_MASK); + + // Temp storage, used when hi bar is written + vbar->addr = PCI_MEM64_BASE_LO(*src); + + } else if (vbar->type == PT_BAR_MEM64_HI) { + struct pt_bar * lo_vbar = &(state->virt_bars[bar_num - 1]); + struct v3_mem_region * old_reg = v3_get_mem_region(dev->vm, V3_MEM_CORE_ANY, vbar->addr); + + if (old_reg == NULL) { + // uh oh... + PrintError(VM_NONE, VCORE_NONE, "Could not find PCI Passthrough memory redirection region (addr=%p)\n", + (void *)(addr_t)vbar->addr); + return -1; + } + + // remove old mapping + v3_delete_mem_region(dev->vm, old_reg); + + // We don't set size, because we assume region is less than 4GB + + // Set reserved bits + *src |= (pbar->val & ~PCI_MEM64_MASK_HI); + + vbar->addr = PCI_MEM64_BASE_HI(*src); + vbar->addr <<= 32; + vbar->addr += lo_vbar->addr; + + PrintDebug(VM_NONE, VCORE_NONE, "Adding pci Passthrough remapping: start=%p, size=%p, end=%p\n", + (void *)(addr_t)vbar->addr, (void *)(addr_t)vbar->size, + (void *)(addr_t)(vbar->addr + vbar->size)); + + if (v3_add_shadow_mem(dev->vm, V3_MEM_CORE_ANY, vbar->addr, + vbar->addr + vbar->size - 1, pbar->addr) == -1) { + + PrintDebug(VM_NONE, VCORE_NONE, "Fail to insert shadow region (%p, %p) -> %p\n", + (void *)(addr_t)vbar->addr, + (void *)(addr_t)(vbar->addr + vbar->size - 1), + (void *)(addr_t)pbar->addr); + return -1; + } } else { - PrintError("Unhandled Pasthrough PCI Bar type %d\n", vbar->type); + PrintError(VM_NONE, VCORE_NONE, "Unhandled Pasthrough PCI Bar type %d\n", vbar->type); return -1; } - vbar->val = *src; - return 0; } -static int pt_config_update(uint_t reg_num, void * src, uint_t length, void * private_data) { +static int pt_config_update(struct pci_device * pci_dev, uint_t reg_num, void * src, uint_t length, void * private_data) { struct vm_device * dev = (struct vm_device *)private_data; struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data; union pci_addr_reg pci_addr = {state->phys_pci_addr.value}; - pci_addr.reg = reg_num; + pci_addr.reg = reg_num >> 2; if (length == 1) { pci_cfg_write8(pci_addr.value, *(uint8_t *)src); @@ -432,11 +603,67 @@ static int pt_config_update(uint_t reg_num, void * src, uint_t length, void * pr pci_cfg_write32(pci_addr.value, *(uint32_t *)src); } - return 0; } +/* This is really iffy.... + * It was totally broken before, but it's _not_ totally fixed now + * The Expansion rom can be enabled/disabled via software using the low order bit + * We should probably handle that somehow here... + */ +static int pt_exp_rom_write(struct pci_device * pci_dev, uint32_t * src, void * priv_data) { + struct vm_device * dev = (struct vm_device *)(priv_data); + struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data; + + struct pt_bar * prom = &(state->phys_exp_rom); + struct pt_bar * vrom = &(state->virt_exp_rom); + + PrintDebug(VM_NONE, VCORE_NONE, "exp_rom update: src=0x%x\n", *src); + PrintDebug(VM_NONE, VCORE_NONE, "vrom is size=%u, addr=0x%x, val=0x%x\n", vrom->size, (uint32_t)vrom->addr, vrom->val); + PrintDebug(VM_NONE, VCORE_NONE, "prom is size=%u, addr=0x%x, val=0x%x\n", prom->size, (uint32_t)prom->addr, prom->val); + + // only remove old mapping if present, I.E. if the rom was enabled previously + if ((vrom->val & 0x1) == 0x1) { + struct v3_mem_region * old_reg = v3_get_mem_region(dev->vm, V3_MEM_CORE_ANY, vrom->addr); + + if (old_reg == NULL) { + // uh oh... + PrintError(VM_NONE, VCORE_NONE, "Could not find PCI Passthrough exp_rom_base redirection region (addr=0x%x)\n", (uint32_t)vrom->addr); + return -1; + } + + v3_delete_mem_region(dev->vm, old_reg); + } + + // clear the low bits to match the size + *src &= ~(prom->size - 1); + + // Set reserved bits + *src |= (prom->val & ~PCI_EXP_ROM_MASK); + + PrintDebug(VM_NONE, VCORE_NONE, "Cooked src=0x%x\n", *src); + + vrom->addr = PCI_EXP_ROM_BASE(*src); + + + if ((prom->val & 0x1) == 0x1) { + PrintDebug(VM_NONE, VCORE_NONE, "Adding pci Passthrough exp_rom_base remapping: start=0x%x, size=%u, end=0x%x\n", + (uint32_t)vrom->addr, vrom->size, (uint32_t)vrom->addr + vrom->size); + + if (v3_add_shadow_mem(dev->vm, V3_MEM_CORE_ANY, vrom->addr, + vrom->addr + vrom->size - 1, prom->addr) == -1) { + PrintError(VM_NONE, VCORE_NONE, "Failed to remap pci exp_rom: start=0x%x, size=%u, end=0x%x\n", + (uint32_t)vrom->addr, vrom->size, (uint32_t)vrom->addr + vrom->size); + return -1; + } + } + + vrom->val = *src; + + return 0; +} + static int find_real_pci_dev(uint16_t vendor_id, uint16_t device_id, struct pt_dev_state * state) { union pci_addr_reg pci_addr = {0x80000000}; @@ -450,8 +677,7 @@ static int find_real_pci_dev(uint16_t vendor_id, uint16_t device_id, struct pt_d } __attribute__((packed)); } __attribute__((packed)) pci_hdr = {0}; - - //PrintDebug("Scanning PCI busses for vendor=%x, device=%x\n", vendor_id, device_id); + //PrintDebug(VM_NONE, VCORE_NONE, "Scanning PCI busses for vendor=%x, device=%x\n", vendor_id, device_id); for (i = 0, pci_addr.bus = 0; i < PCI_BUS_MAX; i++, pci_addr.bus++) { for (j = 0, pci_addr.dev = 0; j < PCI_DEV_MAX; j++, pci_addr.dev++) { for (k = 0, pci_addr.func = 0; k < PCI_FN_MAX; k++, pci_addr.func++) { @@ -459,7 +685,7 @@ static int find_real_pci_dev(uint16_t vendor_id, uint16_t device_id, struct pt_d v3_outdw(PCI_CFG_ADDR, pci_addr.value); pci_hdr.value = v3_indw(PCI_CFG_DATA); - //PrintDebug("\bus=%d, tvendor=%x, device=%x\n", pci_addr.bus, pci_hdr.vendor, pci_hdr.device); + //PrintDebug(VM_NONE, VCORE_NONE, "\bus=%d, tvendor=%x, device=%x\n", pci_addr.bus, pci_hdr.vendor, pci_hdr.device); if ((pci_hdr.vendor == vendor_id) && (pci_hdr.device == device_id)) { uint32_t * cfg_space = (uint32_t *)&state->real_hdr; @@ -472,7 +698,7 @@ static int find_real_pci_dev(uint16_t vendor_id, uint16_t device_id, struct pt_d } - PrintDebug("Found device %x:%x (bus=%d, dev=%d, func=%d)\n", + PrintDebug(VM_NONE, VCORE_NONE, "Found device %x:%x (bus=%d, dev=%d, func=%d)\n", vendor_id, device_id, pci_addr.bus, pci_addr.dev, pci_addr.func); @@ -487,7 +713,7 @@ static int find_real_pci_dev(uint16_t vendor_id, uint16_t device_id, struct pt_d -static int setup_virt_pci_dev(struct guest_info * info, struct vm_device * dev) { +static int setup_virt_pci_dev(struct v3_vm_info * vm_info, struct vm_device * dev) { struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data; struct pci_device * pci_dev = NULL; struct v3_pci_bar bars[6]; @@ -505,15 +731,21 @@ static int setup_virt_pci_dev(struct guest_info * info, struct vm_device * dev) PCI_STD_DEVICE, bus_num, -1, 0, state->name, bars, - pt_config_update, NULL, NULL, + pt_config_update, + NULL, + NULL, + pt_exp_rom_write, dev); - + + // This will overwrite the bar registers.. but that should be ok. memcpy(pci_dev->config_space, (uint8_t *)&(state->real_hdr), sizeof(struct pci_config_header)); state->pci_dev = pci_dev; - v3_sym_map_pci_passthrough(info, pci_dev->bus_num, pci_dev->dev_num, pci_dev->fn_num); + pci_exp_rom_init(dev, state); + + v3_sym_map_pci_passthrough(vm_info, pci_dev->bus_num, pci_dev->dev_num, pci_dev->fn_num); return 0; @@ -522,20 +754,16 @@ static int setup_virt_pci_dev(struct guest_info * info, struct vm_device * dev) static struct v3_device_ops dev_ops = { .free = NULL, - .reset = NULL, - .start = NULL, - .stop = NULL, }; -static int irq_handler(struct guest_info * info, struct v3_interrupt * intr, void * private_data) { +static int irq_handler(struct v3_vm_info * vm, struct v3_interrupt * intr, void * private_data) { struct vm_device * dev = (struct vm_device *)private_data; struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data; -// PrintDebug("Handling E1000 IRQ %d\n", intr->irq); - v3_pci_raise_irq(state->pci_bus, 0, state->pci_dev); + v3_pci_raise_irq(state->pci_bus, state->pci_dev, 0); V3_ACK_IRQ(intr->irq); @@ -545,27 +773,34 @@ static int irq_handler(struct guest_info * info, struct v3_interrupt * intr, voi -static int passthrough_init(struct guest_info * info, v3_cfg_tree_t * cfg) { +static int passthrough_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { struct pt_dev_state * state = V3_Malloc(sizeof(struct pt_dev_state)); struct vm_device * dev = NULL; - struct vm_device * pci = v3_find_dev(info, v3_cfg_val(cfg, "bus")); - char * name = v3_cfg_val(cfg, "name"); + struct vm_device * pci = v3_find_dev(vm, v3_cfg_val(cfg, "bus")); + char * dev_id = v3_cfg_val(cfg, "ID"); + + if (!state) { + PrintError(vm, VCORE_NONE, "Cannot allocate in init\n"); + return -1; + } memset(state, 0, sizeof(struct pt_dev_state)); if (!pci) { - PrintError("Could not find PCI device\n"); + PrintError(vm, VCORE_NONE, "Could not find PCI device\n"); return -1; } state->pci_bus = pci; - strncpy(state->name, name, 32); + strncpy(state->name, dev_id, 32); + state->name[31] = 0 ; - dev = v3_allocate_device(name, &dev_ops, state); + dev = v3_add_device(vm, dev_id, &dev_ops, state); - if (v3_attach_device(info, dev) == -1) { - PrintError("Could not attach device %s\n", name); + if (dev == NULL) { + PrintError(vm, VCORE_NONE, "Could not attach device %s\n", dev_id); + V3_Free(state); return -1; } @@ -573,15 +808,16 @@ static int passthrough_init(struct guest_info * info, v3_cfg_tree_t * cfg) { if (find_real_pci_dev(atox(v3_cfg_val(cfg, "vendor_id")), atox(v3_cfg_val(cfg, "device_id")), state) == -1) { - PrintError("Could not find PCI Device %s:%s\n", + PrintError(vm, VCORE_NONE, "Could not find PCI Device %s:%s\n", v3_cfg_val(cfg, "vendor_id"), v3_cfg_val(cfg, "device_id")); + v3_remove_device(dev); return 0; } - setup_virt_pci_dev(info, dev); + setup_virt_pci_dev(vm, dev); - v3_hook_irq(info, atoi(v3_cfg_val(cfg, "irq")), irq_handler, dev); + v3_hook_irq(vm, atoi(v3_cfg_val(cfg, "irq")), irq_handler, dev); // v3_hook_irq(info, 64, irq_handler, dev); return 0;