1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2019 Joyent, Inc. 14 * Copyright 2020 Oxide Computer Company 15 */ 16 17 /* 18 * VIRTIO BLOCK DRIVER 19 */ 20 21 #ifndef _VIOBLK_H 22 #define _VIOBLK_H 23 24 #include "virtio.h" 25 26 #ifdef __cplusplus 27 extern "C" { 28 #endif 29 30 /* 31 * VIRTIO BLOCK CONFIGURATION REGISTERS 32 * 33 * These are offsets into the device-specific configuration space available 34 * through the virtio_dev_*() family of functions. 35 */ 36 #define VIRTIO_BLK_CONFIG_CAPACITY 0x00 /* 64 R */ 37 #define VIRTIO_BLK_CONFIG_SIZE_MAX 0x08 /* 32 R */ 38 #define VIRTIO_BLK_CONFIG_SEG_MAX 0x0C /* 32 R */ 39 #define VIRTIO_BLK_CONFIG_GEOMETRY_C 0x10 /* 16 R */ 40 #define VIRTIO_BLK_CONFIG_GEOMETRY_H 0x12 /* 8 R */ 41 #define VIRTIO_BLK_CONFIG_GEOMETRY_S 0x13 /* 8 R */ 42 #define VIRTIO_BLK_CONFIG_BLK_SIZE 0x14 /* 32 R */ 43 #define VIRTIO_BLK_CONFIG_TOPO_PBEXP 0x18 /* 8 R */ 44 #define VIRTIO_BLK_CONFIG_TOPO_ALIGN 0x19 /* 8 R */ 45 #define VIRTIO_BLK_CONFIG_TOPO_MIN_SZ 0x1A /* 16 R */ 46 #define VIRTIO_BLK_CONFIG_TOPO_OPT_SZ 0x1C /* 32 R */ 47 #define VIRTIO_BLK_CONFIG_WRITEBACK 0x20 /* 8 R */ 48 /* unused 0x21 */ /* 8 R */ 49 #define VIRTIO_BLK_CONFIG_NUM_QUEUES 0x22 /* 16 R */ 50 #define VIRTIO_BLK_CONFIG_MAX_DISCARD_SECT 0x24 /* 32 R */ 51 #define VIRTIO_BLK_CONFIG_MAX_DISCARD_SEG 0x28 /* 32 R */ 52 #define VIRTIO_BLK_CONFIG_DISCARD_ALIGN 0x2C /* 32 R */ 53 #define VIRTIO_BLK_CONFIG_MAX_WRITE_ZERO_SECT 0x30 /* 32 R */ 54 #define VIRTIO_BLK_CONFIG_MAX_WRITE_ZERO_SEG 0x34 /* 32 R */ 55 #define VIRTIO_BLK_CONFIG_WRITE_ZERO_UNMAP 0x38 /* 8 R */ 56 57 /* 58 * VIRTIO BLOCK VIRTQUEUES 59 * 60 * Virtio block devices have just one queue which is used to make the various 61 * supported I/O requests. 62 */ 63 #define VIRTIO_BLK_VIRTQ_IO 0 64 65 /* 66 * VIRTIO BLOCK FEATURE BITS 67 */ 68 #define VIRTIO_BLK_F_BARRIER (1ULL << 0) 69 #define VIRTIO_BLK_F_SIZE_MAX (1ULL << 1) 70 #define VIRTIO_BLK_F_SEG_MAX (1ULL << 2) 71 #define VIRTIO_BLK_F_GEOMETRY (1ULL << 4) 72 #define VIRTIO_BLK_F_RO (1ULL << 5) 73 #define VIRTIO_BLK_F_BLK_SIZE (1ULL << 6) 74 #define VIRTIO_BLK_F_SCSI (1ULL << 7) 75 #define VIRTIO_BLK_F_FLUSH (1ULL << 9) 76 #define VIRTIO_BLK_F_TOPOLOGY (1ULL << 10) 77 #define VIRTIO_BLK_F_CONFIG_WCE (1ULL << 11) 78 #define VIRTIO_BLK_F_MQ (1ULL << 12) 79 #define VIRTIO_BLK_F_DISCARD (1ULL << 13) 80 #define VIRTIO_BLK_F_WRITE_ZEROES (1ULL << 14) 81 82 /* 83 * These features are supported by the driver and we will request them from the 84 * device. 85 */ 86 #define VIRTIO_BLK_WANTED_FEATURES (VIRTIO_BLK_F_RO | \ 87 VIRTIO_BLK_F_BLK_SIZE | \ 88 VIRTIO_BLK_F_FLUSH | \ 89 VIRTIO_BLK_F_TOPOLOGY | \ 90 VIRTIO_BLK_F_SEG_MAX | \ 91 VIRTIO_BLK_F_SIZE_MAX | \ 92 VIRTIO_BLK_F_DISCARD) 93 94 /* 95 * VIRTIO BLOCK REQUEST HEADER 96 * 97 * This structure appears at the start of each I/O request buffer. Note that 98 * neither the data payload nor the status byte appear in this structure as 99 * both are handled in separate descriptor entries. 100 */ 101 struct vioblk_req_hdr { 102 uint32_t vbh_type; 103 uint32_t vbh_ioprio; 104 uint64_t vbh_sector; 105 } __packed; 106 107 /* 108 * VIRTIO BLOCK REQUEST HEADER: COMMANDS (vbh_type) 109 * 110 * Each of these is a command type, except for BARRIER which is logically 111 * OR-ed with one of the other types. 112 */ 113 #define VIRTIO_BLK_T_IN 0 114 #define VIRTIO_BLK_T_OUT 1 115 #define VIRTIO_BLK_T_SCSI_CMD 2 116 #define VIRTIO_BLK_T_SCSI_CMD_OUT 3 117 #define VIRTIO_BLK_T_FLUSH 4 118 #define VIRTIO_BLK_T_FLUSH_OUT 5 119 #define VIRTIO_BLK_T_GET_ID 8 120 #define VIRTIO_BLK_T_DISCARD 11 121 #define VIRTIO_BLK_T_WRITE_ZEROES 13 122 #define VIRTIO_BLK_T_BARRIER 0x80000000 123 124 /* 125 * VIRTIO BLOCK DISCARD/WRITE ZEROS DATA 126 * 127 * For hosts that support the DISCARD or WRITE ZEROES features, instead of 128 * data, the vioblk_discard_write_zeros struct is used as the 'data' for 129 * the request. 130 */ 131 struct vioblk_discard_write_zeroes { 132 uint64_t vdwz_sector; 133 uint32_t vdwz_num_sectors; 134 uint32_t vdwz_flags; 135 } __packed; 136 137 /* 138 * vdwz_flags values 139 */ 140 141 /* For a WRITE ZEROES request, also unmap the block */ 142 #define VIRTIO_BLK_WRITE_ZEROS_UNMAP (1U << 0) 143 144 /* 145 * The GET_ID command type does not appear in the specification, but 146 * implementations in the wild use a 20 byte buffer into which the device will 147 * write an ASCII string. The string should not be assumed to be 148 * NUL-terminated. 149 */ 150 #define VIRTIO_BLK_ID_BYTES 20 151 152 /* 153 * VIRTIO BLOCK REQUEST HEADER: STATUS CODES 154 * 155 * These are returned in the writeable status byte descriptor included at the 156 * end of each request passed to the device. 157 */ 158 #define VIRTIO_BLK_S_OK 0 159 #define VIRTIO_BLK_S_IOERR 1 160 #define VIRTIO_BLK_S_UNSUPP 2 161 162 /* 163 * DRIVER PARAMETERS 164 */ 165 166 /* 167 * In the event that the device does not negotiate DMA parameters, we have to 168 * make a best guess. 169 */ 170 #define VIRTIO_BLK_DEFAULT_MAX_SEG 128 171 #define VIRTIO_BLK_DEFAULT_MAX_SIZE 4096 172 173 /* 174 * We allocate a fixed number of request buffers in advance and place them in a 175 * per-instance free list. 176 */ 177 #define VIRTIO_BLK_REQ_BUFS 256 178 179 /* 180 * TYPE DEFINITIONS 181 */ 182 183 typedef enum vioblk_req_status { 184 VIOBLK_REQSTAT_ALLOCATED = (0x1 << 0), 185 VIOBLK_REQSTAT_INFLIGHT = (0x1 << 1), 186 VIOBLK_REQSTAT_COMPLETE = (0x1 << 2), 187 VIOBLK_REQSTAT_POLLED = (0x1 << 3), 188 VIOBLK_REQSTAT_POLL_COMPLETE = (0x1 << 4), 189 } vioblk_req_status_t; 190 191 typedef struct vioblk_req { 192 vioblk_req_status_t vbr_status; 193 uint64_t vbr_seqno; 194 int vbr_type; 195 int vbr_error; 196 virtio_dma_t *vbr_dma; 197 virtio_chain_t *vbr_chain; 198 bd_xfer_t *vbr_xfer; 199 list_node_t vbr_link; 200 } vioblk_req_t; 201 202 typedef struct vioblk_stats { 203 struct kstat_named vbs_rw_outofmemory; 204 struct kstat_named vbs_rw_badoffset; 205 struct kstat_named vbs_rw_queuemax; 206 struct kstat_named vbs_rw_cookiesmax; 207 struct kstat_named vbs_rw_cacheflush; 208 struct kstat_named vbs_intr_queuemax; 209 struct kstat_named vbs_intr_total; 210 struct kstat_named vbs_io_errors; 211 struct kstat_named vbs_unsupp_errors; 212 struct kstat_named vbs_nxio_errors; 213 } vioblk_stats_t; 214 215 typedef struct vioblk { 216 dev_info_t *vib_dip; 217 virtio_t *vib_virtio; 218 virtio_queue_t *vib_vq; 219 220 kmutex_t vib_mutex; 221 kcondvar_t vib_cv; 222 223 bd_handle_t vib_bd_h; 224 ddi_dma_attr_t vib_bd_dma_attr; 225 226 list_t vib_reqs; 227 uint_t vib_nreqs_alloc; 228 uint_t vib_reqs_capacity; 229 vioblk_req_t *vib_reqs_mem; 230 231 kstat_t *vib_kstat; 232 vioblk_stats_t *vib_stats; 233 234 uint64_t vib_nblks; 235 boolean_t vib_readonly; 236 uint_t vib_blk_size; 237 uint_t vib_pblk_size; 238 uint_t vib_seg_max; 239 uint_t vib_seg_size_max; 240 241 boolean_t vib_can_discard; /* Write Once */ 242 uint_t vib_max_discard_sectors; /* WO */ 243 uint_t vib_max_discard_seg; /* WO */ 244 uint_t vib_discard_sector_align; /* WO */ 245 246 boolean_t vib_devid_fetched; 247 char vib_devid[VIRTIO_BLK_ID_BYTES + 1]; 248 uint8_t vib_rawid[VIRTIO_BLK_ID_BYTES]; 249 } vioblk_t; 250 251 #ifdef __cplusplus 252 } 253 #endif 254 255 #endif /* _VIOBLK_H */ 256