xref: /illumos-gate/usr/src/cmd/bhyve/common/pci_virtio_scsi.h (revision 044ca4189dfeaedde4c89a0f91f13fcfb6d55ac5)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2016 Jakub Klama <jceel@FreeBSD.org>.
5  * Copyright (c) 2018 Marcelo Araujo <araujo@FreeBSD.org>.
6  * Copyright (c) 2026 Hans Rosenfeld
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer
14  *    in this position and unchanged.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #ifndef	_PCI_VIRTIO_SCSI_H_
33 #define	_PCI_VIRTIO_SCSI_H_
34 
35 #include "iov.h"
36 
37 extern int pci_vtscsi_debug;
38 
39 #define	WPRINTF(msg, params...)	PRINTLN("virtio-scsi: " msg, ##params)
40 #define	DPRINTF(msg, params...)	if (pci_vtscsi_debug) WPRINTF(msg, ##params)
41 
42 /* Absolute limits given by the VirtIO SCSI spec */
43 #define	VIRTIO_SCSI_MAX_CHANNEL	0
44 #define	VIRTIO_SCSI_MAX_TARGET	255
45 #define	VIRTIO_SCSI_MAX_LUN	16383
46 #define	VIRTIO_SCSI_HDR_SEG	2
47 #define	VIRTIO_SCSI_ADDL_Q	2
48 
49 /* Features specific to VirtIO SCSI, none of which we currently support */
50 #define	VIRTIO_SCSI_F_INOUT	(1 << 0)
51 #define	VIRTIO_SCSI_F_HOTPLUG	(1 << 1)
52 #define	VIRTIO_SCSI_F_CHANGE	(1 << 2)
53 
54 /* Default limits which we set. All of these are configurable. */
55 #define	VTSCSI_DEF_RINGSZ	64
56 #define	VTSCSI_MIN_RINGSZ	4
57 #define	VTSCSI_MAX_RINGSZ	4096
58 
59 #define	VTSCSI_DEF_THR_PER_Q	16
60 #define	VTSCSI_MIN_THR_PER_Q	1
61 #define	VTSCSI_MAX_THR_PER_Q	256
62 
63 #define	VTSCSI_DEF_MAXSEG	64
64 #define	VTSCSI_MIN_MAXSEG	(VIRTIO_SCSI_HDR_SEG + 1)
65 #define	VTSCSI_MAX_MAXSEG	\
66     (4096 - VIRTIO_SCSI_HDR_SEG - SPLIT_IOV_ADDL_IOV)
67 
68 #define	VTSCSI_DEF_REQUESTQ	1
69 #define	VTSCSI_MIN_REQUESTQ	1
70 #define	VTSCSI_MAX_REQUESTQ	(32 - VIRTIO_SCSI_ADDL_Q)
71 
72 /*
73  * Device-specific config space registers
74  *
75  * The guest driver may try to modify cdb_size and sense_size by writing the
76  * respective config space registers. Since we currently ignore all writes to
77  * config space, these macros are essentially constant.
78  */
79 #define	VTSCSI_IN_HEADER_LEN(_sc)	\
80 	(sizeof(struct pci_vtscsi_req_cmd_rd) + _sc->vss_config.cdb_size)
81 
82 #define	VTSCSI_OUT_HEADER_LEN(_sc)	\
83 	(sizeof(struct pci_vtscsi_req_cmd_wr) + _sc->vss_config.sense_size)
84 
85 struct pci_vtscsi_config {
86 	uint32_t				num_queues;
87 	uint32_t				seg_max;
88 	uint32_t				max_sectors;
89 	uint32_t				cmd_per_lun;
90 	uint32_t				event_info_size;
91 	uint32_t				sense_size;
92 	uint32_t				cdb_size;
93 	uint16_t				max_channel;
94 	uint16_t				max_target;
95 	uint32_t				max_lun;
96 } __attribute__((packed));
97 
98 
99 /*
100  * I/O request state
101  *
102  * Each pci_vtscsi_queue has configurable number of pci_vtscsi_request
103  * structures pre-allocated on vsq_free_requests. For each I/O request
104  * coming in on the I/O virtqueue, the request queue handler takes
105  * pci_vtscsi_request off vsq_free_requests, fills in the data from the
106  * I/O virtqueue, puts it on vsq_requests, and signals vsq_cv.
107  *
108  * Each pci_vtscsi_queue will have a configurable number of worker threads,
109  * which wait on vsq_cv. When signalled, they repeatedly take a single
110  * pci_vtscsi_request off vsq_requests and hand it to the backend, which
111  * processes it synchronously. After completion, the pci_vtscsi_request
112  * is re-initialized and put back onto vsq_free_requests.
113  *
114  * The worker threads exit when vsq_cv is signalled after vsw_exiting was set.
115  *
116  * The I/O vectors for each request are kept in the preallocated iovec array
117  * vsr_iov, and pointers to the respective header/data in/out portions are set
118  * up to point into the array when the request is queued for processing.
119  *
120  * The number of iovecs preallocated for vsr_iov is derived from the configured
121  * 'seg_max' parameter defined by the virtio spec:
122  *   - 'seg_max' parameter specifies the maximum number of I/O data vectors
123  *     we support in any request
124  *   - we need 2 additional iovecs for the I/O headers (VIRTIO_SCSI_HDR_SEG)
125  *   - we need another 2 additional iovecs for split_iov() (SPLIT_IOV_ADDL_IOV)
126  *
127  * The only time we explicitly need the full size of vsr_iov after preallocation
128  * is during re-initialization after completing a request, and implicitly in the
129  * calls to split_iov() the set up the pointers. In all other cases, we use only
130  * 'seg_max' + VIRTIO_SCSI_HDR_SEG, and we advertise only 'seg_max' to the guest
131  * in accordance to the virtio spec.
132  */
133 STAILQ_HEAD(pci_vtscsi_req_queue, pci_vtscsi_request);
134 
135 struct pci_vtscsi_queue {
136 	struct pci_vtscsi_softc			*vsq_sc;
137 	struct vqueue_info			*vsq_vq;
138 	pthread_mutex_t				vsq_rmtx;
139 	pthread_mutex_t				vsq_fmtx;
140 	pthread_mutex_t				vsq_qmtx;
141 	pthread_cond_t				vsq_cv;
142 	struct pci_vtscsi_req_queue		vsq_requests;
143 	struct pci_vtscsi_req_queue		vsq_free_requests;
144 	LIST_HEAD(, pci_vtscsi_worker)		vsq_workers;
145 };
146 
147 struct pci_vtscsi_worker {
148 	struct pci_vtscsi_queue			*vsw_queue;
149 	pthread_t				vsw_thread;
150 	bool					vsw_exiting;
151 	LIST_ENTRY(pci_vtscsi_worker)		vsw_link;
152 };
153 
154 struct pci_vtscsi_request {
155 	struct pci_vtscsi_queue			*vsr_queue;
156 	struct iovec				*vsr_iov;
157 	struct iovec				*vsr_iov_in;
158 	struct iovec				*vsr_iov_out;
159 	struct iovec				*vsr_data_iov_in;
160 	struct iovec				*vsr_data_iov_out;
161 	struct pci_vtscsi_req_cmd_rd		*vsr_cmd_rd;
162 	struct pci_vtscsi_req_cmd_wr		*vsr_cmd_wr;
163 	void					*vsr_backend;
164 	size_t					vsr_niov_in;
165 	size_t					vsr_niov_out;
166 	size_t					vsr_data_niov_in;
167 	size_t					vsr_data_niov_out;
168 	uint32_t				vsr_idx;
169 	STAILQ_ENTRY(pci_vtscsi_request)	vsr_link;
170 };
171 
172 /*
173  * Per-target state.
174  */
175 struct pci_vtscsi_target {
176 	uint8_t					vst_target;
177 	int					vst_fd;
178 	int					vst_max_sectors;
179 };
180 
181 /*
182  * Per-device softc
183  */
184 struct pci_vtscsi_softc {
185 	struct virtio_softc			vss_vs;
186 	struct virtio_consts			vss_vi_consts;
187 	struct vqueue_info			*vss_vq;
188 	struct pci_vtscsi_queue			*vss_queues;
189 	pthread_mutex_t				vss_mtx;
190 	uint32_t				vss_features;
191 	size_t					vss_num_target;
192 	uint32_t				vss_ctl_ringsz;
193 	uint32_t				vss_evt_ringsz;
194 	uint32_t				vss_req_ringsz;
195 	uint32_t				vss_thr_per_q;
196 	struct pci_vtscsi_config		vss_default_config;
197 	struct pci_vtscsi_config		vss_config;
198 	struct pci_vtscsi_target		*vss_targets;
199 	struct pci_vtscsi_backend		*vss_backend;
200 };
201 
202 /*
203  * VirtIO-SCSI Task Management Function control requests
204  */
205 #define	VIRTIO_SCSI_T_TMF			0
206 #define	VIRTIO_SCSI_T_TMF_ABORT_TASK		0
207 #define	VIRTIO_SCSI_T_TMF_ABORT_TASK_SET	1
208 #define	VIRTIO_SCSI_T_TMF_CLEAR_ACA		2
209 #define	VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET	3
210 #define	VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET	4
211 #define	VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET	5
212 #define	VIRTIO_SCSI_T_TMF_QUERY_TASK		6
213 #define	VIRTIO_SCSI_T_TMF_QUERY_TASK_SET	7
214 
215 #define	VIRTIO_SCSI_T_TMF_MAX_FUNC		VIRTIO_SCSI_T_TMF_QUERY_TASK_SET
216 
217 /* command-specific response values */
218 #define	VIRTIO_SCSI_S_FUNCTION_COMPLETE		0
219 #define	VIRTIO_SCSI_S_FUNCTION_SUCCEEDED	10
220 #define	VIRTIO_SCSI_S_FUNCTION_REJECTED		11
221 
222 struct pci_vtscsi_ctrl_tmf {
223 	const uint32_t	type;
224 	const uint32_t	subtype;
225 	const uint8_t	lun[8];
226 	const uint64_t	id;
227 	uint8_t		response;
228 } __attribute__((packed));
229 
230 
231 /*
232  * VirtIO-SCSI Asynchronous Notification control requests
233  */
234 #define	VIRTIO_SCSI_T_AN_QUERY			1
235 #define	VIRTIO_SCSI_EVT_ASYNC_OPERATIONAL_CHANGE 2
236 #define	VIRTIO_SCSI_EVT_ASYNC_POWER_MGMT	4
237 #define	VIRTIO_SCSI_EVT_ASYNC_EXTERNAL_REQUEST	8
238 #define	VIRTIO_SCSI_EVT_ASYNC_MEDIA_CHANGE	16
239 #define	VIRTIO_SCSI_EVT_ASYNC_MULTI_HOST	32
240 #define	VIRTIO_SCSI_EVT_ASYNC_DEVICE_BUSY	64
241 
242 struct pci_vtscsi_ctrl_an {
243 	const uint32_t	type;
244 	const uint8_t	lun[8];
245 	const uint32_t	event_requested;
246 	uint32_t	event_actual;
247 	uint8_t		response;
248 } __attribute__((packed));
249 
250 /* command-specific response values */
251 #define	VIRTIO_SCSI_S_OK			0
252 #define	VIRTIO_SCSI_S_OVERRUN			1
253 #define	VIRTIO_SCSI_S_ABORTED			2
254 #define	VIRTIO_SCSI_S_BAD_TARGET		3
255 #define	VIRTIO_SCSI_S_RESET			4
256 #define	VIRTIO_SCSI_S_BUSY			5
257 #define	VIRTIO_SCSI_S_TRANSPORT_FAILURE		6
258 #define	VIRTIO_SCSI_S_TARGET_FAILURE		7
259 #define	VIRTIO_SCSI_S_NEXUS_FAILURE		8
260 #define	VIRTIO_SCSI_S_FAILURE			9
261 #define	VIRTIO_SCSI_S_INCORRECT_LUN		12
262 
263 struct pci_vtscsi_event {
264 	uint32_t	event;
265 	uint8_t		lun[8];
266 	uint32_t	reason;
267 } __attribute__((packed));
268 
269 /*
270  * VirtIO-SCSI I/O requests
271  */
272 struct pci_vtscsi_req_cmd_rd {
273 	const uint8_t	lun[8];
274 	const uint64_t	id;
275 	const uint8_t	task_attr;
276 	const uint8_t	prio;
277 	const uint8_t	crn;
278 	const uint8_t	cdb[];
279 } __attribute__((packed));
280 
281 /* task_attr */
282 #define	VIRTIO_SCSI_S_SIMPLE			0
283 #define	VIRTIO_SCSI_S_ORDERED			1
284 #define	VIRTIO_SCSI_S_HEAD			2
285 #define	VIRTIO_SCSI_S_ACA			3
286 
287 struct pci_vtscsi_req_cmd_wr {
288 	uint32_t	sense_len;
289 	uint32_t	residual;
290 	uint16_t	status_qualifier;
291 	uint8_t		status;
292 	uint8_t		response;
293 	uint8_t		sense[];
294 } __attribute__((packed));
295 
296 /*
297  * Backend interface
298  */
299 struct pci_vtscsi_backend {
300 	const char	*vsb_name;
301 	int		(*vsb_init)(struct pci_vtscsi_softc *,
302 			    struct pci_vtscsi_backend *, nvlist_t *);
303 	int		(*vsb_open)(struct pci_vtscsi_softc *, const char *,
304 			    long);
305 	void		(*vsb_reset)(struct pci_vtscsi_softc *);
306 
307 	void*		(*vsb_req_alloc)(struct pci_vtscsi_softc *);
308 	void		(*vsb_req_clear)(void *);
309 	void		(*vsb_req_free)(void *);
310 
311 	void		(*vsb_tmf_hdl)(struct pci_vtscsi_softc *, int,
312 			    struct pci_vtscsi_ctrl_tmf *);
313 	void		(*vsb_an_hdl)(struct pci_vtscsi_softc *, int,
314 			    struct pci_vtscsi_ctrl_an *);
315 	int		(*vsb_req_hdl)(struct pci_vtscsi_softc *, int,
316 			    struct pci_vtscsi_request *);
317 };
318 #define	PCI_VTSCSI_BACKEND_SET(x)	DATA_SET(pci_vtscsi_backend_set, x)
319 
320 /*
321  * LUN address parsing
322  *
323  * The LUN address consists of 8 bytes. While the spec describes this as 0x01,
324  * followed by the target byte, followed by a "single-level LUN structure",
325  * this is actually the same as a hierarchical LUN address as defined by SAM-5,
326  * consisting of four levels of addressing, where in each level the two MSB of
327  * byte 0 select the address mode used in the remaining bits and bytes.
328  *
329  *
330  * Only the first two levels are acutally used by virtio-scsi:
331  *
332  * Level 1: 0x01, 0xTT: Peripheral Device Addressing: Bus 1, Target 0-255
333  * Level 2: 0xLL, 0xLL: Peripheral Device Addressing: Bus MBZ, LUN 0-255
334  *                  or: Flat Space Addressing: LUN (0-16383)
335  * Level 3 and 4: not used, MBZ
336  *
337  *
338  * Alternatively, the first level may contain an extended LUN address to select
339  * the REPORT_LUNS well-known logical unit:
340  *
341  * Level 1: 0xC1, 0x01: Extended LUN Adressing, Well-Known LUN 1 (REPORT_LUNS)
342  * Level 2, 3, and 4: not used, MBZ
343  *
344  * The virtio spec says that we SHOULD implement the REPORT_LUNS well-known
345  * logical unit  but we currently don't.
346  *
347  * According to the virtio spec, these are the only LUNS address formats to be
348  * used with virtio-scsi.
349  */
350 
351 /*
352  * Check that the given LUN address conforms to the virtio spec, does not
353  * address an unknown target, and especially does not address the REPORT_LUNS
354  * well-known logical unit.
355  */
356 static inline bool
pci_vtscsi_check_lun(struct pci_vtscsi_softc * sc,const uint8_t * lun)357 pci_vtscsi_check_lun(struct pci_vtscsi_softc *sc, const uint8_t *lun)
358 {
359 	if (lun[0] == 0xC1)
360 		return (false);
361 
362 	if (lun[0] != 0x01)
363 		return (false);
364 
365 	if (lun[1] >= sc->vss_num_target)
366 		return (false);
367 
368 	if (lun[1] != sc->vss_targets[lun[1]].vst_target)
369 		return (false);
370 
371 	if (sc->vss_targets[lun[1]].vst_fd < 0)
372 		return (false);
373 
374 	if (lun[2] != 0x00 && (lun[2] & 0xc0) != 0x40)
375 		return (false);
376 
377 	if (lun[4] != 0 || lun[5] != 0 || lun[6] != 0 || lun[7] != 0)
378 		return (false);
379 
380 	return (true);
381 }
382 
383 /*
384  * Get the target id from a LUN address.
385  *
386  * Every code path using this function must have called pci_vtscsi_check_lun()
387  * before to make sure the LUN address is valid.
388  */
389 static inline uint8_t
pci_vtscsi_get_target(struct pci_vtscsi_softc * sc,const uint8_t * lun)390 pci_vtscsi_get_target(struct pci_vtscsi_softc *sc, const uint8_t *lun)
391 {
392 	assert(lun[0] == 0x01);
393 	assert(lun[1] < sc->vss_num_target);
394 	assert(lun[1] == sc->vss_targets[lun[1]].vst_target);
395 	assert(sc->vss_targets[lun[1]].vst_fd >= 0);
396 	assert(lun[2] == 0x00 || (lun[2] & 0xc0) == 0x40);
397 
398 	return (lun[1]);
399 }
400 
401 /*
402  * Get the LUN id from a LUN address.
403  *
404  * Every code path using this function must have called pci_vtscsi_check_lun()
405  * before to make sure the LUN address is valid.
406  */
407 static inline uint16_t
pci_vtscsi_get_lun(struct pci_vtscsi_softc * sc,const uint8_t * lun)408 pci_vtscsi_get_lun(struct pci_vtscsi_softc *sc, const uint8_t *lun)
409 {
410 	assert(lun[0] == 0x01);
411 	assert(lun[1] < sc->vss_num_target);
412 	assert(lun[1] == sc->vss_targets[lun[1]].vst_target);
413 	assert(sc->vss_targets[lun[1]].vst_fd >= 0);
414 	assert(lun[2] == 0x00 || (lun[2] & 0xc0) == 0x40);
415 
416 	return (((lun[2] << 8) | lun[3]) & 0x3fff);
417 }
418 
419 #endif	/* _PCI_VIRTIO_SCSI_H_ */
420