mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-18 09:23:44 +00:00
dm: virtio: refine header file
Reuse linux common virtio header file and remove the repetitive definition. Tracked-On: #2145 Signed-off-by: Conghui Chen <conghui.chen@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
parent
09634d8215
commit
eb96914a1c
@ -206,7 +206,7 @@ vhost_vq_register_eventfd(struct vhost_dev *vdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* register ioeventfd for kick */
|
/* register ioeventfd for kick */
|
||||||
if (base->device_caps & ACRN_VIRTIO_F_VERSION_1) {
|
if (base->device_caps & (1UL << VIRTIO_F_VERSION_1)) {
|
||||||
/*
|
/*
|
||||||
* in the current implementation, if virtio 1.0 with pio
|
* in the current implementation, if virtio 1.0 with pio
|
||||||
* notity, its bar idx should be set to non-zero
|
* notity, its bar idx should be set to non-zero
|
||||||
@ -234,7 +234,7 @@ vhost_vq_register_eventfd(struct vhost_dev *vdev,
|
|||||||
} else {
|
} else {
|
||||||
bar = &vdev->base->dev->bar[base->legacy_pio_bar_idx];
|
bar = &vdev->base->dev->bar[base->legacy_pio_bar_idx];
|
||||||
ioeventfd.data = vdev->vq_idx + idx;
|
ioeventfd.data = vdev->vq_idx + idx;
|
||||||
ioeventfd.addr = bar->addr + VIRTIO_CR_QNOTIFY;
|
ioeventfd.addr = bar->addr + VIRTIO_PCI_QUEUE_NOTIFY;
|
||||||
ioeventfd.len = 2;
|
ioeventfd.len = 2;
|
||||||
ioeventfd.flags |= (ACRN_IOEVENTFD_FLAG_DATAMATCH |
|
ioeventfd.flags |= (ACRN_IOEVENTFD_FLAG_DATAMATCH |
|
||||||
ACRN_IOEVENTFD_FLAG_PIO);
|
ACRN_IOEVENTFD_FLAG_PIO);
|
||||||
@ -677,7 +677,7 @@ vhost_dev_start(struct vhost_dev *vdev)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((vdev->base->status & VIRTIO_CR_STATUS_DRIVER_OK) == 0) {
|
if ((vdev->base->status & VIRTIO_CONFIG_S_DRIVER_OK) == 0) {
|
||||||
WPRINTF("status error 0x%x\n", vdev->base->status);
|
WPRINTF("status error 0x%x\n", vdev->base->status);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ virtio_poll_timer(void *arg)
|
|||||||
|
|
||||||
for (i = 0; i < base->vops->nvq; i++) {
|
for (i = 0; i < base->vops->nvq; i++) {
|
||||||
vq = &base->queues[i];
|
vq = &base->queues[i];
|
||||||
vq->used->flags |= ACRN_VRING_USED_F_NO_NOTIFY;
|
vq->used->flags |= VRING_USED_F_NO_NOTIFY;
|
||||||
/* TODO: call notify when necessary */
|
/* TODO: call notify when necessary */
|
||||||
if (vq->notify)
|
if (vq->notify)
|
||||||
(*vq->notify)(DEV_STRUCT(base), vq);
|
(*vq->notify)(DEV_STRUCT(base), vq);
|
||||||
@ -204,10 +204,10 @@ virtio_set_io_bar(struct virtio_base *base, int barnum)
|
|||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ??? should we use CFG0 if MSI-X is disabled?
|
* ??? should we use VIRTIO_PCI_CONFIG_OFF(0) if MSI-X
|
||||||
* Existing code did not...
|
* is disabled? Existing code did not...
|
||||||
*/
|
*/
|
||||||
size = VIRTIO_CR_CFG1 + base->vops->cfgsize;
|
size = VIRTIO_PCI_CONFIG_OFF(1) + base->vops->cfgsize;
|
||||||
pci_emul_alloc_bar(base->dev, barnum, PCIBAR_IO, size);
|
pci_emul_alloc_bar(base->dev, barnum, PCIBAR_IO, size);
|
||||||
base->legacy_pio_bar_idx = barnum;
|
base->legacy_pio_bar_idx = barnum;
|
||||||
}
|
}
|
||||||
@ -286,22 +286,22 @@ virtio_vq_init(struct virtio_base *base, uint32_t pfn)
|
|||||||
vq = &base->queues[base->curq];
|
vq = &base->queues[base->curq];
|
||||||
vq->pfn = pfn;
|
vq->pfn = pfn;
|
||||||
phys = (uint64_t)pfn << VRING_PAGE_BITS;
|
phys = (uint64_t)pfn << VRING_PAGE_BITS;
|
||||||
size = virtio_vring_size(vq->qsize);
|
size = vring_size(vq->qsize, VIRTIO_PCI_VRING_ALIGN);
|
||||||
vb = paddr_guest2host(base->dev->vmctx, phys, size);
|
vb = paddr_guest2host(base->dev->vmctx, phys, size);
|
||||||
|
|
||||||
/* First page(s) are descriptors... */
|
/* First page(s) are descriptors... */
|
||||||
vq->desc = (struct virtio_desc *)vb;
|
vq->desc = (struct vring_desc *)vb;
|
||||||
vb += vq->qsize * sizeof(struct virtio_desc);
|
vb += vq->qsize * sizeof(struct vring_desc);
|
||||||
|
|
||||||
/* ... immediately followed by "avail" ring (entirely uint16_t's) */
|
/* ... immediately followed by "avail" ring (entirely uint16_t's) */
|
||||||
vq->avail = (struct virtio_vring_avail *)vb;
|
vq->avail = (struct vring_avail *)vb;
|
||||||
vb += (2 + vq->qsize + 1) * sizeof(uint16_t);
|
vb += (2 + vq->qsize + 1) * sizeof(uint16_t);
|
||||||
|
|
||||||
/* Then it's rounded up to the next page... */
|
/* Then it's rounded up to the next page... */
|
||||||
vb = (char *)roundup2((uintptr_t)vb, VRING_ALIGN);
|
vb = (char *)roundup2((uintptr_t)vb, VIRTIO_PCI_VRING_ALIGN);
|
||||||
|
|
||||||
/* ... and the last page(s) are the used ring. */
|
/* ... and the last page(s) are the used ring. */
|
||||||
vq->used = (struct virtio_vring_used *)vb;
|
vq->used = (struct vring_used *)vb;
|
||||||
|
|
||||||
/* Mark queue as allocated, and start at 0 when we use it. */
|
/* Mark queue as allocated, and start at 0 when we use it. */
|
||||||
vq->flags = VQ_ALLOC;
|
vq->flags = VQ_ALLOC;
|
||||||
@ -329,21 +329,21 @@ virtio_vq_enable(struct virtio_base *base)
|
|||||||
|
|
||||||
/* descriptors */
|
/* descriptors */
|
||||||
phys = (((uint64_t)vq->gpa_desc[1]) << 32) | vq->gpa_desc[0];
|
phys = (((uint64_t)vq->gpa_desc[1]) << 32) | vq->gpa_desc[0];
|
||||||
size = qsz * sizeof(struct virtio_desc);
|
size = qsz * sizeof(struct vring_desc);
|
||||||
vb = paddr_guest2host(base->dev->vmctx, phys, size);
|
vb = paddr_guest2host(base->dev->vmctx, phys, size);
|
||||||
vq->desc = (struct virtio_desc *)vb;
|
vq->desc = (struct vring_desc *)vb;
|
||||||
|
|
||||||
/* available ring */
|
/* available ring */
|
||||||
phys = (((uint64_t)vq->gpa_avail[1]) << 32) | vq->gpa_avail[0];
|
phys = (((uint64_t)vq->gpa_avail[1]) << 32) | vq->gpa_avail[0];
|
||||||
size = (2 + qsz + 1) * sizeof(uint16_t);
|
size = (2 + qsz + 1) * sizeof(uint16_t);
|
||||||
vb = paddr_guest2host(base->dev->vmctx, phys, size);
|
vb = paddr_guest2host(base->dev->vmctx, phys, size);
|
||||||
vq->avail = (struct virtio_vring_avail *)vb;
|
vq->avail = (struct vring_avail *)vb;
|
||||||
|
|
||||||
/* used ring */
|
/* used ring */
|
||||||
phys = (((uint64_t)vq->gpa_used[1]) << 32) | vq->gpa_used[0];
|
phys = (((uint64_t)vq->gpa_used[1]) << 32) | vq->gpa_used[0];
|
||||||
size = sizeof(uint16_t) * 3 + sizeof(struct virtio_used) * qsz;
|
size = sizeof(uint16_t) * 3 + sizeof(struct vring_used_elem) * qsz;
|
||||||
vb = paddr_guest2host(base->dev->vmctx, phys, size);
|
vb = paddr_guest2host(base->dev->vmctx, phys, size);
|
||||||
vq->used = (struct virtio_vring_used *)vb;
|
vq->used = (struct vring_used *)vb;
|
||||||
|
|
||||||
/* Mark queue as allocated, and start at 0 when we use it. */
|
/* Mark queue as allocated, and start at 0 when we use it. */
|
||||||
vq->flags = VQ_ALLOC;
|
vq->flags = VQ_ALLOC;
|
||||||
@ -359,7 +359,7 @@ virtio_vq_enable(struct virtio_base *base)
|
|||||||
* descriptor.
|
* descriptor.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
_vq_record(int i, volatile struct virtio_desc *vd, struct vmctx *ctx,
|
_vq_record(int i, volatile struct vring_desc *vd, struct vmctx *ctx,
|
||||||
struct iovec *iov, int n_iov, uint16_t *flags) {
|
struct iovec *iov, int n_iov, uint16_t *flags) {
|
||||||
|
|
||||||
if (i >= n_iov)
|
if (i >= n_iov)
|
||||||
@ -418,7 +418,7 @@ vq_getchain(struct virtio_vq_info *vq, uint16_t *pidx,
|
|||||||
u_int ndesc, n_indir;
|
u_int ndesc, n_indir;
|
||||||
u_int idx, next;
|
u_int idx, next;
|
||||||
|
|
||||||
volatile struct virtio_desc *vdir, *vindir, *vp;
|
volatile struct vring_desc *vdir, *vindir, *vp;
|
||||||
struct vmctx *ctx;
|
struct vmctx *ctx;
|
||||||
struct virtio_base *base;
|
struct virtio_base *base;
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -471,11 +471,11 @@ vq_getchain(struct virtio_vq_info *vq, uint16_t *pidx,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
vdir = &vq->desc[next];
|
vdir = &vq->desc[next];
|
||||||
if ((vdir->flags & ACRN_VRING_DESC_F_INDIRECT) == 0) {
|
if ((vdir->flags & VRING_DESC_F_INDIRECT) == 0) {
|
||||||
_vq_record(i, vdir, ctx, iov, n_iov, flags);
|
_vq_record(i, vdir, ctx, iov, n_iov, flags);
|
||||||
i++;
|
i++;
|
||||||
} else if ((base->device_caps &
|
} else if ((base->device_caps &
|
||||||
ACRN_VIRTIO_RING_F_INDIRECT_DESC) == 0) {
|
(1 << VIRTIO_RING_F_INDIRECT_DESC)) == 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: descriptor has forbidden INDIRECT flag, "
|
"%s: descriptor has forbidden INDIRECT flag, "
|
||||||
"driver confused?\r\n",
|
"driver confused?\r\n",
|
||||||
@ -502,7 +502,7 @@ vq_getchain(struct virtio_vq_info *vq, uint16_t *pidx,
|
|||||||
next = 0;
|
next = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
vp = &vindir[next];
|
vp = &vindir[next];
|
||||||
if (vp->flags & ACRN_VRING_DESC_F_INDIRECT) {
|
if (vp->flags & VRING_DESC_F_INDIRECT) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: indirect desc has INDIR flag,"
|
"%s: indirect desc has INDIR flag,"
|
||||||
" driver confused?\r\n",
|
" driver confused?\r\n",
|
||||||
@ -512,7 +512,7 @@ vq_getchain(struct virtio_vq_info *vq, uint16_t *pidx,
|
|||||||
_vq_record(i, vp, ctx, iov, n_iov, flags);
|
_vq_record(i, vp, ctx, iov, n_iov, flags);
|
||||||
if (++i > VQ_MAX_DESCRIPTORS)
|
if (++i > VQ_MAX_DESCRIPTORS)
|
||||||
goto loopy;
|
goto loopy;
|
||||||
if ((vp->flags & ACRN_VRING_DESC_F_NEXT) == 0)
|
if ((vp->flags & VRING_DESC_F_NEXT) == 0)
|
||||||
break;
|
break;
|
||||||
next = vp->next;
|
next = vp->next;
|
||||||
if (next >= n_indir) {
|
if (next >= n_indir) {
|
||||||
@ -524,7 +524,7 @@ vq_getchain(struct virtio_vq_info *vq, uint16_t *pidx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((vdir->flags & ACRN_VRING_DESC_F_NEXT) == 0)
|
if ((vdir->flags & VRING_DESC_F_NEXT) == 0)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
loopy:
|
loopy:
|
||||||
@ -557,8 +557,8 @@ void
|
|||||||
vq_relchain(struct virtio_vq_info *vq, uint16_t idx, uint32_t iolen)
|
vq_relchain(struct virtio_vq_info *vq, uint16_t idx, uint32_t iolen)
|
||||||
{
|
{
|
||||||
uint16_t uidx, mask;
|
uint16_t uidx, mask;
|
||||||
volatile struct virtio_vring_used *vuh;
|
volatile struct vring_used *vuh;
|
||||||
volatile struct virtio_used *vue;
|
volatile struct vring_used_elem *vue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notes:
|
* Notes:
|
||||||
@ -575,8 +575,8 @@ vq_relchain(struct virtio_vq_info *vq, uint16_t idx, uint32_t iolen)
|
|||||||
|
|
||||||
uidx = vuh->idx;
|
uidx = vuh->idx;
|
||||||
vue = &vuh->ring[uidx++ & mask];
|
vue = &vuh->ring[uidx++ & mask];
|
||||||
vue->idx = idx;
|
vue->id = idx;
|
||||||
vue->tlen = iolen;
|
vue->len = iolen;
|
||||||
vuh->idx = uidx;
|
vuh->idx = uidx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,7 +606,7 @@ vq_endchains(struct virtio_vq_info *vq, int used_all_avail)
|
|||||||
* Interrupt generation: if we're using EVENT_IDX,
|
* Interrupt generation: if we're using EVENT_IDX,
|
||||||
* interrupt if we've crossed the event threshold.
|
* interrupt if we've crossed the event threshold.
|
||||||
* Otherwise interrupt is generated if we added "used" entries,
|
* Otherwise interrupt is generated if we added "used" entries,
|
||||||
* but suppressed by ACRN_VRING_AVAIL_F_NO_INTERRUPT.
|
* but suppressed by VRING_AVAIL_F_NO_INTERRUPT.
|
||||||
*
|
*
|
||||||
* In any case, though, if NOTIFY_ON_EMPTY is set and the
|
* In any case, though, if NOTIFY_ON_EMPTY is set and the
|
||||||
* entire avail was processed, we need to interrupt always.
|
* entire avail was processed, we need to interrupt always.
|
||||||
@ -615,9 +615,9 @@ vq_endchains(struct virtio_vq_info *vq, int used_all_avail)
|
|||||||
old_idx = vq->save_used;
|
old_idx = vq->save_used;
|
||||||
vq->save_used = new_idx = vq->used->idx;
|
vq->save_used = new_idx = vq->used->idx;
|
||||||
if (used_all_avail &&
|
if (used_all_avail &&
|
||||||
(base->negotiated_caps & ACRN_VIRTIO_F_NOTIFY_ON_EMPTY))
|
(base->negotiated_caps & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)))
|
||||||
intr = 1;
|
intr = 1;
|
||||||
else if (base->negotiated_caps & ACRN_VIRTIO_RING_F_EVENT_IDX) {
|
else if (base->negotiated_caps & (1 << VIRTIO_RING_F_EVENT_IDX)) {
|
||||||
event_idx = VQ_USED_EVENT_IDX(vq);
|
event_idx = VQ_USED_EVENT_IDX(vq);
|
||||||
/*
|
/*
|
||||||
* This calculation is per docs and the kernel
|
* This calculation is per docs and the kernel
|
||||||
@ -627,7 +627,7 @@ vq_endchains(struct virtio_vq_info *vq, int used_all_avail)
|
|||||||
(uint16_t)(new_idx - old_idx);
|
(uint16_t)(new_idx - old_idx);
|
||||||
} else {
|
} else {
|
||||||
intr = new_idx != old_idx &&
|
intr = new_idx != old_idx &&
|
||||||
!(vq->avail->flags & ACRN_VRING_AVAIL_F_NO_INTERRUPT);
|
!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT);
|
||||||
}
|
}
|
||||||
if (intr)
|
if (intr)
|
||||||
vq_interrupt(base, vq);
|
vq_interrupt(base, vq);
|
||||||
@ -654,7 +654,7 @@ void vq_clear_used_ring_flags(struct virtio_base *base, struct virtio_vq_info *v
|
|||||||
if (virtio_poll_enabled && backend_type == BACKEND_VBSU && polling_in_progress == 1)
|
if (virtio_poll_enabled && backend_type == BACKEND_VBSU && polling_in_progress == 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vq->used->flags &= ~ACRN_VRING_USED_F_NO_NOTIFY;
|
vq->used->flags &= ~VRING_USED_F_NO_NOTIFY;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct config_reg {
|
struct config_reg {
|
||||||
@ -666,39 +666,39 @@ struct config_reg {
|
|||||||
|
|
||||||
/* Note: these are in sorted order to make for a fast search */
|
/* Note: these are in sorted order to make for a fast search */
|
||||||
static struct config_reg legacy_config_regs[] = {
|
static struct config_reg legacy_config_regs[] = {
|
||||||
{ VIRTIO_CR_HOSTCAP, 4, 1, "HOSTCAP" },
|
{ VIRTIO_PCI_HOST_FEATURES, 4, 1, "HOSTCAP" },
|
||||||
{ VIRTIO_CR_GUESTCAP, 4, 0, "GUESTCAP" },
|
{ VIRTIO_PCI_GUEST_FEATURES, 4, 0, "GUESTCAP" },
|
||||||
{ VIRTIO_CR_PFN, 4, 0, "PFN" },
|
{ VIRTIO_PCI_QUEUE_PFN, 4, 0, "PFN" },
|
||||||
{ VIRTIO_CR_QNUM, 2, 1, "QNUM" },
|
{ VIRTIO_PCI_QUEUE_NUM, 2, 1, "QNUM" },
|
||||||
{ VIRTIO_CR_QSEL, 2, 0, "QSEL" },
|
{ VIRTIO_PCI_QUEUE_SEL, 2, 0, "QSEL" },
|
||||||
{ VIRTIO_CR_QNOTIFY, 2, 0, "QNOTIFY" },
|
{ VIRTIO_PCI_QUEUE_NOTIFY, 2, 0, "QNOTIFY" },
|
||||||
{ VIRTIO_CR_STATUS, 1, 0, "STATUS" },
|
{ VIRTIO_PCI_STATUS, 1, 0, "STATUS" },
|
||||||
{ VIRTIO_CR_ISR, 1, 0, "ISR" },
|
{ VIRTIO_PCI_ISR, 1, 0, "ISR" },
|
||||||
{ VIRTIO_CR_CFGVEC, 2, 0, "CFGVEC" },
|
{ VIRTIO_MSI_CONFIG_VECTOR, 2, 0, "CFGVEC" },
|
||||||
{ VIRTIO_CR_QVEC, 2, 0, "QVEC" },
|
{ VIRTIO_MSI_QUEUE_VECTOR, 2, 0, "QVEC" },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Note: these are in sorted order to make for a fast search */
|
/* Note: these are in sorted order to make for a fast search */
|
||||||
static struct config_reg modern_config_regs[] = {
|
static struct config_reg modern_config_regs[] = {
|
||||||
{ VIRTIO_COMMON_DFSELECT, 4, 0, "DFSELECT" },
|
{ VIRTIO_PCI_COMMON_DFSELECT, 4, 0, "DFSELECT" },
|
||||||
{ VIRTIO_COMMON_DF, 4, 1, "DF" },
|
{ VIRTIO_PCI_COMMON_DF, 4, 1, "DF" },
|
||||||
{ VIRTIO_COMMON_GFSELECT, 4, 0, "GFSELECT" },
|
{ VIRTIO_PCI_COMMON_GFSELECT, 4, 0, "GFSELECT" },
|
||||||
{ VIRTIO_COMMON_GF, 4, 0, "GF" },
|
{ VIRTIO_PCI_COMMON_GF, 4, 0, "GF" },
|
||||||
{ VIRTIO_COMMON_MSIX, 2, 0, "MSIX" },
|
{ VIRTIO_PCI_COMMON_MSIX, 2, 0, "MSIX" },
|
||||||
{ VIRTIO_COMMON_NUMQ, 2, 1, "NUMQ" },
|
{ VIRTIO_PCI_COMMON_NUMQ, 2, 1, "NUMQ" },
|
||||||
{ VIRTIO_COMMON_STATUS, 1, 0, "STATUS" },
|
{ VIRTIO_PCI_COMMON_STATUS, 1, 0, "STATUS" },
|
||||||
{ VIRTIO_COMMON_CFGGENERATION, 1, 1, "CFGGENERATION" },
|
{ VIRTIO_PCI_COMMON_CFGGENERATION, 1, 1, "CFGGENERATION" },
|
||||||
{ VIRTIO_COMMON_Q_SELECT, 2, 0, "Q_SELECT" },
|
{ VIRTIO_PCI_COMMON_Q_SELECT, 2, 0, "Q_SELECT" },
|
||||||
{ VIRTIO_COMMON_Q_SIZE, 2, 0, "Q_SIZE" },
|
{ VIRTIO_PCI_COMMON_Q_SIZE, 2, 0, "Q_SIZE" },
|
||||||
{ VIRTIO_COMMON_Q_MSIX, 2, 0, "Q_MSIX" },
|
{ VIRTIO_PCI_COMMON_Q_MSIX, 2, 0, "Q_MSIX" },
|
||||||
{ VIRTIO_COMMON_Q_ENABLE, 2, 0, "Q_ENABLE" },
|
{ VIRTIO_PCI_COMMON_Q_ENABLE, 2, 0, "Q_ENABLE" },
|
||||||
{ VIRTIO_COMMON_Q_NOFF, 2, 1, "Q_NOFF" },
|
{ VIRTIO_PCI_COMMON_Q_NOFF, 2, 1, "Q_NOFF" },
|
||||||
{ VIRTIO_COMMON_Q_DESCLO, 4, 0, "Q_DESCLO" },
|
{ VIRTIO_PCI_COMMON_Q_DESCLO, 4, 0, "Q_DESCLO" },
|
||||||
{ VIRTIO_COMMON_Q_DESCHI, 4, 0, "Q_DESCHI" },
|
{ VIRTIO_PCI_COMMON_Q_DESCHI, 4, 0, "Q_DESCHI" },
|
||||||
{ VIRTIO_COMMON_Q_AVAILLO, 4, 0, "Q_AVAILLO" },
|
{ VIRTIO_PCI_COMMON_Q_AVAILLO, 4, 0, "Q_AVAILLO" },
|
||||||
{ VIRTIO_COMMON_Q_AVAILHI, 4, 0, "Q_AVAILHI" },
|
{ VIRTIO_PCI_COMMON_Q_AVAILHI, 4, 0, "Q_AVAILHI" },
|
||||||
{ VIRTIO_COMMON_Q_USEDLO, 4, 0, "Q_USEDLO" },
|
{ VIRTIO_PCI_COMMON_Q_USEDLO, 4, 0, "Q_USEDLO" },
|
||||||
{ VIRTIO_COMMON_Q_USEDHI, 4, 0, "Q_USEDHI" },
|
{ VIRTIO_PCI_COMMON_Q_USEDHI, 4, 0, "Q_USEDHI" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline const struct config_reg *
|
static inline const struct config_reg *
|
||||||
@ -769,9 +769,9 @@ virtio_pci_legacy_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
|
|||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
if (pci_msix_enabled(dev))
|
if (pci_msix_enabled(dev))
|
||||||
virtio_config_size = VIRTIO_CR_CFG1;
|
virtio_config_size = VIRTIO_PCI_CONFIG_OFF(1);
|
||||||
else
|
else
|
||||||
virtio_config_size = VIRTIO_CR_CFG0;
|
virtio_config_size = VIRTIO_PCI_CONFIG_OFF(0);
|
||||||
|
|
||||||
if (offset >= virtio_config_size) {
|
if (offset >= virtio_config_size) {
|
||||||
/*
|
/*
|
||||||
@ -806,39 +806,39 @@ bad:
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case VIRTIO_CR_HOSTCAP:
|
case VIRTIO_PCI_HOST_FEATURES:
|
||||||
value = base->device_caps;
|
value = base->device_caps;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_GUESTCAP:
|
case VIRTIO_PCI_GUEST_FEATURES:
|
||||||
value = base->negotiated_caps;
|
value = base->negotiated_caps;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_PFN:
|
case VIRTIO_PCI_QUEUE_PFN:
|
||||||
if (base->curq < vops->nvq)
|
if (base->curq < vops->nvq)
|
||||||
value = base->queues[base->curq].pfn;
|
value = base->queues[base->curq].pfn;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_QNUM:
|
case VIRTIO_PCI_QUEUE_NUM:
|
||||||
value = base->curq < vops->nvq ?
|
value = base->curq < vops->nvq ?
|
||||||
base->queues[base->curq].qsize : 0;
|
base->queues[base->curq].qsize : 0;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_QSEL:
|
case VIRTIO_PCI_QUEUE_SEL:
|
||||||
value = base->curq;
|
value = base->curq;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_QNOTIFY:
|
case VIRTIO_PCI_QUEUE_NOTIFY:
|
||||||
value = 0; /* XXX */
|
value = 0; /* XXX */
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_STATUS:
|
case VIRTIO_PCI_STATUS:
|
||||||
value = base->status;
|
value = base->status;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_ISR:
|
case VIRTIO_PCI_ISR:
|
||||||
value = base->isr;
|
value = base->isr;
|
||||||
base->isr = 0; /* a read clears this flag */
|
base->isr = 0; /* a read clears this flag */
|
||||||
if (value)
|
if (value)
|
||||||
pci_lintr_deassert(dev);
|
pci_lintr_deassert(dev);
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_CFGVEC:
|
case VIRTIO_MSI_CONFIG_VECTOR:
|
||||||
value = base->msix_cfg_idx;
|
value = base->msix_cfg_idx;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_QVEC:
|
case VIRTIO_MSI_QUEUE_VECTOR:
|
||||||
value = base->curq < vops->nvq ?
|
value = base->curq < vops->nvq ?
|
||||||
base->queues[base->curq].msix_idx :
|
base->queues[base->curq].msix_idx :
|
||||||
VIRTIO_MSI_NO_VECTOR;
|
VIRTIO_MSI_NO_VECTOR;
|
||||||
@ -882,9 +882,9 @@ virtio_pci_legacy_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
|
|||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
if (pci_msix_enabled(dev))
|
if (pci_msix_enabled(dev))
|
||||||
virtio_config_size = VIRTIO_CR_CFG1;
|
virtio_config_size = VIRTIO_PCI_CONFIG_OFF(1);
|
||||||
else
|
else
|
||||||
virtio_config_size = VIRTIO_CR_CFG0;
|
virtio_config_size = VIRTIO_PCI_CONFIG_OFF(0);
|
||||||
|
|
||||||
if (offset >= virtio_config_size) {
|
if (offset >= virtio_config_size) {
|
||||||
/*
|
/*
|
||||||
@ -923,18 +923,18 @@ bad:
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case VIRTIO_CR_GUESTCAP:
|
case VIRTIO_PCI_GUEST_FEATURES:
|
||||||
base->negotiated_caps = value & base->device_caps;
|
base->negotiated_caps = value & base->device_caps;
|
||||||
if (vops->apply_features)
|
if (vops->apply_features)
|
||||||
(*vops->apply_features)(DEV_STRUCT(base),
|
(*vops->apply_features)(DEV_STRUCT(base),
|
||||||
base->negotiated_caps);
|
base->negotiated_caps);
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_PFN:
|
case VIRTIO_PCI_QUEUE_PFN:
|
||||||
if (base->curq >= vops->nvq)
|
if (base->curq >= vops->nvq)
|
||||||
goto bad_qindex;
|
goto bad_qindex;
|
||||||
virtio_vq_init(base, value);
|
virtio_vq_init(base, value);
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_QSEL:
|
case VIRTIO_PCI_QUEUE_SEL:
|
||||||
/*
|
/*
|
||||||
* Note that the guest is allowed to select an
|
* Note that the guest is allowed to select an
|
||||||
* invalid queue; we just need to return a QNUM
|
* invalid queue; we just need to return a QNUM
|
||||||
@ -942,7 +942,7 @@ bad:
|
|||||||
*/
|
*/
|
||||||
base->curq = value;
|
base->curq = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_QNOTIFY:
|
case VIRTIO_PCI_QUEUE_NOTIFY:
|
||||||
if (value >= vops->nvq) {
|
if (value >= vops->nvq) {
|
||||||
fprintf(stderr, "%s: queue %d notify out of range\r\n",
|
fprintf(stderr, "%s: queue %d notify out of range\r\n",
|
||||||
name, (int)value);
|
name, (int)value);
|
||||||
@ -958,13 +958,13 @@ bad:
|
|||||||
"%s: qnotify queue %d: missing vq/vops notify\r\n",
|
"%s: qnotify queue %d: missing vq/vops notify\r\n",
|
||||||
name, (int)value);
|
name, (int)value);
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_STATUS:
|
case VIRTIO_PCI_STATUS:
|
||||||
base->status = value;
|
base->status = value;
|
||||||
if (vops->set_status)
|
if (vops->set_status)
|
||||||
(*vops->set_status)(DEV_STRUCT(base), value);
|
(*vops->set_status)(DEV_STRUCT(base), value);
|
||||||
if (value == 0)
|
if (value == 0)
|
||||||
(*vops->reset)(DEV_STRUCT(base));
|
(*vops->reset)(DEV_STRUCT(base));
|
||||||
if ((value & VIRTIO_CR_STATUS_DRIVER_OK) &&
|
if ((value & VIRTIO_CONFIG_S_DRIVER_OK) &&
|
||||||
base->backend_type == BACKEND_VBSU &&
|
base->backend_type == BACKEND_VBSU &&
|
||||||
virtio_poll_enabled) {
|
virtio_poll_enabled) {
|
||||||
base->polling_timer.clockid = CLOCK_MONOTONIC;
|
base->polling_timer.clockid = CLOCK_MONOTONIC;
|
||||||
@ -976,10 +976,10 @@ bad:
|
|||||||
virtio_start_timer(&base->polling_timer, 5, 0);
|
virtio_start_timer(&base->polling_timer, 5, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_CFGVEC:
|
case VIRTIO_MSI_CONFIG_VECTOR:
|
||||||
base->msix_cfg_idx = value;
|
base->msix_cfg_idx = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_CR_QVEC:
|
case VIRTIO_MSI_QUEUE_VECTOR:
|
||||||
if (base->curq >= vops->nvq)
|
if (base->curq >= vops->nvq)
|
||||||
goto bad_qindex;
|
goto bad_qindex;
|
||||||
vq = &base->queues[base->curq];
|
vq = &base->queues[base->curq];
|
||||||
@ -1154,7 +1154,7 @@ virtio_set_modern_bar(struct virtio_base *base, bool use_notify_pio)
|
|||||||
|
|
||||||
vops = base->vops;
|
vops = base->vops;
|
||||||
|
|
||||||
if (!vops || (base->device_caps & ACRN_VIRTIO_F_VERSION_1) == 0)
|
if (!vops || (base->device_caps & (1UL << VIRTIO_F_VERSION_1)) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (use_notify_pio)
|
if (use_notify_pio)
|
||||||
@ -1181,12 +1181,12 @@ virtio_set_modern_bar(struct virtio_base *base, bool use_notify_pio)
|
|||||||
void
|
void
|
||||||
virtio_dev_error(struct virtio_base *base)
|
virtio_dev_error(struct virtio_base *base)
|
||||||
{
|
{
|
||||||
if (base->negotiated_caps & ACRN_VIRTIO_F_VERSION_1) {
|
if (base->negotiated_caps & (1UL << VIRTIO_F_VERSION_1)) {
|
||||||
/* see 2.1.2. if DRIVER_OK is set, need to send
|
/* see 2.1.2. if DRIVER_OK is set, need to send
|
||||||
* a device configuration change notification to the driver
|
* a device configuration change notification to the driver
|
||||||
*/
|
*/
|
||||||
base->status |= VIRTIO_CR_STATUS_NEEDS_RESET;
|
base->status |= VIRTIO_CONFIG_S_NEEDS_RESET;
|
||||||
if (base->status & VIRTIO_CR_STATUS_DRIVER_OK)
|
if (base->status & VIRTIO_CONFIG_S_DRIVER_OK)
|
||||||
virtio_config_changed(base);
|
virtio_config_changed(base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1251,10 +1251,10 @@ virtio_common_cfg_read(struct pci_vdev *dev, uint64_t offset, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case VIRTIO_COMMON_DFSELECT:
|
case VIRTIO_PCI_COMMON_DFSELECT:
|
||||||
value = base->device_feature_select;
|
value = base->device_feature_select;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_DF:
|
case VIRTIO_PCI_COMMON_DF:
|
||||||
if (base->device_feature_select == 0)
|
if (base->device_feature_select == 0)
|
||||||
value = base->device_caps & 0xffffffff;
|
value = base->device_caps & 0xffffffff;
|
||||||
else if (base->device_feature_select == 1)
|
else if (base->device_feature_select == 1)
|
||||||
@ -1262,10 +1262,10 @@ virtio_common_cfg_read(struct pci_vdev *dev, uint64_t offset, int size)
|
|||||||
else /* present 0, see 4.1.4.3.1 */
|
else /* present 0, see 4.1.4.3.1 */
|
||||||
value = 0;
|
value = 0;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_GFSELECT:
|
case VIRTIO_PCI_COMMON_GFSELECT:
|
||||||
value = base->driver_feature_select;
|
value = base->driver_feature_select;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_GF:
|
case VIRTIO_PCI_COMMON_GF:
|
||||||
/* see 4.1.4.3.1. Present any valid feature bits the driver
|
/* see 4.1.4.3.1. Present any valid feature bits the driver
|
||||||
* has written in driver_feature. Valid feature bits are those
|
* has written in driver_feature. Valid feature bits are those
|
||||||
* which are subset of the corresponding device_feature bits
|
* which are subset of the corresponding device_feature bits
|
||||||
@ -1277,58 +1277,58 @@ virtio_common_cfg_read(struct pci_vdev *dev, uint64_t offset, int size)
|
|||||||
else
|
else
|
||||||
value = 0;
|
value = 0;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_MSIX:
|
case VIRTIO_PCI_COMMON_MSIX:
|
||||||
value = base->msix_cfg_idx;
|
value = base->msix_cfg_idx;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_NUMQ:
|
case VIRTIO_PCI_COMMON_NUMQ:
|
||||||
value = vops->nvq;
|
value = vops->nvq;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_STATUS:
|
case VIRTIO_PCI_COMMON_STATUS:
|
||||||
value = base->status;
|
value = base->status;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_CFGGENERATION:
|
case VIRTIO_PCI_COMMON_CFGGENERATION:
|
||||||
value = base->config_generation;
|
value = base->config_generation;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_SELECT:
|
case VIRTIO_PCI_COMMON_Q_SELECT:
|
||||||
value = base->curq;
|
value = base->curq;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_SIZE:
|
case VIRTIO_PCI_COMMON_Q_SIZE:
|
||||||
value = base->curq < vops->nvq ?
|
value = base->curq < vops->nvq ?
|
||||||
base->queues[base->curq].qsize : 0;
|
base->queues[base->curq].qsize : 0;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_MSIX:
|
case VIRTIO_PCI_COMMON_Q_MSIX:
|
||||||
value = base->curq < vops->nvq ?
|
value = base->curq < vops->nvq ?
|
||||||
base->queues[base->curq].msix_idx :
|
base->queues[base->curq].msix_idx :
|
||||||
VIRTIO_MSI_NO_VECTOR;
|
VIRTIO_MSI_NO_VECTOR;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_ENABLE:
|
case VIRTIO_PCI_COMMON_Q_ENABLE:
|
||||||
value = base->curq < vops->nvq ?
|
value = base->curq < vops->nvq ?
|
||||||
base->queues[base->curq].enabled : 0;
|
base->queues[base->curq].enabled : 0;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_NOFF:
|
case VIRTIO_PCI_COMMON_Q_NOFF:
|
||||||
value = base->curq;
|
value = base->curq;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_DESCLO:
|
case VIRTIO_PCI_COMMON_Q_DESCLO:
|
||||||
value = base->curq < vops->nvq ?
|
value = base->curq < vops->nvq ?
|
||||||
base->queues[base->curq].gpa_desc[0] : 0;
|
base->queues[base->curq].gpa_desc[0] : 0;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_DESCHI:
|
case VIRTIO_PCI_COMMON_Q_DESCHI:
|
||||||
value = base->curq < vops->nvq ?
|
value = base->curq < vops->nvq ?
|
||||||
base->queues[base->curq].gpa_desc[1] : 0;
|
base->queues[base->curq].gpa_desc[1] : 0;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_AVAILLO:
|
case VIRTIO_PCI_COMMON_Q_AVAILLO:
|
||||||
value = base->curq < vops->nvq ?
|
value = base->curq < vops->nvq ?
|
||||||
base->queues[base->curq].gpa_avail[0] : 0;
|
base->queues[base->curq].gpa_avail[0] : 0;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_AVAILHI:
|
case VIRTIO_PCI_COMMON_Q_AVAILHI:
|
||||||
value = base->curq < vops->nvq ?
|
value = base->curq < vops->nvq ?
|
||||||
base->queues[base->curq].gpa_avail[1] : 0;
|
base->queues[base->curq].gpa_avail[1] : 0;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_USEDLO:
|
case VIRTIO_PCI_COMMON_Q_USEDLO:
|
||||||
value = base->curq < vops->nvq ?
|
value = base->curq < vops->nvq ?
|
||||||
base->queues[base->curq].gpa_used[0] : 0;
|
base->queues[base->curq].gpa_used[0] : 0;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_USEDHI:
|
case VIRTIO_PCI_COMMON_Q_USEDHI:
|
||||||
value = base->curq < vops->nvq ?
|
value = base->curq < vops->nvq ?
|
||||||
base->queues[base->curq].gpa_used[1] : 0;
|
base->queues[base->curq].gpa_used[1] : 0;
|
||||||
break;
|
break;
|
||||||
@ -1372,14 +1372,14 @@ virtio_common_cfg_write(struct pci_vdev *dev, uint64_t offset, int size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case VIRTIO_COMMON_DFSELECT:
|
case VIRTIO_PCI_COMMON_DFSELECT:
|
||||||
base->device_feature_select = value;
|
base->device_feature_select = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_GFSELECT:
|
case VIRTIO_PCI_COMMON_GFSELECT:
|
||||||
base->driver_feature_select = value;
|
base->driver_feature_select = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_GF:
|
case VIRTIO_PCI_COMMON_GF:
|
||||||
if (base->status & VIRTIO_CR_STATUS_DRIVER_OK)
|
if (base->status & VIRTIO_CONFIG_S_DRIVER_OK)
|
||||||
break;
|
break;
|
||||||
if (base->driver_feature_select < 2) {
|
if (base->driver_feature_select < 2) {
|
||||||
value &= 0xffffffff;
|
value &= 0xffffffff;
|
||||||
@ -1391,10 +1391,10 @@ virtio_common_cfg_write(struct pci_vdev *dev, uint64_t offset, int size,
|
|||||||
base->negotiated_caps);
|
base->negotiated_caps);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_MSIX:
|
case VIRTIO_PCI_COMMON_MSIX:
|
||||||
base->msix_cfg_idx = value;
|
base->msix_cfg_idx = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_STATUS:
|
case VIRTIO_PCI_COMMON_STATUS:
|
||||||
base->status = value & 0xff;
|
base->status = value & 0xff;
|
||||||
if (vops->set_status)
|
if (vops->set_status)
|
||||||
(*vops->set_status)(DEV_STRUCT(base), value);
|
(*vops->set_status)(DEV_STRUCT(base), value);
|
||||||
@ -1402,7 +1402,7 @@ virtio_common_cfg_write(struct pci_vdev *dev, uint64_t offset, int size,
|
|||||||
(*vops->reset)(DEV_STRUCT(base));
|
(*vops->reset)(DEV_STRUCT(base));
|
||||||
/* TODO: virtio poll mode for modern devices */
|
/* TODO: virtio poll mode for modern devices */
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_SELECT:
|
case VIRTIO_PCI_COMMON_Q_SELECT:
|
||||||
/*
|
/*
|
||||||
* Note that the guest is allowed to select an
|
* Note that the guest is allowed to select an
|
||||||
* invalid queue; we just need to return a QNUM
|
* invalid queue; we just need to return a QNUM
|
||||||
@ -1410,54 +1410,54 @@ virtio_common_cfg_write(struct pci_vdev *dev, uint64_t offset, int size,
|
|||||||
*/
|
*/
|
||||||
base->curq = value;
|
base->curq = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_SIZE:
|
case VIRTIO_PCI_COMMON_Q_SIZE:
|
||||||
if (base->curq >= vops->nvq)
|
if (base->curq >= vops->nvq)
|
||||||
goto bad_qindex;
|
goto bad_qindex;
|
||||||
vq = &base->queues[base->curq];
|
vq = &base->queues[base->curq];
|
||||||
vq->qsize = value;
|
vq->qsize = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_MSIX:
|
case VIRTIO_PCI_COMMON_Q_MSIX:
|
||||||
if (base->curq >= vops->nvq)
|
if (base->curq >= vops->nvq)
|
||||||
goto bad_qindex;
|
goto bad_qindex;
|
||||||
vq = &base->queues[base->curq];
|
vq = &base->queues[base->curq];
|
||||||
vq->msix_idx = value;
|
vq->msix_idx = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_ENABLE:
|
case VIRTIO_PCI_COMMON_Q_ENABLE:
|
||||||
if (base->curq >= vops->nvq)
|
if (base->curq >= vops->nvq)
|
||||||
goto bad_qindex;
|
goto bad_qindex;
|
||||||
virtio_vq_enable(base);
|
virtio_vq_enable(base);
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_DESCLO:
|
case VIRTIO_PCI_COMMON_Q_DESCLO:
|
||||||
if (base->curq >= vops->nvq)
|
if (base->curq >= vops->nvq)
|
||||||
goto bad_qindex;
|
goto bad_qindex;
|
||||||
vq = &base->queues[base->curq];
|
vq = &base->queues[base->curq];
|
||||||
vq->gpa_desc[0] = value;
|
vq->gpa_desc[0] = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_DESCHI:
|
case VIRTIO_PCI_COMMON_Q_DESCHI:
|
||||||
if (base->curq >= vops->nvq)
|
if (base->curq >= vops->nvq)
|
||||||
goto bad_qindex;
|
goto bad_qindex;
|
||||||
vq = &base->queues[base->curq];
|
vq = &base->queues[base->curq];
|
||||||
vq->gpa_desc[1] = value;
|
vq->gpa_desc[1] = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_AVAILLO:
|
case VIRTIO_PCI_COMMON_Q_AVAILLO:
|
||||||
if (base->curq >= vops->nvq)
|
if (base->curq >= vops->nvq)
|
||||||
goto bad_qindex;
|
goto bad_qindex;
|
||||||
vq = &base->queues[base->curq];
|
vq = &base->queues[base->curq];
|
||||||
vq->gpa_avail[0] = value;
|
vq->gpa_avail[0] = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_AVAILHI:
|
case VIRTIO_PCI_COMMON_Q_AVAILHI:
|
||||||
if (base->curq >= vops->nvq)
|
if (base->curq >= vops->nvq)
|
||||||
goto bad_qindex;
|
goto bad_qindex;
|
||||||
vq = &base->queues[base->curq];
|
vq = &base->queues[base->curq];
|
||||||
vq->gpa_avail[1] = value;
|
vq->gpa_avail[1] = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_USEDLO:
|
case VIRTIO_PCI_COMMON_Q_USEDLO:
|
||||||
if (base->curq >= vops->nvq)
|
if (base->curq >= vops->nvq)
|
||||||
goto bad_qindex;
|
goto bad_qindex;
|
||||||
vq = &base->queues[base->curq];
|
vq = &base->queues[base->curq];
|
||||||
vq->gpa_used[0] = value;
|
vq->gpa_used[0] = value;
|
||||||
break;
|
break;
|
||||||
case VIRTIO_COMMON_Q_USEDHI:
|
case VIRTIO_PCI_COMMON_Q_USEDHI:
|
||||||
if (base->curq >= vops->nvq)
|
if (base->curq >= vops->nvq)
|
||||||
goto bad_qindex;
|
goto bad_qindex;
|
||||||
vq = &base->queues[base->curq];
|
vq = &base->queues[base->curq];
|
||||||
|
@ -224,7 +224,7 @@ virtio_audio_k_set_status(void *base, uint64_t status)
|
|||||||
nvq = virt_audio->base.vops->nvq;
|
nvq = virt_audio->base.vops->nvq;
|
||||||
|
|
||||||
if (virt_audio->vbs_k.kstatus == VIRTIO_DEV_INIT_SUCCESS &&
|
if (virt_audio->vbs_k.kstatus == VIRTIO_DEV_INIT_SUCCESS &&
|
||||||
(status & VIRTIO_CR_STATUS_DRIVER_OK)) {
|
(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||||
/* time to kickoff VBS-K side */
|
/* time to kickoff VBS-K side */
|
||||||
/* init vdev first */
|
/* init vdev first */
|
||||||
rc = virtio_audio_kernel_dev_set(
|
rc = virtio_audio_kernel_dev_set(
|
||||||
|
@ -65,7 +65,7 @@
|
|||||||
(VIRTIO_BLK_F_SEG_MAX | \
|
(VIRTIO_BLK_F_SEG_MAX | \
|
||||||
VIRTIO_BLK_F_BLK_SIZE | \
|
VIRTIO_BLK_F_BLK_SIZE | \
|
||||||
VIRTIO_BLK_F_TOPOLOGY | \
|
VIRTIO_BLK_F_TOPOLOGY | \
|
||||||
ACRN_VIRTIO_RING_F_INDIRECT_DESC) /* indirect descriptors */
|
(1 << VIRTIO_RING_F_INDIRECT_DESC)) /* indirect descriptors */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Writeback cache bits
|
* Writeback cache bits
|
||||||
@ -218,7 +218,7 @@ virtio_blk_proc(struct virtio_blk *blk, struct virtio_vq_info *vq)
|
|||||||
assert(n >= 2 && n <= BLOCKIF_IOV_MAX + 2);
|
assert(n >= 2 && n <= BLOCKIF_IOV_MAX + 2);
|
||||||
|
|
||||||
io = &blk->ios[idx];
|
io = &blk->ios[idx];
|
||||||
assert((flags[0] & ACRN_VRING_DESC_F_WRITE) == 0);
|
assert((flags[0] & VRING_DESC_F_WRITE) == 0);
|
||||||
assert(iov[0].iov_len == sizeof(struct virtio_blk_hdr));
|
assert(iov[0].iov_len == sizeof(struct virtio_blk_hdr));
|
||||||
vbh = iov[0].iov_base;
|
vbh = iov[0].iov_base;
|
||||||
memcpy(&io->req.iov, &iov[1], sizeof(struct iovec) * (n - 2));
|
memcpy(&io->req.iov, &iov[1], sizeof(struct iovec) * (n - 2));
|
||||||
@ -226,7 +226,7 @@ virtio_blk_proc(struct virtio_blk *blk, struct virtio_vq_info *vq)
|
|||||||
io->req.offset = vbh->sector * DEV_BSIZE;
|
io->req.offset = vbh->sector * DEV_BSIZE;
|
||||||
io->status = iov[--n].iov_base;
|
io->status = iov[--n].iov_base;
|
||||||
assert(iov[n].iov_len == 1);
|
assert(iov[n].iov_len == 1);
|
||||||
assert(flags[n] & ACRN_VRING_DESC_F_WRITE);
|
assert(flags[n] & VRING_DESC_F_WRITE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX
|
* XXX
|
||||||
@ -244,7 +244,7 @@ virtio_blk_proc(struct virtio_blk *blk, struct virtio_vq_info *vq)
|
|||||||
* therefore test the inverse of the descriptor bit
|
* therefore test the inverse of the descriptor bit
|
||||||
* to the op.
|
* to the op.
|
||||||
*/
|
*/
|
||||||
assert(((flags[i] & ACRN_VRING_DESC_F_WRITE) == 0) == writeop);
|
assert(((flags[i] & VRING_DESC_F_WRITE) == 0) == writeop);
|
||||||
iolen += iov[i].iov_len;
|
iolen += iov[i].iov_len;
|
||||||
}
|
}
|
||||||
io->req.resid = iolen;
|
io->req.resid = iolen;
|
||||||
|
@ -405,7 +405,7 @@ virtio_console_notify_rx(void *vdev, struct virtio_vq_info *vq)
|
|||||||
|
|
||||||
if (!port->rx_ready) {
|
if (!port->rx_ready) {
|
||||||
port->rx_ready = 1;
|
port->rx_ready = 1;
|
||||||
vq->used->flags |= ACRN_VRING_USED_F_NO_NOTIFY;
|
vq->used->flags |= VRING_USED_F_NO_NOTIFY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ virtio_hyper_dmabuf_set_status(void *base, uint64_t status)
|
|||||||
nvq = hyper_dmabuf->base.vops->nvq;
|
nvq = hyper_dmabuf->base.vops->nvq;
|
||||||
|
|
||||||
if (kstatus == VIRTIO_DEV_INIT_SUCCESS &&
|
if (kstatus == VIRTIO_DEV_INIT_SUCCESS &&
|
||||||
(status & VIRTIO_CR_STATUS_DRIVER_OK)) {
|
(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||||
/* time to kickoff VBS-K side */
|
/* time to kickoff VBS-K side */
|
||||||
/* init vdev first */
|
/* init vdev first */
|
||||||
rc = virtio_hyper_dmabuf_k_dev_set(
|
rc = virtio_hyper_dmabuf_k_dev_set(
|
||||||
|
@ -47,7 +47,7 @@ static int virtio_input_debug;
|
|||||||
/*
|
/*
|
||||||
* Host capabilities
|
* Host capabilities
|
||||||
*/
|
*/
|
||||||
#define VIRTIO_INPUT_S_HOSTCAPS (ACRN_VIRTIO_F_VERSION_1)
|
#define VIRTIO_INPUT_S_HOSTCAPS (1UL << VIRTIO_F_VERSION_1)
|
||||||
|
|
||||||
enum virtio_input_config_select {
|
enum virtio_input_config_select {
|
||||||
VIRTIO_INPUT_CFG_UNSET = 0x00,
|
VIRTIO_INPUT_CFG_UNSET = 0x00,
|
||||||
@ -170,7 +170,7 @@ virtio_input_set_status(void *vdev, uint64_t status)
|
|||||||
{
|
{
|
||||||
struct virtio_input *vi = vdev;
|
struct virtio_input *vi = vdev;
|
||||||
|
|
||||||
if (status & VIRTIO_CR_STATUS_DRIVER_OK) {
|
if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
|
||||||
if (!vi->ready)
|
if (!vi->ready)
|
||||||
vi->ready = true;
|
vi->ready = true;
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ virtio_ipu_set_status(void *base, uint64_t status)
|
|||||||
ipu = (struct virtio_ipu *) base;
|
ipu = (struct virtio_ipu *) base;
|
||||||
nvq = ipu->base.vops->nvq;
|
nvq = ipu->base.vops->nvq;
|
||||||
if (ipu->vbs_k.ipu_kstatus == VIRTIO_DEV_INIT_SUCCESS &&
|
if (ipu->vbs_k.ipu_kstatus == VIRTIO_DEV_INIT_SUCCESS &&
|
||||||
(status & VIRTIO_CR_STATUS_DRIVER_OK)) {
|
(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||||
/* time to kickoff VBS-K side */
|
/* time to kickoff VBS-K side */
|
||||||
/* init vdev first */
|
/* init vdev first */
|
||||||
rc = virtio_ipu_k_dev_set(
|
rc = virtio_ipu_k_dev_set(
|
||||||
|
@ -1583,7 +1583,7 @@ vmei_notify_tx(void *data, struct virtio_vq_info *vq)
|
|||||||
|
|
||||||
pthread_mutex_lock(&vmei->tx_mutex);
|
pthread_mutex_lock(&vmei->tx_mutex);
|
||||||
DPRINTF("TX: New OUT buffer available!\n");
|
DPRINTF("TX: New OUT buffer available!\n");
|
||||||
vq->used->flags |= ACRN_VRING_USED_F_NO_NOTIFY;
|
vq->used->flags |= VRING_USED_F_NO_NOTIFY;
|
||||||
pthread_mutex_unlock(&vmei->tx_mutex);
|
pthread_mutex_unlock(&vmei->tx_mutex);
|
||||||
|
|
||||||
while (vq_has_descs(vq))
|
while (vq_has_descs(vq))
|
||||||
@ -1899,7 +1899,7 @@ static void *vmei_rx_thread(void *param)
|
|||||||
if (err || vmei->status == VMEI_STST_DEINIT)
|
if (err || vmei->status == VMEI_STST_DEINIT)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
vq->used->flags |= ACRN_VRING_USED_F_NO_NOTIFY;
|
vq->used->flags |= VRING_USED_F_NO_NOTIFY;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
vmei->rx_need_sched = vmei_proc_rx(vmei, vq);
|
vmei->rx_need_sched = vmei_proc_rx(vmei, vq);
|
||||||
@ -1926,7 +1926,7 @@ vmei_notify_rx(void *data, struct virtio_vq_info *vq)
|
|||||||
/* Signal the rx thread for processing */
|
/* Signal the rx thread for processing */
|
||||||
pthread_mutex_lock(&vmei->rx_mutex);
|
pthread_mutex_lock(&vmei->rx_mutex);
|
||||||
DPRINTF("RX: New IN buffer available!\n");
|
DPRINTF("RX: New IN buffer available!\n");
|
||||||
vq->used->flags |= ACRN_VRING_USED_F_NO_NOTIFY;
|
vq->used->flags |= VRING_USED_F_NO_NOTIFY;
|
||||||
pthread_cond_signal(&vmei->rx_cond);
|
pthread_cond_signal(&vmei->rx_cond);
|
||||||
pthread_mutex_unlock(&vmei->rx_mutex);
|
pthread_mutex_unlock(&vmei->rx_mutex);
|
||||||
}
|
}
|
||||||
|
@ -78,12 +78,12 @@
|
|||||||
|
|
||||||
#define VIRTIO_NET_S_HOSTCAPS \
|
#define VIRTIO_NET_S_HOSTCAPS \
|
||||||
(VIRTIO_NET_F_MAC | VIRTIO_NET_F_MRG_RXBUF | VIRTIO_NET_F_STATUS | \
|
(VIRTIO_NET_F_MAC | VIRTIO_NET_F_MRG_RXBUF | VIRTIO_NET_F_STATUS | \
|
||||||
ACRN_VIRTIO_F_NOTIFY_ON_EMPTY | ACRN_VIRTIO_RING_F_INDIRECT_DESC)
|
(1 << VIRTIO_F_NOTIFY_ON_EMPTY) | (1 << VIRTIO_RING_F_INDIRECT_DESC))
|
||||||
|
|
||||||
#define VIRTIO_NET_S_VHOSTCAPS \
|
#define VIRTIO_NET_S_VHOSTCAPS \
|
||||||
(ACRN_VIRTIO_F_NOTIFY_ON_EMPTY | ACRN_VIRTIO_RING_F_INDIRECT_DESC | \
|
((1 << VIRTIO_F_NOTIFY_ON_EMPTY) | (1 << VIRTIO_RING_F_INDIRECT_DESC) | \
|
||||||
ACRN_VIRTIO_RING_F_EVENT_IDX | VIRTIO_NET_F_MRG_RXBUF | \
|
(1 << VIRTIO_RING_F_EVENT_IDX) | VIRTIO_NET_F_MRG_RXBUF | \
|
||||||
ACRN_VIRTIO_F_VERSION_1)
|
(1UL << VIRTIO_F_VERSION_1))
|
||||||
|
|
||||||
/* is address mcast/bcast? */
|
/* is address mcast/bcast? */
|
||||||
#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01)
|
#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01)
|
||||||
@ -476,7 +476,7 @@ virtio_net_ping_rxq(void *vdev, struct virtio_vq_info *vq)
|
|||||||
*/
|
*/
|
||||||
if (net->rx_ready == 0) {
|
if (net->rx_ready == 0) {
|
||||||
net->rx_ready = 1;
|
net->rx_ready = 1;
|
||||||
vq->used->flags |= ACRN_VRING_USED_F_NO_NOTIFY;
|
vq->used->flags |= VRING_USED_F_NO_NOTIFY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,7 +522,7 @@ virtio_net_ping_txq(void *vdev, struct virtio_vq_info *vq)
|
|||||||
|
|
||||||
/* Signal the tx thread for processing */
|
/* Signal the tx thread for processing */
|
||||||
pthread_mutex_lock(&net->tx_mtx);
|
pthread_mutex_lock(&net->tx_mtx);
|
||||||
vq->used->flags |= ACRN_VRING_USED_F_NO_NOTIFY;
|
vq->used->flags |= VRING_USED_F_NO_NOTIFY;
|
||||||
if (net->tx_in_progress == 0)
|
if (net->tx_in_progress == 0)
|
||||||
pthread_cond_signal(&net->tx_cond);
|
pthread_cond_signal(&net->tx_cond);
|
||||||
pthread_mutex_unlock(&net->tx_mtx);
|
pthread_mutex_unlock(&net->tx_mtx);
|
||||||
@ -571,7 +571,7 @@ virtio_net_tx_thread(void *param)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vq->used->flags |= ACRN_VRING_USED_F_NO_NOTIFY;
|
vq->used->flags |= VRING_USED_F_NO_NOTIFY;
|
||||||
net->tx_in_progress = 1;
|
net->tx_in_progress = 1;
|
||||||
pthread_mutex_unlock(&net->tx_mtx);
|
pthread_mutex_unlock(&net->tx_mtx);
|
||||||
|
|
||||||
@ -935,7 +935,7 @@ virtio_net_set_status(void *vdev, uint64_t status)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!net->vhost_net->vhost_started &&
|
if (!net->vhost_net->vhost_started &&
|
||||||
(status & VIRTIO_CR_STATUS_DRIVER_OK)) {
|
(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||||
if (net->mevp)
|
if (net->mevp)
|
||||||
mevent_disable(net->mevp);
|
mevent_disable(net->mevp);
|
||||||
|
|
||||||
@ -945,7 +945,7 @@ virtio_net_set_status(void *vdev, uint64_t status)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (net->vhost_net->vhost_started &&
|
} else if (net->vhost_net->vhost_started &&
|
||||||
((status & VIRTIO_CR_STATUS_DRIVER_OK) == 0)) {
|
((status & VIRTIO_CONFIG_S_DRIVER_OK) == 0)) {
|
||||||
rc = vhost_net_stop(net->vhost_net);
|
rc = vhost_net_stop(net->vhost_net);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
WPRINTF(("vhost_net_stop failed\n"));
|
WPRINTF(("vhost_net_stop failed\n"));
|
||||||
|
@ -141,7 +141,7 @@ virtio_rnd_k_set_status(void *base, uint64_t status)
|
|||||||
nvq = rnd->base.vops->nvq;
|
nvq = rnd->base.vops->nvq;
|
||||||
|
|
||||||
if (rnd->vbs_k.status == VIRTIO_DEV_INIT_SUCCESS &&
|
if (rnd->vbs_k.status == VIRTIO_DEV_INIT_SUCCESS &&
|
||||||
(status & VIRTIO_CR_STATUS_DRIVER_OK)) {
|
(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||||
/* time to kickoff VBS-K side */
|
/* time to kickoff VBS-K side */
|
||||||
/* init vdev first */
|
/* init vdev first */
|
||||||
rc = virtio_rnd_kernel_dev_set(&rnd->vbs_k.dev,
|
rc = virtio_rnd_kernel_dev_set(&rnd->vbs_k.dev,
|
||||||
|
@ -116,7 +116,7 @@
|
|||||||
* The two event fields, <used_event> and <avail_event>, in the
|
* The two event fields, <used_event> and <avail_event>, in the
|
||||||
* avail and used rings (respectively -- note the reversal!), are
|
* avail and used rings (respectively -- note the reversal!), are
|
||||||
* always provided, but are used only if the virtual device
|
* always provided, but are used only if the virtual device
|
||||||
* negotiates the ACRN_VIRTIO_RING_F_EVENT_IDX feature during feature
|
* negotiates the VIRTIO_RING_F_EVENT_IDX feature during feature
|
||||||
* negotiation. Similarly, both rings provide a flag --
|
* negotiation. Similarly, both rings provide a flag --
|
||||||
* ACRN_VRING_AVAIL_F_NO_INTERRUPT and ACRN_VRING_USED_F_NO_NOTIFY -- in
|
* ACRN_VRING_AVAIL_F_NO_INTERRUPT and ACRN_VRING_USED_F_NO_NOTIFY -- in
|
||||||
* their <flags> field, indicating that the guest does not need an
|
* their <flags> field, indicating that the guest does not need an
|
||||||
@ -126,6 +126,10 @@
|
|||||||
* not be implemented.)
|
* not be implemented.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/virtio_ring.h>
|
||||||
|
#include <linux/virtio_config.h>
|
||||||
|
#include <linux/virtio_pci.h>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
@ -136,42 +140,6 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VRING_ALIGN 4096
|
|
||||||
|
|
||||||
#define ACRN_VRING_DESC_F_NEXT (1 << 0)
|
|
||||||
#define ACRN_VRING_DESC_F_WRITE (1 << 1)
|
|
||||||
#define ACRN_VRING_DESC_F_INDIRECT (1 << 2)
|
|
||||||
|
|
||||||
struct virtio_desc { /* AKA vring_desc */
|
|
||||||
uint64_t addr; /* guest physical address */
|
|
||||||
uint32_t len; /* length of scatter/gather seg */
|
|
||||||
uint16_t flags; /* VRING_F_DESC_* */
|
|
||||||
uint16_t next; /* next desc if F_NEXT */
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
struct virtio_used { /* AKA vring_used_elem */
|
|
||||||
uint32_t idx; /* head of used descriptor chain */
|
|
||||||
uint32_t tlen; /* length written-to */
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
#define ACRN_VRING_AVAIL_F_NO_INTERRUPT 1
|
|
||||||
|
|
||||||
struct virtio_vring_avail {
|
|
||||||
uint16_t flags; /* VRING_AVAIL_F_* */
|
|
||||||
uint16_t idx; /* counts to 65535, then cycles */
|
|
||||||
uint16_t ring[]; /* size N, reported in QNUM value */
|
|
||||||
/* uint16_t used_event; -- after N ring entries */
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
#define ACRN_VRING_USED_F_NO_NOTIFY 1
|
|
||||||
struct virtio_vring_used {
|
|
||||||
uint16_t flags; /* VRING_USED_F_* */
|
|
||||||
uint16_t idx; /* counts to 65535, then cycles */
|
|
||||||
struct virtio_used ring[];
|
|
||||||
/* size N */
|
|
||||||
/* uint16_t avail_event; -- after N ring entries */
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BACKEND_UNKNOWN = 0,
|
BACKEND_UNKNOWN = 0,
|
||||||
BACKEND_VBSU,
|
BACKEND_VBSU,
|
||||||
@ -262,94 +230,12 @@ enum {
|
|||||||
#define VIRTIO_DEV_COREU 0x8608
|
#define VIRTIO_DEV_COREU 0x8608
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PCI config space constants.
|
* Bits in VIRTIO_PCI_ISR. These apply only if not using MSI-X.
|
||||||
*
|
|
||||||
* If MSI-X is enabled, the ISR register is generally not used,
|
|
||||||
* and the configuration vector and queue vector appear at offsets
|
|
||||||
* 20 and 22 with the remaining configuration registers at 24.
|
|
||||||
* If MSI-X is not enabled, those two registers disappear and
|
|
||||||
* the remaining configuration registers start at offset 20.
|
|
||||||
*/
|
|
||||||
#define VIRTIO_CR_HOSTCAP 0
|
|
||||||
#define VIRTIO_CR_GUESTCAP 4
|
|
||||||
#define VIRTIO_CR_PFN 8
|
|
||||||
#define VIRTIO_CR_QNUM 12
|
|
||||||
#define VIRTIO_CR_QSEL 14
|
|
||||||
#define VIRTIO_CR_QNOTIFY 16
|
|
||||||
#define VIRTIO_CR_STATUS 18
|
|
||||||
#define VIRTIO_CR_ISR 19
|
|
||||||
#define VIRTIO_CR_CFGVEC 20
|
|
||||||
#define VIRTIO_CR_QVEC 22
|
|
||||||
#define VIRTIO_CR_CFG0 20 /* No MSI-X */
|
|
||||||
#define VIRTIO_CR_CFG1 24 /* With MSI-X */
|
|
||||||
#define VIRTIO_CR_MSIX 20
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bits in VIRTIO_CR_STATUS. Guests need not actually set any of these,
|
|
||||||
* but a guest writing 0 to this register means "please reset".
|
|
||||||
*/
|
|
||||||
#define VIRTIO_CR_STATUS_ACK 0x01
|
|
||||||
/* guest OS has acknowledged dev */
|
|
||||||
#define VIRTIO_CR_STATUS_DRIVER 0x02
|
|
||||||
/* guest OS driver is loaded */
|
|
||||||
#define VIRTIO_CR_STATUS_DRIVER_OK 0x04
|
|
||||||
/* guest OS driver ready */
|
|
||||||
#define VIRTIO_CR_STATUS_FEATURES_OK 0x08
|
|
||||||
/* features negotiation complete */
|
|
||||||
#define VIRTIO_CR_STATUS_NEEDS_RESET 0x40
|
|
||||||
/* device experienced an error and cannot
|
|
||||||
* recover, guest driver must reset it
|
|
||||||
*/
|
|
||||||
#define VIRTIO_CR_STATUS_FAILED 0x80
|
|
||||||
/* guest has given up on this dev */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bits in VIRTIO_CR_ISR. These apply only if not using MSI-X.
|
|
||||||
*
|
*
|
||||||
* (We don't [yet?] ever use CONF_CHANGED.)
|
* (We don't [yet?] ever use CONF_CHANGED.)
|
||||||
*/
|
*/
|
||||||
#define VIRTIO_CR_ISR_QUEUES 0x01
|
#define VIRTIO_PCI_ISR_QUEUES 0x01
|
||||||
/* re-scan queues */
|
/* re-scan queues */
|
||||||
#define VIRTIO_CR_ISR_CONF_CHANGED 0x02
|
|
||||||
/* configuration changed */
|
|
||||||
|
|
||||||
#define VIRTIO_MSI_NO_VECTOR 0xFFFF
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Feature flags.
|
|
||||||
* Note: bits 0 through 23 are reserved to each device type.
|
|
||||||
*/
|
|
||||||
#define ACRN_VIRTIO_F_NOTIFY_ON_EMPTY (1 << 24)
|
|
||||||
#define ACRN_VIRTIO_RING_F_INDIRECT_DESC (1 << 28)
|
|
||||||
#define ACRN_VIRTIO_RING_F_EVENT_IDX (1 << 29)
|
|
||||||
|
|
||||||
/* v1.0 compliant. */
|
|
||||||
#define ACRN_VIRTIO_F_VERSION_1 (1UL << 32)
|
|
||||||
|
|
||||||
/* From section 2.3, "Virtqueue Configuration", of the virtio specification */
|
|
||||||
/**
|
|
||||||
* @brief Calculate size of a virtual ring, this interface is only valid for
|
|
||||||
* legacy virtio.
|
|
||||||
*
|
|
||||||
* @param qsz Size of raw data in a certain virtqueue.
|
|
||||||
*
|
|
||||||
* @return size of a certain virtqueue, in bytes.
|
|
||||||
*/
|
|
||||||
static inline size_t
|
|
||||||
virtio_vring_size(u_int qsz)
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
/* constant 3 below = flags, va_idx, va_used_event */
|
|
||||||
size = sizeof(struct virtio_desc) * qsz + sizeof(uint16_t) * (3 + qsz);
|
|
||||||
size = roundup2(size, VRING_ALIGN);
|
|
||||||
|
|
||||||
/* constant 3 below = flags, idx, avail_event */
|
|
||||||
size += sizeof(uint16_t) * 3 + sizeof(struct virtio_used) * qsz;
|
|
||||||
size = roundup2(size, VRING_ALIGN);
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct vmctx;
|
struct vmctx;
|
||||||
struct pci_vdev;
|
struct pci_vdev;
|
||||||
@ -437,76 +323,6 @@ struct virtio_vq_info;
|
|||||||
/* PCI configuration access */
|
/* PCI configuration access */
|
||||||
#define VIRTIO_PCI_CAP_PCI_CFG 5
|
#define VIRTIO_PCI_CAP_PCI_CFG 5
|
||||||
|
|
||||||
#define VIRTIO_COMMON_DFSELECT 0
|
|
||||||
#define VIRTIO_COMMON_DF 4
|
|
||||||
#define VIRTIO_COMMON_GFSELECT 8
|
|
||||||
#define VIRTIO_COMMON_GF 12
|
|
||||||
#define VIRTIO_COMMON_MSIX 16
|
|
||||||
#define VIRTIO_COMMON_NUMQ 18
|
|
||||||
#define VIRTIO_COMMON_STATUS 20
|
|
||||||
#define VIRTIO_COMMON_CFGGENERATION 21
|
|
||||||
#define VIRTIO_COMMON_Q_SELECT 22
|
|
||||||
#define VIRTIO_COMMON_Q_SIZE 24
|
|
||||||
#define VIRTIO_COMMON_Q_MSIX 26
|
|
||||||
#define VIRTIO_COMMON_Q_ENABLE 28
|
|
||||||
#define VIRTIO_COMMON_Q_NOFF 30
|
|
||||||
#define VIRTIO_COMMON_Q_DESCLO 32
|
|
||||||
#define VIRTIO_COMMON_Q_DESCHI 36
|
|
||||||
#define VIRTIO_COMMON_Q_AVAILLO 40
|
|
||||||
#define VIRTIO_COMMON_Q_AVAILHI 44
|
|
||||||
#define VIRTIO_COMMON_Q_USEDLO 48
|
|
||||||
#define VIRTIO_COMMON_Q_USEDHI 52
|
|
||||||
|
|
||||||
/* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */
|
|
||||||
struct virtio_pci_common_cfg {
|
|
||||||
/* About the whole device. */
|
|
||||||
uint32_t device_feature_select; /* read-write */
|
|
||||||
uint32_t device_feature; /* read-only */
|
|
||||||
uint32_t guest_feature_select; /* read-write */
|
|
||||||
uint32_t guest_feature; /* read-write */
|
|
||||||
uint16_t msix_config; /* read-write */
|
|
||||||
uint16_t num_queues; /* read-only */
|
|
||||||
uint8_t device_status; /* read-write */
|
|
||||||
uint8_t config_generation; /* read-only */
|
|
||||||
|
|
||||||
/* About a specific virtqueue. */
|
|
||||||
uint16_t queue_select; /* read-write */
|
|
||||||
uint16_t queue_size; /* read-write, power of 2. */
|
|
||||||
uint16_t queue_msix_vector; /* read-write */
|
|
||||||
uint16_t queue_enable; /* read-write */
|
|
||||||
uint16_t queue_notify_off; /* read-only */
|
|
||||||
uint32_t queue_desc_lo; /* read-write */
|
|
||||||
uint32_t queue_desc_hi; /* read-write */
|
|
||||||
uint32_t queue_avail_lo; /* read-write */
|
|
||||||
uint32_t queue_avail_hi; /* read-write */
|
|
||||||
uint32_t queue_used_lo; /* read-write */
|
|
||||||
uint32_t queue_used_hi; /* read-write */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* PCI capability header: */
|
|
||||||
struct virtio_pci_cap {
|
|
||||||
uint8_t cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */
|
|
||||||
uint8_t cap_next; /* Generic PCI field: next ptr. */
|
|
||||||
uint8_t cap_len; /* Generic PCI field: capability length */
|
|
||||||
uint8_t cfg_type; /* Identifies the structure. */
|
|
||||||
uint8_t bar; /* Where to find it. */
|
|
||||||
uint8_t padding[3]; /* Pad to full dword. */
|
|
||||||
uint32_t offset; /* Offset within bar. */
|
|
||||||
uint32_t length; /* Length of the structure, in bytes. */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Fields in VIRTIO_PCI_CAP_NOTIFY_CFG: */
|
|
||||||
struct virtio_pci_notify_cap {
|
|
||||||
struct virtio_pci_cap cap;
|
|
||||||
uint32_t notify_off_multiplier; /* Multiplier for queue_notify_off. */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
|
|
||||||
struct virtio_pci_cfg_cap {
|
|
||||||
struct virtio_pci_cap cap;
|
|
||||||
uint8_t pci_cfg_data[4]; /* Data for BAR access. */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Base component to any virtio device
|
* @brief Base component to any virtio device
|
||||||
*/
|
*/
|
||||||
@ -604,11 +420,11 @@ struct virtio_vq_info {
|
|||||||
|
|
||||||
uint32_t pfn; /**< PFN of virt queue (not shifted!) */
|
uint32_t pfn; /**< PFN of virt queue (not shifted!) */
|
||||||
|
|
||||||
volatile struct virtio_desc *desc;
|
volatile struct vring_desc *desc;
|
||||||
/**< descriptor array */
|
/**< descriptor array */
|
||||||
volatile struct virtio_vring_avail *avail;
|
volatile struct vring_avail *avail;
|
||||||
/**< the "avail" ring */
|
/**< the "avail" ring */
|
||||||
volatile struct virtio_vring_used *used;
|
volatile struct vring_used *used;
|
||||||
/**< the "used" ring */
|
/**< the "used" ring */
|
||||||
|
|
||||||
uint32_t gpa_desc[2]; /**< gpa of descriptors */
|
uint32_t gpa_desc[2]; /**< gpa of descriptors */
|
||||||
@ -669,7 +485,7 @@ vq_interrupt(struct virtio_base *vb, struct virtio_vq_info *vq)
|
|||||||
pci_generate_msix(vb->dev, vq->msix_idx);
|
pci_generate_msix(vb->dev, vq->msix_idx);
|
||||||
else {
|
else {
|
||||||
VIRTIO_BASE_LOCK(vb);
|
VIRTIO_BASE_LOCK(vb);
|
||||||
vb->isr |= VIRTIO_CR_ISR_QUEUES;
|
vb->isr |= VIRTIO_PCI_ISR_QUEUES;
|
||||||
pci_generate_msi(vb->dev, 0);
|
pci_generate_msi(vb->dev, 0);
|
||||||
pci_lintr_assert(vb->dev);
|
pci_lintr_assert(vb->dev);
|
||||||
VIRTIO_BASE_UNLOCK(vb);
|
VIRTIO_BASE_UNLOCK(vb);
|
||||||
@ -688,7 +504,7 @@ vq_interrupt(struct virtio_base *vb, struct virtio_vq_info *vq)
|
|||||||
static inline void
|
static inline void
|
||||||
virtio_config_changed(struct virtio_base *vb)
|
virtio_config_changed(struct virtio_base *vb)
|
||||||
{
|
{
|
||||||
if (!(vb->status & VIRTIO_CR_STATUS_DRIVER_OK))
|
if (!(vb->status & VIRTIO_CONFIG_S_DRIVER_OK))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vb->config_generation++;
|
vb->config_generation++;
|
||||||
@ -697,7 +513,7 @@ virtio_config_changed(struct virtio_base *vb)
|
|||||||
pci_generate_msix(vb->dev, vb->msix_cfg_idx);
|
pci_generate_msix(vb->dev, vb->msix_cfg_idx);
|
||||||
else {
|
else {
|
||||||
VIRTIO_BASE_LOCK(vb);
|
VIRTIO_BASE_LOCK(vb);
|
||||||
vb->isr |= VIRTIO_CR_ISR_CONF_CHANGED;
|
vb->isr |= VIRTIO_PCI_ISR_CONFIG;
|
||||||
pci_generate_msi(vb->dev, 0);
|
pci_generate_msi(vb->dev, 0);
|
||||||
pci_lintr_assert(vb->dev);
|
pci_lintr_assert(vb->dev);
|
||||||
VIRTIO_BASE_UNLOCK(vb);
|
VIRTIO_BASE_UNLOCK(vb);
|
||||||
|
Loading…
Reference in New Issue
Block a user