File:  [Isaki's NoNo m68k/m88k emulator] / nono / vm / virtio_def.h
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:50 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, v026, v025, HEAD
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;

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.