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