|
|
1.1 root 1: //
2: // VirtIO 定義
3: // https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.html
4: //
5:
6: #pragma once
7:
8: #include "header.h"
9:
10: // 元仕様をそのまま記述するために用意しておく。
11: using u8 = uint8;
12: using le16 = uint16;
13: using le32 = uint32;
14: using le64 = uint64;
15: #define QUEUE_SIZE_ (0)
16:
17: // レジスタ名とかのプレフィックスを持たない名前。
18: class VirtIO
19: {
20: public:
21: // レジスタ (仕様は LE だがゲストエンディアンで動作させる)
22: static const uint32 MAGIC_VALUE = 0x000; // R-
23: static const uint32 VERSION = 0x004; // R-
24: static const uint32 DEVICE_ID = 0x008; // R-
25: static const uint32 VENDOR_ID = 0x00c; // R-
26: static const uint32 DEVICE_FEATURES = 0x010; // R-
27: static const uint32 DEVICE_FEATURES_SEL = 0x014; // -W
28: static const uint32 DRIVER_FEATURES = 0x020; // -W
29: static const uint32 DRIVER_FEATURES_SEL = 0x024; // -W
30: static const uint32 QUEUE_SEL = 0x030; // -W
31: static const uint32 QUEUE_NUM_MAX = 0x034; // R-
32: static const uint32 QUEUE_NUM = 0x038; // -W
33: static const uint32 QUEUE_READY = 0x044; // RW
34: static const uint32 QUEUE_NOTIFY = 0x050; // -W
35: static const uint32 INTERRUPT_STATUS = 0x060; // R-
36: static const uint32 INTERRUPT_ACK = 0x064; // -W
37: static const uint32 STATUS = 0x070; // RW
38: static const uint32 QUEUE_DESC_LOW = 0x080; // -W
39: static const uint32 QUEUE_DESC_HIGH = 0x084; // -W
40: static const uint32 QUEUE_DRIVER_LOW = 0x090; // -W
41: static const uint32 QUEUE_DRIVER_HIGH = 0x094; // -W
42: static const uint32 QUEUE_DEVICE_LOW = 0x0a0; // -W
43: static const uint32 QUEUE_DEVICE_HIGH = 0x0a4; // -W
44: static const uint32 CONFIG_GENERATION = 0x0fc; // R-
45:
46: // マジック
47: static const uint32 MAGIC_STRING = 0x74726976; // 'virt'
48:
49: // バージョン
50: static const uint32 DEVICE_VERSION = 2;
51:
52: // DEVICE_ID
53: static const uint32 DEVICE_ID_INVALID = 0;
1.1.1.2 root 54: static const uint32 DEVICE_ID_NETWORK = 1;
1.1 root 55: static const uint32 DEVICE_ID_BLOCK = 2;
1.1.1.2 root 56: static const uint32 DEVICE_ID_CONSOLE = 3;
57: static const uint32 DEVICE_ID_ENTROPY = 4;
1.1.1.3 ! root 58: static const uint32 DEVICE_ID_BALLOON = 5;
! 59: static const uint32 DEVICE_ID_SCSI = 8;
1.1 root 60: static std::string DeviceIDStr(uint32);
61:
62: // STATUS
63: static const uint32 STATUS_RESET = 0;
64: static const uint32 STATUS_ACKNOWLEDGE = (1U << 0);
65: static const uint32 STATUS_DRIVER = (1U << 1);
66: static const uint32 STATUS_OK = (1U << 2);
67: static const uint32 STATUS_FEATURES_OK = (1U << 3);
68: static const uint32 STATUS_NEEDS_RESET = (1U << 6);
69: static const uint32 STATUS_FAILED = (1U << 7);
70: static std::string StatusBits(uint32);
71: };
72:
73: // FEATURES (共通)
74: static const uint VIRTIO_F_RING_INDIRECT_DESC = 28;
75: static const uint VIRTIO_F_RING_EVENT_IDX = 29;
76: static const uint VIRTIO_F_VERSION_1 = 32;
77: static const uint VIRTIO_F_ACCESS_PLATFORM = 33;
78: static const uint VIRTIO_F_RING_PACKED = 34;
79: static const uint VIRTIO_F_IN_ORDER = 35;
80: static const uint VIRTIO_F_ORDER_PLATFORM = 36;
81: static const uint VIRTIO_F_SF_IOV = 37;
82: static const uint VIRTIO_F_NOTIFICATION_DATA = 38;
83: // FEATURES (NetworkDevice)
84: static const uint VIRTIO_NET_F_CSUM = 0;
85: static const uint VIRTIO_NET_F_GUEST_CSUM = 1;
86: static const uint VIRTIO_NET_F_CTRL_GUEST_OFFLOADS = 2;
87: static const uint VIRTIO_NET_F_MTU = 3;
88: static const uint VIRTIO_NET_F_MAC = 5;
89: static const uint VIRTIO_NET_F_GUEST_TSO4 = 7;
90: static const uint VIRTIO_NET_F_GUEST_TSO6 = 8;
91: static const uint VIRTIO_NET_F_GUEST_ECN = 9;
92: static const uint VIRTIO_NET_F_GUEST_UFO = 10;
93: static const uint VIRTIO_NET_F_HOST_TSO4 = 11;
94: static const uint VIRTIO_NET_F_HOST_TSO6 = 12;
95: static const uint VIRTIO_NET_F_HOST_ECN = 13;
96: static const uint VIRTIO_NET_F_HOST_UFO = 14;
97: static const uint VIRTIO_NET_F_MRG_RXBUF = 15;
98: static const uint VIRTIO_NET_F_STATUS = 16;
99: static const uint VIRTIO_NET_F_CTRL_VQ = 17;
100: static const uint VIRTIO_NET_F_CTRL_RX = 18;
101: static const uint VIRTIO_NET_F_CTRL_VLAN = 19;
102: static const uint VIRTIO_NET_F_GUEST_ANNOUNCE = 21;
103: static const uint VIRTIO_NET_F_MQ = 22;
104: static const uint VIRTIO_NET_F_CTRL_MAC_ADDR = 23;
105: static const uint VIRTIO_NET_F_RSC_EXT = 61;
106: static const uint VIRTIO_NET_F_STANDBY = 62;
107: // FEATURES (BlockDevice)
108: static const uint VIRTIO_BLK_F_SIZE_MAX = 1;
109: static const uint VIRTIO_BLK_F_SEG_MAX = 2;
110: static const uint VIRTIO_BLK_F_GEOMETRY = 4;
111: static const uint VIRTIO_BLK_F_RO = 5;
112: static const uint VIRTIO_BLK_F_BLK_SIZE = 6;
113: static const uint VIRTIO_BLK_F_FLUSH = 9;
114: static const uint VIRTIO_BLK_F_TOPOLOGY = 10;
115: static const uint VIRTIO_BLK_F_CONFIG_WCE = 11;
116: static const uint VIRTIO_BLK_F_DISCARD = 13;
117: static const uint VIRTIO_BLK_F_WRITE_ZEROES = 14;
1.1.1.3 ! root 118: // FEATURES (SCSIDevice)
! 119: static const uint VIRTIO_SCSI_F_INOUT = 0;
! 120: static const uint VIRTIO_SCSI_F_HOTPLUG = 1;
! 121: static const uint VIRTIO_SCSI_F_CHANGE = 2;
! 122: static const uint VIRTIO_SCSI_F_T10_PI = 4;
1.1 root 123:
124:
125: // こっちは仕様上の構造体定義。クラスのほうを使うこと。
126: struct virtq_desc {
127: le64 addr; // Guest physical address
128: le32 len; // Length
129: le16 flags; // The flags as indicated above
130: le16 next; // Next field if flags & NEXT
131: };
132: static const uint16 VIRTQ_DESC_F_NEXT = 1;
133: static const uint16 VIRTQ_DESC_F_WRITE = 2;
134: static const uint16 VIRTQ_DESC_F_INDIRECT = 4;
135:
136: class VirtQDesc
137: {
138: public:
139: uint32 addr {};
140: uint32 len {};
141: uint32 flag {};
142: uint32 next {};
143: public:
144: bool IsWrite() const { return (flag & VIRTQ_DESC_F_WRITE); }
145: bool IsRead() const { return !IsWrite(); }
146: bool IsNext() const { return (flag & VIRTQ_DESC_F_NEXT); }
147: std::string ToStr() const;
148: };
149:
150: struct virtq_avail {
151: le16 flags;
152: le16 idx;
153: le16 ring[QUEUE_SIZE_];
154: le16 used_event; // Only if F_EVENT_IDX
155: };
156: static const uint16 VIRTQ_AVAIL_F_NO_INTERRUPT = 1;
157:
158: struct virtq_used {
159: le16 flags;
160: le16 idx;
161: struct virtq_used_elem {
162: le32 id; // Index of start of used descriptor chan
163: le32 len; // Total length of the descriptor chain which was used
164: } ring[QUEUE_SIZE_];
165: le16 avail_count; // Only if F_EVENT_IDX
166: };
167: static const uint16 VIRTQ_USED_F_NO_NOTIFY = 1;
168:
169:
1.1.1.3 ! root 170: // NetworkDevice
1.1 root 171:
172: struct virtio_net_hdr {
173: u8 flags;
174: u8 gso_type;
175: le16 hdr_len;
176: le16 gso_size;
177: le16 csum_start;
178: le16 csum_offset;
179: le16 num_buffers;
180: } __packed;
181:
182: static const uint8 VIRTIO_NET_HDR_F_NEED_CSUM = 1;
183: static const uint8 VIRTIO_NET_HDR_F_DATA_VALID = 2;
184: static const uint8 VIRTIO_NET_HDR_F_RSC_INFO = 4;
185:
186: static const uint8 VIRTIO_NET_HDR_GSO_NONE = 0;
187: static const uint8 VIRTIO_NET_HDR_GSO_TCPV4 = 1;
188: static const uint8 VIRTIO_NET_HDR_GSO_UDP = 3;
189: static const uint8 VIRTIO_NET_HDR_GSO_TCPV6 = 4;
190: static const uint8 VIRTIO_NET_HDR_GSO_ECN = 0x80;
191:
192: // BlockDevice
193:
194: struct virtio_blk_req {
195: le32 type;
196: le32 reserved;
197: le64 sector;
198: u8 data[0]; // u8 data[][512]
199: u8 status;
200: };
201:
202: static const uint32 VIRTIO_BLK_T_IN = 0;
203: static const uint32 VIRTIO_BLK_T_OUT = 1;
204: static const uint32 VIRTIO_BLK_T_FLUSH = 4;
205: static const uint32 VIRTIO_BLK_T_DISCARD = 11;
206: static const uint32 VIRTIO_BLK_T_WRITE_ZEROES = 13;
207:
208: static const uint8 VIRTIO_BLK_S_OK = 0;
209: static const uint8 VIRTIO_BLK_S_IOERR = 1;
210: static const uint8 VIRTIO_BLK_S_UNSUPP = 2;
211:
212: struct virtio_blk_discard_write_zeroes {
213: le64 sector;
214: le32 num_sectors;
215: //struct {
216: // le32 unmap:1;
217: // le32 reserved:31;
218: //} flags;
219: le32 flags;
220: };
1.1.1.3 ! root 221:
! 222: // SCSIDevice
! 223:
! 224: struct virtio_scsi_req_cmd {
! 225: // Device-readable part
! 226: u8 lun[8];
! 227: le64 id;
! 228: u8 task_attr;
! 229: u8 prio;
! 230: u8 crn;
! 231: u8 cdb[0]; // [cdb_size]
! 232: // The next three fields are only present if VIRTIO_SCSI_F_T10_PI
! 233: // is negotiated.
! 234: //le32 pi_bytesout;
! 235: //le32 pi_bytesin;
! 236: //u8 pi_out[pi_bytesout];
! 237: u8 dataout[0];
! 238:
! 239: // Device-writable part
! 240: le32 sense_len;
! 241: le32 residual;
! 242: le16 status_qualifier;
! 243: u8 status;
! 244: u8 response;
! 245: u8 sense[0]; // [sense_size]
! 246: // The next field is only present if VIRTIO_SCS_IF_T10_PI
! 247: // is negotiated.
! 248: //u8 pi_in[pi_bytesin];
! 249: u8 datain[0];
! 250: };
! 251:
! 252: struct virtio_scsi_ctrl {
! 253: le32 type;
! 254: //
! 255: u8 response;
! 256: };
! 257:
! 258: static const uint8 VIRTIO_SCSI_S_OK = 0;
! 259: static const uint8 VIRTIO_SCSI_S_OVERRUN = 1;
! 260: static const uint8 VIRTIO_SCSI_S_ABORTED = 2;
! 261: static const uint8 VIRTIO_SCSI_S_BAD_TARGET = 3;
! 262: static const uint8 VIRTIO_SCSI_S_RESET = 4;
! 263: static const uint8 VIRTIO_SCSI_S_BUSY = 5;
! 264: static const uint8 VIRTIO_SCSI_S_TRANSPORT_FAILURE = 6;
! 265: static const uint8 VIRTIO_SCSI_S_TARGET_FAILURE = 7;
! 266: static const uint8 VIRTIO_SCSI_S_NEXUS_FAILURE = 8;
! 267: static const uint8 VIRTIO_SCSI_S_FAILURE = 9;
! 268: static const uint8 VIRTIO_SCSI_S_INCORRECT_LUN = 12;
! 269: // task_attr
! 270: static const uint8 VIRTIO_SCSI_S_SIMPLE = 0;
! 271: static const uint8 VIRTIO_SCSI_S_ORDERED = 1;
! 272: static const uint8 VIRTIO_SCSI_S_HEAD = 2;
! 273: 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.