aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFlorian Freudiger <25648113+FlorianFreudiger@users.noreply.github.com>2023-08-15 13:24:23 +0200
committerGitHub <noreply@github.com>2023-08-15 12:24:23 +0100
commit1cca91aeb8ae8f531f9c3b9c59d83630e9941a5e (patch)
treea0b700608a3f29be7cc8cb14060eb2b703edf59c /lib
parent852ca25f41bf7be8a6a2a8b30c0e2374c10b480e (diff)
downloadlibvfio-user-1cca91aeb8ae8f531f9c3b9c59d83630e9941a5e.zip
libvfio-user-1cca91aeb8ae8f531f9c3b9c59d83630e9941a5e.tar.gz
libvfio-user-1cca91aeb8ae8f531f9c3b9c59d83630e9941a5e.tar.bz2
Allow adding MSI capability via vfu_pci_add_capability (#758)
Signed-off-by: Florian Freudiger <25648113+FlorianFreudiger@users.noreply.github.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/pci_caps.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/pci_caps.c b/lib/pci_caps.c
index 39acec8..a6f400f 100644
--- a/lib/pci_caps.c
+++ b/lib/pci_caps.c
@@ -99,6 +99,8 @@ cap_size(vfu_ctx_t *vfu_ctx, void *data, bool extended)
return PCI_PM_SIZEOF;
case PCI_CAP_ID_EXP:
return VFIO_USER_PCI_CAP_EXP_SIZEOF;
+ case PCI_CAP_ID_MSI:
+ return VFIO_USER_PCI_CAP_MSI_SIZEOF;
case PCI_CAP_ID_MSIX:
return PCI_CAP_MSIX_SIZEOF;
case PCI_CAP_ID_VNDR:
@@ -167,6 +169,67 @@ cap_write_pm(vfu_ctx_t *vfu_ctx, struct pci_cap *cap, char * buf,
}
static ssize_t
+cap_write_msi(vfu_ctx_t *vfu_ctx, struct pci_cap *cap, char *buf,
+ size_t count, loff_t offset)
+{
+ struct msicap *msi = cap_data(vfu_ctx, cap);
+ struct msicap new_msi = *msi;
+
+ memcpy((char *)&new_msi + offset - cap->off, buf, count);
+
+ if (msi->mc.msie != new_msi.mc.msie) {
+ msi->mc.msie = new_msi.mc.msie;
+ vfu_log(vfu_ctx, LOG_DEBUG, "%s MSI",
+ msi->mc.msie ? "enable" : "disable");
+ }
+
+ if (msi->mc.mme != new_msi.mc.mme) {
+ if (new_msi.mc.mme > 5) {
+ vfu_log(vfu_ctx, LOG_ERR,
+ "MSI cannot have more than 32 interrupt vectors");
+ return ERROR_INT(EINVAL);
+ }
+
+ if (new_msi.mc.mme > msi->mc.mmc) {
+ vfu_log(vfu_ctx, LOG_ERR,
+ "MSI cannot have more interrupt vectors"
+ " in MME than defined in MMC");
+ return ERROR_INT(EINVAL);
+ }
+ msi->mc.mme = new_msi.mc.mme;
+
+ vfu_log(vfu_ctx, LOG_DEBUG,
+ "MSI Updated Multiple Message Enable count");
+ }
+
+ if (msi->ma.addr != new_msi.ma.addr) {
+ msi->ma.addr = new_msi.ma.addr;
+ vfu_log(vfu_ctx, LOG_DEBUG,
+ "MSI Message Address set to %x", msi->ma.addr << 2);
+ }
+
+ if (msi->mua != new_msi.mua) {
+ msi->mua = new_msi.mua;
+ vfu_log(vfu_ctx, LOG_DEBUG,
+ "MSI Message Upper Address set to %x", msi->mua);
+ }
+
+ if (msi->md != new_msi.md) {
+ msi->md = new_msi.md;
+ vfu_log(vfu_ctx, LOG_DEBUG,
+ "MSI Message Data set to %x", msi->md);
+ }
+
+ if (msi->mmask != new_msi.mmask) {
+ msi->mmask = new_msi.mmask;
+ vfu_log(vfu_ctx, LOG_DEBUG,
+ "MSI Mask Bits set to %x", msi->mmask);
+ }
+
+ return count;
+}
+
+static ssize_t
cap_write_msix(vfu_ctx_t *vfu_ctx, struct pci_cap *cap, char *buf,
size_t count, loff_t offset)
{
@@ -682,6 +745,10 @@ vfu_pci_add_capability(vfu_ctx_t *vfu_ctx, size_t pos, int flags, void *data)
cap.name = "PCI Express";
cap.cb = cap_write_px;
break;
+ case PCI_CAP_ID_MSI:
+ cap.name = "MSI";
+ cap.cb = cap_write_msi;
+ break;
case PCI_CAP_ID_MSIX:
cap.name = "MSI-X";
cap.cb = cap_write_msix;