1
2
3
4
5
6
7
8
9
10
11#ifndef VIRTIO_H
12#define VIRTIO_H
13
14
15
16#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
17
18#define VIRTIO_CONFIG_S_DRIVER 2
19
20#define VIRTIO_CONFIG_S_DRIVER_OK 4
21
22#define VIRTIO_CONFIG_S_FAILED 0x80
23
24enum VirtioDevType {
25 VIRTIO_ID_NET = 1,
26 VIRTIO_ID_BLOCK = 2,
27 VIRTIO_ID_CONSOLE = 3,
28 VIRTIO_ID_BALLOON = 5,
29 VIRTIO_ID_SCSI = 8,
30};
31typedef enum VirtioDevType VirtioDevType;
32
33struct VqInfo {
34 uint64_t queue;
35 uint32_t align;
36 uint16_t index;
37 uint16_t num;
38} __attribute__((packed));
39typedef struct VqInfo VqInfo;
40
41struct VqConfig {
42 uint16_t index;
43 uint16_t num;
44} __attribute__((packed));
45typedef struct VqConfig VqConfig;
46
47#define VIRTIO_RING_SIZE (PAGE_SIZE * 8)
48#define VIRTIO_MAX_VQS 3
49#define KVM_S390_VIRTIO_RING_ALIGN 4096
50
51#define VRING_USED_F_NO_NOTIFY 1
52
53
54#define VRING_DESC_F_NEXT 1
55
56#define VRING_DESC_F_WRITE 2
57
58#define VRING_DESC_F_INDIRECT 4
59
60
61#define VRING_HIDDEN_IS_CHAIN 256
62
63
64struct VRingDesc {
65
66 uint64_t addr;
67
68 uint32_t len;
69
70 uint16_t flags;
71
72 uint16_t next;
73} __attribute__((packed));
74typedef struct VRingDesc VRingDesc;
75
76struct VRingAvail {
77 uint16_t flags;
78 uint16_t idx;
79 uint16_t ring[];
80} __attribute__((packed));
81typedef struct VRingAvail VRingAvail;
82
83
84struct VRingUsedElem {
85
86 uint32_t id;
87
88 uint32_t len;
89} __attribute__((packed));
90typedef struct VRingUsedElem VRingUsedElem;
91
92struct VRingUsed {
93 uint16_t flags;
94 uint16_t idx;
95 VRingUsedElem ring[];
96} __attribute__((packed));
97typedef struct VRingUsed VRingUsed;
98
99struct VRing {
100 unsigned int num;
101 int next_idx;
102 int used_idx;
103 VRingDesc *desc;
104 VRingAvail *avail;
105 VRingUsed *used;
106 SubChannelId schid;
107 long cookie;
108 int id;
109};
110typedef struct VRing VRing;
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129#define VIRTIO_BLK_T_IN 0
130#define VIRTIO_BLK_T_OUT 1
131
132
133#define VIRTIO_BLK_T_SCSI_CMD 2
134
135
136#define VIRTIO_BLK_T_FLUSH 4
137
138
139#define VIRTIO_BLK_T_BARRIER 0x80000000
140
141
142struct VirtioBlkOuthdr {
143
144 uint32_t type;
145
146 uint32_t ioprio;
147
148 uint64_t sector;
149};
150typedef struct VirtioBlkOuthdr VirtioBlkOuthdr;
151
152struct VirtioBlkConfig {
153 uint64_t capacity;
154 uint32_t size_max;
155 uint32_t seg_max;
156
157 struct VirtioBlkGeometry {
158 uint16_t cylinders;
159 uint8_t heads;
160 uint8_t sectors;
161 } geometry;
162
163 uint32_t blk_size;
164
165
166 uint8_t physical_block_exp;
167 uint8_t alignment_offset;
168 uint16_t min_io_size;
169
170 uint32_t opt_io_size;
171
172 uint8_t wce;
173} __attribute__((packed));
174typedef struct VirtioBlkConfig VirtioBlkConfig;
175
176enum guessed_disk_nature_type {
177 VIRTIO_GDN_NONE = 0,
178 VIRTIO_GDN_DASD = 1,
179 VIRTIO_GDN_CDROM = 2,
180 VIRTIO_GDN_SCSI = 3,
181};
182typedef enum guessed_disk_nature_type VirtioGDN;
183
184VirtioGDN virtio_guessed_disk_nature(void);
185void virtio_assume_scsi(void);
186void virtio_assume_eckd(void);
187void virtio_assume_iso9660(void);
188
189extern bool virtio_disk_is_scsi(void);
190extern bool virtio_disk_is_eckd(void);
191extern bool virtio_ipl_disk_is_valid(void);
192extern int virtio_get_block_size(void);
193extern uint8_t virtio_get_heads(void);
194extern uint8_t virtio_get_sectors(void);
195extern uint64_t virtio_get_blocks(void);
196extern int virtio_read_many(ulong sector, void *load_addr, int sec_num);
197
198#define VIRTIO_SECTOR_SIZE 512
199#define VIRTIO_ISO_BLOCK_SIZE 2048
200#define VIRTIO_SCSI_BLOCK_SIZE 512
201
202static inline ulong virtio_sector_adjust(ulong sector)
203{
204 return sector * (virtio_get_block_size() / VIRTIO_SECTOR_SIZE);
205}
206
207struct VirtioScsiConfig {
208 uint32_t num_queues;
209 uint32_t seg_max;
210 uint32_t max_sectors;
211 uint32_t cmd_per_lun;
212 uint32_t event_info_size;
213 uint32_t sense_size;
214 uint32_t cdb_size;
215 uint16_t max_channel;
216 uint16_t max_target;
217 uint32_t max_lun;
218} __attribute__((packed));
219typedef struct VirtioScsiConfig VirtioScsiConfig;
220
221struct ScsiDevice {
222 uint16_t channel;
223 uint16_t target;
224 uint32_t lun;
225};
226typedef struct ScsiDevice ScsiDevice;
227
228struct VirtioNetConfig {
229 uint8_t mac[6];
230
231
232};
233typedef struct VirtioNetConfig VirtioNetConfig;
234
235struct VDev {
236 int nr_vqs;
237 VRing *vrings;
238 int cmd_vr_idx;
239 void *ring_area;
240 long wait_reply_timeout;
241 VirtioGDN guessed_disk_nature;
242 SubChannelId schid;
243 SenseId senseid;
244 union {
245 VirtioBlkConfig blk;
246 VirtioScsiConfig scsi;
247 VirtioNetConfig net;
248 } config;
249 ScsiDevice *scsi_device;
250 bool is_cdrom;
251 int scsi_block_size;
252 int blk_factor;
253 uint64_t scsi_last_block;
254 uint32_t scsi_dev_cyls;
255 uint8_t scsi_dev_heads;
256 bool scsi_device_selected;
257 ScsiDevice selected_scsi_device;
258 uint64_t netboot_start_addr;
259 uint32_t max_transfer;
260 uint32_t guest_features[2];
261};
262typedef struct VDev VDev;
263
264VDev *virtio_get_device(void);
265VirtioDevType virtio_get_device_type(void);
266
267struct VirtioCmd {
268 void *data;
269 int size;
270 int flags;
271};
272typedef struct VirtioCmd VirtioCmd;
273
274bool vring_notify(VRing *vr);
275int drain_irqs(SubChannelId schid);
276void vring_send_buf(VRing *vr, void *p, int len, int flags);
277int vr_poll(VRing *vr);
278int vring_wait_reply(void);
279int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd);
280void virtio_setup_ccw(VDev *vdev);
281
282int virtio_net_init(void *mac_addr);
283
284#endif
285