xref: /openbsd-src/sys/dev/pv/vioscsi.c (revision fc405d53b73a2d73393cb97f684863d17b583e38)
1 /*	$OpenBSD: vioscsi.c,v 1.31 2023/04/27 13:52:58 krw Exp $	*/
2 /*
3  * Copyright (c) 2013 Google Inc.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/mutex.h>
22 
23 #include <machine/bus.h>
24 #include <machine/intr.h>
25 
26 #include <dev/pv/vioscsireg.h>
27 #include <dev/pv/virtiovar.h>
28 
29 #include <scsi/scsi_all.h>
30 #include <scsi/scsiconf.h>
31 
32 enum { vioscsi_debug = 0 };
33 #define DPRINTF(f...) do { if (vioscsi_debug) printf(f); } while (0)
34 
35 /* Number of DMA segments for buffers that the device must support */
36 #define SEG_MAX		(MAXPHYS/PAGE_SIZE + 1)
37 /* In the virtqueue, we need space for header and footer, too */
38 #define ALLOC_SEGS	(SEG_MAX + 2)
39 
40 struct vioscsi_req {
41 	struct virtio_scsi_req_hdr	 vr_req;
42 	struct virtio_scsi_res_hdr	 vr_res;
43 	struct scsi_xfer		*vr_xs;
44 	bus_dmamap_t			 vr_control;
45 	bus_dmamap_t			 vr_data;
46 	SLIST_ENTRY(vioscsi_req)	 vr_list;
47 	int				 vr_qe_index;
48 };
49 
50 struct vioscsi_softc {
51 	struct device		 sc_dev;
52 	struct scsi_iopool	 sc_iopool;
53 	struct mutex		 sc_vr_mtx;
54 
55 	struct virtqueue	 sc_vqs[3];
56 	struct vioscsi_req	*sc_reqs;
57 	bus_dma_segment_t        sc_reqs_segs[1];
58 	SLIST_HEAD(, vioscsi_req) sc_freelist;
59 };
60 
61 int		 vioscsi_match(struct device *, void *, void *);
62 void		 vioscsi_attach(struct device *, struct device *, void *);
63 
64 int		 vioscsi_alloc_reqs(struct vioscsi_softc *,
65 		    struct virtio_softc *, int);
66 void		 vioscsi_scsi_cmd(struct scsi_xfer *);
67 int		 vioscsi_vq_done(struct virtqueue *);
68 void		 vioscsi_req_done(struct vioscsi_softc *, struct virtio_softc *,
69 		    struct vioscsi_req *);
70 void		*vioscsi_req_get(void *);
71 void		 vioscsi_req_put(void *, void *);
72 
73 const struct cfattach vioscsi_ca = {
74 	sizeof(struct vioscsi_softc),
75 	vioscsi_match,
76 	vioscsi_attach,
77 };
78 
79 struct cfdriver vioscsi_cd = {
80 	NULL, "vioscsi", DV_DULL,
81 };
82 
83 const struct scsi_adapter vioscsi_switch = {
84 	vioscsi_scsi_cmd, NULL, NULL, NULL, NULL
85 };
86 
87 const char *const vioscsi_vq_names[] = {
88 	"control",
89 	"event",
90 	"request",
91 };
92 
93 int
94 vioscsi_match(struct device *parent, void *self, void *aux)
95 {
96 	struct virtio_softc *va = (struct virtio_softc *)aux;
97 
98 	if (va->sc_childdevid == PCI_PRODUCT_VIRTIO_SCSI)
99 		return (1);
100 	return (0);
101 }
102 
103 void
104 vioscsi_attach(struct device *parent, struct device *self, void *aux)
105 {
106 	struct virtio_softc *vsc = (struct virtio_softc *)parent;
107 	struct vioscsi_softc *sc = (struct vioscsi_softc *)self;
108 	struct scsibus_attach_args saa;
109 	int i, rv;
110 
111 	if (vsc->sc_child != NULL) {
112 		printf(": parent already has a child\n");
113 		return;
114 	}
115 	vsc->sc_child = &sc->sc_dev;
116 	vsc->sc_ipl = IPL_BIO;
117 
118 	// TODO(matthew): Negotiate hotplug.
119 
120 	vsc->sc_vqs = sc->sc_vqs;
121 	vsc->sc_nvqs = nitems(sc->sc_vqs);
122 
123 	virtio_negotiate_features(vsc, NULL);
124 	uint32_t cmd_per_lun = virtio_read_device_config_4(vsc,
125 	    VIRTIO_SCSI_CONFIG_CMD_PER_LUN);
126 	uint32_t seg_max = virtio_read_device_config_4(vsc,
127 	    VIRTIO_SCSI_CONFIG_SEG_MAX);
128 	uint16_t max_target = virtio_read_device_config_2(vsc,
129 	    VIRTIO_SCSI_CONFIG_MAX_TARGET);
130 
131 	if (seg_max < SEG_MAX) {
132 		printf("\nMax number of segments %d too small\n", seg_max);
133 		goto err;
134 	}
135 
136 	for (i = 0; i < nitems(sc->sc_vqs); i++) {
137 		rv = virtio_alloc_vq(vsc, &sc->sc_vqs[i], i, MAXPHYS,
138 		    ALLOC_SEGS, vioscsi_vq_names[i]);
139 		if (rv) {
140 			printf(": failed to allocate virtqueue %d\n", i);
141 			goto err;
142 		}
143 		sc->sc_vqs[i].vq_done = vioscsi_vq_done;
144 	}
145 
146 	int qsize = sc->sc_vqs[2].vq_num;
147 	printf(": qsize %d\n", qsize);
148 
149 	SLIST_INIT(&sc->sc_freelist);
150 	mtx_init(&sc->sc_vr_mtx, IPL_BIO);
151 	scsi_iopool_init(&sc->sc_iopool, sc, vioscsi_req_get, vioscsi_req_put);
152 
153 	int nreqs = vioscsi_alloc_reqs(sc, vsc, qsize);
154 	if (nreqs == 0) {
155 		printf("\nCan't alloc reqs\n");
156 		goto err;
157 	}
158 
159 	saa.saa_adapter = &vioscsi_switch;
160 	saa.saa_adapter_softc = sc;
161 	saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET;
162 	saa.saa_adapter_buswidth = max_target;
163 	saa.saa_luns = 8;
164 	saa.saa_openings = (nreqs > cmd_per_lun) ? cmd_per_lun : nreqs;
165 	saa.saa_pool = &sc->sc_iopool;
166 	saa.saa_quirks = saa.saa_flags = 0;
167 	saa.saa_wwpn = saa.saa_wwnn = 0;
168 
169 	config_found(self, &saa, scsiprint);
170 	return;
171 
172 err:
173 	vsc->sc_child = VIRTIO_CHILD_ERROR;
174 	return;
175 }
176 
177 void
178 vioscsi_scsi_cmd(struct scsi_xfer *xs)
179 {
180 	struct vioscsi_softc *sc = xs->sc_link->bus->sb_adapter_softc;
181 	struct virtio_softc *vsc = (struct virtio_softc *)sc->sc_dev.dv_parent;
182 	struct vioscsi_req *vr = xs->io;
183 	struct virtio_scsi_req_hdr *req = &vr->vr_req;
184 	struct virtqueue *vq = &sc->sc_vqs[2];
185 	int slot = vr->vr_qe_index;
186 
187 	DPRINTF("vioscsi_scsi_cmd: enter\n");
188 
189 	// TODO(matthew): Support bidirectional SCSI commands?
190 	if ((xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT))
191 	    == (SCSI_DATA_IN | SCSI_DATA_OUT)) {
192 		goto stuffup;
193 	}
194 
195 	vr->vr_xs = xs;
196 
197 	/*
198 	 * "The only supported format for the LUN field is: first byte set to
199 	 * 1, second byte set to target, third and fourth byte representing a
200 	 * single level LUN structure, followed by four zero bytes."
201 	 */
202 	if (xs->sc_link->target >= 256 || xs->sc_link->lun >= 16384)
203 		goto stuffup;
204 	req->lun[0] = 1;
205 	req->lun[1] = xs->sc_link->target;
206 	req->lun[2] = 0x40 | (xs->sc_link->lun >> 8);
207 	req->lun[3] = xs->sc_link->lun;
208 	memset(req->lun + 4, 0, 4);
209 
210 	if ((size_t)xs->cmdlen > sizeof(req->cdb))
211 		goto stuffup;
212 	memset(req->cdb, 0, sizeof(req->cdb));
213 	memcpy(req->cdb, &xs->cmd, xs->cmdlen);
214 
215 	int isread = !!(xs->flags & SCSI_DATA_IN);
216 
217 	int nsegs = 2;
218 	if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
219 		if (bus_dmamap_load(vsc->sc_dmat, vr->vr_data,
220 		    xs->data, xs->datalen, NULL,
221 		    ((isread ? BUS_DMA_READ : BUS_DMA_WRITE) |
222 		     BUS_DMA_NOWAIT)))
223 			goto stuffup;
224 		nsegs += vr->vr_data->dm_nsegs;
225 	}
226 
227 	/*
228 	 * Adjust reservation to the number needed, or virtio gets upset. Note
229 	 * that it may trim UP if 'xs' is being recycled w/o getting a new
230 	 * reservation!
231 	 */
232 	int s = splbio();
233 	virtio_enqueue_trim(vq, slot, nsegs);
234 	splx(s);
235 
236 	bus_dmamap_sync(vsc->sc_dmat, vr->vr_control,
237 	    offsetof(struct vioscsi_req, vr_req),
238 	    sizeof(struct virtio_scsi_req_hdr),
239 	    BUS_DMASYNC_PREWRITE);
240 	bus_dmamap_sync(vsc->sc_dmat, vr->vr_control,
241 	    offsetof(struct vioscsi_req, vr_res),
242             sizeof(struct virtio_scsi_res_hdr),
243 	    BUS_DMASYNC_PREREAD);
244 	if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT))
245 		bus_dmamap_sync(vsc->sc_dmat, vr->vr_data, 0, xs->datalen,
246 		    isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
247 
248 	s = splbio();
249 	virtio_enqueue_p(vq, slot, vr->vr_control,
250 	    offsetof(struct vioscsi_req, vr_req),
251             sizeof(struct virtio_scsi_req_hdr),
252 	    1);
253 	if (xs->flags & SCSI_DATA_OUT)
254 		virtio_enqueue(vq, slot, vr->vr_data, 1);
255 	virtio_enqueue_p(vq, slot, vr->vr_control,
256 	    offsetof(struct vioscsi_req, vr_res),
257             sizeof(struct virtio_scsi_res_hdr),
258 	    0);
259 	if (xs->flags & SCSI_DATA_IN)
260 		virtio_enqueue(vq, slot, vr->vr_data, 0);
261 
262 	virtio_enqueue_commit(vsc, vq, slot, 1);
263 
264 	if (ISSET(xs->flags, SCSI_POLL)) {
265 		DPRINTF("vioscsi_scsi_cmd: polling...\n");
266 		int timeout = 1000;
267 		do {
268 			virtio_poll_intr(vsc);
269 			if (vr->vr_xs != xs)
270 				break;
271 			delay(1000);
272 		} while (--timeout > 0);
273 		if (vr->vr_xs == xs) {
274 			// TODO(matthew): Abort the request.
275 			xs->error = XS_TIMEOUT;
276 			xs->resid = xs->datalen;
277 			DPRINTF("vioscsi_scsi_cmd: polling timeout\n");
278 			scsi_done(xs);
279 		}
280 		DPRINTF("vioscsi_scsi_cmd: done (timeout=%d)\n", timeout);
281 	}
282 	splx(s);
283 	return;
284 
285 stuffup:
286 	xs->error = XS_DRIVER_STUFFUP;
287 	xs->resid = xs->datalen;
288 	DPRINTF("vioscsi_scsi_cmd: stuffup\n");
289 	scsi_done(xs);
290 }
291 
292 void
293 vioscsi_req_done(struct vioscsi_softc *sc, struct virtio_softc *vsc,
294     struct vioscsi_req *vr)
295 {
296 	struct scsi_xfer *xs = vr->vr_xs;
297 	DPRINTF("vioscsi_req_done: enter vr: %p xs: %p\n", vr, xs);
298 
299 	bus_dmamap_sync(vsc->sc_dmat, vr->vr_control,
300 	    offsetof(struct vioscsi_req, vr_req),
301 	    sizeof(struct virtio_scsi_req_hdr),
302 	    BUS_DMASYNC_POSTWRITE);
303 	bus_dmamap_sync(vsc->sc_dmat, vr->vr_control,
304 	    offsetof(struct vioscsi_req, vr_res),
305 	    sizeof(struct virtio_scsi_res_hdr),
306 	    BUS_DMASYNC_POSTREAD);
307 
308 	/*
309 	 * XXX Should be impossible but somehow happens on Oracle Cloud and
310 	 *     particular QEMU configurations.
311 	 *
312 	 *     Stop the crashing while investigation into
313 	 *     the apparent queuing/dequeuing issue proceeds.
314 	 */
315 	if (xs == NULL)
316 		return;
317 
318 	int isread = !!(xs->flags & SCSI_DATA_IN);
319 	if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
320 		bus_dmamap_sync(vsc->sc_dmat, vr->vr_data, 0, xs->datalen,
321 		    isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
322 		bus_dmamap_unload(vsc->sc_dmat, vr->vr_data);
323 	}
324 
325 	if (vr->vr_res.response != VIRTIO_SCSI_S_OK) {
326 		xs->error = XS_DRIVER_STUFFUP;
327 		xs->resid = xs->datalen;
328 		DPRINTF("vioscsi_req_done: stuffup: %d\n", vr->vr_res.response);
329 		goto done;
330 	}
331 
332 	size_t sense_len = MIN(sizeof(xs->sense), vr->vr_res.sense_len);
333 	memcpy(&xs->sense, vr->vr_res.sense, sense_len);
334 	xs->error = (sense_len == 0) ? XS_NOERROR : XS_SENSE;
335 
336 	xs->status = vr->vr_res.status;
337 	xs->resid = vr->vr_res.residual;
338 
339 	DPRINTF("vioscsi_req_done: done %d, %d, %zd\n",
340 	    xs->error, xs->status, xs->resid);
341 
342 done:
343 	vr->vr_xs = NULL;
344 	scsi_done(xs);
345 }
346 
347 int
348 vioscsi_vq_done(struct virtqueue *vq)
349 {
350 	struct virtio_softc *vsc = vq->vq_owner;
351 	struct vioscsi_softc *sc = (struct vioscsi_softc *)vsc->sc_child;
352 	struct vq_entry *qe;
353 	struct vioscsi_req *vr;
354 	int ret = 0;
355 
356 	DPRINTF("vioscsi_vq_done: enter\n");
357 
358 	for (;;) {
359 		int r, s, slot;
360 		s = splbio();
361 		r = virtio_dequeue(vsc, vq, &slot, NULL);
362 		splx(s);
363 		if (r != 0)
364 			break;
365 
366 		DPRINTF("vioscsi_vq_done: slot=%d\n", slot);
367 		qe = &vq->vq_entries[slot];
368 		vr = &sc->sc_reqs[qe->qe_vr_index];
369 		vioscsi_req_done(sc, vsc, vr);
370 		ret = 1;
371 	}
372 
373 	DPRINTF("vioscsi_vq_done: exit %d\n", ret);
374 
375 	return (ret);
376 }
377 
378 /*
379  * vioscso_req_get() provides the SCSI layer with all the
380  * resources necessary to start an I/O on the device.
381  *
382  * Since the size of the I/O is unknown at this time the
383  * resources allocated (a.k.a. reserved) must be sufficient
384  * to allow the maximum possible I/O size.
385  *
386  * When the I/O is actually attempted via vioscsi_scsi_cmd()
387  * excess resources will be returned via virtio_enqueue_trim().
388  */
389 void *
390 vioscsi_req_get(void *cookie)
391 {
392 	struct vioscsi_softc *sc = cookie;
393 	struct vioscsi_req *vr = NULL;
394 
395 	mtx_enter(&sc->sc_vr_mtx);
396 	vr = SLIST_FIRST(&sc->sc_freelist);
397 	if (vr != NULL)
398 		SLIST_REMOVE_HEAD(&sc->sc_freelist, vr_list);
399 	mtx_leave(&sc->sc_vr_mtx);
400 
401 	DPRINTF("vioscsi_req_get: %p\n", vr);
402 
403 	return (vr);
404 }
405 
406 void
407 vioscsi_req_put(void *cookie, void *io)
408 {
409 	struct vioscsi_softc *sc = cookie;
410 	struct vioscsi_req *vr = io;
411 
412 	DPRINTF("vioscsi_req_put: %p\n", vr);
413 
414 	mtx_enter(&sc->sc_vr_mtx);
415 	/*
416 	 * Do *NOT* call virtio_dequeue_commit()!
417 	 *
418 	 * Descriptors are permanently associated with the vioscsi_req and
419 	 * should not be placed on the free list!
420 	 */
421 	SLIST_INSERT_HEAD(&sc->sc_freelist, vr, vr_list);
422 	mtx_leave(&sc->sc_vr_mtx);
423 }
424 
425 int
426 vioscsi_alloc_reqs(struct vioscsi_softc *sc, struct virtio_softc *vsc,
427     int qsize)
428 {
429 	struct virtqueue *vq = &sc->sc_vqs[2];
430 	struct vioscsi_req *vr;
431 	struct vring_desc *vd;
432 	size_t allocsize;
433 	int i, r, nreqs, rsegs, slot;
434 	void *vaddr;
435 
436 	if (vq->vq_indirect != NULL)
437 		nreqs = qsize;
438 	else
439 		nreqs = qsize / ALLOC_SEGS;
440 
441 	allocsize = nreqs * sizeof(struct vioscsi_req);
442 	r = bus_dmamem_alloc(vsc->sc_dmat, allocsize, 0, 0,
443 	    &sc->sc_reqs_segs[0], 1, &rsegs, BUS_DMA_NOWAIT);
444 	if (r != 0) {
445 		printf("bus_dmamem_alloc, size %zd, error %d\n",
446 		    allocsize, r);
447 		return 0;
448 	}
449 	r = bus_dmamem_map(vsc->sc_dmat, &sc->sc_reqs_segs[0], 1,
450 	    allocsize, (caddr_t *)&vaddr, BUS_DMA_NOWAIT);
451 	if (r != 0) {
452 		printf("bus_dmamem_map failed, error %d\n", r);
453 		bus_dmamem_free(vsc->sc_dmat, &sc->sc_reqs_segs[0], 1);
454 		return 0;
455 	}
456 	sc->sc_reqs = vaddr;
457 	memset(vaddr, 0, allocsize);
458 
459 	for (i = 0; i < nreqs; i++) {
460 		/*
461 		 * Assign descriptors and create the DMA maps for each
462 		 * allocated request.
463 		 */
464 		vr = &sc->sc_reqs[i];
465 		r = virtio_enqueue_prep(vq, &slot);
466 		if (r == 0)
467 			r = virtio_enqueue_reserve(vq, slot, ALLOC_SEGS);
468 		if (r != 0)
469 			return i;
470 
471 		if (vq->vq_indirect == NULL) {
472 			/*
473 			 * The reserved slots must be a contiguous block
474 			 * starting at vq_desc[slot].
475 			 */
476 			vd = &vq->vq_desc[slot];
477 			for (r = 0; r < ALLOC_SEGS - 1; r++) {
478 				DPRINTF("vd[%d].next = %d should be %d\n",
479 				    r, vd[r].next, (slot + r + 1));
480 				if (vd[r].next != (slot + r + 1))
481 					return i;
482 			}
483 			if (r == (ALLOC_SEGS -1) && vd[r].next != 0)
484 				return i;
485 			DPRINTF("Reserved slots are contiguous as required!\n");
486 		}
487 
488 		vr->vr_qe_index = slot;
489 		vr->vr_req.id = slot;
490 		vr->vr_req.task_attr = VIRTIO_SCSI_S_SIMPLE;
491 		vq->vq_entries[slot].qe_vr_index = i;
492 
493 		r = bus_dmamap_create(vsc->sc_dmat,
494 		    offsetof(struct vioscsi_req, vr_xs), 1,
495 		    offsetof(struct vioscsi_req, vr_xs), 0,
496 		    BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vr->vr_control);
497 		if (r != 0) {
498 			printf("bus_dmamap_create vr_control failed, error  %d\n", r);
499 			return i;
500 		}
501 		r = bus_dmamap_create(vsc->sc_dmat, MAXPHYS, SEG_MAX,
502 		    MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vr->vr_data);
503 		if (r != 0) {
504 			printf("bus_dmamap_create vr_data failed, error %d\n", r );
505 			return i;
506 		}
507 		r = bus_dmamap_load(vsc->sc_dmat, vr->vr_control,
508 		    vr, offsetof(struct vioscsi_req, vr_xs), NULL,
509 		    BUS_DMA_NOWAIT);
510 		if (r != 0) {
511 			printf("bus_dmamap_load vr_control failed, error %d\n", r );
512 			return i;
513 		}
514 
515 		SLIST_INSERT_HEAD(&sc->sc_freelist, vr, vr_list);
516 	}
517 
518 	return nreqs;
519 }
520