summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/VirtIO/Virtio.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/Devices/VirtIO/Virtio.h
parentInitial commit. (diff)
downloadvirtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz
virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/VirtIO/Virtio.h')
-rw-r--r--src/VBox/Devices/VirtIO/Virtio.h334
1 files changed, 334 insertions, 0 deletions
diff --git a/src/VBox/Devices/VirtIO/Virtio.h b/src/VBox/Devices/VirtIO/Virtio.h
new file mode 100644
index 00000000..6b569bb0
--- /dev/null
+++ b/src/VBox/Devices/VirtIO/Virtio.h
@@ -0,0 +1,334 @@
+/* $Id: Virtio.h $ */
+/** @file
+ * Virtio.h - Virtio Declarations
+ */
+
+/*
+ * Copyright (C) 2009-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_INCLUDED_SRC_VirtIO_Virtio_h
+#define VBOX_INCLUDED_SRC_VirtIO_Virtio_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/ctype.h>
+
+
+/** @name Saved state versions.
+ * The saved state version is changed if either common or any of specific
+ * parts are changed. That is, it is perfectly possible that the version
+ * of saved vnet state will increase as a result of change in vblk structure
+ * for example.
+ */
+#define VIRTIO_SAVEDSTATE_VERSION_3_1_BETA1 1
+#define VIRTIO_SAVEDSTATE_VERSION 2
+/** @} */
+
+#define DEVICE_PCI_VENDOR_ID 0x1AF4
+#define DEVICE_PCI_BASE_ID 0x1000
+#define DEVICE_PCI_SUBSYSTEM_VENDOR_ID 0x1AF4
+#define DEVICE_PCI_SUBSYSTEM_BASE_ID 1
+
+#define VIRTIO_MAX_NQUEUES 3
+
+#define VPCI_HOST_FEATURES 0x0
+#define VPCI_GUEST_FEATURES 0x4
+#define VPCI_QUEUE_PFN 0x8
+#define VPCI_QUEUE_NUM 0xC
+#define VPCI_QUEUE_SEL 0xE
+#define VPCI_QUEUE_NOTIFY 0x10
+#define VPCI_STATUS 0x12
+#define VPCI_ISR 0x13
+#define VPCI_CONFIG 0x14
+
+#define VPCI_ISR_QUEUE 0x1
+#define VPCI_ISR_CONFIG 0x3
+
+#define VPCI_STATUS_ACK 0x01
+#define VPCI_STATUS_DRV 0x02
+#define VPCI_STATUS_DRV_OK 0x04
+#define VPCI_STATUS_FAILED 0x80
+
+#define VPCI_F_NOTIFY_ON_EMPTY 0x01000000
+#define VPCI_F_ANY_LAYOUT 0x08000000
+#define VPCI_F_RING_INDIRECT_DESC 0x10000000
+#define VPCI_F_RING_EVENT_IDX 0x20000000
+#define VPCI_F_BAD_FEATURE 0x40000000
+
+#define VRINGDESC_MAX_SIZE (2 * 1024 * 1024)
+#define VRINGDESC_F_NEXT 0x01
+#define VRINGDESC_F_WRITE 0x02
+#define VRINGDESC_F_INDIRECT 0x04
+
+typedef struct VRingDesc
+{
+ uint64_t u64Addr;
+ uint32_t uLen;
+ uint16_t u16Flags;
+ uint16_t u16Next;
+} VRINGDESC;
+typedef VRINGDESC *PVRINGDESC;
+
+#define VRINGAVAIL_F_NO_INTERRUPT 0x01
+
+typedef struct VRingAvail
+{
+ uint16_t uFlags;
+ uint16_t uNextFreeIndex;
+ uint16_t auRing[1];
+} VRINGAVAIL;
+
+typedef struct VRingUsedElem
+{
+ uint32_t uId;
+ uint32_t uLen;
+} VRINGUSEDELEM;
+
+#define VRINGUSED_F_NO_NOTIFY 0x01
+
+typedef struct VRingUsed
+{
+ uint16_t uFlags;
+ uint16_t uIndex;
+ VRINGUSEDELEM aRing[1];
+} VRINGUSED;
+typedef VRINGUSED *PVRINGUSED;
+
+#define VRING_MAX_SIZE 1024
+
+typedef struct VRing
+{
+ uint16_t uSize;
+ uint16_t padding[3];
+ RTGCPHYS addrDescriptors;
+ RTGCPHYS addrAvail;
+ RTGCPHYS addrUsed;
+} VRING;
+typedef VRING *PVRING;
+
+/**
+ * Queue callback (consumer?).
+ *
+ * @param pvState Pointer to the VirtIO PCI core state, VPCISTATE.
+ * @param pQueue Pointer to the queue structure.
+ */
+typedef DECLCALLBACK(void) FNVPCIQUEUECALLBACK(void *pvState, struct VQueue *pQueue);
+/** Pointer to a VQUEUE callback function. */
+typedef FNVPCIQUEUECALLBACK *PFNVPCIQUEUECALLBACK;
+
+typedef struct VQueue
+{
+ VRING VRing;
+ uint16_t uNextAvailIndex;
+ uint16_t uNextUsedIndex;
+ uint32_t uPageNumber;
+ R3PTRTYPE(PFNVPCIQUEUECALLBACK) pfnCallback;
+ R3PTRTYPE(const char *) pcszName;
+} VQUEUE;
+typedef VQUEUE *PVQUEUE;
+
+typedef struct VQueueElemSeg
+{
+ RTGCPHYS addr;
+ void *pv;
+ uint32_t cb;
+} VQUEUESEG;
+
+typedef struct VQueueElem
+{
+ uint32_t uIndex;
+ uint32_t nIn;
+ uint32_t nOut;
+ VQUEUESEG aSegsIn[VRING_MAX_SIZE];
+ VQUEUESEG aSegsOut[VRING_MAX_SIZE];
+} VQUEUEELEM;
+typedef VQUEUEELEM *PVQUEUEELEM;
+
+
+enum VirtioDeviceType
+{
+ VIRTIO_NET_ID = 0,
+ VIRTIO_BLK_ID = 1,
+ VIRTIO_32BIT_HACK = 0x7fffffff
+};
+
+
+/**
+ * The core (/common) state of the VirtIO PCI device
+ *
+ * @implements PDMILEDPORTS
+ */
+typedef struct VPCIState_st
+{
+ PDMCRITSECT cs; /**< Critical section - what is it protecting? */
+ /* Read-only part, never changes after initialization. */
+ char szInstance[8]; /**< Instance name, e.g. VNet#1. */
+
+#if HC_ARCH_BITS != 64
+ uint32_t padding1;
+#endif
+
+ /** Status LUN: Base interface. */
+ PDMIBASE IBase;
+ /** Status LUN: LED port interface. */
+ PDMILEDPORTS ILeds;
+ /** Status LUN: LED connector (peer). */
+ R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector;
+
+ PPDMDEVINSR3 pDevInsR3; /**< Device instance - R3. */
+ PPDMDEVINSR0 pDevInsR0; /**< Device instance - R0. */
+ PPDMDEVINSRC pDevInsRC; /**< Device instance - RC. */
+
+#if HC_ARCH_BITS == 64
+ uint32_t padding2;
+#endif
+
+ /** TODO */
+ PDMPCIDEV pciDevice;
+ /** Base port of I/O space region. */
+ RTIOPORT IOPortBase;
+
+ /* Read/write part, protected with critical section. */
+ /** Status LED. */
+ PDMLED led;
+
+ uint32_t uGuestFeatures;
+ uint16_t uQueueSelector; /**< An index in aQueues array. */
+ uint8_t uStatus; /**< Device Status (bits are device-specific). */
+ uint8_t uISR; /**< Interrupt Status Register. */
+
+#if HC_ARCH_BITS != 64
+ uint32_t padding3;
+#endif
+
+ uint32_t nQueues; /**< Actual number of queues used. */
+ VQUEUE Queues[VIRTIO_MAX_NQUEUES];
+
+#if defined(VBOX_WITH_STATISTICS)
+ STAMPROFILEADV StatIOReadR3;
+ STAMPROFILEADV StatIOReadR0;
+ STAMPROFILEADV StatIOReadRC;
+ STAMPROFILEADV StatIOWriteR3;
+ STAMPROFILEADV StatIOWriteR0;
+ STAMPROFILEADV StatIOWriteRC;
+ STAMCOUNTER StatIntsRaised;
+ STAMCOUNTER StatIntsSkipped;
+ STAMPROFILE StatCsR3;
+ STAMPROFILE StatCsR0;
+ STAMPROFILE StatCsRC;
+#endif /* VBOX_WITH_STATISTICS */
+} VPCISTATE;
+/** Pointer to the core (/common) state of a VirtIO PCI device. */
+typedef VPCISTATE *PVPCISTATE;
+
+typedef DECLCALLBACK(uint32_t) FNGETHOSTFEATURES(void *pvState);
+typedef FNGETHOSTFEATURES *PFNGETHOSTFEATURES;
+
+/** @name VirtIO port I/O callbacks.
+ * @{ */
+typedef struct VPCIIOCALLBACKS
+{
+ DECLCALLBACKMEMBER(uint32_t, pfnGetHostFeatures)(void *pvState);
+ DECLCALLBACKMEMBER(uint32_t, pfnGetHostMinimalFeatures)(void *pvState);
+ DECLCALLBACKMEMBER(void, pfnSetHostFeatures)(void *pvState, uint32_t fFeatures);
+ DECLCALLBACKMEMBER(int, pfnGetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData);
+ DECLCALLBACKMEMBER(int, pfnSetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData);
+ DECLCALLBACKMEMBER(int, pfnReset)(void *pvState);
+ DECLCALLBACKMEMBER(void, pfnReady)(void *pvState);
+} VPCIIOCALLBACKS;
+/** Pointer to a const VirtIO port I/O callback structure. */
+typedef const VPCIIOCALLBACKS *PCVPCIIOCALLBACKS;
+/** @} */
+
+int vpciRaiseInterrupt(VPCISTATE *pState, int rcBusy, uint8_t u8IntCause);
+int vpciIOPortIn(PPDMDEVINS pDevIns,
+ void *pvUser,
+ RTIOPORT port,
+ uint32_t *pu32,
+ unsigned cb,
+ PCVPCIIOCALLBACKS pCallbacks);
+
+int vpciIOPortOut(PPDMDEVINS pDevIns,
+ void *pvUser,
+ RTIOPORT port,
+ uint32_t u32,
+ unsigned cb,
+ PCVPCIIOCALLBACKS pCallbacks);
+
+void vpciSetWriteLed(PVPCISTATE pState, bool fOn);
+void vpciSetReadLed(PVPCISTATE pState, bool fOn);
+int vpciSaveExec(PVPCISTATE pState, PSSMHANDLE pSSM);
+int vpciLoadExec(PVPCISTATE pState, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t nQueues);
+int vpciConstruct(PPDMDEVINS pDevIns, VPCISTATE *pState, int iInstance, const char *pcszNameFmt,
+ uint16_t uDeviceId, uint16_t uClass, uint32_t nQueues);
+int vpciDestruct(VPCISTATE* pState);
+void vpciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta);
+void vpciReset(PVPCISTATE pState);
+void *vpciQueryInterface(struct PDMIBASE *pInterface, const char *pszIID);
+PVQUEUE vpciAddQueue(VPCISTATE* pState, unsigned uSize, PFNVPCIQUEUECALLBACK pfnCallback, const char *pcszName);
+
+#define VPCI_CS
+DECLINLINE(int) vpciCsEnter(VPCISTATE *pState, int rcBusy)
+{
+#ifdef VPCI_CS
+ STAM_PROFILE_START(&pState->CTX_SUFF(StatCs), a);
+ int rc = PDMCritSectEnter(&pState->cs, rcBusy);
+ STAM_PROFILE_STOP(&pState->CTX_SUFF(StatCs), a);
+ return rc;
+#else
+ return VINF_SUCCESS;
+#endif
+}
+
+DECLINLINE(void) vpciCsLeave(VPCISTATE *pState)
+{
+#ifdef VPCI_CS
+ PDMCritSectLeave(&pState->cs);
+#endif
+}
+
+void vringSetNotification(PVPCISTATE pState, PVRING pVRing, bool fEnabled);
+
+DECLINLINE(uint16_t) vringReadAvailIndex(PVPCISTATE pState, PVRING pVRing)
+{
+ uint16_t tmp;
+
+ PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns),
+ pVRing->addrAvail + RT_UOFFSETOF(VRINGAVAIL, uNextFreeIndex),
+ &tmp, sizeof(tmp));
+ return tmp;
+}
+
+bool vqueueSkip(PVPCISTATE pState, PVQUEUE pQueue);
+bool vqueueGet(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true);
+void vqueuePut(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t uLen, uint32_t uReserved = 0);
+void vqueueNotify(PVPCISTATE pState, PVQUEUE pQueue);
+void vqueueSync(PVPCISTATE pState, PVQUEUE pQueue);
+
+DECLINLINE(bool) vqueuePeek(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem)
+{
+ return vqueueGet(pState, pQueue, pElem, /* fRemove */ false);
+}
+
+DECLINLINE(bool) vqueueIsReady(PVPCISTATE pState, PVQUEUE pQueue)
+{
+ NOREF(pState);
+ return !!pQueue->VRing.addrAvail;
+}
+
+DECLINLINE(bool) vqueueIsEmpty(PVPCISTATE pState, PVQUEUE pQueue)
+{
+ return (vringReadAvailIndex(pState, &pQueue->VRing) == pQueue->uNextAvailIndex);
+}
+
+#endif /* !VBOX_INCLUDED_SRC_VirtIO_Virtio_h */