VirtualBox

source: vbox/trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h@ 79973

Last change on this file since 79973 was 79973, checked in by vboxsync, 6 years ago

Just checking in changes. Working out new interface between Virtio_1.0.cpp and its clients. Currently crashing in DrvSCSI construct (that was working when it was all contained in DevVirtioScsi). Next thing to troubleshoot.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.5 KB
Line 
1/* $Id: Virtio_1_0.h 79973 2019-07-25 08:10:25Z vboxsync $ */
2/** @file
3 * Virtio_1_0p .h - Virtio Declarations
4 */
5
6/*
7 * Copyright (C) 2009-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef VBOX_INCLUDED_SRC_VirtIO_Virtio_1_0_h
19#define VBOX_INCLUDED_SRC_VirtIO_Virtio_1_0_h
20#ifndef RT_WITHOUT_PRAGMA_ONCE
21# pragma once
22#endif
23
24#include <iprt/ctype.h>
25
26/** @name Saved state versions.
27 * The saved state version is changed if either common or any of specific
28 * parts are changed. That is, it is perfectly possible that the version
29 * of saved vnet state will increase as a result of change in vblk structure
30 * for example.
31 */
32#define VIRTIO_SAVEDSTATE_VERSION_3_1_BETA1 1
33#define VIRTIO_SAVEDSTATE_VERSION 2
34/** @} */
35
36/** Mandatory for Virtio PCI device identification, per spec */
37#define DEVICE_PCI_VENDOR_ID_VIRTIO 0x1AF4
38
39/** Virtio spec suggests >= 1 for non-transitional drivers */
40#define DEVICE_PCI_REVISION_ID_VIRTIO 1
41
42/* Virtio Device PCI Capabilities type codes */
43#define VIRTIO_PCI_CAP_COMMON_CFG 1
44#define VIRTIO_PCI_CAP_NOTIFY_CFG 2
45#define VIRTIO_PCI_CAP_ISR_CFG 3
46#define VIRTIO_PCI_CAP_DEVICE_CFG 4
47#define VIRTIO_PCI_CAP_PCI_CFG 5
48
49/** Device Status field constants (from Virtio 1.0 spec) */
50#define VIRTIO_STATUS_ACKNOWLEDGE 0x01 /** Guest found this emulated PCI device */
51#define VIRTIO_STATUS_DRIVER 0x02 /** Guest can drive this PCI device */
52#define VIRTIO_STATUS_DRIVER_OK 0x04 /** Guest VirtIO driver setup and ready */
53#define VIRTIO_STATUS_FEATURES_OK 0x08 /** Guest says feature negotiation complete */
54#define VIRTIO_STATUS_FAILED 0x80 /** Fatal: Something wrong, guest gave up */
55#define VIRTIO_STATUS_DEVICE_NEEDS_RESET 0x40 /** Device experienced unrecoverable error */
56
57
58#define VIRTIO_MAX_NQUEUES 256 /** Max queues we allow guest to create */
59#define VIRTQUEUEDESC_MAX_SIZE (2 * 1024 * 1024) /** Legacy only? */
60#define VIRTQUEUE_MAX_SIZE 1024 /** According to? Legacy only? */
61#define VIRTIO_ISR_QUEUE 0x1 /* Legacy only? Now derived from feature negotiation? */
62#define VIRTIO_ISR_CONFIG 0x3 /* Legacy only? Now derived from feature negotiation? */
63
64#define VIRTIO_PCI_CAP_ID_VENDOR 0x09
65
66/* Vector value used to disable MSI for queue */
67#define VIRTIO_MSI_NO_VECTOR 0xffff
68
69typedef DECLCALLBACK(uint32_t) FNGETHOSTFEATURES(void *pvState);
70typedef FNGETHOSTFEATURES *PFNGETHOSTFEATURES;
71
72/** @name VirtIO port I/O callbacks.
73 * @{ */
74typedef struct VIRTIOIOCALLBACKS
75{
76 DECLCALLBACKMEMBER(uint32_t, pfnGetHostFeatures)(void *pvState);
77 DECLCALLBACKMEMBER(uint32_t, pfnGetHostMinimalFeatures)(void *pvState);
78 DECLCALLBACKMEMBER(void, pfnSetHostFeatures)(void *pvState, uint32_t fFeatures);
79 DECLCALLBACKMEMBER(int, pfnGetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData);
80 DECLCALLBACKMEMBER(int, pfnSetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData);
81 DECLCALLBACKMEMBER(int, pfnReset)(void *pvState);
82 DECLCALLBACKMEMBER(void, pfnReady)(void *pvState);
83} VIRTIOIOCALLBACKS;
84/** Pointer to a const VirtIO port I/O callback structure. */
85typedef const VIRTIOIOCALLBACKS *PCVIRTIOIOCALLBACKS;
86/** @} */
87
88
89/** Most of the following definitions attempt to adhere to the names and
90 * and forms used by the VirtIO 1.0 specification to increase the maintainability
91 * and speed of ramp-up, in other words, to as unambiguously as possible
92 * map the spec to the VirtualBox implementation of it */
93
94/** Indicates that this descriptor chains to another */
95#define VIRTQ_DESC_F_NEXT 1
96
97/** Marks buffer as write-only (default ro) */
98#define VIRTQ_DESC_F_WRITE 2
99
100/** This means the buffer contains a list of buffer descriptors. */
101#define VIRTQ_DESC_F_INDIRECT 4
102
103/** Optimization: Device advises driver (unreliably): Don't kick me when adding buffer */
104#define VIRTQ_USED_F_NO_NOTIFY 1
105
106/** Optimization: Driver advises device (unreliably): Don't interrupt when buffer consumed */
107#define VIRTQ_AVAIL_F_NO_INTERRUPT 1
108
109/** Using indirect descriptors */
110#define VIRTIO_F_INDIRECT_DESC 28
111
112/** Indicates either avail_event, or used_event fields are in play */
113#define VIRTIO_F_EVENT_IDX 29
114
115/** Allow aribtary descriptor layouts */
116#define VIRTIO_F_ANY_LAYOUT 27
117
118typedef struct VIRTIOPCIPARAMS
119{
120 uint16_t uDeviceId;
121 uint16_t uClassBase;
122 uint16_t uClassSub;
123 uint16_t uClassProg;
124 uint16_t uSubsystemId;
125 uint16_t uSubsystemVendorId;
126 uint16_t uRevisionId;
127 uint16_t uInterruptLine;
128 uint16_t uInterruptPin;
129} VIRTIOPCIPARAMS, *PVIRTIOPCIPARAMS;
130
131typedef struct virtio_pci_cap
132{
133 /* All little-endian */
134 uint8_t uCapVndr; /** Generic PCI field: PCI_CAP_ID_VNDR */
135 uint8_t uCapNext; /** Generic PCI field: next ptr. */
136 uint8_t uCapLen; /** Generic PCI field: capability length */
137 uint8_t uCfgType; /** Identifies the structure. */
138 uint8_t uBar; /** Where to find it. */
139 uint8_t uPadding[3]; /** Pad to full dword. */
140 uint32_t uOffset; /** Offset within bar. (L.E.) */
141 uint32_t uLength; /** Length of struct, in bytes. (L.E.) */
142} VIRTIOPCICAP, *PVIRTIOPCICAP;
143
144typedef struct virtio_pci_common_cfg /* VirtIO 1.0 specification name of this struct */
145{
146 /**
147 *
148 * RW = driver (guest) writes value into this field.
149 * RO = device (host) writes value into this field.
150 */
151
152 /* Per device fields */
153 uint32_t uDeviceFeatureSelect; /** RW (driver selects device features) */
154 uint32_t uDeviceFeature; /** RO (device reports features to driver) */
155 uint32_t uDriverFeatureSelect; /** RW (driver selects driver features) */
156 uint32_t uDriverFeature; /** RW (driver accepts device features) */
157 uint16_t uMsixConfig; /** RW (driver sets MSI-X config vector) */
158 uint16_t uNumQueues; /** RO (device specifies max queues) */
159 uint8_t uDeviceStatus; /** RW (driver writes device status, 0 resets) */
160 uint8_t uConfigGeneration; /** RO (device changes when changing configs) */
161
162 /* Per virtqueue fields (as determined by uQueueSelect) */
163 uint16_t uQueueSelect; /** RW (selects queue focus for these fields) */
164 uint16_t uQueueSize; /** RW (queue size, 0 - 2^n) */
165 uint16_t uQueueMsixVector; /** RW (driver selects MSI-X queue vector) */
166 uint16_t uQueueEnable; /** RW (driver controls usability of queue) */
167 uint16_t uQueueNotifyOff; /** RO (offset to virtqueue; see spec) */
168 uint64_t uQueueDesc; /** RW (driver writes desc table phys addr) */
169 uint64_t uQueueAvail; /** RW (driver writes avail ring phys addr) */
170 uint64_t uQueueUsed; /** RW (driver writes used ring phys addr) */
171} VIRTIOCOMMONCFG, *PVIRTIOCOMMONCFG;
172
173typedef struct virtio_pci_notify_cap
174{
175 struct virtio_pci_cap cap;
176 uint32_t uNotifyOffMultiplier; /* notify_off_multiplier */
177} VIRTIONOTIFYCAP, *PVIRTIONOTIFYCAP;
178
179typedef uint8_t VIRTIOISRCAP, *PVIRTIOISRCAP;
180
181/* Device-specific configuration (if any) ... T.B.D. (if and when neeed), provide an
182 * interface/callback that lets the client of this code manage it, if and when needed.
183 * probably just passing in a struct length and a callback from our capabilities
184 * region handler */
185typedef struct virtio_pci_dev_cfg
186{
187} VIRTIODEVCAP, *PVIRTIODEVCAP;
188
189typedef struct virtio_pci_cfg_cap {
190 struct virtio_pci_cap cap;
191 uint8_t pci_cfg_data[4]; /* Data for BAR access. */
192} VIRTIOPCICFGCAP, *PVIRTIOPCICFGCAP;
193
194typedef struct virtq_desc /* VirtIO 1.0 specification formal name of this struct */
195{
196 uint64_t pGcPhysBuf; /** addr GC physical address of buffer */
197 uint32_t cbBuf; /** len Buffer length */
198 uint16_t fFlags; /** flags Buffer specific flags */
199 uint16_t uNext; /** next Chain idx if VIRTIO_DESC_F_NEXT */
200} VIRTQUEUEDESC, *PVIRTQUEUEDESC;
201
202typedef struct virtq_avail /* VirtIO 1.0 specification formal name of this struct */
203{
204 uint16_t fFlags; /** flags avail ring guest-to-host flags */
205 uint16_t uIdx; /** idx Index of next free ring slot */
206 uint16_t auRing[1]; /** ring Ring: avail guest-to-host bufs */
207 uint16_t uUsedEventIdx; /** used_event (if VIRTQ_USED_F_NO_NOTIFY) */
208} VIRTQUEUEAVAIL, *PVIRTQUEUEAVAIL;
209
210typedef struct virtq_used_elem /* VirtIO 1.0 specification formal name of this struct */
211{
212 uint32_t uIdx; /** idx Start of used descriptor chain */
213 uint32_t cbElem; /** len Total len of used desc chain */
214} VIRTQUEUEUSEDELEM;
215
216typedef struct virt_used /* VirtIO 1.0 specification formal name of this struct */
217{
218 uint16_t fFlags; /** flags used ring host-to-guest flags */
219 uint16_t uIdx; /** idx Index of next ring slot */
220 VIRTQUEUEUSEDELEM aRing[1]; /** ring Ring: used host-to-guest bufs */
221 uint16_t uAvailEventIdx; /** avail_event if (VIRTQ_USED_F_NO_NOTIFY) */
222} VIRTQUEUEUSED, *PVIRTQUEUEUSED;
223
224
225typedef struct virtq
226{
227 uint16_t cbQueue; /** virtq size */
228 uint16_t padding[3]; /** 64-bit-align phys ptrs to start of struct */
229 RTGCPHYS pGcPhysVirtqDescriptors; /** (struct virtq_desc *) */
230 RTGCPHYS pGcPhysVirtqAvail; /** (struct virtq_avail *) */
231 RTGCPHYS pGcPhysVirtqUsed; /** (struct virtq_used *) */
232} VIRTQUEUE, *PVIRTQUEUE;
233
234/**
235 * Queue callback (consumer?).
236 *
237 * @param pvState Pointer to the VirtIO PCI core state, VIRTIOSTATE.
238 * @param pQueue Pointer to the queue structure.
239 */
240typedef DECLCALLBACK(void) FNVIRTIOQUEUECALLBACK(void *pvState, struct VQueue *pQueue);
241/** Pointer to a VQUEUE callback function. */
242typedef FNVIRTIOQUEUECALLBACK *PFNVIRTIOQUEUECALLBACK;
243
244//PCIDevGetCapabilityList
245//PCIDevSetCapabilityList
246//DECLINLINE(void) PDMPciDevSetCapabilityList(PPDMPCIDEV pPciDev, uint8_t u8Offset)
247// PDMPciDevSetByte(pPciDev, VBOX_PCI_CAPABILITY_LIST, u8Offset);
248//DECLINLINE(uint8_t) PDMPciDevGetCapabilityList(PPDMPCIDEV pPciDev)
249// return PDMPciDevGetByte(pPciDev, VBOX_PCI_CAPABILITY_LIST);
250
251typedef struct VQueue
252{
253 VIRTQUEUE VirtQueue;
254 uint16_t uNextAvailIndex;
255 uint16_t uNextUsedIndex;
256 uint32_t uPageNumber;
257 R3PTRTYPE(PFNVIRTIOQUEUECALLBACK) pfnCallback;
258 R3PTRTYPE(const char *) pcszName;
259} VQUEUE;
260typedef VQUEUE *PVQUEUE;
261
262typedef struct VQueueElemSeg
263{
264 RTGCPHYS addr;
265 void *pv;
266 uint32_t cb;
267} VQUEUESEG;
268
269typedef struct VQueueElem
270{
271 uint32_t idx;
272 uint32_t nIn;
273 uint32_t nOut;
274 VQUEUESEG aSegsIn[VIRTQUEUE_MAX_SIZE];
275 VQUEUESEG aSegsOut[VIRTQUEUE_MAX_SIZE];
276} VQUEUEELEM;
277typedef VQUEUEELEM *PVQUEUEELEM;
278
279
280/**
281 * Interface this library uses to let the client handle VirtioIO device-specific capabilities I/O
282 */
283
284typedef DECLCALLBACK(int) FNVIRTIODEVCAPWRITE(PPDMDEVINS pDevIns, RTGCPHYS GCPhysAddr, const void *pvBuf, size_t cbWrite);
285typedef FNVIRTIODEVCAPWRITE *PFNVIRTIODEVCAPWRITE;
286
287typedef DECLCALLBACK(int) FNVIRTIODEVCAPREAD(PPDMDEVINS pDevIns, RTGCPHYS GCPhysAddr, const void *pvBuf, size_t cbRead);
288typedef FNVIRTIODEVCAPREAD *PFNVIRTIODEVCAPREAD;
289
290/**
291 * The core (/common) state of the VirtIO PCI device
292 *
293 * @implements PDMILEDPORTS
294 */
295typedef struct VIRTIOSTATE
296{
297 PDMPCIDEV dev;
298 PDMCRITSECT cs; /**< Critical section - what is it protecting? */
299 /* Read-only part, never changes after initialization. */
300 char szInstance[8]; /**< Instance name, e.g. VNet#1. */
301
302#if HC_ARCH_BITS != 64
303 uint32_t padding1;
304#endif
305
306 /** Status LUN: Base interface. */
307 PDMIBASE IBase;
308 /** Status LUN: LED port interface. */
309 PDMILEDPORTS ILeds;
310 /** Status LUN: LED connector (peer). */
311 R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector;
312
313 PPDMDEVINSR3 pDevInsR3; /**< Device instance - R3. */
314 PPDMDEVINSR0 pDevInsR0; /**< Device instance - R0. */
315 PPDMDEVINSRC pDevInsRC; /**< Device instance - RC. */
316
317 /** Base address of PCI capabilities */
318 RTGCPHYS GCPhysPciCapBase;
319
320 VIRTIOCOMMONCFG pGcPhysVirtioCommonCfg;
321 VIRTIONOTIFYCAP pGcPhysVirtioNotifyCap;
322 VIRTIOISRCAP pGcPhysVirtioIsrCap;
323 VIRTIODEVCAP pGcPhysVirtioDevCap;
324 VIRTIOPCICFGCAP pGcPhysVirtioPciCap;
325
326 /** Callbacks when guest driver reads or writes VirtIO device-specific capabilities(s) */
327
328 PFNVIRTIODEVCAPWRITE pfnVirtioDevCapWrite;
329 PFNVIRTIODEVCAPREAD pfnVirtioDevCapRead;
330
331#if HC_ARCH_BITS == 64
332 uint32_t padding2;
333#endif
334
335 /** Base port of I/O space region. */
336 RTIOPORT IOPortBase;
337
338 /* Read/write part, protected with critical section. */
339 /** Status LED. */
340 PDMLED led;
341
342 uint32_t uGuestFeatures;
343 uint16_t uQueueSelector; /**< An index in aQueues array. */
344 uint8_t uStatus; /**< Device Status (bits are device-specific). */
345 uint8_t uISR; /**< Interrupt Status Register. */
346
347#if HC_ARCH_BITS != 64
348 uint32_t padding3;
349#endif
350
351 uint32_t nQueues; /**< Actual number of queues used. */
352 VQUEUE Queues[VIRTIO_MAX_NQUEUES];
353
354 PVIRTIOPCICAP pCommonCfg;
355 PVIRTIOPCICAP pNotifyCap;
356 PVIRTIOPCICAP pISRCap;
357 PVIRTIOPCICAP pPCICfgCap;
358 PVIRTIOPCICAP pDeviceCap;
359} VIRTIOSTATE, *PVIRTIOSTATE;
360
361void virtioRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta);
362void *virtioQueryInterface(struct PDMIBASE *pInterface, const char *pszIID);
363
364int virtioIOPortIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port,
365 uint32_t *pu32, unsigned cb, PCVIRTIOIOCALLBACKS pCallbacks);
366
367int virtioIOPortOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port,
368 uint32_t u32, unsigned cb, PCVIRTIOIOCALLBACKS pCallbacks);
369
370int virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance,
371 PVIRTIOPCIPARAMS pPciParams, const char *pcszNameFmt,
372 uint32_t nQueues, uint32_t uVirtioRegion,
373 PFNVIRTIODEVCAPREAD devCapReadCallback, PFNVIRTIODEVCAPWRITE devCapWriteCallback,
374 uint16_t cbDevSpecificCap);
375
376
377int virtioDestruct( PVIRTIOSTATE pState);
378void virtioReset( PVIRTIOSTATE pState);
379int virtioSaveExec( PVIRTIOSTATE pState, PSSMHANDLE pSSM);
380int virtioLoadExec( PVIRTIOSTATE pState, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t nQueues);
381void virtioSetReadLed( PVIRTIOSTATE pState, bool fOn);
382void virtioSetWriteLed( PVIRTIOSTATE pState, bool fOn);
383int virtioRaiseInterrupt( PVIRTIOSTATE pState, int rcBusy, uint8_t uint8_tIntCause);
384
385PVQUEUE virtioAddQueue( PVIRTIOSTATE pState, unsigned uSize, PFNVIRTIOQUEUECALLBACK pfnCallback, const char *pcszName);
386bool virtQueueSkip( PVIRTIOSTATE pState, PVQUEUE pQueue);
387bool virtQueueGet( PVIRTIOSTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true);
388void virtQueuePut( PVIRTIOSTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t len, uint32_t uReserved = 0);
389void virtQueueNotify( PVIRTIOSTATE pState, PVQUEUE pQueue);
390void virtQueueSync( PVIRTIOSTATE pState, PVQUEUE pQueue);
391void vringSetNotification( PVIRTIOSTATE pState, PVIRTQUEUE pVirtQueue, bool fEnabled);
392
393
394/*
395 static inline int virtq_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old_idx)
396 return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old_idx);
397 }
398 // Get location of event indices (only with VIRTIO_F_EVENT_IDX)
399 static inline le16 *virtq_used_event(struct virtq *vq)
400 {
401 // For backwards compat, used event index is at *end* of avail ring.
402 return &vq->avail->ring[vq->num];
403}
404 static inline le16 *virtq_avail_event(struct virtq *vq)
405 {
406 // For backwards compat, avail event index is at *end* of used ring.
407 return (le16 *)&vq->used->ring[vq->num];
408 }
409}
410*/
411
412DECLINLINE(uint16_t) vringReadAvail(PVIRTIOSTATE pState, PVIRTQUEUE pVirtQueue)
413{
414 uint16_t dataWord;
415 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns),
416 pVirtQueue->pGcPhysVirtqAvail + RT_UOFFSETOF(VIRTQUEUEAVAIL, uIdx),
417 &dataWord, sizeof(dataWord));
418 return dataWord;
419}
420
421DECLINLINE(bool) virtQueuePeek(PVIRTIOSTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem)
422{
423 return virtQueueGet(pState, pQueue, pElem, /* fRemove */ false);
424}
425
426DECLINLINE(bool) virtQueueIsReady(PVIRTIOSTATE pState, PVQUEUE pQueue)
427{
428 NOREF(pState);
429 return !!pQueue->VirtQueue.pGcPhysVirtqAvail;
430}
431
432DECLINLINE(bool) virtQueueIsEmpty(PVIRTIOSTATE pState, PVQUEUE pQueue)
433{
434 return (vringReadAvail(pState, &pQueue->VirtQueue) == pQueue->uNextAvailIndex);
435}
436
437DECLINLINE(int) virtioLock(VIRTIOSTATE *pState, int rcBusy)
438{
439 int rc = PDMCritSectEnter(&pState->cs, rcBusy);
440 return rc;
441}
442
443DECLINLINE(void) virtioUnlock(VIRTIOSTATE *pState)
444{
445 PDMCritSectLeave(&pState->cs);
446}
447
448#endif /* !VBOX_INCLUDED_SRC_VirtIO_Virtio_1_0_h */
Note: See TracBrowser for help on using the repository browser.

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