mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-09-24 18:27:18 +00:00
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>
This commit is contained in:
@@ -130,6 +130,7 @@ virtio_set_io_bar(struct virtio_base *base, int barnum)
|
||||
*/
|
||||
size = VIRTIO_CR_CFG1 + base->vops->cfgsize;
|
||||
pci_emul_alloc_bar(base->dev, barnum, PCIBAR_IO, size);
|
||||
base->legacy_pio_bar_idx = barnum;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -561,7 +562,7 @@ virtio_pci_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
|
||||
}
|
||||
|
||||
/* XXX probably should do something better than just assert() */
|
||||
assert(baridx == 0);
|
||||
assert(baridx == base->legacy_pio_bar_idx);
|
||||
|
||||
if (base->mtx)
|
||||
pthread_mutex_lock(base->mtx);
|
||||
@@ -683,7 +684,7 @@ virtio_pci_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
|
||||
}
|
||||
|
||||
/* XXX probably should do something better than just assert() */
|
||||
assert(baridx == 0);
|
||||
assert(baridx == base->legacy_pio_bar_idx);
|
||||
|
||||
if (base->mtx)
|
||||
pthread_mutex_lock(base->mtx);
|
||||
@@ -798,3 +799,134 @@ done:
|
||||
if (base->mtx)
|
||||
pthread_mutex_unlock(base->mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set virtio modern MMIO BAR (usually 4) to map the 4 capabilities.
|
||||
*/
|
||||
static int
|
||||
virtio_set_modern_mmio_bar(struct virtio_base *base, int barnum)
|
||||
{
|
||||
struct virtio_ops *vops;
|
||||
int rc;
|
||||
struct virtio_pci_cap cap = {
|
||||
.cap_vndr = PCIY_VENDOR,
|
||||
.cap_next = 0,
|
||||
.cap_len = sizeof(cap),
|
||||
.bar = barnum,
|
||||
};
|
||||
struct virtio_pci_notify_cap notify = {
|
||||
.cap.cap_vndr = PCIY_VENDOR,
|
||||
.cap.cap_next = 0,
|
||||
.cap.cap_len = sizeof(notify),
|
||||
.cap.cfg_type = VIRTIO_PCI_CAP_NOTIFY_CFG,
|
||||
.cap.bar = barnum,
|
||||
.cap.offset = VIRTIO_CAP_NOTIFY_OFFSET,
|
||||
.cap.length = VIRTIO_CAP_NOTIFY_SIZE,
|
||||
.notify_off_multiplier = VIRTIO_MODERN_NOTIFY_OFF_MULT,
|
||||
};
|
||||
struct virtio_pci_cfg_cap cfg = {
|
||||
.cap.cap_vndr = PCIY_VENDOR,
|
||||
.cap.cap_next = 0,
|
||||
.cap.cap_len = sizeof(cfg),
|
||||
.cap.cfg_type = VIRTIO_PCI_CAP_PCI_CFG,
|
||||
};
|
||||
|
||||
vops = base->vops;
|
||||
|
||||
if (vops->cfgsize > VIRTIO_CAP_DEVICE_SIZE) {
|
||||
fprintf(stderr,
|
||||
"%s: cfgsize %lu > max %d\r\n",
|
||||
vops->name, vops->cfgsize, VIRTIO_CAP_DEVICE_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* common configuration capability */
|
||||
cap.cfg_type = VIRTIO_PCI_CAP_COMMON_CFG;
|
||||
cap.offset = VIRTIO_CAP_COMMON_OFFSET;
|
||||
cap.length = VIRTIO_CAP_COMMON_SIZE;
|
||||
rc = pci_emul_add_capability(base->dev, (u_char *)&cap, sizeof(cap));
|
||||
assert(rc == 0);
|
||||
|
||||
/* isr status capability */
|
||||
cap.cfg_type = VIRTIO_PCI_CAP_ISR_CFG;
|
||||
cap.offset = VIRTIO_CAP_ISR_OFFSET;
|
||||
cap.length = VIRTIO_CAP_ISR_SIZE;
|
||||
rc = pci_emul_add_capability(base->dev, (u_char *)&cap, sizeof(cap));
|
||||
assert(rc == 0);
|
||||
|
||||
/* device specific configuration capability */
|
||||
cap.cfg_type = VIRTIO_PCI_CAP_DEVICE_CFG;
|
||||
cap.offset = VIRTIO_CAP_DEVICE_OFFSET;
|
||||
cap.length = VIRTIO_CAP_DEVICE_SIZE;
|
||||
rc = pci_emul_add_capability(base->dev, (u_char *)&cap, sizeof(cap));
|
||||
assert(rc == 0);
|
||||
|
||||
/* notification capability */
|
||||
rc = pci_emul_add_capability(base->dev, (u_char *)¬ify,
|
||||
sizeof(notify));
|
||||
assert(rc == 0);
|
||||
|
||||
/* pci alternative configuration access capability */
|
||||
rc = pci_emul_add_capability(base->dev, (u_char *)&cfg, sizeof(cfg));
|
||||
assert(rc == 0);
|
||||
|
||||
/* allocate and register modern memory bar */
|
||||
rc = pci_emul_alloc_bar(base->dev, barnum, PCIBAR_MEM64,
|
||||
VIRTIO_MODERN_MEM_BAR_SIZE);
|
||||
assert(rc == 0);
|
||||
|
||||
base->modern_mmio_bar_idx = barnum;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set virtio modern PIO BAR (usually 2) to map notify capability.
|
||||
*/
|
||||
static int
|
||||
virtio_set_modern_pio_bar(struct virtio_base *base, int barnum)
|
||||
{
|
||||
int rc;
|
||||
struct virtio_pci_notify_cap notify_pio = {
|
||||
.cap.cap_vndr = PCIY_VENDOR,
|
||||
.cap.cap_next = 0,
|
||||
.cap.cap_len = sizeof(notify_pio),
|
||||
.cap.cfg_type = VIRTIO_PCI_CAP_NOTIFY_CFG,
|
||||
.cap.bar = barnum,
|
||||
.cap.offset = 0,
|
||||
.cap.length = 4,
|
||||
.notify_off_multiplier = 0,
|
||||
};
|
||||
|
||||
/* notification capability */
|
||||
rc = pci_emul_add_capability(base->dev, (u_char *)¬ify_pio,
|
||||
sizeof(notify_pio));
|
||||
assert(rc == 0);
|
||||
|
||||
/* allocate and register modern pio bar */
|
||||
rc = pci_emul_alloc_bar(base->dev, barnum, PCIBAR_IO, 4);
|
||||
assert(rc == 0);
|
||||
|
||||
base->modern_pio_bar_idx = barnum;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
virtio_set_modern_bar(struct virtio_base *base, bool use_notify_pio)
|
||||
{
|
||||
struct virtio_ops *vops;
|
||||
int rc = 0;
|
||||
|
||||
vops = base->vops;
|
||||
|
||||
if (!vops || (vops->hv_caps & VIRTIO_F_VERSION_1) == 0)
|
||||
return -1;
|
||||
|
||||
if (use_notify_pio)
|
||||
rc = virtio_set_modern_pio_bar(base,
|
||||
VIRTIO_MODERN_PIO_BAR_IDX);
|
||||
if (!rc)
|
||||
rc = virtio_set_modern_mmio_bar(base,
|
||||
VIRTIO_MODERN_MMIO_BAR_IDX);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
Reference in New Issue
Block a user