aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/msi.c17
-rw-r--r--hw/msi.h1
-rw-r--r--hw/msix.c13
-rw-r--r--hw/msix.h1
4 files changed, 32 insertions, 0 deletions
diff --git a/hw/msi.c b/hw/msi.c
index 52332041e7..e2273a09ae 100644
--- a/hw/msi.c
+++ b/hw/msi.c
@@ -105,6 +105,23 @@ static inline uint8_t msi_pending_off(const PCIDevice* dev, bool msi64bit)
return dev->msi_cap + (msi64bit ? PCI_MSI_PENDING_64 : PCI_MSI_PENDING_32);
}
+/*
+ * Special API for POWER to configure the vectors through
+ * a side channel. Should never be used by devices.
+ */
+void msi_set_message(PCIDevice *dev, MSIMessage msg)
+{
+ uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
+ bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
+
+ if (msi64bit) {
+ pci_set_quad(dev->config + msi_address_lo_off(dev), msg.address);
+ } else {
+ pci_set_long(dev->config + msi_address_lo_off(dev), msg.address);
+ }
+ pci_set_word(dev->config + msi_data_off(dev, msi64bit), msg.data);
+}
+
bool msi_enabled(const PCIDevice *dev)
{
return msi_present(dev) &&
diff --git a/hw/msi.h b/hw/msi.h
index 75747abc25..6ec1f99f80 100644
--- a/hw/msi.h
+++ b/hw/msi.h
@@ -31,6 +31,7 @@ struct MSIMessage {
extern bool msi_supported;
+void msi_set_message(PCIDevice *dev, MSIMessage msg);
bool msi_enabled(const PCIDevice *dev);
int msi_init(struct PCIDevice *dev, uint8_t offset,
unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask);
diff --git a/hw/msix.c b/hw/msix.c
index fd9ea95da1..800fc32f0b 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -37,6 +37,19 @@ static MSIMessage msix_get_message(PCIDevice *dev, unsigned vector)
return msg;
}
+/*
+ * Special API for POWER to configure the vectors through
+ * a side channel. Should never be used by devices.
+ */
+void msix_set_message(PCIDevice *dev, int vector, struct MSIMessage msg)
+{
+ uint8_t *table_entry = dev->msix_table + vector * PCI_MSIX_ENTRY_SIZE;
+
+ pci_set_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR, msg.address);
+ pci_set_long(table_entry + PCI_MSIX_ENTRY_DATA, msg.data);
+ table_entry[PCI_MSIX_ENTRY_VECTOR_CTRL] &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
+}
+
static uint8_t msix_pending_mask(int vector)
{
return 1 << (vector % 8);
diff --git a/hw/msix.h b/hw/msix.h
index 1786e2766b..15211cb592 100644
--- a/hw/msix.h
+++ b/hw/msix.h
@@ -4,6 +4,7 @@
#include "qemu-common.h"
#include "pci.h"
+void msix_set_message(PCIDevice *dev, int vector, MSIMessage msg);
int msix_init(PCIDevice *dev, unsigned short nentries,
MemoryRegion *table_bar, uint8_t table_bar_nr,
unsigned table_offset, MemoryRegion *pba_bar,