From: Jack Lange Date: Tue, 31 Mar 2009 22:48:29 +0000 (-0500) Subject: added pci bar update handler X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=59b6853965a3cd4b17d0466c3650feed594cd89e added pci bar update handler --- diff --git a/palacios/include/devices/pci.h b/palacios/include/devices/pci.h index 79718a7..d39eae3 100644 --- a/palacios/include/devices/pci.h +++ b/palacios/include/devices/pci.h @@ -57,10 +57,15 @@ struct v3_pci_bar { }; // Internal PCI data + uint32_t val; int updated; uint32_t mask; }; + +#define PCI_IO_BASE(bar_val) (bar_val & 0xfffffffc) +#define PCI_MEM32_BASE(bar_val) (bar_val & 0xfffffff0) + struct pci_device { union { uint8_t config_space[256]; diff --git a/palacios/src/devices/pci.c b/palacios/src/devices/pci.c index ad53670..964cd48 100644 --- a/palacios/src/devices/pci.c +++ b/palacios/src/devices/pci.c @@ -352,9 +352,42 @@ static inline int is_cfg_reg_writable(uchar_t header_type, int reg_num) { } -static int bar_update(struct pci_device * pci, int bar_num) { - PrintError("Bar Updates not handled (bar=%d)\n", bar_num); - return -1; +static int bar_update(struct pci_device * pci, int bar_num, uint32_t new_val) { + struct v3_pci_bar * bar = &(pci->bar[bar_num]); + + PrintError("Updating BAR Register (Dev=%s) (bar=%d) (val=%x)\n", + pci->name, bar_num, new_val); + + switch (bar->type) { + case PCI_BAR_IO: { + int i = 0; + + // only do this if pci device is enabled.... + for (i = 0; i < bar->num_ports; i++) { + PrintDebug("Rehooking IO Port %x\n", PCI_IO_BASE(bar->val) + i); + + v3_dev_unhook_io(pci->vm_dev, PCI_IO_BASE(bar->val) + i); + + v3_dev_hook_io(pci->vm_dev, PCI_IO_BASE(new_val) + i, + bar->io_read, bar->io_write); + } + + bar->val = new_val; + + break; + } + case PCI_BAR_NONE: { + PrintError("Reprogramming an unsupported BAR register (Dev=%s) (bar=%d) (val=%x)\n", + pci->name, bar_num, new_val); + bar->val = new_val; + break; + } + default: + PrintError("Invalid Bar Reg updated (bar=%d)\n", bar_num); + return -1; + } + + return 0; } @@ -433,7 +466,7 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d *(uint32_t *)(pci_dev->config_space + bar_offset) &= pci_dev->bar[i].mask; // bar_update - if (bar_update(pci_dev, i) == -1) { + if (bar_update(pci_dev, i, *(uint32_t *)(pci_dev->config_space + bar_offset)) == -1) { PrintError("PCI Device %s: Bar update Error Bar=%d\n", pci_dev->name, i); return -1; } @@ -588,9 +621,9 @@ static inline int init_bars(struct pci_device * pci_dev) { if (pci_dev->bar[i].type == PCI_BAR_IO) { int j = 0; pci_dev->bar[i].mask = (~((pci_dev->bar[i].num_ports) - 1)) | 0x01; - - *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].default_base_port & pci_dev->bar[i].mask; - *(uint32_t *)(pci_dev->config_space + bar_offset) |= 0x00000001; + + pci_dev->bar[i].val = pci_dev->bar[i].default_base_port & pci_dev->bar[i].mask; + pci_dev->bar[i].val |= 0x00000001; for (j = 0; j < pci_dev->bar[i].num_ports; j++) { // hook IO @@ -601,11 +634,13 @@ static inline int init_bars(struct pci_device * pci_dev) { } } + *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val; + } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) { pci_dev->bar[i].mask = ~((pci_dev->bar[i].num_pages << 12) - 1); pci_dev->bar[i].mask |= 0xf; // preserve the configuration flags - *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].default_base_addr & pci_dev->bar[i].mask; + pci_dev->bar[i].val = pci_dev->bar[i].default_base_addr & pci_dev->bar[i].mask; // hook memory if (pci_dev->bar[i].mem_read) { @@ -624,14 +659,18 @@ static inline int init_bars(struct pci_device * pci_dev) { */ } else { // set the prefetchable flag... - *(uint8_t *)(pci_dev->config_space + bar_offset) |= 0x00000008; + pci_dev->bar[i].val |= 0x00000008; } + + *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val; + } else if (pci_dev->bar[i].type == PCI_BAR_MEM16) { PrintError("16 Bit memory ranges not supported (reg: %d)\n", i); return -1; } else if (pci_dev->bar[i].type == PCI_BAR_NONE) { - *(uint32_t *)(pci_dev->config_space + bar_offset) = 0x00000000; + pci_dev->bar[i].val = 0x00000000; + *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val; } else { PrintError("Invalid BAR type for bar #%d\n", i); return -1;