X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fpci.c;h=ab85aea13f10ca7bbe19c5a98557666e8963db5d;hb=4eb8163fe76127f9748caa43f8ffad1e4d739bb8;hp=6b5472dbe156733c60682f3552d6f1b23817eefa;hpb=a0e1d8274aef54adcf50dce0b3843489f2a3cd21;p=palacios.git diff --git a/palacios/src/devices/pci.c b/palacios/src/devices/pci.c index 6b5472d..ab85aea 100644 --- a/palacios/src/devices/pci.c +++ b/palacios/src/devices/pci.c @@ -74,6 +74,10 @@ struct pci_bus { // Bitmap of the allocated device numbers uint8_t dev_map[MAX_BUS_DEVICES / 8]; + + int (*raise_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev); + int (*lower_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev); + struct vm_device * irq_bridge_dev; }; @@ -121,9 +125,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); if (bus->dev_map[i] != 0xff) { // availability for (j = 0; j < 8; j++) { + PrintDebug("\tj=%d\n", j); if (!(bus->dev_map[i] & (0x1 << j))) { return ((i * 8) + j); } @@ -397,6 +403,22 @@ static int bar_update(struct pci_device * pci, int bar_num, uint32_t new_val) { break; } + case PCI_BAR_MEM32: { + v3_unhook_mem(pci->vm_dev->vm, (addr_t)(bar->val)); + + if (bar->mem_read) { + v3_hook_full_mem(pci->vm_dev->vm, PCI_MEM32_BASE(new_val), + PCI_MEM32_BASE(new_val) + (bar->num_pages * PAGE_SIZE_4KB), + bar->mem_read, bar->mem_write, pci->vm_dev); + } else { + PrintError("Write hooks not supported for PCI\n"); + return -1; + } + + bar->val = new_val; + + break; + } case PCI_BAR_NONE: { PrintDebug("Reprogramming an unsupported BAR register (Dev=%s) (bar=%d) (val=%x)\n", pci->name, bar_num, new_val); @@ -422,9 +444,10 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d return length; } - PrintDebug("Writing PCI Data register. bus = %d, dev = %d, reg = %d (%x) addr_reg = %x (val=%x, len=%d)\n", + PrintDebug("Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (%x) addr_reg = %x (val=%x, len=%d)\n", pci_state->addr_reg.bus_num, pci_state->addr_reg.dev_num, + pci_state->addr_reg.fn_num, reg_num, reg_num, pci_state->addr_reg.val, *(uint32_t *)src, length); @@ -482,6 +505,8 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d // BIST update pci_dev->config_header.BIST = 0x00; } + } else { + PrintError("PCI Write to read only register %d\n", cur_reg); } } @@ -540,7 +565,7 @@ static int pci_stop_device(struct vm_device * dev) { -static int pci_deinit_device(struct vm_device * dev) { +static int pci_free(struct vm_device * dev) { int i = 0; for (i = 0; i < 4; i++){ @@ -565,14 +590,30 @@ static void init_pci_busses(struct pci_internal * pci_state) { -static int pci_init_device(struct vm_device * dev) { - struct pci_internal * pci_state = (struct pci_internal *)dev->private_data;; + +static struct v3_device_ops dev_ops = { + .free = pci_free, + .reset = pci_reset_device, + .start = pci_start_device, + .stop = pci_stop_device, +}; + + + + +static int pci_init(struct guest_info * vm, void * cfg_data) { + struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal)); int i = 0; - PrintDebug("pci: init_device\n"); + PrintDebug("PCI internal at %p\n",(void *)pci_state); + + struct vm_device * dev = v3_allocate_device("PCI", &dev_ops, pci_state); + + if (v3_attach_device(vm, dev) == -1) { + PrintError("Could not attach device %s\n", "PCI"); + return -1; + } - // JRL: Fix this.... - // dev->vm->pci = dev; //should be in vmm_config.c pci_state->addr_reg.val = 0; @@ -589,25 +630,7 @@ static int pci_init_device(struct vm_device * dev) { } -static struct vm_device_ops dev_ops = { - .init = pci_init_device, - .deinit = pci_deinit_device, - .reset = pci_reset_device, - .start = pci_start_device, - .stop = pci_stop_device, -}; - - -struct vm_device * v3_create_pci() { - struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal)); - - PrintDebug("PCI internal at %p\n",(void *)pci_state); - - struct vm_device * device = v3_create_device("PCI", &dev_ops, pci_state); - - return device; -} - +device_register("PCI", pci_init) static inline int init_bars(struct pci_device * pci_dev) { @@ -625,10 +648,12 @@ static inline int init_bars(struct pci_device * pci_dev) { for (j = 0; j < pci_dev->bar[i].num_ports; j++) { // hook IO - if (v3_dev_hook_io(pci_dev->vm_dev, pci_dev->bar[i].default_base_port + j, - pci_dev->bar[i].io_read, pci_dev->bar[i].io_write) == -1) { - PrintError("Could not hook default io port %x\n", pci_dev->bar[i].default_base_port + j); - return -1; + if (pci_dev->bar[i].default_base_port != 0xffff) { + if (v3_dev_hook_io(pci_dev->vm_dev, pci_dev->bar[i].default_base_port + j, + pci_dev->bar[i].io_read, pci_dev->bar[i].io_write) == -1) { + PrintError("Could not hook default io port %x\n", pci_dev->bar[i].default_base_port + j); + return -1; + } } } @@ -680,6 +705,34 @@ static inline int init_bars(struct pci_device * pci_dev) { } +int v3_pci_set_irq_bridge(struct vm_device * pci_bus, int bus_num, + int (*raise_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev), + int (*lower_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev), + struct vm_device * bridge_dev) { + struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data; + + + pci_state->bus_list[bus_num].raise_pci_irq = raise_pci_irq; + pci_state->bus_list[bus_num].lower_pci_irq = lower_pci_irq; + pci_state->bus_list[bus_num].irq_bridge_dev = bridge_dev; + + return 0; +} + +int v3_pci_raise_irq(struct vm_device * pci_bus, int bus_num, struct pci_device * dev) { + struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data; + struct pci_bus * bus = &(pci_state->bus_list[bus_num]); + + return bus->raise_pci_irq(bus->irq_bridge_dev, dev); +} + +int v3_pci_lower_irq(struct vm_device * pci_bus, int bus_num, struct pci_device * dev) { + struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data; + struct pci_bus * bus = &(pci_state->bus_list[bus_num]); + + return bus->lower_pci_irq(bus->irq_bridge_dev, dev); +} + // if dev_num == -1, auto assign struct pci_device * v3_pci_register_device(struct vm_device * pci, pci_device_type_t dev_type, @@ -703,13 +756,16 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, return NULL; } - if (dev_num == -1) { + if (dev_num == PCI_AUTO_DEV_NUM) { + PrintDebug("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); return NULL; } } + PrintDebug("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", dev_num, bus->bus_num); @@ -761,11 +817,16 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, pci_dev->bar[i].default_base_port = bars[i].default_base_port; pci_dev->bar[i].io_read = bars[i].io_read; pci_dev->bar[i].io_write = bars[i].io_write; - } else { + } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) { pci_dev->bar[i].num_pages = bars[i].num_pages; pci_dev->bar[i].default_base_addr = bars[i].default_base_addr; pci_dev->bar[i].mem_read = bars[i].mem_read; pci_dev->bar[i].mem_write = bars[i].mem_write; + } else { + pci_dev->bar[i].num_pages = 0; + pci_dev->bar[i].default_base_addr = 0; + pci_dev->bar[i].mem_read = NULL; + pci_dev->bar[i].mem_write = NULL; } }