diff options
author | Florian Freudiger <25648113+FlorianFreudiger@users.noreply.github.com> | 2023-08-15 13:24:23 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-15 12:24:23 +0100 |
commit | 1cca91aeb8ae8f531f9c3b9c59d83630e9941a5e (patch) | |
tree | a0b700608a3f29be7cc8cb14060eb2b703edf59c /lib | |
parent | 852ca25f41bf7be8a6a2a8b30c0e2374c10b480e (diff) | |
download | libvfio-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.c | 67 |
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; |