11e17c2c1SAlexander Graf /*
21e17c2c1SAlexander Graf * Virtio driver bits
31e17c2c1SAlexander Graf *
41e17c2c1SAlexander Graf * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
51e17c2c1SAlexander Graf *
61e17c2c1SAlexander Graf * This work is licensed under the terms of the GNU GPL, version 2 or (at
71e17c2c1SAlexander Graf * your option) any later version. See the COPYING file in the top-level
81e17c2c1SAlexander Graf * directory.
91e17c2c1SAlexander Graf */
101e17c2c1SAlexander Graf
111e17c2c1SAlexander Graf #ifndef VIRTIO_H
121e17c2c1SAlexander Graf #define VIRTIO_H
131e17c2c1SAlexander Graf
141e17c2c1SAlexander Graf /* Status byte for guest to report progress, and synchronize features. */
151e17c2c1SAlexander Graf /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
161e17c2c1SAlexander Graf #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
171e17c2c1SAlexander Graf /* We have found a driver for the device. */
181e17c2c1SAlexander Graf #define VIRTIO_CONFIG_S_DRIVER 2
191e17c2c1SAlexander Graf /* Driver has used its parts of the config, and is happy */
201e17c2c1SAlexander Graf #define VIRTIO_CONFIG_S_DRIVER_OK 4
211e17c2c1SAlexander Graf /* We've given up on this device. */
221e17c2c1SAlexander Graf #define VIRTIO_CONFIG_S_FAILED 0x80
231e17c2c1SAlexander Graf
24b88d7fa5SEugene (jno) Dvurechenski enum VirtioDevType {
251e17c2c1SAlexander Graf VIRTIO_ID_NET = 1,
261e17c2c1SAlexander Graf VIRTIO_ID_BLOCK = 2,
271e17c2c1SAlexander Graf VIRTIO_ID_CONSOLE = 3,
281e17c2c1SAlexander Graf VIRTIO_ID_BALLOON = 5,
2980ba3e24SEugene (jno) Dvurechenski VIRTIO_ID_SCSI = 8,
301e17c2c1SAlexander Graf };
31b88d7fa5SEugene (jno) Dvurechenski typedef enum VirtioDevType VirtioDevType;
321e17c2c1SAlexander Graf
33b88d7fa5SEugene (jno) Dvurechenski struct VqInfo {
34b88d7fa5SEugene (jno) Dvurechenski uint64_t queue;
35b88d7fa5SEugene (jno) Dvurechenski uint32_t align;
36b88d7fa5SEugene (jno) Dvurechenski uint16_t index;
37b88d7fa5SEugene (jno) Dvurechenski uint16_t num;
381e17c2c1SAlexander Graf } __attribute__((packed));
39b88d7fa5SEugene (jno) Dvurechenski typedef struct VqInfo VqInfo;
401e17c2c1SAlexander Graf
41b88d7fa5SEugene (jno) Dvurechenski struct VqConfig {
42b88d7fa5SEugene (jno) Dvurechenski uint16_t index;
43b88d7fa5SEugene (jno) Dvurechenski uint16_t num;
44abbbe3deSCornelia Huck } __attribute__((packed));
45b88d7fa5SEugene (jno) Dvurechenski typedef struct VqConfig VqConfig;
46abbbe3deSCornelia Huck
4785129891SEugene (jno) Dvurechenski #define VIRTIO_RING_SIZE (PAGE_SIZE * 8)
4885129891SEugene (jno) Dvurechenski #define VIRTIO_MAX_VQS 3
491e17c2c1SAlexander Graf #define KVM_S390_VIRTIO_RING_ALIGN 4096
501e17c2c1SAlexander Graf
511e17c2c1SAlexander Graf #define VRING_USED_F_NO_NOTIFY 1
521e17c2c1SAlexander Graf
531e17c2c1SAlexander Graf /* This marks a buffer as continuing via the next field. */
541e17c2c1SAlexander Graf #define VRING_DESC_F_NEXT 1
551e17c2c1SAlexander Graf /* This marks a buffer as write-only (otherwise read-only). */
561e17c2c1SAlexander Graf #define VRING_DESC_F_WRITE 2
571e17c2c1SAlexander Graf /* This means the buffer contains a list of buffer descriptors. */
581e17c2c1SAlexander Graf #define VRING_DESC_F_INDIRECT 4
591e17c2c1SAlexander Graf
601e17c2c1SAlexander Graf /* Internal flag to mark follow-up segments as such */
611e17c2c1SAlexander Graf #define VRING_HIDDEN_IS_CHAIN 256
621e17c2c1SAlexander Graf
631e17c2c1SAlexander Graf /* Virtio ring descriptors: 16 bytes. These can chain together via "next". */
64b88d7fa5SEugene (jno) Dvurechenski struct VRingDesc {
651e17c2c1SAlexander Graf /* Address (guest-physical). */
66b88d7fa5SEugene (jno) Dvurechenski uint64_t addr;
671e17c2c1SAlexander Graf /* Length. */
68b88d7fa5SEugene (jno) Dvurechenski uint32_t len;
691e17c2c1SAlexander Graf /* The flags as indicated above. */
70b88d7fa5SEugene (jno) Dvurechenski uint16_t flags;
711e17c2c1SAlexander Graf /* We chain unused descriptors via this, too */
72b88d7fa5SEugene (jno) Dvurechenski uint16_t next;
731e17c2c1SAlexander Graf } __attribute__((packed));
74b88d7fa5SEugene (jno) Dvurechenski typedef struct VRingDesc VRingDesc;
751e17c2c1SAlexander Graf
76b88d7fa5SEugene (jno) Dvurechenski struct VRingAvail {
77b88d7fa5SEugene (jno) Dvurechenski uint16_t flags;
78b88d7fa5SEugene (jno) Dvurechenski uint16_t idx;
79b88d7fa5SEugene (jno) Dvurechenski uint16_t ring[];
801e17c2c1SAlexander Graf } __attribute__((packed));
81b88d7fa5SEugene (jno) Dvurechenski typedef struct VRingAvail VRingAvail;
821e17c2c1SAlexander Graf
83b88d7fa5SEugene (jno) Dvurechenski /* uint32_t is used here for ids for padding reasons. */
84b88d7fa5SEugene (jno) Dvurechenski struct VRingUsedElem {
851e17c2c1SAlexander Graf /* Index of start of used descriptor chain. */
86b88d7fa5SEugene (jno) Dvurechenski uint32_t id;
871e17c2c1SAlexander Graf /* Total length of the descriptor chain which was used (written to) */
88b88d7fa5SEugene (jno) Dvurechenski uint32_t len;
891e17c2c1SAlexander Graf } __attribute__((packed));
90b88d7fa5SEugene (jno) Dvurechenski typedef struct VRingUsedElem VRingUsedElem;
911e17c2c1SAlexander Graf
92b88d7fa5SEugene (jno) Dvurechenski struct VRingUsed {
93b88d7fa5SEugene (jno) Dvurechenski uint16_t flags;
94b88d7fa5SEugene (jno) Dvurechenski uint16_t idx;
95b88d7fa5SEugene (jno) Dvurechenski VRingUsedElem ring[];
961e17c2c1SAlexander Graf } __attribute__((packed));
97b88d7fa5SEugene (jno) Dvurechenski typedef struct VRingUsed VRingUsed;
981e17c2c1SAlexander Graf
99b88d7fa5SEugene (jno) Dvurechenski struct VRing {
1001e17c2c1SAlexander Graf unsigned int num;
1011e17c2c1SAlexander Graf int next_idx;
102441ea695SCornelia Huck int used_idx;
103b88d7fa5SEugene (jno) Dvurechenski VRingDesc *desc;
104b88d7fa5SEugene (jno) Dvurechenski VRingAvail *avail;
105b88d7fa5SEugene (jno) Dvurechenski VRingUsed *used;
106b88d7fa5SEugene (jno) Dvurechenski SubChannelId schid;
10785129891SEugene (jno) Dvurechenski long cookie;
10885129891SEugene (jno) Dvurechenski int id;
1091e17c2c1SAlexander Graf };
110b88d7fa5SEugene (jno) Dvurechenski typedef struct VRing VRing;
1111e17c2c1SAlexander Graf
1121e17c2c1SAlexander Graf
1131e17c2c1SAlexander Graf /***********************************************
1141e17c2c1SAlexander Graf * Virtio block *
1151e17c2c1SAlexander Graf ***********************************************/
1161e17c2c1SAlexander Graf
1171e17c2c1SAlexander Graf /*
1181e17c2c1SAlexander Graf * Command types
1191e17c2c1SAlexander Graf *
1201e17c2c1SAlexander Graf * Usage is a bit tricky as some bits are used as flags and some are not.
1211e17c2c1SAlexander Graf *
1221e17c2c1SAlexander Graf * Rules:
1231e17c2c1SAlexander Graf * VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or
1241e17c2c1SAlexander Graf * VIRTIO_BLK_T_BARRIER. VIRTIO_BLK_T_FLUSH is a command of its own
1251e17c2c1SAlexander Graf * and may not be combined with any of the other flags.
1261e17c2c1SAlexander Graf */
1271e17c2c1SAlexander Graf
1281e17c2c1SAlexander Graf /* These two define direction. */
1291e17c2c1SAlexander Graf #define VIRTIO_BLK_T_IN 0
1301e17c2c1SAlexander Graf #define VIRTIO_BLK_T_OUT 1
1311e17c2c1SAlexander Graf
1321e17c2c1SAlexander Graf /* This bit says it's a scsi command, not an actual read or write. */
1331e17c2c1SAlexander Graf #define VIRTIO_BLK_T_SCSI_CMD 2
1341e17c2c1SAlexander Graf
1351e17c2c1SAlexander Graf /* Cache flush command */
1361e17c2c1SAlexander Graf #define VIRTIO_BLK_T_FLUSH 4
1371e17c2c1SAlexander Graf
1381e17c2c1SAlexander Graf /* Barrier before this op. */
1391e17c2c1SAlexander Graf #define VIRTIO_BLK_T_BARRIER 0x80000000
1401e17c2c1SAlexander Graf
1411e17c2c1SAlexander Graf /* This is the first element of the read scatter-gather list. */
142b88d7fa5SEugene (jno) Dvurechenski struct VirtioBlkOuthdr {
1431e17c2c1SAlexander Graf /* VIRTIO_BLK_T* */
144b88d7fa5SEugene (jno) Dvurechenski uint32_t type;
1451e17c2c1SAlexander Graf /* io priority. */
146b88d7fa5SEugene (jno) Dvurechenski uint32_t ioprio;
1471e17c2c1SAlexander Graf /* Sector (ie. 512 byte offset) */
148b88d7fa5SEugene (jno) Dvurechenski uint64_t sector;
1491e17c2c1SAlexander Graf };
150b88d7fa5SEugene (jno) Dvurechenski typedef struct VirtioBlkOuthdr VirtioBlkOuthdr;
1511e17c2c1SAlexander Graf
152b88d7fa5SEugene (jno) Dvurechenski struct VirtioBlkConfig {
153b88d7fa5SEugene (jno) Dvurechenski uint64_t capacity; /* in 512-byte sectors */
154b88d7fa5SEugene (jno) Dvurechenski uint32_t size_max; /* max segment size (if VIRTIO_BLK_F_SIZE_MAX) */
155b88d7fa5SEugene (jno) Dvurechenski uint32_t seg_max; /* max number of segments (if VIRTIO_BLK_F_SEG_MAX) */
15691a03f9bSEugene (jno) Dvurechenski
157b88d7fa5SEugene (jno) Dvurechenski struct VirtioBlkGeometry {
158b88d7fa5SEugene (jno) Dvurechenski uint16_t cylinders;
159b88d7fa5SEugene (jno) Dvurechenski uint8_t heads;
160b88d7fa5SEugene (jno) Dvurechenski uint8_t sectors;
16191a03f9bSEugene (jno) Dvurechenski } geometry; /* (if VIRTIO_BLK_F_GEOMETRY) */
16291a03f9bSEugene (jno) Dvurechenski
163b88d7fa5SEugene (jno) Dvurechenski uint32_t blk_size; /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
16491a03f9bSEugene (jno) Dvurechenski
16591a03f9bSEugene (jno) Dvurechenski /* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY */
166b88d7fa5SEugene (jno) Dvurechenski uint8_t physical_block_exp; /* exponent for physical blk per logical blk */
167b88d7fa5SEugene (jno) Dvurechenski uint8_t alignment_offset; /* alignment offset in logical blocks */
168b88d7fa5SEugene (jno) Dvurechenski uint16_t min_io_size; /* min I/O size without performance penalty
16991a03f9bSEugene (jno) Dvurechenski in logical blocks */
170b88d7fa5SEugene (jno) Dvurechenski uint32_t opt_io_size; /* optimal sustained I/O size in logical blks */
17191a03f9bSEugene (jno) Dvurechenski
172b88d7fa5SEugene (jno) Dvurechenski uint8_t wce; /* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */
173b88d7fa5SEugene (jno) Dvurechenski } __attribute__((packed));
174b88d7fa5SEugene (jno) Dvurechenski typedef struct VirtioBlkConfig VirtioBlkConfig;
17591a03f9bSEugene (jno) Dvurechenski
176a1102cebSEugene (jno) Dvurechenski enum guessed_disk_nature_type {
177a1102cebSEugene (jno) Dvurechenski VIRTIO_GDN_NONE = 0,
178a1102cebSEugene (jno) Dvurechenski VIRTIO_GDN_DASD = 1,
179a1102cebSEugene (jno) Dvurechenski VIRTIO_GDN_CDROM = 2,
180a1102cebSEugene (jno) Dvurechenski VIRTIO_GDN_SCSI = 3,
181a1102cebSEugene (jno) Dvurechenski };
182a1102cebSEugene (jno) Dvurechenski typedef enum guessed_disk_nature_type VirtioGDN;
183a1102cebSEugene (jno) Dvurechenski
184a1102cebSEugene (jno) Dvurechenski VirtioGDN virtio_guessed_disk_nature(void);
18591a03f9bSEugene (jno) Dvurechenski void virtio_assume_eckd(void);
186866cac91SMaxim Samoylov void virtio_assume_iso9660(void);
18791a03f9bSEugene (jno) Dvurechenski
1883953ae18SThomas Huth bool virtio_ipl_disk_is_valid(void);
1893953ae18SThomas Huth int virtio_get_block_size(void);
1903953ae18SThomas Huth uint8_t virtio_get_heads(void);
1913953ae18SThomas Huth uint8_t virtio_get_sectors(void);
1923953ae18SThomas Huth uint64_t virtio_get_blocks(void);
193f7f2f96fSJuan Quintela int virtio_read_many(unsigned long sector, void *load_addr, int sec_num);
19491a03f9bSEugene (jno) Dvurechenski
19591a03f9bSEugene (jno) Dvurechenski #define VIRTIO_SECTOR_SIZE 512
19680ba3e24SEugene (jno) Dvurechenski #define VIRTIO_ISO_BLOCK_SIZE 2048
19780ba3e24SEugene (jno) Dvurechenski #define VIRTIO_SCSI_BLOCK_SIZE 512
1981f2c2ee4SThomas Huth #define VIRTIO_DASD_DEFAULT_BLOCK_SIZE 4096
19991a03f9bSEugene (jno) Dvurechenski
virtio_sector_adjust(unsigned long sector)200f7f2f96fSJuan Quintela static inline unsigned long virtio_sector_adjust(unsigned long sector)
20191a03f9bSEugene (jno) Dvurechenski {
20238150be8SMaxim Samoylov return sector * (virtio_get_block_size() / VIRTIO_SECTOR_SIZE);
20391a03f9bSEugene (jno) Dvurechenski }
20491a03f9bSEugene (jno) Dvurechenski
20580ba3e24SEugene (jno) Dvurechenski struct VirtioScsiConfig {
20680ba3e24SEugene (jno) Dvurechenski uint32_t num_queues;
20780ba3e24SEugene (jno) Dvurechenski uint32_t seg_max;
20880ba3e24SEugene (jno) Dvurechenski uint32_t max_sectors;
20980ba3e24SEugene (jno) Dvurechenski uint32_t cmd_per_lun;
21080ba3e24SEugene (jno) Dvurechenski uint32_t event_info_size;
21180ba3e24SEugene (jno) Dvurechenski uint32_t sense_size;
21280ba3e24SEugene (jno) Dvurechenski uint32_t cdb_size;
21380ba3e24SEugene (jno) Dvurechenski uint16_t max_channel;
21480ba3e24SEugene (jno) Dvurechenski uint16_t max_target;
21580ba3e24SEugene (jno) Dvurechenski uint32_t max_lun;
21680ba3e24SEugene (jno) Dvurechenski } __attribute__((packed));
21780ba3e24SEugene (jno) Dvurechenski typedef struct VirtioScsiConfig VirtioScsiConfig;
21880ba3e24SEugene (jno) Dvurechenski
21980ba3e24SEugene (jno) Dvurechenski struct ScsiDevice {
22080ba3e24SEugene (jno) Dvurechenski uint16_t channel; /* Always 0 in QEMU */
22180ba3e24SEugene (jno) Dvurechenski uint16_t target; /* will be scanned over */
22280ba3e24SEugene (jno) Dvurechenski uint32_t lun; /* will be reported */
22380ba3e24SEugene (jno) Dvurechenski };
22480ba3e24SEugene (jno) Dvurechenski typedef struct ScsiDevice ScsiDevice;
22580ba3e24SEugene (jno) Dvurechenski
22600dde1e6SThomas Huth struct VirtioNetConfig {
22700dde1e6SThomas Huth uint8_t mac[6];
22800dde1e6SThomas Huth /* uint16_t status; */ /* Only with VIRTIO_NET_F_STATUS */
22900dde1e6SThomas Huth /* uint16_t max_virtqueue_pairs; */ /* Only with VIRTIO_NET_F_MQ */
23000dde1e6SThomas Huth };
23100dde1e6SThomas Huth typedef struct VirtioNetConfig VirtioNetConfig;
23200dde1e6SThomas Huth
23369429682SEugene (jno) Dvurechenski struct VDev {
23469429682SEugene (jno) Dvurechenski int nr_vqs;
23569429682SEugene (jno) Dvurechenski VRing *vrings;
23669429682SEugene (jno) Dvurechenski int cmd_vr_idx;
23769429682SEugene (jno) Dvurechenski void *ring_area;
23869429682SEugene (jno) Dvurechenski long wait_reply_timeout;
239a1102cebSEugene (jno) Dvurechenski VirtioGDN guessed_disk_nature;
24069429682SEugene (jno) Dvurechenski SubChannelId schid;
24169429682SEugene (jno) Dvurechenski SenseId senseid;
24269429682SEugene (jno) Dvurechenski union {
24369429682SEugene (jno) Dvurechenski VirtioBlkConfig blk;
24480ba3e24SEugene (jno) Dvurechenski VirtioScsiConfig scsi;
24500dde1e6SThomas Huth VirtioNetConfig net;
24669429682SEugene (jno) Dvurechenski } config;
24780ba3e24SEugene (jno) Dvurechenski ScsiDevice *scsi_device;
24880ba3e24SEugene (jno) Dvurechenski bool is_cdrom;
24980ba3e24SEugene (jno) Dvurechenski int scsi_block_size;
25080ba3e24SEugene (jno) Dvurechenski int blk_factor;
25180ba3e24SEugene (jno) Dvurechenski uint64_t scsi_last_block;
25280ba3e24SEugene (jno) Dvurechenski uint32_t scsi_dev_cyls;
25380ba3e24SEugene (jno) Dvurechenski uint8_t scsi_dev_heads;
254b39b7718SEugene (jno) Dvurechenski bool scsi_device_selected;
255b39b7718SEugene (jno) Dvurechenski ScsiDevice selected_scsi_device;
256fe921fc8SEric Farman uint32_t max_transfer;
25759efbff1SThomas Huth uint32_t guest_features[2];
25869429682SEugene (jno) Dvurechenski };
25969429682SEugene (jno) Dvurechenski typedef struct VDev VDev;
26069429682SEugene (jno) Dvurechenski
26169429682SEugene (jno) Dvurechenski VDev *virtio_get_device(void);
26269429682SEugene (jno) Dvurechenski VirtioDevType virtio_get_device_type(void);
26369429682SEugene (jno) Dvurechenski
2648944edc3SEugene (jno) Dvurechenski struct VirtioCmd {
2658944edc3SEugene (jno) Dvurechenski void *data;
2668944edc3SEugene (jno) Dvurechenski int size;
2678944edc3SEugene (jno) Dvurechenski int flags;
2688944edc3SEugene (jno) Dvurechenski };
2698944edc3SEugene (jno) Dvurechenski typedef struct VirtioCmd VirtioCmd;
2708944edc3SEugene (jno) Dvurechenski
271867e039aSThomas Huth bool vring_notify(VRing *vr);
272867e039aSThomas Huth int drain_irqs(SubChannelId schid);
273867e039aSThomas Huth void vring_send_buf(VRing *vr, void *p, int len, int flags);
274867e039aSThomas Huth int vr_poll(VRing *vr);
275867e039aSThomas Huth int vring_wait_reply(void);
2768944edc3SEugene (jno) Dvurechenski int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd);
277*0181e237SJared Rossi int virtio_setup_ccw(VDev *vdev);
2788944edc3SEugene (jno) Dvurechenski
27900dde1e6SThomas Huth int virtio_net_init(void *mac_addr);
28000dde1e6SThomas Huth
2811e17c2c1SAlexander Graf #endif /* VIRTIO_H */
282