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 #include "s390-ccw.h" 151e17c2c1SAlexander Graf 161e17c2c1SAlexander Graf /* Status byte for guest to report progress, and synchronize features. */ 171e17c2c1SAlexander Graf /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ 181e17c2c1SAlexander Graf #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 191e17c2c1SAlexander Graf /* We have found a driver for the device. */ 201e17c2c1SAlexander Graf #define VIRTIO_CONFIG_S_DRIVER 2 211e17c2c1SAlexander Graf /* Driver has used its parts of the config, and is happy */ 221e17c2c1SAlexander Graf #define VIRTIO_CONFIG_S_DRIVER_OK 4 231e17c2c1SAlexander Graf /* We've given up on this device. */ 241e17c2c1SAlexander Graf #define VIRTIO_CONFIG_S_FAILED 0x80 251e17c2c1SAlexander Graf 26b88d7fa5SEugene (jno) Dvurechenski enum VirtioDevType { 271e17c2c1SAlexander Graf VIRTIO_ID_NET = 1, 281e17c2c1SAlexander Graf VIRTIO_ID_BLOCK = 2, 291e17c2c1SAlexander Graf VIRTIO_ID_CONSOLE = 3, 301e17c2c1SAlexander Graf VIRTIO_ID_BALLOON = 5, 311e17c2c1SAlexander Graf }; 32b88d7fa5SEugene (jno) Dvurechenski typedef enum VirtioDevType VirtioDevType; 331e17c2c1SAlexander Graf 34b88d7fa5SEugene (jno) Dvurechenski struct VirtioDevHeader { 35b88d7fa5SEugene (jno) Dvurechenski VirtioDevType type:8; 36b88d7fa5SEugene (jno) Dvurechenski uint8_t num_vq; 37b88d7fa5SEugene (jno) Dvurechenski uint8_t feature_len; 38b88d7fa5SEugene (jno) Dvurechenski uint8_t config_len; 39b88d7fa5SEugene (jno) Dvurechenski uint8_t status; 40b88d7fa5SEugene (jno) Dvurechenski uint8_t vqconfig[]; 411e17c2c1SAlexander Graf } __attribute__((packed)); 42b88d7fa5SEugene (jno) Dvurechenski typedef struct VirtioDevHeader VirtioDevHeader; 431e17c2c1SAlexander Graf 44b88d7fa5SEugene (jno) Dvurechenski struct VirtioVqConfig { 45b88d7fa5SEugene (jno) Dvurechenski uint64_t token; 46b88d7fa5SEugene (jno) Dvurechenski uint64_t address; 47b88d7fa5SEugene (jno) Dvurechenski uint16_t num; 48b88d7fa5SEugene (jno) Dvurechenski uint8_t pad[6]; 491e17c2c1SAlexander Graf } __attribute__((packed)); 50b88d7fa5SEugene (jno) Dvurechenski typedef struct VirtioVqConfig VirtioVqConfig; 511e17c2c1SAlexander Graf 52b88d7fa5SEugene (jno) Dvurechenski struct VqInfo { 53b88d7fa5SEugene (jno) Dvurechenski uint64_t queue; 54b88d7fa5SEugene (jno) Dvurechenski uint32_t align; 55b88d7fa5SEugene (jno) Dvurechenski uint16_t index; 56b88d7fa5SEugene (jno) Dvurechenski uint16_t num; 571e17c2c1SAlexander Graf } __attribute__((packed)); 58b88d7fa5SEugene (jno) Dvurechenski typedef struct VqInfo VqInfo; 591e17c2c1SAlexander Graf 60b88d7fa5SEugene (jno) Dvurechenski struct VqConfig { 61b88d7fa5SEugene (jno) Dvurechenski uint16_t index; 62b88d7fa5SEugene (jno) Dvurechenski uint16_t num; 63abbbe3deSCornelia Huck } __attribute__((packed)); 64b88d7fa5SEugene (jno) Dvurechenski typedef struct VqConfig VqConfig; 65abbbe3deSCornelia Huck 66b88d7fa5SEugene (jno) Dvurechenski struct VirtioDev { 67b88d7fa5SEugene (jno) Dvurechenski VirtioDevHeader *header; 68b88d7fa5SEugene (jno) Dvurechenski VirtioVqConfig *vqconfig; 691e17c2c1SAlexander Graf char *host_features; 701e17c2c1SAlexander Graf char *guest_features; 711e17c2c1SAlexander Graf char *config; 721e17c2c1SAlexander Graf }; 73b88d7fa5SEugene (jno) Dvurechenski typedef struct VirtioDev VirtioDev; 741e17c2c1SAlexander Graf 7585129891SEugene (jno) Dvurechenski #define VIRTIO_RING_SIZE (PAGE_SIZE * 8) 7685129891SEugene (jno) Dvurechenski #define VIRTIO_MAX_VQS 3 771e17c2c1SAlexander Graf #define KVM_S390_VIRTIO_RING_ALIGN 4096 781e17c2c1SAlexander Graf 791e17c2c1SAlexander Graf #define VRING_USED_F_NO_NOTIFY 1 801e17c2c1SAlexander Graf 811e17c2c1SAlexander Graf /* This marks a buffer as continuing via the next field. */ 821e17c2c1SAlexander Graf #define VRING_DESC_F_NEXT 1 831e17c2c1SAlexander Graf /* This marks a buffer as write-only (otherwise read-only). */ 841e17c2c1SAlexander Graf #define VRING_DESC_F_WRITE 2 851e17c2c1SAlexander Graf /* This means the buffer contains a list of buffer descriptors. */ 861e17c2c1SAlexander Graf #define VRING_DESC_F_INDIRECT 4 871e17c2c1SAlexander Graf 881e17c2c1SAlexander Graf /* Internal flag to mark follow-up segments as such */ 891e17c2c1SAlexander Graf #define VRING_HIDDEN_IS_CHAIN 256 901e17c2c1SAlexander Graf 911e17c2c1SAlexander Graf /* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ 92b88d7fa5SEugene (jno) Dvurechenski struct VRingDesc { 931e17c2c1SAlexander Graf /* Address (guest-physical). */ 94b88d7fa5SEugene (jno) Dvurechenski uint64_t addr; 951e17c2c1SAlexander Graf /* Length. */ 96b88d7fa5SEugene (jno) Dvurechenski uint32_t len; 971e17c2c1SAlexander Graf /* The flags as indicated above. */ 98b88d7fa5SEugene (jno) Dvurechenski uint16_t flags; 991e17c2c1SAlexander Graf /* We chain unused descriptors via this, too */ 100b88d7fa5SEugene (jno) Dvurechenski uint16_t next; 1011e17c2c1SAlexander Graf } __attribute__((packed)); 102b88d7fa5SEugene (jno) Dvurechenski typedef struct VRingDesc VRingDesc; 1031e17c2c1SAlexander Graf 104b88d7fa5SEugene (jno) Dvurechenski struct VRingAvail { 105b88d7fa5SEugene (jno) Dvurechenski uint16_t flags; 106b88d7fa5SEugene (jno) Dvurechenski uint16_t idx; 107b88d7fa5SEugene (jno) Dvurechenski uint16_t ring[]; 1081e17c2c1SAlexander Graf } __attribute__((packed)); 109b88d7fa5SEugene (jno) Dvurechenski typedef struct VRingAvail VRingAvail; 1101e17c2c1SAlexander Graf 111b88d7fa5SEugene (jno) Dvurechenski /* uint32_t is used here for ids for padding reasons. */ 112b88d7fa5SEugene (jno) Dvurechenski struct VRingUsedElem { 1131e17c2c1SAlexander Graf /* Index of start of used descriptor chain. */ 114b88d7fa5SEugene (jno) Dvurechenski uint32_t id; 1151e17c2c1SAlexander Graf /* Total length of the descriptor chain which was used (written to) */ 116b88d7fa5SEugene (jno) Dvurechenski uint32_t len; 1171e17c2c1SAlexander Graf } __attribute__((packed)); 118b88d7fa5SEugene (jno) Dvurechenski typedef struct VRingUsedElem VRingUsedElem; 1191e17c2c1SAlexander Graf 120b88d7fa5SEugene (jno) Dvurechenski struct VRingUsed { 121b88d7fa5SEugene (jno) Dvurechenski uint16_t flags; 122b88d7fa5SEugene (jno) Dvurechenski uint16_t idx; 123b88d7fa5SEugene (jno) Dvurechenski VRingUsedElem ring[]; 1241e17c2c1SAlexander Graf } __attribute__((packed)); 125b88d7fa5SEugene (jno) Dvurechenski typedef struct VRingUsed VRingUsed; 1261e17c2c1SAlexander Graf 127b88d7fa5SEugene (jno) Dvurechenski struct VRing { 1281e17c2c1SAlexander Graf unsigned int num; 1291e17c2c1SAlexander Graf int next_idx; 130441ea695SCornelia Huck int used_idx; 131b88d7fa5SEugene (jno) Dvurechenski VRingDesc *desc; 132b88d7fa5SEugene (jno) Dvurechenski VRingAvail *avail; 133b88d7fa5SEugene (jno) Dvurechenski VRingUsed *used; 134b88d7fa5SEugene (jno) Dvurechenski SubChannelId schid; 13585129891SEugene (jno) Dvurechenski long cookie; 13685129891SEugene (jno) Dvurechenski int id; 1371e17c2c1SAlexander Graf }; 138b88d7fa5SEugene (jno) Dvurechenski typedef struct VRing VRing; 1391e17c2c1SAlexander Graf 1401e17c2c1SAlexander Graf 1411e17c2c1SAlexander Graf /*********************************************** 1421e17c2c1SAlexander Graf * Virtio block * 1431e17c2c1SAlexander Graf ***********************************************/ 1441e17c2c1SAlexander Graf 1451e17c2c1SAlexander Graf /* 1461e17c2c1SAlexander Graf * Command types 1471e17c2c1SAlexander Graf * 1481e17c2c1SAlexander Graf * Usage is a bit tricky as some bits are used as flags and some are not. 1491e17c2c1SAlexander Graf * 1501e17c2c1SAlexander Graf * Rules: 1511e17c2c1SAlexander Graf * VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or 1521e17c2c1SAlexander Graf * VIRTIO_BLK_T_BARRIER. VIRTIO_BLK_T_FLUSH is a command of its own 1531e17c2c1SAlexander Graf * and may not be combined with any of the other flags. 1541e17c2c1SAlexander Graf */ 1551e17c2c1SAlexander Graf 1561e17c2c1SAlexander Graf /* These two define direction. */ 1571e17c2c1SAlexander Graf #define VIRTIO_BLK_T_IN 0 1581e17c2c1SAlexander Graf #define VIRTIO_BLK_T_OUT 1 1591e17c2c1SAlexander Graf 1601e17c2c1SAlexander Graf /* This bit says it's a scsi command, not an actual read or write. */ 1611e17c2c1SAlexander Graf #define VIRTIO_BLK_T_SCSI_CMD 2 1621e17c2c1SAlexander Graf 1631e17c2c1SAlexander Graf /* Cache flush command */ 1641e17c2c1SAlexander Graf #define VIRTIO_BLK_T_FLUSH 4 1651e17c2c1SAlexander Graf 1661e17c2c1SAlexander Graf /* Barrier before this op. */ 1671e17c2c1SAlexander Graf #define VIRTIO_BLK_T_BARRIER 0x80000000 1681e17c2c1SAlexander Graf 1691e17c2c1SAlexander Graf /* This is the first element of the read scatter-gather list. */ 170b88d7fa5SEugene (jno) Dvurechenski struct VirtioBlkOuthdr { 1711e17c2c1SAlexander Graf /* VIRTIO_BLK_T* */ 172b88d7fa5SEugene (jno) Dvurechenski uint32_t type; 1731e17c2c1SAlexander Graf /* io priority. */ 174b88d7fa5SEugene (jno) Dvurechenski uint32_t ioprio; 1751e17c2c1SAlexander Graf /* Sector (ie. 512 byte offset) */ 176b88d7fa5SEugene (jno) Dvurechenski uint64_t sector; 1771e17c2c1SAlexander Graf }; 178b88d7fa5SEugene (jno) Dvurechenski typedef struct VirtioBlkOuthdr VirtioBlkOuthdr; 1791e17c2c1SAlexander Graf 180b88d7fa5SEugene (jno) Dvurechenski struct VirtioBlkConfig { 181b88d7fa5SEugene (jno) Dvurechenski uint64_t capacity; /* in 512-byte sectors */ 182b88d7fa5SEugene (jno) Dvurechenski uint32_t size_max; /* max segment size (if VIRTIO_BLK_F_SIZE_MAX) */ 183b88d7fa5SEugene (jno) Dvurechenski uint32_t seg_max; /* max number of segments (if VIRTIO_BLK_F_SEG_MAX) */ 18491a03f9bSEugene (jno) Dvurechenski 185b88d7fa5SEugene (jno) Dvurechenski struct VirtioBlkGeometry { 186b88d7fa5SEugene (jno) Dvurechenski uint16_t cylinders; 187b88d7fa5SEugene (jno) Dvurechenski uint8_t heads; 188b88d7fa5SEugene (jno) Dvurechenski uint8_t sectors; 18991a03f9bSEugene (jno) Dvurechenski } geometry; /* (if VIRTIO_BLK_F_GEOMETRY) */ 19091a03f9bSEugene (jno) Dvurechenski 191b88d7fa5SEugene (jno) Dvurechenski uint32_t blk_size; /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */ 19291a03f9bSEugene (jno) Dvurechenski 19391a03f9bSEugene (jno) Dvurechenski /* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY */ 194b88d7fa5SEugene (jno) Dvurechenski uint8_t physical_block_exp; /* exponent for physical blk per logical blk */ 195b88d7fa5SEugene (jno) Dvurechenski uint8_t alignment_offset; /* alignment offset in logical blocks */ 196b88d7fa5SEugene (jno) Dvurechenski uint16_t min_io_size; /* min I/O size without performance penalty 19791a03f9bSEugene (jno) Dvurechenski in logical blocks */ 198b88d7fa5SEugene (jno) Dvurechenski uint32_t opt_io_size; /* optimal sustained I/O size in logical blks */ 19991a03f9bSEugene (jno) Dvurechenski 200b88d7fa5SEugene (jno) Dvurechenski uint8_t wce; /* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */ 201b88d7fa5SEugene (jno) Dvurechenski } __attribute__((packed)); 202b88d7fa5SEugene (jno) Dvurechenski typedef struct VirtioBlkConfig VirtioBlkConfig; 20391a03f9bSEugene (jno) Dvurechenski 204a1102cebSEugene (jno) Dvurechenski enum guessed_disk_nature_type { 205a1102cebSEugene (jno) Dvurechenski VIRTIO_GDN_NONE = 0, 206a1102cebSEugene (jno) Dvurechenski VIRTIO_GDN_DASD = 1, 207a1102cebSEugene (jno) Dvurechenski VIRTIO_GDN_CDROM = 2, 208a1102cebSEugene (jno) Dvurechenski VIRTIO_GDN_SCSI = 3, 209a1102cebSEugene (jno) Dvurechenski }; 210a1102cebSEugene (jno) Dvurechenski typedef enum guessed_disk_nature_type VirtioGDN; 211a1102cebSEugene (jno) Dvurechenski 212a1102cebSEugene (jno) Dvurechenski VirtioGDN virtio_guessed_disk_nature(void); 21391a03f9bSEugene (jno) Dvurechenski void virtio_assume_scsi(void); 21491a03f9bSEugene (jno) Dvurechenski void virtio_assume_eckd(void); 215866cac91SMaxim Samoylov void virtio_assume_iso9660(void); 21691a03f9bSEugene (jno) Dvurechenski 21791a03f9bSEugene (jno) Dvurechenski extern bool virtio_disk_is_scsi(void); 21891a03f9bSEugene (jno) Dvurechenski extern bool virtio_disk_is_eckd(void); 21991a03f9bSEugene (jno) Dvurechenski extern bool virtio_ipl_disk_is_valid(void); 22091a03f9bSEugene (jno) Dvurechenski extern int virtio_get_block_size(void); 22191a03f9bSEugene (jno) Dvurechenski extern uint8_t virtio_get_heads(void); 22291a03f9bSEugene (jno) Dvurechenski extern uint8_t virtio_get_sectors(void); 223f04db28bSEugene (jno) Dvurechenski extern uint64_t virtio_get_blocks(void); 22491a03f9bSEugene (jno) Dvurechenski extern int virtio_read_many(ulong sector, void *load_addr, int sec_num); 22591a03f9bSEugene (jno) Dvurechenski 22691a03f9bSEugene (jno) Dvurechenski #define VIRTIO_SECTOR_SIZE 512 22791a03f9bSEugene (jno) Dvurechenski 22891a03f9bSEugene (jno) Dvurechenski static inline ulong virtio_sector_adjust(ulong sector) 22991a03f9bSEugene (jno) Dvurechenski { 23038150be8SMaxim Samoylov return sector * (virtio_get_block_size() / VIRTIO_SECTOR_SIZE); 23191a03f9bSEugene (jno) Dvurechenski } 23291a03f9bSEugene (jno) Dvurechenski 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; 24469429682SEugene (jno) Dvurechenski } config; 24569429682SEugene (jno) Dvurechenski }; 24669429682SEugene (jno) Dvurechenski typedef struct VDev VDev; 24769429682SEugene (jno) Dvurechenski 24869429682SEugene (jno) Dvurechenski VDev *virtio_get_device(void); 24969429682SEugene (jno) Dvurechenski VirtioDevType virtio_get_device_type(void); 25069429682SEugene (jno) Dvurechenski 251*8944edc3SEugene (jno) Dvurechenski struct VirtioCmd { 252*8944edc3SEugene (jno) Dvurechenski void *data; 253*8944edc3SEugene (jno) Dvurechenski int size; 254*8944edc3SEugene (jno) Dvurechenski int flags; 255*8944edc3SEugene (jno) Dvurechenski }; 256*8944edc3SEugene (jno) Dvurechenski typedef struct VirtioCmd VirtioCmd; 257*8944edc3SEugene (jno) Dvurechenski 258*8944edc3SEugene (jno) Dvurechenski int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd); 259*8944edc3SEugene (jno) Dvurechenski 2601e17c2c1SAlexander Graf #endif /* VIRTIO_H */ 261