Virtio.h revision ee4d840f54fd2dcea8a73b1b86d5ec0db370b05d
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* $Id$ */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/** @file
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Virtio.h - Virtio Declarations
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/*
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Copyright (C) 2009 Sun Microsystems, Inc.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync *
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * available from http://www.virtualbox.org. This file is free software;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * you can redistribute it and/or modify it under the terms of the GNU
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * General Public License (GPL) as published by the Free Software
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync *
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * additional information or have any questions.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifndef ___VBox_Virtio_h
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define ___VBox_Virtio_h
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#include <iprt/ctype.h>
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VIRTIO_RELOCATE(p, o) *(RTHCUINTPTR *)&p += o
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/*
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * The saved state version is changed if either common or any of specific
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * parts are changed. That is, it is perfectly possible that the version
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * of saved vnet state will increase as a result of change in vblk structure
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * for example.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VIRTIO_SAVEDSTATE_VERSION_3_1_BETA1 1
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VIRTIO_SAVEDSTATE_VERSION 2
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define DEVICE_PCI_VENDOR_ID 0x1AF4
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define DEVICE_PCI_DEVICE_ID 0x1000
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define DEVICE_PCI_SUBSYSTEM_VENDOR_ID 0x1AF4
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VIRTIO_MAX_NQUEUES 3
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_HOST_FEATURES 0x0
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_GUEST_FEATURES 0x4
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_QUEUE_PFN 0x8
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_QUEUE_NUM 0xC
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_QUEUE_SEL 0xE
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_QUEUE_NOTIFY 0x10
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_STATUS 0x12
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_ISR 0x13
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_CONFIG 0x14
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_ISR_QUEUE 0x1
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_ISR_CONFIG 0x3
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_STATUS_ACK 0x01
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_STATUS_DRV 0x02
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_STATUS_DRV_OK 0x04
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_STATUS_FAILED 0x80
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_F_NOTIFY_ON_EMPTY 0x01000000
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VPCI_F_BAD_FEATURE 0x40000000
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VRINGDESC_MAX_SIZE (2 * 1024 * 1024)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VRINGDESC_F_NEXT 0x01
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VRINGDESC_F_WRITE 0x02
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstruct VRingDesc
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint64_t u64Addr;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint32_t uLen;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint16_t u16Flags;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint16_t u16Next;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync};
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsynctypedef struct VRingDesc VRINGDESC;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsynctypedef VRINGDESC *PVRINGDESC;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define VRINGAVAIL_F_NO_INTERRUPT 0x01
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstruct VRingAvail
{
uint16_t uFlags;
uint16_t uNextFreeIndex;
uint16_t auRing[1];
};
typedef struct VRingAvail VRINGAVAIL;
struct VRingUsedElem
{
uint32_t uId;
uint32_t uLen;
};
typedef struct VRingUsedElem VRINGUSEDELEM;
#define VRINGUSED_F_NO_NOTIFY 0x01
struct VRingUsed
{
uint16_t uFlags;
uint16_t uIndex;
VRINGUSEDELEM aRing[1];
};
typedef struct VRingUsed VRINGUSED;
typedef VRINGUSED *PVRINGUSED;
#define VRING_MAX_SIZE 1024
struct VRing
{
uint16_t uSize;
uint16_t padding[3];
RTGCPHYS addrDescriptors;
RTGCPHYS addrAvail;
RTGCPHYS addrUsed;
};
typedef struct VRing VRING;
typedef VRING *PVRING;
struct VQueue
{
VRING VRing;
uint16_t uNextAvailIndex;
uint16_t uNextUsedIndex;
uint32_t uPageNumber;
#ifdef IN_RING3
void (*pfnCallback)(void *pvState, struct VQueue *pQueue);
#else
RTR3UINTPTR pfnCallback;
#endif
R3PTRTYPE(const char *) pcszName;
};
typedef struct VQueue VQUEUE;
typedef VQUEUE *PVQUEUE;
struct VQueueElemSeg
{
RTGCPHYS addr;
void *pv;
uint32_t cb;
};
typedef struct VQueueElemSeg VQUEUESEG;
struct VQueueElem
{
uint32_t uIndex;
uint32_t nIn;
uint32_t nOut;
VQUEUESEG aSegsIn[VRING_MAX_SIZE];
VQUEUESEG aSegsOut[VRING_MAX_SIZE];
};
typedef struct VQueueElem VQUEUEELEM;
typedef VQUEUEELEM *PVQUEUEELEM;
enum VirtioDeviceType
{
VIRTIO_NET_ID = 0,
VIRTIO_BLK_ID = 1,
VIRTIO_32BIT_HACK = 0x7fffffff
};
/**
* The state of the VirtIO PCI device
*
* @implements PDMILEDPORTS
*/
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 */
PCIDEVICE pciDevice;
/** Base port of I/O space region. */
RTIOPORT addrIOPort;
/* 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 StatIOReadGC;
STAMPROFILEADV StatIOReadHC;
STAMPROFILEADV StatIOWriteGC;
STAMPROFILEADV StatIOWriteHC;
STAMCOUNTER StatIntsRaised;
STAMCOUNTER StatIntsSkipped;
STAMPROFILE StatCsGC;
STAMPROFILE StatCsHC;
#endif /* VBOX_WITH_STATISTICS */
};
typedef struct VPCIState_st VPCISTATE;
typedef VPCISTATE *PVPCISTATE;
/* Callbacks *****************************************************************/
typedef uint32_t (*PFNGETHOSTFEATURES)(void *pState);
typedef uint32_t (*PFNGETHOSTMINIMALFEATURES)(void *pState);
typedef void (*PFNSETHOSTFEATURES)(void *pState, uint32_t uFeatures);
typedef int (*PFNGETCONFIG)(void *pState, uint32_t port, uint32_t cb, void *data);
typedef int (*PFNSETCONFIG)(void *pState, uint32_t port, uint32_t cb, void *data);
typedef void (*PFNRESET)(void *pState);
typedef void (*PFNREADY)(void *pState);
/*****************************************************************************/
int vpciRaiseInterrupt(VPCISTATE *pState, int rcBusy, uint8_t u8IntCause);
int vpciIOPortIn(PPDMDEVINS pDevIns,
void *pvUser,
RTIOPORT port,
uint32_t *pu32,
unsigned cb,
PFNGETHOSTFEATURES pfnGetHostFeatures,
PFNGETCONFIG pfnGetConfig);
int vpciIOPortOut(PPDMDEVINS pDevIns,
void *pvUser,
RTIOPORT port,
uint32_t u32,
unsigned cb,
PFNGETHOSTMINIMALFEATURES pfnGetHostMinimalFeatures,
PFNGETHOSTFEATURES pfnGetHostFeatures,
PFNSETHOSTFEATURES pfnSetHostFeatures,
PFNRESET pfnReset,
PFNREADY pfnReady,
PFNSETCONFIG pfnSetConfig);
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 uSubsystemId, 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,
void (*pfnCallback)(void *pvState, PVQUEUE pQueue),
const char *pcszName);
#define VPCI_CS
DECLINLINE(int) vpciCsEnter(VPCISTATE *pState, int iBusyRc)
{
#ifdef VPCI_CS
STAM_PROFILE_START(&pState->CTXSUFF(StatCs), a);
int rc = PDMCritSectEnter(&pState->cs, iBusyRc);
STAM_PROFILE_STOP(&pState->CTXSUFF(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_OFFSETOF(VRINGAVAIL, uNextFreeIndex),
&tmp, sizeof(tmp));
return tmp;
}
bool vqueueGet(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem);
void vqueuePut(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t uLen);
void vqueueNotify(PVPCISTATE pState, PVQUEUE pQueue);
void vqueueSync(PVPCISTATE pState, PVQUEUE pQueue);
DECLINLINE(bool) vqueueIsReady(PVPCISTATE pState, PVQUEUE pQueue)
{
return !!pQueue->VRing.addrAvail;
}
DECLINLINE(bool) vqueueIsEmpty(PVPCISTATE pState, PVQUEUE pQueue)
{
return (vringReadAvailIndex(pState, &pQueue->VRing) == pQueue->uNextAvailIndex);
}
#endif /* ___VBox_Virtio_h */