VirtualBox

Changeset 94969 in vbox for trunk/src/VBox/Devices/VirtIO


Ignore:
Timestamp:
May 9, 2022 5:06:17 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
151379
Message:

Devices/Virtio|ai: Fixes and performance improvements for the 1.0 virtio-net implementation, bugref:8651

Location:
trunk/src/VBox/Devices/VirtIO
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/VirtIO/VirtioCore.cpp

    r94287 r94969  
    620620    uint16_t uUsedIdxShadow  = pVirtq->uUsedIdxShadow;
    621621
     622#ifdef VIRTIO_VBUF_ON_STACK
     623    VIRTQBUF_T VirtqBuf;
     624    PVIRTQBUF pVirtqBuf = &VirtqBuf;
     625#else /* !VIRTIO_VBUF_ON_STACK */
    622626    PVIRTQBUF pVirtqBuf = NULL;
     627#endif /* !VIRTIO_VBUF_ON_STACK */
    623628
    624629    bool fEmpty = IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtq);
     
    629634    if (!fEmpty)
    630635    {
     636#ifdef VIRTIO_VBUF_ON_STACK
     637        virtioCoreR3VirtqAvailBufPeek(pDevIns,  pVirtio, uVirtq, pVirtqBuf);
     638#else /* !VIRTIO_VBUF_ON_STACK */
    631639        virtioCoreR3VirtqAvailBufPeek(pDevIns,  pVirtio, uVirtq, &pVirtqBuf);
     640#endif /* !VIRTIO_VBUF_ON_STACK */
    632641        cSendSegs   = pVirtqBuf->pSgPhysSend ? pVirtqBuf->pSgPhysSend->cSegs : 0;
    633642        cReturnSegs = pVirtqBuf->pSgPhysReturn ? pVirtqBuf->pSgPhysReturn->cSegs : 0;
     
    680689}
    681690
     691#ifdef VIRTIO_VBUF_ON_STACK
     692/** API Function: See header file */
     693PVIRTQBUF virtioCoreR3VirtqBufAlloc(void)
     694{
     695    PVIRTQBUF pVirtqBuf = (PVIRTQBUF)RTMemAllocZ(sizeof(VIRTQBUF_T));
     696    AssertReturn(pVirtqBuf, NULL);
     697    pVirtqBuf->u32Magic  = VIRTQBUF_MAGIC;
     698    pVirtqBuf->cRefs     = 1;
     699    return pVirtqBuf;
     700}
     701#endif /* VIRTIO_VBUF_ON_STACK */
     702
    682703/** API Function: See header file */
    683704uint32_t virtioCoreR3VirtqBufRetain(PVIRTQBUF pVirtqBuf)
     
    752773
    753774/** API function: See Header file  */
     775#ifdef VIRTIO_VBUF_ON_STACK
     776int virtioCoreR3VirtqAvailBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq, PVIRTQBUF pVirtqBuf)
     777{
     778    return virtioCoreR3VirtqAvailBufGet(pDevIns, pVirtio, uVirtq, pVirtqBuf, false);
     779}
     780#else /* !VIRTIO_VBUF_ON_STACK */
    754781int virtioCoreR3VirtqAvailBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq,
    755782                         PPVIRTQBUF ppVirtqBuf)
     
    757784    return virtioCoreR3VirtqAvailBufGet(pDevIns, pVirtio, uVirtq, ppVirtqBuf, false);
    758785}
     786#endif /* !VIRTIO_VBUF_ON_STACK */
    759787
    760788/** API function: See Header file  */
     
    778806
    779807/** API Function: See header file */
     808#ifdef VIRTIO_VBUF_ON_STACK
     809int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq,
     810                                 uint16_t uHeadIdx, PVIRTQBUF pVirtqBuf)
     811#else /* !VIRTIO_VBUF_ON_STACK */
    780812int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq,
    781813                             uint16_t uHeadIdx, PPVIRTQBUF ppVirtqBuf)
    782 {
     814#endif /* !VIRTIO_VBUF_ON_STACK */
     815{
     816#ifndef VIRTIO_VBUF_ON_STACK
    783817    AssertReturn(ppVirtqBuf, VERR_INVALID_POINTER);
    784818    *ppVirtqBuf = NULL;
     819#endif /* !VIRTIO_VBUF_ON_STACK */
    785820
    786821    AssertMsgReturn(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues),
     
    800835     * Allocate and initialize the descriptor chain structure.
    801836     */
     837#ifndef VIRTIO_VBUF_ON_STACK
    802838    PVIRTQBUF pVirtqBuf = (PVIRTQBUF)RTMemAllocZ(sizeof(VIRTQBUF_T));
    803839    AssertReturn(pVirtqBuf, VERR_NO_MEMORY);
    804840    pVirtqBuf->u32Magic  = VIRTQBUF_MAGIC;
    805841    pVirtqBuf->cRefs     = 1;
     842#endif /* !VIRTIO_VBUF_ON_STACK */
    806843    pVirtqBuf->uHeadIdx  = uHeadIdx;
    807844    pVirtqBuf->uVirtq    = uVirtq;
     845#ifndef VIRTIO_VBUF_ON_STACK
    808846    *ppVirtqBuf          = pVirtqBuf;
     847#endif /* !VIRTIO_VBUF_ON_STACK */
    809848
    810849    /*
     
    904943
    905944/** API function: See Header file  */
     945#ifdef VIRTIO_VBUF_ON_STACK
     946int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq,
     947                                 PVIRTQBUF pVirtqBuf, bool fRemove)
     948#else /* !VIRTIO_VBUF_ON_STACK */
    906949int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq,
    907950                         PPVIRTQBUF ppVirtqBuf, bool fRemove)
     951#endif /* !VIRTIO_VBUF_ON_STACK */
    908952{
    909953    Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues));
     
    921965        pVirtq->uAvailIdxShadow++;
    922966
     967#ifdef VIRTIO_VBUF_ON_STACK
     968    int rc = virtioCoreR3VirtqAvailBufGet(pDevIns, pVirtio, uVirtq, uHeadIdx, pVirtqBuf);
     969#else /* !VIRTIO_VBUF_ON_STACK */
    923970    int rc = virtioCoreR3VirtqAvailBufGet(pDevIns, pVirtio, uVirtq, uHeadIdx, ppVirtqBuf);
     971#endif /* !VIRTIO_VBUF_ON_STACK */
    924972    return rc;
    925973}
  • trunk/src/VBox/Devices/VirtIO/VirtioCore.h

    r94275 r94969  
    2222# pragma once
    2323#endif
     24
     25/* Do not allocate VIRTQBUF from the heap when possible */
     26#define VIRTIO_VBUF_ON_STACK 1
    2427
    2528#include <iprt/ctype.h>
     
    676679uint16_t virtioCoreVirtqAvailBufCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr);
    677680
     681#ifdef VIRTIO_VBUF_ON_STACK
     682/**
     683 * This function is identical to virtioCoreR3VirtqAvailBufGet(), *except* it doesn't consume
     684 * peeked buffer from avail ring of the virtq. The function *becomes* identical to the
     685 * virtioCoreR3VirtqAvailBufGet() only if virtioCoreR3VirtqAvailRingNext() is invoked to
     686 * consume buf from the queue's avail ring, followed by invocation of virtioCoreR3VirtqUsedBufPut(),
     687 * to hand host-processed buffer back to guest, which completes guest-initiated virtq buffer circuit.
     688 *
     689 * @param   pDevIns     The device instance.
     690 * @param   pVirtio     Pointer to the shared virtio state.
     691 * @param   uVirtqNbr   Virtq number
     692 * @param   pVirtqBuf   Pointer to descriptor chain that contains the
     693 *                      pre-processed transaction information pulled from the virtq.
     694 *
     695 * @returns VBox status code:
     696 * @retval  VINF_SUCCESS         Success
     697 * @retval  VERR_INVALID_STATE   VirtIO not in ready state (asserted).
     698 * @retval  VERR_NOT_AVAILABLE   If the queue is empty.
     699 */
     700int  virtioCoreR3VirtqAvailBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
     701                                   PVIRTQBUF pVirtqBuf);
     702
     703/**
     704 * This function fetches the next buffer (descriptor chain) from the VirtIO "avail" ring of
     705 * indicated queue, separating the buf's s/g vectors into OUT (e.g. guest-to-host)
     706 * components and and IN (host-to-guest) components.
     707 *
     708 * Caller is responsible for GCPhys to host virtual memory conversions. If the
     709 * virtq buffer being peeked at is "consumed", virtioCoreR3VirtqAvailRingNext() must
     710 * be called, and after that virtioCoreR3VirtqUsedBufPut() must be called to
     711 * complete the buffer transfer cycle with the guest.
     712 *
     713 * @param   pDevIns     The device instance.
     714 * @param   pVirtio     Pointer to the shared virtio state.
     715 * @param   uVirtqNbr   Virtq number
     716 * @param   pVirtqBuf   Pointer to descriptor chain that contains the
     717 *                      pre-processed transaction information pulled from the virtq.
     718 * @param   fRemove     flags whether to remove desc chain from queue (false = peek)
     719 *
     720 * @returns VBox status code:
     721 * @retval  VINF_SUCCESS         Success
     722 * @retval  VERR_INVALID_STATE   VirtIO not in ready state (asserted).
     723 * @retval  VERR_NOT_AVAILABLE   If the queue is empty.
     724 */
     725int  virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
     726                                  PVIRTQBUF pVirtqBuf, bool fRemove);
     727
     728/**
     729 * Fetches a specific descriptor chain using avail ring of indicated queue and converts the
     730 * descriptor chain into its OUT (to device) and IN (to guest) components.
     731 *
     732 * The caller is responsible for GCPhys to host virtual memory conversions and *must*
     733 * return the virtq buffer using virtioCoreR3VirtqUsedBufPut() to complete the roundtrip
     734 * virtq transaction.
     735 * *
     736 * @param   pDevIns     The device instance.
     737 * @param   pVirtio     Pointer to the shared virtio state.
     738 * @param   uVirtqNbr   Virtq number
     739 * @param   pVirtqBuf   Pointer to descriptor chain that contains the
     740 *                      pre-processed transaction information pulled from the virtq.
     741 * @param   fRemove     flags whether to remove desc chain from queue (false = peek)
     742 *
     743 * @returns VBox status code:
     744 * @retval  VINF_SUCCESS         Success
     745 * @retval  VERR_INVALID_STATE   VirtIO not in ready state (asserted).
     746 * @retval  VERR_NOT_AVAILABLE   If the queue is empty.
     747 */
     748int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
     749                                  uint16_t uHeadIdx, PVIRTQBUF pVirtqBuf);
     750#else /* !VIRTIO_VBUF_ON_STACK */
    678751/**
    679752 * This function is identical to virtioCoreR3VirtqAvailBufGet(), *except* it doesn't consume
     
    748821int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
    749822                                  uint16_t uHeadIdx, PPVIRTQBUF ppVirtqBuf);
     823#endif /* !VIRTIO_VBUF_ON_STACK */
    750824
    751825/**
     
    10921166int  virtioCoreVirtqUsedRingSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr);
    10931167
     1168#ifdef VIRTIO_VBUF_ON_STACK
     1169/**
     1170 * Allocates a descriptor chain object with the reference count of one. Copying the reference
     1171 * to this object requires a call to virtioCoreR3VirtqBufRetain. All references must be later
     1172 * released with virtioCoreR3VirtqBufRelease. Just to be clear, one alloc plus one retain will
     1173 * require two releases.
     1174 *
     1175 * @returns A descriptor chain object.
     1176 *
     1177 * @retval  NULL if out of memory.
     1178 *
     1179 * NOTE: VIRTQBUF_T objects allocated on the stack will have garbage in the u32Magic field,
     1180 * triggering an assertion if virtioCoreR3VirtqBufRelease is called on them.
     1181 */
     1182PVIRTQBUF virtioCoreR3VirtqBufAlloc(void);
     1183#endif /* VIRTIO_VBUF_ON_STACK */
     1184
    10941185/**
    10951186 * Retains a reference to the given descriptor chain.
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette