xref: /openbmc/qemu/pc-bios/s390-ccw/virtio.h (revision f7f2f96f)
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);
193*f7f2f96fSJuan 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)200*f7f2f96fSJuan 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;
25699b72e0fSFarhan Ali     uint64_t netboot_start_addr;
257fe921fc8SEric Farman     uint32_t max_transfer;
25859efbff1SThomas Huth     uint32_t guest_features[2];
25969429682SEugene (jno) Dvurechenski };
26069429682SEugene (jno) Dvurechenski typedef struct VDev VDev;
26169429682SEugene (jno) Dvurechenski 
26269429682SEugene (jno) Dvurechenski VDev *virtio_get_device(void);
26369429682SEugene (jno) Dvurechenski VirtioDevType virtio_get_device_type(void);
26469429682SEugene (jno) Dvurechenski 
2658944edc3SEugene (jno) Dvurechenski struct VirtioCmd {
2668944edc3SEugene (jno) Dvurechenski     void *data;
2678944edc3SEugene (jno) Dvurechenski     int size;
2688944edc3SEugene (jno) Dvurechenski     int flags;
2698944edc3SEugene (jno) Dvurechenski };
2708944edc3SEugene (jno) Dvurechenski typedef struct VirtioCmd VirtioCmd;
2718944edc3SEugene (jno) Dvurechenski 
272867e039aSThomas Huth bool vring_notify(VRing *vr);
273867e039aSThomas Huth int drain_irqs(SubChannelId schid);
274867e039aSThomas Huth void vring_send_buf(VRing *vr, void *p, int len, int flags);
275867e039aSThomas Huth int vr_poll(VRing *vr);
276867e039aSThomas Huth int vring_wait_reply(void);
2778944edc3SEugene (jno) Dvurechenski int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd);
278867e039aSThomas Huth void virtio_setup_ccw(VDev *vdev);
2798944edc3SEugene (jno) Dvurechenski 
28000dde1e6SThomas Huth int virtio_net_init(void *mac_addr);
28100dde1e6SThomas Huth 
2821e17c2c1SAlexander Graf #endif /* VIRTIO_H */
283