virtio.h (8068B)
1/* 2 * Virtio driver bits 3 * 4 * Copyright (c) 2013 Alexander Graf <agraf@suse.de> 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or (at 7 * your option) any later version. See the COPYING file in the top-level 8 * directory. 9 */ 10 11#ifndef VIRTIO_H 12#define VIRTIO_H 13 14/* Status byte for guest to report progress, and synchronize features. */ 15/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ 16#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 17/* We have found a driver for the device. */ 18#define VIRTIO_CONFIG_S_DRIVER 2 19/* Driver has used its parts of the config, and is happy */ 20#define VIRTIO_CONFIG_S_DRIVER_OK 4 21/* We've given up on this device. */ 22#define VIRTIO_CONFIG_S_FAILED 0x80 23 24enum VirtioDevType { 25 VIRTIO_ID_NET = 1, 26 VIRTIO_ID_BLOCK = 2, 27 VIRTIO_ID_CONSOLE = 3, 28 VIRTIO_ID_BALLOON = 5, 29 VIRTIO_ID_SCSI = 8, 30}; 31typedef enum VirtioDevType VirtioDevType; 32 33struct VqInfo { 34 uint64_t queue; 35 uint32_t align; 36 uint16_t index; 37 uint16_t num; 38} __attribute__((packed)); 39typedef struct VqInfo VqInfo; 40 41struct VqConfig { 42 uint16_t index; 43 uint16_t num; 44} __attribute__((packed)); 45typedef struct VqConfig VqConfig; 46 47#define VIRTIO_RING_SIZE (PAGE_SIZE * 8) 48#define VIRTIO_MAX_VQS 3 49#define KVM_S390_VIRTIO_RING_ALIGN 4096 50 51#define VRING_USED_F_NO_NOTIFY 1 52 53/* This marks a buffer as continuing via the next field. */ 54#define VRING_DESC_F_NEXT 1 55/* This marks a buffer as write-only (otherwise read-only). */ 56#define VRING_DESC_F_WRITE 2 57/* This means the buffer contains a list of buffer descriptors. */ 58#define VRING_DESC_F_INDIRECT 4 59 60/* Internal flag to mark follow-up segments as such */ 61#define VRING_HIDDEN_IS_CHAIN 256 62 63/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ 64struct VRingDesc { 65 /* Address (guest-physical). */ 66 uint64_t addr; 67 /* Length. */ 68 uint32_t len; 69 /* The flags as indicated above. */ 70 uint16_t flags; 71 /* We chain unused descriptors via this, too */ 72 uint16_t next; 73} __attribute__((packed)); 74typedef struct VRingDesc VRingDesc; 75 76struct VRingAvail { 77 uint16_t flags; 78 uint16_t idx; 79 uint16_t ring[]; 80} __attribute__((packed)); 81typedef struct VRingAvail VRingAvail; 82 83/* uint32_t is used here for ids for padding reasons. */ 84struct VRingUsedElem { 85 /* Index of start of used descriptor chain. */ 86 uint32_t id; 87 /* Total length of the descriptor chain which was used (written to) */ 88 uint32_t len; 89} __attribute__((packed)); 90typedef struct VRingUsedElem VRingUsedElem; 91 92struct VRingUsed { 93 uint16_t flags; 94 uint16_t idx; 95 VRingUsedElem ring[]; 96} __attribute__((packed)); 97typedef struct VRingUsed VRingUsed; 98 99struct VRing { 100 unsigned int num; 101 int next_idx; 102 int used_idx; 103 VRingDesc *desc; 104 VRingAvail *avail; 105 VRingUsed *used; 106 SubChannelId schid; 107 long cookie; 108 int id; 109}; 110typedef struct VRing VRing; 111 112 113/*********************************************** 114 * Virtio block * 115 ***********************************************/ 116 117/* 118 * Command types 119 * 120 * Usage is a bit tricky as some bits are used as flags and some are not. 121 * 122 * Rules: 123 * VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or 124 * VIRTIO_BLK_T_BARRIER. VIRTIO_BLK_T_FLUSH is a command of its own 125 * and may not be combined with any of the other flags. 126 */ 127 128/* These two define direction. */ 129#define VIRTIO_BLK_T_IN 0 130#define VIRTIO_BLK_T_OUT 1 131 132/* This bit says it's a scsi command, not an actual read or write. */ 133#define VIRTIO_BLK_T_SCSI_CMD 2 134 135/* Cache flush command */ 136#define VIRTIO_BLK_T_FLUSH 4 137 138/* Barrier before this op. */ 139#define VIRTIO_BLK_T_BARRIER 0x80000000 140 141/* This is the first element of the read scatter-gather list. */ 142struct VirtioBlkOuthdr { 143 /* VIRTIO_BLK_T* */ 144 uint32_t type; 145 /* io priority. */ 146 uint32_t ioprio; 147 /* Sector (ie. 512 byte offset) */ 148 uint64_t sector; 149}; 150typedef struct VirtioBlkOuthdr VirtioBlkOuthdr; 151 152struct VirtioBlkConfig { 153 uint64_t capacity; /* in 512-byte sectors */ 154 uint32_t size_max; /* max segment size (if VIRTIO_BLK_F_SIZE_MAX) */ 155 uint32_t seg_max; /* max number of segments (if VIRTIO_BLK_F_SEG_MAX) */ 156 157 struct VirtioBlkGeometry { 158 uint16_t cylinders; 159 uint8_t heads; 160 uint8_t sectors; 161 } geometry; /* (if VIRTIO_BLK_F_GEOMETRY) */ 162 163 uint32_t blk_size; /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */ 164 165 /* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY */ 166 uint8_t physical_block_exp; /* exponent for physical blk per logical blk */ 167 uint8_t alignment_offset; /* alignment offset in logical blocks */ 168 uint16_t min_io_size; /* min I/O size without performance penalty 169 in logical blocks */ 170 uint32_t opt_io_size; /* optimal sustained I/O size in logical blks */ 171 172 uint8_t wce; /* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */ 173} __attribute__((packed)); 174typedef struct VirtioBlkConfig VirtioBlkConfig; 175 176enum guessed_disk_nature_type { 177 VIRTIO_GDN_NONE = 0, 178 VIRTIO_GDN_DASD = 1, 179 VIRTIO_GDN_CDROM = 2, 180 VIRTIO_GDN_SCSI = 3, 181}; 182typedef enum guessed_disk_nature_type VirtioGDN; 183 184VirtioGDN virtio_guessed_disk_nature(void); 185void virtio_assume_scsi(void); 186void virtio_assume_eckd(void); 187void virtio_assume_iso9660(void); 188 189extern bool virtio_disk_is_scsi(void); 190extern bool virtio_disk_is_eckd(void); 191extern bool virtio_ipl_disk_is_valid(void); 192extern int virtio_get_block_size(void); 193extern uint8_t virtio_get_heads(void); 194extern uint8_t virtio_get_sectors(void); 195extern uint64_t virtio_get_blocks(void); 196extern int virtio_read_many(ulong sector, void *load_addr, int sec_num); 197 198#define VIRTIO_SECTOR_SIZE 512 199#define VIRTIO_ISO_BLOCK_SIZE 2048 200#define VIRTIO_SCSI_BLOCK_SIZE 512 201 202static inline ulong virtio_sector_adjust(ulong sector) 203{ 204 return sector * (virtio_get_block_size() / VIRTIO_SECTOR_SIZE); 205} 206 207struct VirtioScsiConfig { 208 uint32_t num_queues; 209 uint32_t seg_max; 210 uint32_t max_sectors; 211 uint32_t cmd_per_lun; 212 uint32_t event_info_size; 213 uint32_t sense_size; 214 uint32_t cdb_size; 215 uint16_t max_channel; 216 uint16_t max_target; 217 uint32_t max_lun; 218} __attribute__((packed)); 219typedef struct VirtioScsiConfig VirtioScsiConfig; 220 221struct ScsiDevice { 222 uint16_t channel; /* Always 0 in QEMU */ 223 uint16_t target; /* will be scanned over */ 224 uint32_t lun; /* will be reported */ 225}; 226typedef struct ScsiDevice ScsiDevice; 227 228struct VirtioNetConfig { 229 uint8_t mac[6]; 230 /* uint16_t status; */ /* Only with VIRTIO_NET_F_STATUS */ 231 /* uint16_t max_virtqueue_pairs; */ /* Only with VIRTIO_NET_F_MQ */ 232}; 233typedef struct VirtioNetConfig VirtioNetConfig; 234 235struct VDev { 236 int nr_vqs; 237 VRing *vrings; 238 int cmd_vr_idx; 239 void *ring_area; 240 long wait_reply_timeout; 241 VirtioGDN guessed_disk_nature; 242 SubChannelId schid; 243 SenseId senseid; 244 union { 245 VirtioBlkConfig blk; 246 VirtioScsiConfig scsi; 247 VirtioNetConfig net; 248 } config; 249 ScsiDevice *scsi_device; 250 bool is_cdrom; 251 int scsi_block_size; 252 int blk_factor; 253 uint64_t scsi_last_block; 254 uint32_t scsi_dev_cyls; 255 uint8_t scsi_dev_heads; 256 bool scsi_device_selected; 257 ScsiDevice selected_scsi_device; 258 uint64_t netboot_start_addr; 259 uint32_t max_transfer; 260 uint32_t guest_features[2]; 261}; 262typedef struct VDev VDev; 263 264VDev *virtio_get_device(void); 265VirtioDevType virtio_get_device_type(void); 266 267struct VirtioCmd { 268 void *data; 269 int size; 270 int flags; 271}; 272typedef struct VirtioCmd VirtioCmd; 273 274bool vring_notify(VRing *vr); 275int drain_irqs(SubChannelId schid); 276void vring_send_buf(VRing *vr, void *p, int len, int flags); 277int vr_poll(VRing *vr); 278int vring_wait_reply(void); 279int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd); 280void virtio_setup_ccw(VDev *vdev); 281 282int virtio_net_init(void *mac_addr); 283 284#endif /* VIRTIO_H */