Skip to content

Commit 5670f33

Browse files
chejianjjren1
authored andcommitted
dm/VBS-U: implement virtio_set_modern_bar
virtio_set_modern_bar is an external interface that backend virtio driver can call to initialize the PCI capabilities and PCI bars defined in the virtio 1.0 spec. The following are done in the function: - 5 PCI capabilities are added to the PCI configuration space of the virtio PCI device. (common/isr/device_specific/notify/cfg_access) - A 64-bit MMIO bar is allocated to accommodate the registers defined in the 4 PCI capabilities. (cfg_access capability does not require MMIO.) - If use_notify_pio is true, a PIO notify capability is added to the PCI configuration space and a PIO bar is allocated for it accordingly. Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com> Reviewed-by: Hao Li <hao.l.li@intel.com> Reviewed-by: Zhao Yakui <yakui.zhao@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent 9c2378f commit 5670f33

File tree

2 files changed

+149
-2
lines changed

2 files changed

+149
-2
lines changed

devicemodel/hw/pci/virtio/virtio.c

Lines changed: 134 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ virtio_set_io_bar(struct virtio_base *base, int barnum)
130130
*/
131131
size = VIRTIO_CR_CFG1 + base->vops->cfgsize;
132132
pci_emul_alloc_bar(base->dev, barnum, PCIBAR_IO, size);
133+
base->legacy_pio_bar_idx = barnum;
133134
}
134135

135136
/*
@@ -561,7 +562,7 @@ virtio_pci_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
561562
}
562563

563564
/* XXX probably should do something better than just assert() */
564-
assert(baridx == 0);
565+
assert(baridx == base->legacy_pio_bar_idx);
565566

566567
if (base->mtx)
567568
pthread_mutex_lock(base->mtx);
@@ -683,7 +684,7 @@ virtio_pci_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
683684
}
684685

685686
/* XXX probably should do something better than just assert() */
686-
assert(baridx == 0);
687+
assert(baridx == base->legacy_pio_bar_idx);
687688

