|
|
nono 1.5.0
//
// VirtIO 定義
// https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.html
//
#pragma once
#include "header.h"
// 元仕様をそのまま記述するために用意しておく。
using u8 = uint8;
using le16 = uint16;
using le32 = uint32;
using le64 = uint64;
#define QUEUE_SIZE_ (0)
// レジスタ名とかのプレフィックスを持たない名前。
class VirtIO
{
public:
// レジスタ (仕様は LE だがゲストエンディアンで動作させる)
static const uint32 MAGIC_VALUE = 0x000; // R-
static const uint32 VERSION = 0x004; // R-
static const uint32 DEVICE_ID = 0x008; // R-
static const uint32 VENDOR_ID = 0x00c; // R-
static const uint32 DEVICE_FEATURES = 0x010; // R-
static const uint32 DEVICE_FEATURES_SEL = 0x014; // -W
static const uint32 DRIVER_FEATURES = 0x020; // -W
static const uint32 DRIVER_FEATURES_SEL = 0x024; // -W
static const uint32 QUEUE_SEL = 0x030; // -W
static const uint32 QUEUE_NUM_MAX = 0x034; // R-
static const uint32 QUEUE_NUM = 0x038; // -W
static const uint32 QUEUE_READY = 0x044; // RW
static const uint32 QUEUE_NOTIFY = 0x050; // -W
static const uint32 INTERRUPT_STATUS = 0x060; // R-
static const uint32 INTERRUPT_ACK = 0x064; // -W
static const uint32 STATUS = 0x070; // RW
static const uint32 QUEUE_DESC_LOW = 0x080; // -W
static const uint32 QUEUE_DESC_HIGH = 0x084; // -W
static const uint32 QUEUE_DRIVER_LOW = 0x090; // -W
static const uint32 QUEUE_DRIVER_HIGH = 0x094; // -W
static const uint32 QUEUE_DEVICE_LOW = 0x0a0; // -W
static const uint32 QUEUE_DEVICE_HIGH = 0x0a4; // -W
static const uint32 CONFIG_GENERATION = 0x0fc; // R-
// マジック
static const uint32 MAGIC_STRING = 0x74726976; // 'virt'
// バージョン
static const uint32 DEVICE_VERSION = 2;
// DEVICE_ID
static const uint32 DEVICE_ID_INVALID = 0;
static const uint32 DEVICE_ID_NETWORK = 1;
static const uint32 DEVICE_ID_BLOCK = 2;
static const uint32 DEVICE_ID_CONSOLE = 3;
static const uint32 DEVICE_ID_ENTROPY = 4;
static const uint32 DEVICE_ID_BALLOON = 5;
static const uint32 DEVICE_ID_SCSI = 8;
static std::string DeviceIDStr(uint32);
// STATUS
static const uint32 STATUS_RESET = 0;
static const uint32 STATUS_ACKNOWLEDGE = (1U << 0);
static const uint32 STATUS_DRIVER = (1U << 1);
static const uint32 STATUS_OK = (1U << 2);
static const uint32 STATUS_FEATURES_OK = (1U << 3);
static const uint32 STATUS_NEEDS_RESET = (1U << 6);
static const uint32 STATUS_FAILED = (1U << 7);
static std::string StatusBits(uint32);
};
// FEATURES (共通)
static const uint VIRTIO_F_RING_INDIRECT_DESC = 28;
static const uint VIRTIO_F_RING_EVENT_IDX = 29;
static const uint VIRTIO_F_VERSION_1 = 32;
static const uint VIRTIO_F_ACCESS_PLATFORM = 33;
static const uint VIRTIO_F_RING_PACKED = 34;
static const uint VIRTIO_F_IN_ORDER = 35;
static const uint VIRTIO_F_ORDER_PLATFORM = 36;
static const uint VIRTIO_F_SF_IOV = 37;
static const uint VIRTIO_F_NOTIFICATION_DATA = 38;
// FEATURES (NetworkDevice)
static const uint VIRTIO_NET_F_CSUM = 0;
static const uint VIRTIO_NET_F_GUEST_CSUM = 1;
static const uint VIRTIO_NET_F_CTRL_GUEST_OFFLOADS = 2;
static const uint VIRTIO_NET_F_MTU = 3;
static const uint VIRTIO_NET_F_MAC = 5;
static const uint VIRTIO_NET_F_GUEST_TSO4 = 7;
static const uint VIRTIO_NET_F_GUEST_TSO6 = 8;
static const uint VIRTIO_NET_F_GUEST_ECN = 9;
static const uint VIRTIO_NET_F_GUEST_UFO = 10;
static const uint VIRTIO_NET_F_HOST_TSO4 = 11;
static const uint VIRTIO_NET_F_HOST_TSO6 = 12;
static const uint VIRTIO_NET_F_HOST_ECN = 13;
static const uint VIRTIO_NET_F_HOST_UFO = 14;
static const uint VIRTIO_NET_F_MRG_RXBUF = 15;
static const uint VIRTIO_NET_F_STATUS = 16;
static const uint VIRTIO_NET_F_CTRL_VQ = 17;
static const uint VIRTIO_NET_F_CTRL_RX = 18;
static const uint VIRTIO_NET_F_CTRL_VLAN = 19;
static const uint VIRTIO_NET_F_GUEST_ANNOUNCE = 21;
static const uint VIRTIO_NET_F_MQ = 22;
static const uint VIRTIO_NET_F_CTRL_MAC_ADDR = 23;
static const uint VIRTIO_NET_F_RSC_EXT = 61;
static const uint VIRTIO_NET_F_STANDBY = 62;
// FEATURES (BlockDevice)
static const uint VIRTIO_BLK_F_SIZE_MAX = 1;
static const uint VIRTIO_BLK_F_SEG_MAX = 2;
static const uint VIRTIO_BLK_F_GEOMETRY = 4;
static const uint VIRTIO_BLK_F_RO = 5;
static const uint VIRTIO_BLK_F_BLK_SIZE = 6;
static const uint VIRTIO_BLK_F_FLUSH = 9;
static const uint VIRTIO_BLK_F_TOPOLOGY = 10;
static const uint VIRTIO_BLK_F_CONFIG_WCE = 11;
static const uint VIRTIO_BLK_F_DISCARD = 13;
static const uint VIRTIO_BLK_F_WRITE_ZEROES = 14;
// FEATURES (SCSIDevice)
static const uint VIRTIO_SCSI_F_INOUT = 0;
static const uint VIRTIO_SCSI_F_HOTPLUG = 1;
static const uint VIRTIO_SCSI_F_CHANGE = 2;
static const uint VIRTIO_SCSI_F_T10_PI = 4;
// こっちは仕様上の構造体定義。クラスのほうを使うこと。
struct virtq_desc {
le64 addr; // Guest physical address
le32 len; // Length
le16 flags; // The flags as indicated above
le16 next; // Next field if flags & NEXT
};
static const uint16 VIRTQ_DESC_F_NEXT = 1;
static const uint16 VIRTQ_DESC_F_WRITE = 2;
static const uint16 VIRTQ_DESC_F_INDIRECT = 4;
class VirtQDesc
{
public:
uint32 addr {};
uint32 len {};
uint32 flag {};
uint32 next {};
public:
bool IsWrite() const { return (flag & VIRTQ_DESC_F_WRITE); }
bool IsRead() const { return !IsWrite(); }
bool IsNext() const { return (flag & VIRTQ_DESC_F_NEXT); }
std::string ToStr() const;
};
struct virtq_avail {
le16 flags;
le16 idx;
le16 ring[QUEUE_SIZE_];
le16 used_event; // Only if F_EVENT_IDX
};
static const uint16 VIRTQ_AVAIL_F_NO_INTERRUPT = 1;
struct virtq_used {
le16 flags;
le16 idx;
struct virtq_used_elem {
le32 id; // Index of start of used descriptor chan
le32 len; // Total length of the descriptor chain which was used
} ring[QUEUE_SIZE_];
le16 avail_count; // Only if F_EVENT_IDX
};
static const uint16 VIRTQ_USED_F_NO_NOTIFY = 1;
// NetworkDevice
struct virtio_net_hdr {
u8 flags;
u8 gso_type;
le16 hdr_len;
le16 gso_size;
le16 csum_start;
le16 csum_offset;
le16 num_buffers;
} __packed;
static const uint8 VIRTIO_NET_HDR_F_NEED_CSUM = 1;
static const uint8 VIRTIO_NET_HDR_F_DATA_VALID = 2;
static const uint8 VIRTIO_NET_HDR_F_RSC_INFO = 4;
static const uint8 VIRTIO_NET_HDR_GSO_NONE = 0;
static const uint8 VIRTIO_NET_HDR_GSO_TCPV4 = 1;
static const uint8 VIRTIO_NET_HDR_GSO_UDP = 3;
static const uint8 VIRTIO_NET_HDR_GSO_TCPV6 = 4;
static const uint8 VIRTIO_NET_HDR_GSO_ECN = 0x80;
// BlockDevice
struct virtio_blk_req {
le32 type;
le32 reserved;
le64 sector;
u8 data[0]; // u8 data[][512]
u8 status;
};
static const uint32 VIRTIO_BLK_T_IN = 0;
static const uint32 VIRTIO_BLK_T_OUT = 1;
static const uint32 VIRTIO_BLK_T_FLUSH = 4;
static const uint32 VIRTIO_BLK_T_GET_ID = 8;
static const uint32 VIRTIO_BLK_T_DISCARD = 11;
static const uint32 VIRTIO_BLK_T_WRITE_ZEROES = 13;
static const uint8 VIRTIO_BLK_S_OK = 0;
static const uint8 VIRTIO_BLK_S_IOERR = 1;
static const uint8 VIRTIO_BLK_S_UNSUPP = 2;
struct virtio_blk_discard_write_zeroes {
le64 sector;
le32 num_sectors;
//struct {
// le32 unmap:1;
// le32 reserved:31;
//} flags;
le32 flags;
};
// SCSIDevice
struct virtio_scsi_req_cmd {
// Device-readable part
u8 lun[8];
le64 id;
u8 task_attr;
u8 prio;
u8 crn;
u8 cdb[0]; // [cdb_size]
// The next three fields are only present if VIRTIO_SCSI_F_T10_PI
// is negotiated.
//le32 pi_bytesout;
//le32 pi_bytesin;
//u8 pi_out[pi_bytesout];
u8 dataout[0];
// Device-writable part
le32 sense_len;
le32 residual;
le16 status_qualifier;
u8 status;
u8 response;
u8 sense[0]; // [sense_size]
// The next field is only present if VIRTIO_SCS_IF_T10_PI
// is negotiated.
//u8 pi_in[pi_bytesin];
u8 datain[0];
};
struct virtio_scsi_ctrl {
le32 type;
//
u8 response;
};
static const uint8 VIRTIO_SCSI_S_OK = 0;
static const uint8 VIRTIO_SCSI_S_OVERRUN = 1;
static const uint8 VIRTIO_SCSI_S_ABORTED = 2;
static const uint8 VIRTIO_SCSI_S_BAD_TARGET = 3;
static const uint8 VIRTIO_SCSI_S_RESET = 4;
static const uint8 VIRTIO_SCSI_S_BUSY = 5;
static const uint8 VIRTIO_SCSI_S_TRANSPORT_FAILURE = 6;
static const uint8 VIRTIO_SCSI_S_TARGET_FAILURE = 7;
static const uint8 VIRTIO_SCSI_S_NEXUS_FAILURE = 8;
static const uint8 VIRTIO_SCSI_S_FAILURE = 9;
static const uint8 VIRTIO_SCSI_S_INCORRECT_LUN = 12;
// task_attr
static const uint8 VIRTIO_SCSI_S_SIMPLE = 0;
static const uint8 VIRTIO_SCSI_S_ORDERED = 1;
static const uint8 VIRTIO_SCSI_S_HEAD = 2;
static const uint8 VIRTIO_SCSI_S_ACA = 3;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.