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 26*b88d7fa5SEugene (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 }; 32*b88d7fa5SEugene (jno) Dvurechenski typedef enum VirtioDevType VirtioDevType; 331e17c2c1SAlexander Graf 34*b88d7fa5SEugene (jno) Dvurechenski struct VirtioDevHeader { 35*b88d7fa5SEugene (jno) Dvurechenski VirtioDevType type:8; 36*b88d7fa5SEugene (jno) Dvurechenski uint8_t num_vq; 37*b88d7fa5SEugene (jno) Dvurechenski uint8_t feature_len; 38*b88d7fa5SEugene (jno) Dvurechenski uint8_t config_len; 39*b88d7fa5SEugene (jno) Dvurechenski uint8_t status; 40*b88d7fa5SEugene (jno) Dvurechenski uint8_t vqconfig[]; 411e17c2c1SAlexander Graf } __attribute__((packed)); 42*b88d7fa5SEugene (jno) Dvurechenski typedef struct VirtioDevHeader VirtioDevHeader; 431e17c2c1SAlexander Graf 44*b88d7fa5SEugene (jno) Dvurechenski struct VirtioVqConfig { 45*b88d7fa5SEugene (jno) Dvurechenski uint64_t token; 46*b88d7fa5SEugene (jno) Dvurechenski uint64_t address; 47*b88d7fa5SEugene (jno) Dvurechenski uint16_t num; 48*b88d7fa5SEugene (jno) Dvurechenski uint8_t pad[6]; 491e17c2c1SAlexander Graf } __attribute__((packed)); 50*b88d7fa5SEugene (jno) Dvurechenski typedef struct VirtioVqConfig VirtioVqConfig; 511e17c2c1SAlexander Graf 52*b88d7fa5SEugene (jno) Dvurechenski struct VqInfo { 53*b88d7fa5SEugene (jno) Dvurechenski uint64_t queue; 54*b88d7fa5SEugene (jno) Dvurechenski uint32_t align; 55*b88d7fa5SEugene (jno) Dvurechenski uint16_t index; 56*b88d7fa5SEugene (jno) Dvurechenski uint16_t num; 571e17c2c1SAlexander Graf } __attribute__((packed)); 58*b88d7fa5SEugene (jno) Dvurechenski typedef struct VqInfo VqInfo; 591e17c2c1SAlexander Graf 60*b88d7fa5SEugene (jno) Dvurechenski struct VqConfig { 61*b88d7fa5SEugene (jno) Dvurechenski uint16_t index; 62*b88d7fa5SEugene (jno) Dvurechenski uint16_t num; 63abbbe3deSCornelia Huck } __attribute__((packed)); 64*b88d7fa5SEugene (jno) Dvurechenski typedef struct VqConfig VqConfig; 65abbbe3deSCornelia Huck 66*b88d7fa5SEugene (jno) Dvurechenski struct VirtioDev { 67*b88d7fa5SEugene (jno) Dvurechenski VirtioDevHeader *header; 68*b88d7fa5SEugene (jno) Dvurechenski VirtioVqConfig *vqconfig; 691e17c2c1SAlexander Graf char *host_features; 701e17c2c1SAlexander Graf char *guest_features; 711e17c2c1SAlexander Graf char *config; 721e17c2c1SAlexander Graf }; 73*b88d7fa5SEugene (jno) Dvurechenski typedef struct VirtioDev VirtioDev; 741e17c2c1SAlexander Graf 751e17c2c1SAlexander Graf #define KVM_S390_VIRTIO_RING_ALIGN 4096 761e17c2c1SAlexander Graf 771e17c2c1SAlexander Graf #define VRING_USED_F_NO_NOTIFY 1 781e17c2c1SAlexander Graf 791e17c2c1SAlexander Graf /* This marks a buffer as continuing via the next field. */ 801e17c2c1SAlexander Graf #define VRING_DESC_F_NEXT 1 811e17c2c1SAlexander Graf /* This marks a buffer as write-only (otherwise read-only). */ 821e17c2c1SAlexander Graf #define VRING_DESC_F_WRITE 2 831e17c2c1SAlexander Graf /* This means the buffer contains a list of buffer descriptors. */ 841e17c2c1SAlexander Graf #define VRING_DESC_F_INDIRECT 4 851e17c2c1SAlexander Graf 861e17c2c1SAlexander Graf /* Internal flag to mark follow-up segments as such */ 871e17c2c1SAlexander Graf #define VRING_HIDDEN_IS_CHAIN 256 881e17c2c1SAlexander Graf 891e17c2c1SAlexander Graf /* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ 90*b88d7fa5SEugene (jno) Dvurechenski struct VRingDesc { 911e17c2c1SAlexander Graf /* Address (guest-physical). */ 92*b88d7fa5SEugene (jno) Dvurechenski uint64_t addr; 931e17c2c1SAlexander Graf /* Length. */ 94*b88d7fa5SEugene (jno) Dvurechenski uint32_t len; 951e17c2c1SAlexander Graf /* The flags as indicated above. */ 96*b88d7fa5SEugene (jno) Dvurechenski uint16_t flags; 971e17c2c1SAlexander Graf /* We chain unused descriptors via this, too */ 98*b88d7fa5SEugene (jno) Dvurechenski uint16_t next; 991e17c2c1SAlexander Graf } __attribute__((packed)); 100*b88d7fa5SEugene (jno) Dvurechenski typedef struct VRingDesc VRingDesc; 1011e17c2c1SAlexander Graf 102*b88d7fa5SEugene (jno) Dvurechenski struct VRingAvail { 103*b88d7fa5SEugene (jno) Dvurechenski uint16_t flags; 104*b88d7fa5SEugene (jno) Dvurechenski uint16_t idx; 105*b88d7fa5SEugene (jno) Dvurechenski uint16_t ring[]; 1061e17c2c1SAlexander Graf } __attribute__((packed)); 107*b88d7fa5SEugene (jno) Dvurechenski typedef struct VRingAvail VRingAvail; 1081e17c2c1SAlexander Graf 109*b88d7fa5SEugene (jno) Dvurechenski /* uint32_t is used here for ids for padding reasons. */ 110*b88d7fa5SEugene (jno) Dvurechenski struct VRingUsedElem { 1111e17c2c1SAlexander Graf /* Index of start of used descriptor chain. */ 112*b88d7fa5SEugene (jno) Dvurechenski uint32_t id; 1131e17c2c1SAlexander Graf /* Total length of the descriptor chain which was used (written to) */ 114*b88d7fa5SEugene (jno) Dvurechenski uint32_t len; 1151e17c2c1SAlexander Graf } __attribute__((packed)); 116*b88d7fa5SEugene (jno) Dvurechenski typedef struct VRingUsedElem VRingUsedElem; 1171e17c2c1SAlexander Graf 118*b88d7fa5SEugene (jno) Dvurechenski struct VRingUsed { 119*b88d7fa5SEugene (jno) Dvurechenski uint16_t flags; 120*b88d7fa5SEugene (jno) Dvurechenski uint16_t idx; 121*b88d7fa5SEugene (jno) Dvurechenski VRingUsedElem ring[]; 1221e17c2c1SAlexander Graf } __attribute__((packed)); 123*b88d7fa5SEugene (jno) Dvurechenski typedef struct VRingUsed VRingUsed; 1241e17c2c1SAlexander Graf 125*b88d7fa5SEugene (jno) Dvurechenski struct VRing { 1261e17c2c1SAlexander Graf unsigned int num; 1271e17c2c1SAlexander Graf int next_idx; 128441ea695SCornelia Huck int used_idx; 129*b88d7fa5SEugene (jno) Dvurechenski VRingDesc *desc; 130*b88d7fa5SEugene (jno) Dvurechenski VRingAvail *avail; 131*b88d7fa5SEugene (jno) Dvurechenski VRingUsed *used; 132*b88d7fa5SEugene (jno) Dvurechenski SubChannelId schid; 1331e17c2c1SAlexander Graf }; 134*b88d7fa5SEugene (jno) Dvurechenski typedef struct VRing VRing; 1351e17c2c1SAlexander Graf 1361e17c2c1SAlexander Graf 1371e17c2c1SAlexander Graf /*********************************************** 1381e17c2c1SAlexander Graf * Virtio block * 1391e17c2c1SAlexander Graf ***********************************************/ 1401e17c2c1SAlexander Graf 1411e17c2c1SAlexander Graf /* 1421e17c2c1SAlexander Graf * Command types 1431e17c2c1SAlexander Graf * 1441e17c2c1SAlexander Graf * Usage is a bit tricky as some bits are used as flags and some are not. 1451e17c2c1SAlexander Graf * 1461e17c2c1SAlexander Graf * Rules: 1471e17c2c1SAlexander Graf * VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or 1481e17c2c1SAlexander Graf * VIRTIO_BLK_T_BARRIER. VIRTIO_BLK_T_FLUSH is a command of its own 1491e17c2c1SAlexander Graf * and may not be combined with any of the other flags. 1501e17c2c1SAlexander Graf */ 1511e17c2c1SAlexander Graf 1521e17c2c1SAlexander Graf /* These two define direction. */ 1531e17c2c1SAlexander Graf #define VIRTIO_BLK_T_IN 0 1541e17c2c1SAlexander Graf #define VIRTIO_BLK_T_OUT 1 1551e17c2c1SAlexander Graf 1561e17c2c1SAlexander Graf /* This bit says it's a scsi command, not an actual read or write. */ 1571e17c2c1SAlexander Graf #define VIRTIO_BLK_T_SCSI_CMD 2 1581e17c2c1SAlexander Graf 1591e17c2c1SAlexander Graf /* Cache flush command */ 1601e17c2c1SAlexander Graf #define VIRTIO_BLK_T_FLUSH 4 1611e17c2c1SAlexander Graf 1621e17c2c1SAlexander Graf /* Barrier before this op. */ 1631e17c2c1SAlexander Graf #define VIRTIO_BLK_T_BARRIER 0x80000000 1641e17c2c1SAlexander Graf 1651e17c2c1SAlexander Graf /* This is the first element of the read scatter-gather list. */ 166*b88d7fa5SEugene (jno) Dvurechenski struct VirtioBlkOuthdr { 1671e17c2c1SAlexander Graf /* VIRTIO_BLK_T* */ 168*b88d7fa5SEugene (jno) Dvurechenski uint32_t type; 1691e17c2c1SAlexander Graf /* io priority. */ 170*b88d7fa5SEugene (jno) Dvurechenski uint32_t ioprio; 1711e17c2c1SAlexander Graf /* Sector (ie. 512 byte offset) */ 172*b88d7fa5SEugene (jno) Dvurechenski uint64_t sector; 1731e17c2c1SAlexander Graf }; 174*b88d7fa5SEugene (jno) Dvurechenski typedef struct VirtioBlkOuthdr VirtioBlkOuthdr; 1751e17c2c1SAlexander Graf 176*b88d7fa5SEugene (jno) Dvurechenski struct VirtioBlkConfig { 177*b88d7fa5SEugene (jno) Dvurechenski uint64_t capacity; /* in 512-byte sectors */ 178*b88d7fa5SEugene (jno) Dvurechenski uint32_t size_max; /* max segment size (if VIRTIO_BLK_F_SIZE_MAX) */ 179*b88d7fa5SEugene (jno) Dvurechenski uint32_t seg_max; /* max number of segments (if VIRTIO_BLK_F_SEG_MAX) */ 18091a03f9bSEugene (jno) Dvurechenski 181*b88d7fa5SEugene (jno) Dvurechenski struct VirtioBlkGeometry { 182*b88d7fa5SEugene (jno) Dvurechenski uint16_t cylinders; 183*b88d7fa5SEugene (jno) Dvurechenski uint8_t heads; 184*b88d7fa5SEugene (jno) Dvurechenski uint8_t sectors; 18591a03f9bSEugene (jno) Dvurechenski } geometry; /* (if VIRTIO_BLK_F_GEOMETRY) */ 18691a03f9bSEugene (jno) Dvurechenski 187*b88d7fa5SEugene (jno) Dvurechenski uint32_t blk_size; /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */ 18891a03f9bSEugene (jno) Dvurechenski 18991a03f9bSEugene (jno) Dvurechenski /* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY */ 190*b88d7fa5SEugene (jno) Dvurechenski uint8_t physical_block_exp; /* exponent for physical blk per logical blk */ 191*b88d7fa5SEugene (jno) Dvurechenski uint8_t alignment_offset; /* alignment offset in logical blocks */ 192*b88d7fa5SEugene (jno) Dvurechenski uint16_t min_io_size; /* min I/O size without performance penalty 19391a03f9bSEugene (jno) Dvurechenski in logical blocks */ 194*b88d7fa5SEugene (jno) Dvurechenski uint32_t opt_io_size; /* optimal sustained I/O size in logical blks */ 19591a03f9bSEugene (jno) Dvurechenski 196*b88d7fa5SEugene (jno) Dvurechenski uint8_t wce; /* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */ 197*b88d7fa5SEugene (jno) Dvurechenski } __attribute__((packed)); 198*b88d7fa5SEugene (jno) Dvurechenski typedef struct VirtioBlkConfig VirtioBlkConfig; 19991a03f9bSEugene (jno) Dvurechenski 20091a03f9bSEugene (jno) Dvurechenski bool virtio_guessed_disk_nature(void); 20191a03f9bSEugene (jno) Dvurechenski void virtio_assume_scsi(void); 20291a03f9bSEugene (jno) Dvurechenski void virtio_assume_eckd(void); 203866cac91SMaxim Samoylov void virtio_assume_iso9660(void); 20491a03f9bSEugene (jno) Dvurechenski 20591a03f9bSEugene (jno) Dvurechenski extern bool virtio_disk_is_scsi(void); 20691a03f9bSEugene (jno) Dvurechenski extern bool virtio_disk_is_eckd(void); 20791a03f9bSEugene (jno) Dvurechenski extern bool virtio_ipl_disk_is_valid(void); 20891a03f9bSEugene (jno) Dvurechenski extern int virtio_get_block_size(void); 20991a03f9bSEugene (jno) Dvurechenski extern uint8_t virtio_get_heads(void); 21091a03f9bSEugene (jno) Dvurechenski extern uint8_t virtio_get_sectors(void); 211f04db28bSEugene (jno) Dvurechenski extern uint64_t virtio_get_blocks(void); 21291a03f9bSEugene (jno) Dvurechenski extern int virtio_read_many(ulong sector, void *load_addr, int sec_num); 21391a03f9bSEugene (jno) Dvurechenski 21491a03f9bSEugene (jno) Dvurechenski #define VIRTIO_SECTOR_SIZE 512 21591a03f9bSEugene (jno) Dvurechenski 21691a03f9bSEugene (jno) Dvurechenski static inline ulong virtio_sector_adjust(ulong sector) 21791a03f9bSEugene (jno) Dvurechenski { 21838150be8SMaxim Samoylov return sector * (virtio_get_block_size() / VIRTIO_SECTOR_SIZE); 21991a03f9bSEugene (jno) Dvurechenski } 22091a03f9bSEugene (jno) Dvurechenski 2211e17c2c1SAlexander Graf #endif /* VIRTIO_H */ 222