688689
if (base->mtx)
689690
pthread_mutex_lock(base->mtx);
@@ -798,3 +799,134 @@ virtio_pci_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
798799
if (base->mtx)
799800
pthread_mutex_unlock(base->mtx);
800801
}
802+
803+
/*
804+
* Set virtio modern MMIO BAR (usually 4) to map the 4 capabilities.
805+
*/
806+
static int
807+
virtio_set_modern_mmio_bar(struct virtio_base *base, int barnum)
808+
{
809+
struct virtio_ops *vops;
810+
int rc;
811+
struct virtio_pci_cap cap = {
812+
.cap_vndr = PCIY_VENDOR,
813+
.cap_next = 0,
814+
.cap_len = sizeof(cap),
815+
.bar = barnum,
816+
};
817+
struct virtio_pci_notify_cap notify = {
818+
.cap.cap_vndr = PCIY_VENDOR,
819+
.cap.cap_next = 0,
820+
.cap.cap_len = sizeof(notify),
821+
.cap.cfg_type = VIRTIO_PCI_CAP_NOTIFY_CFG,
822+
.cap.bar = barnum,
823+
.cap.offset = VIRTIO_CAP_NOTIFY_OFFSET,
824+
.cap.length = VIRTIO_CAP_NOTIFY_SIZE,
825+
.notify_off_multiplier = VIRTIO_MODERN_NOTIFY_OFF_MULT,
826+
};
827+
struct virtio_pci_cfg_cap cfg = {
828+
.cap.cap_vndr = PCIY_VENDOR,
829+
.cap.cap_next = 0,
830+
.cap.cap_len = sizeof(cfg),
831+
.cap.cfg_type = VIRTIO_PCI_CAP_PCI_CFG,
832+
};
833+
834+
vops = base->vops;
835+
836+
if (vops->cfgsize > VIRTIO_CAP_DEVICE_SIZE) {
837+
fprintf(stderr,
838+
"%s: cfgsize %lu > max %d\r\n",
839+
vops->name, vops->cfgsize, VIRTIO_CAP_DEVICE_SIZE);
840+
return -1;
841+
}
842+
843+
/* common configuration capability */
844+
cap.cfg_type = VIRTIO_PCI_CAP_COMMON_CFG;
845+
cap.offset = VIRTIO_CAP_COMMON_OFFSET;
846+
cap.length = VIRTIO_CAP_COMMON_SIZE;
847+
rc = pci_emul_add_capability(base->dev, (u_char *)&cap, sizeof(cap));
848+
assert(rc == 0);
849+
850+
/* isr status capability */
851+
cap.cfg_type = VIRTIO_PCI_CAP_ISR_CFG;
852+
cap.offset = VIRTIO_CAP_ISR_OFFSET;
853+
cap.length = VIRTIO_CAP_ISR_SIZE;
854+
rc = pci_emul_add_capability(base->dev, (u_char *)&cap, sizeof(cap));
855+
assert(rc == 0);
856+
857+
/* device specific configuration capability */
858+
cap.cfg_type = VIRTIO_PCI_CAP_DEVICE_CFG;
859+
cap.offset = VIRTIO_CAP_DEVICE_OFFSET;
860+
cap.length = VIRTIO_CAP_DEVICE_SIZE;
861+
rc = pci_emul_add_capability(base->dev, (u_char *)&cap, sizeof(cap));
862+
assert(rc == 0);
863+
864+
/* notification capability */
865+
rc = pci_emul_add_capability(base->dev, (u_char *)&notify,
866+
sizeof(notify));
867+
assert(rc == 0);
868+
869+
/* pci alternative configuration access capability */
870+
rc = pci_emul_add_capability(base->dev, (u_char *)&cfg, sizeof(cfg));
871+
assert(rc == 0);
872+
873+
/* allocate and register modern memory bar */
874+
rc = pci_emul_alloc_bar(base->dev, barnum, PCIBAR_MEM64,
875+
VIRTIO_MODERN_MEM_BAR_SIZE);
876+
assert(rc == 0);
877+
878+
base->modern_mmio_bar_idx = barnum;
879+
return 0;
880+
}
881+
882+
/*
883+
* Set virtio modern PIO BAR (usually 2) to map notify capability.
884+
*/
885+
static int
886+
virtio_set_modern_pio_bar(struct virtio_base *base, int barnum)
887+
{
888+
int rc;
889+
struct virtio_pci_notify_cap notify_pio = {
890+
.cap.cap_vndr = PCIY_VENDOR,
891+
.cap.cap_next = 0,
892+
.cap.cap_len = sizeof(notify_pio),
893+
.cap.cfg_type = VIRTIO_PCI_CAP_NOTIFY_CFG,
894+
.cap.bar = barnum,
895+
.cap.offset = 0,
896+
.cap.length = 4,
897+
.notify_off_multiplier = 0,
898+
};
899+
900+
/* notification capability */
901+
rc = pci_emul_add_capability(base->dev, (u_char *)&notify_pio,
902+
sizeof(notify_pio));
903+
assert(rc == 0);
904+
905+
/* allocate and register modern pio bar */
906+
rc = pci_emul_alloc_bar(base->dev, barnum, PCIBAR_IO, 4);
907+
assert(rc == 0);
908+
909+
base->modern_pio_bar_idx = barnum;
910+
return 0;
911+
}
912+
913+
int
914+
virtio_set_modern_bar(struct virtio_base *base, bool use_notify_pio)
915+
{
916+
struct virtio_ops *vops;
917+
int rc = 0;
918+
919+
vops = base->vops;
920+
921+
if (!vops || (vops->hv_caps & VIRTIO_F_VERSION_1) == 0)
922+
return -1;
923+
924+
if (use_notify_pio)
925+
rc = virtio_set_modern_pio_bar(base,
926+
VIRTIO_MODERN_PIO_BAR_IDX);
927+
if (!rc)
928+
rc = virtio_set_modern_mmio_bar(base,
929+
VIRTIO_MODERN_MMIO_BAR_IDX);
930+
931+
return rc;
932+
}

devicemodel/include/virtio.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,21 @@ uint64_t virtio_pci_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
839839
*/
840840
void virtio_pci_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
841841
int baridx, uint64_t offset, int size, uint64_t value);
842+
843+
/**
844+
* @brief Set modern BAR (usually 4) to map PCI config registers.
845+
*
846+
* Set modern MMIO BAR (usually 4) to map virtio 1.0 capabilities and optional
847+
* set modern PIO BAR (usually 2) to map notify capability. This interface is
848+
* only valid for modern virtio.
849+
*
850+
* @param base Pointer to struct virtio_base.
851+
* @param use_notify_pio Whether use pio for notify capability.
852+
*
853+
* @return 0 on success and non-zero on fail.
854+
*/
855+
int virtio_set_modern_bar(struct virtio_base *base, bool use_notify_pio);
856+
842857
/**
843858
* @}
844859
*/

0 commit comments

Comments
 (0)