-
Notifications
You must be signed in to change notification settings - Fork 76
/
virtio.h
129 lines (113 loc) · 4.72 KB
/
virtio.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "types.h"
/*
* References:
* 1. https://github.com/ianchen0119/xv6-riscv/blob/riscv/kernel/virtio.h
* 2. https://github.com/sgmarz/osblog/blob/master/risc_v/src/virtio.rs
*/
#define VIRTIO_MMIO_BASE 0x10001000
/* OFFSET */
#define VIRTIO_MMIO_MAGIC_VALUE 0x000 // Magic value must be 0x74726976
#define VIRTIO_MMIO_VERSION 0x004 // Version: 1 (Legacy)
/*
* Device ID:
* 1 (Network Device)
* 2 (Block Device)
* 4 (Random number generator Device)
* 16 (GPU Device)
* 18 (Input Device)
*/
#define VIRTIO_MMIO_DEVICE_ID 0x008
#define VIRTIO_MMIO_VENDOR_ID 0x00c // 0x554d4551
#define VIRTIO_MMIO_DEVICE_FEATURES 0x010
#define VIRTIO_MMIO_DRIVER_FEATURES 0x020
#define VIRTIO_MMIO_GUEST_PAGE_SIZE 0x028 // page size for PFN, write-only
#define VIRTIO_MMIO_QUEUE_SEL 0x030 // select queue, write-only
#define VIRTIO_MMIO_QUEUE_NUM_MAX 0x034 // max size of current queue, read-only
#define VIRTIO_MMIO_QUEUE_NUM 0x038 // size of current queue, write-only
#define VIRTIO_MMIO_QUEUE_ALIGN 0x03c // used ring alignment, write-only
#define VIRTIO_MMIO_QUEUE_PFN 0x040 // physical page number for queue, read/write
#define VIRTIO_MMIO_QUEUE_READY 0x044 // ready bit
#define VIRTIO_MMIO_QUEUE_NOTIFY 0x050 // write-only
#define VIRTIO_MMIO_INTERRUPT_STATUS 0x060 // read-only
#define VIRTIO_MMIO_INTERRUPT_ACK 0x064 // write-only
#define VIRTIO_MMIO_STATUS 0x070 // read/write
#define VIRTIO_MMIO_QueueDescLow 0x080
#define VIRTIO_MMIO_QueueDescHigh 0x084
#define VIRTIO_MMIO_QueueAvailLow 0x090
#define VIRTIO_MMIO_QueueAvailHigh 0x094
#define VIRTIO_MMIO_QueueUsedLow 0x0a0
#define VIRTIO_MMIO_QueueUsedHigh 0x0a4
// status register bits, from qemu virtio_config.h
#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
#define VIRTIO_CONFIG_S_DRIVER 2
#define VIRTIO_CONFIG_S_DRIVER_OK 4
#define VIRTIO_CONFIG_S_FEATURES_OK 8
// device feature bits
#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */
#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */
#define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */
#define VIRTIO_BLK_F_MQ 12 /* support more than one vq */
#define VIRTIO_F_ANY_LAYOUT 27
#define VIRTIO_RING_F_INDIRECT_DESC 28
#define VIRTIO_RING_F_EVENT_IDX 29
// this many virtio descriptors.
#define NUM 8
// 描述符包含這些訊息: 地址,地址長度,某些標誌和其他信息。使用此描述符,我們可以將設備指向 RAM 中任何緩衝區的內存地址。
typedef struct virtq_desc
{
/*
* addr: 我們可以在 64-bit 內存地址內的任何位置告訴設備存儲位置。
* len: 讓 Device 知道有多少內存可用。
* flags: 用於控制 descriptor 。
* next: 告訴 Device 下一個描述符的 Index 。如果指定了 VIRTQ_DESC_F_NEXT, Device 僅讀取該字段。否則無效。
*/
uint64 addr;
uint32 len;
uint16 flags;
uint16 next;
} virtq_desc_t;
#define VRING_DESC_F_NEXT 1 // chained with another descriptor
#define VRING_DESC_F_WRITE 2 // device writes (vs read)
#define VRING_DESC_F_INDIRECT 4 // buffer contains a list of buffer descriptors
/*
* 用來存放 descriptor 的索引,當 Device 收到通知時,它會檢查 AvailableRing 確認需要讀取哪些 Descriptor 。
* 注意: Descriptor 和 AvailableRing 都存儲在 RAM 中。
*/
typedef struct virtq_avail
{
uint16 flags; // always zero
uint16 idx; // driver will write ring[idx] next
uint16 ring[NUM]; // descriptor numbers of chain heads
} virtq_avail_t;
/*
* 當內部的 Index 與 UsedRing 的 Index 相等,代表所有資料都已經被讀取,這個 Device 是唯一需要被寫進 Index 的。
*/
typedef struct virtq_used_elem
{
uint32 id; // index of start of completed descriptor chain
uint32 len;
} virtq_used_elem_t;
/*
* Device 可以使用 UsedRing 向 OS 發送訊息。
* Device 通常使用它來告知 OS 它已完成先前通知的請求。
* AvailableRing 與 UsedRing 非常相似,差異在於: OS 需要查看 UsedRing 得知哪個 Descriptor 已經被服務。
*/
typedef struct virtq_used
{
uint16 flags; // always zero
uint16 idx; // device increments when it adds a ring[] entry
struct virtq_used_elem ring[NUM];
} virtq_used_t;
// these are specific to virtio block devices, e.g. disks,
// described in Section 5.2 of the spec.
#define VIRTIO_BLK_T_IN 0 // read the disk
#define VIRTIO_BLK_T_OUT 1 // write the disk
// the format of the first descriptor in a disk request.
// to be followed by two more descriptors containing
// the block, and a one-byte status.
typedef struct virtio_blk_req
{
uint32 type; // VIRTIO_BLK_T_IN or ..._OUT
uint32 reserved; // 將 Header 擴充到 16-byte ,並將 64-bit sector 移到正確的位置。
uint64 sector;
} virtio_blk_req_t;