diff --git a/xen/drivers/vpci/msix.c b/xen/drivers/vpci/msix.c
index 6bd8c55bb4..faa7c1cd49 100644
--- a/xen/drivers/vpci/msix.c
+++ b/xen/drivers/vpci/msix.c
@@ -17,6 +17,7 @@
* License along with this program; If not, see .
*/
+#include
#include
#include
@@ -723,6 +724,51 @@ static int cf_check init_msix(struct pci_dev *pdev)
if ( !msix )
return -ENOMEM;
+ msix->tables[VPCI_MSIX_TABLE] =
+ pci_conf_read32(pdev->sbdf, msix_table_offset_reg(msix_offset));
+ msix->tables[VPCI_MSIX_PBA] =
+ pci_conf_read32(pdev->sbdf, msix_pba_offset_reg(msix_offset));
+
+ /* Check that the referenced BAR(s) regions are valid. */
+ for ( i = 0; i < ARRAY_SIZE(msix->tables); i++ )
+ {
+ const char *name = (i == VPCI_MSIX_TABLE) ? "vector" : "PBA";
+ const struct vpci_bar *bars = pdev->vpci->header.bars;
+ unsigned int bir = msix->tables[i] & PCI_MSIX_BIRMASK;
+ unsigned int type;
+ unsigned int offset = msix->tables[i] & ~PCI_MSIX_BIRMASK;
+ unsigned int size =
+ (i == VPCI_MSIX_TABLE) ? max_entries * PCI_MSIX_ENTRY_SIZE
+ : ROUNDUP(DIV_ROUND_UP(max_entries, 8), 8);
+
+ if ( bir >= ARRAY_SIZE(pdev->vpci->header.bars) )
+ {
+ printk(XENLOG_ERR DEV_BUG_PREFIX
+ "%pp: MSI-X %s table with out of range BIR %u\n",
+ &pdev->sbdf, name, bir);
+ invalid:
+ xfree(msix);
+ return -ENODEV;
+ }
+
+ type = bars[bir].type;
+ if ( type != VPCI_BAR_MEM32 && type != VPCI_BAR_MEM64_LO )
+ {
+ printk(XENLOG_ERR DEV_BUG_PREFIX
+ "%pp: MSI-X %s table at invalid BAR%u with type %u\n",
+ &pdev->sbdf, name, bir, type);
+ goto invalid;
+ }
+
+ if ( (uint64_t)offset + size > bars[bir].size )
+ {
+ printk(XENLOG_ERR DEV_BUG_PREFIX
+ "%pp: MSI-X %s table offset %#x size %#x outside of BAR%u size %#lx\n",
+ &pdev->sbdf, name, offset, size, bir, bars[bir].size);
+ goto invalid;
+ }
+ }
+
rc = vpci_add_register(pdev->vpci, control_read, control_write,
msix_control_reg(msix_offset), 2, msix);
if ( rc )
@@ -734,11 +780,6 @@ static int cf_check init_msix(struct pci_dev *pdev)
msix->max_entries = max_entries;
msix->pdev = pdev;
- msix->tables[VPCI_MSIX_TABLE] =
- pci_conf_read32(pdev->sbdf, msix_table_offset_reg(msix_offset));
- msix->tables[VPCI_MSIX_PBA] =
- pci_conf_read32(pdev->sbdf, msix_pba_offset_reg(msix_offset));
-
for ( i = 0; i < max_entries; i++)
{
msix->entries[i].masked = true;
diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h
index 130f96791f..1a09f8ada9 100644
--- a/xen/include/xen/lib.h
+++ b/xen/include/xen/lib.h
@@ -58,6 +58,9 @@ static inline void
debugtrace_printk(const char *fmt, ...) {}
#endif
+/* Common log prefixes for platform related issues. */
+#define DEV_BUG_PREFIX "DEVICE BUG: "
+
extern void printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2), cold));
void vprintk(const char *fmt, va_list args)