Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 22 Jun 2019 01:20:45 +0000 (UTC)
From:      Eric van Gyzen <vangyzen@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r349285 - head/sys/dev/virtio/scsi
Message-ID:  <201906220120.x5M1KjVs032914@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: vangyzen
Date: Sat Jun 22 01:20:45 2019
New Revision: 349285
URL: https://svnweb.freebsd.org/changeset/base/349285

Log:
  VirtIO SCSI:  validate seg_max on attach
  
  Until r349278, bhyve presented a seg_max to the guest that was too large.
  Detect this case and clamp it to the virtqueue size.  Otherwise, we would
  fail the "too many segments to enqueue" assertion in virtqueue_enqueue().
  
  I hit this by running a guest with a MAXPHYS of 256 KB.
  
  Reviewed by:	bryanv cem
  MFC after:	1 week
  Sponsored by:	Dell EMC Isilon
  Differential Revision:	https://reviews.freebsd.org/D20703

Modified:
  head/sys/dev/virtio/scsi/virtio_scsi.c

Modified: head/sys/dev/virtio/scsi/virtio_scsi.c
==============================================================================
--- head/sys/dev/virtio/scsi/virtio_scsi.c	Sat Jun 22 01:06:41 2019	(r349284)
+++ head/sys/dev/virtio/scsi/virtio_scsi.c	Sat Jun 22 01:20:45 2019	(r349285)
@@ -81,6 +81,7 @@ static void	vtscsi_read_config(struct vtscsi_softc *,
 		    struct virtio_scsi_config *);
 static int	vtscsi_maximum_segments(struct vtscsi_softc *, int);
 static int	vtscsi_alloc_virtqueues(struct vtscsi_softc *);
+static void	vtscsi_check_sizes(struct vtscsi_softc *);
 static void	vtscsi_write_device_config(struct vtscsi_softc *);
 static int	vtscsi_reinit(struct vtscsi_softc *);
 
@@ -311,6 +312,8 @@ vtscsi_attach(device_t dev)
 		goto fail;
 	}
 
+	vtscsi_check_sizes(sc);
+
 	error = vtscsi_init_event_vq(sc);
 	if (error) {
 		device_printf(dev, "cannot populate the eventvq\n");
@@ -475,6 +478,26 @@ vtscsi_alloc_virtqueues(struct vtscsi_softc *sc)
 	    "%s request", device_get_nameunit(dev));
 
 	return (virtio_alloc_virtqueues(dev, 0, nvqs, vq_info));
+}
+
+static void
+vtscsi_check_sizes(struct vtscsi_softc *sc)
+{
+	int rqsize;
+
+	if ((sc->vtscsi_flags & VTSCSI_FLAG_INDIRECT) == 0) {
+		/*
+		 * Ensure the assertions in virtqueue_enqueue(),
+		 * even if the hypervisor reports a bad seg_max.
+		 */
+		rqsize = virtqueue_size(sc->vtscsi_request_vq);
+		if (sc->vtscsi_max_nsegs > rqsize) {
+			device_printf(sc->vtscsi_dev,
+			    "clamping seg_max (%d %d)\n", sc->vtscsi_max_nsegs,
+			    rqsize);
+			sc->vtscsi_max_nsegs = rqsize;
+		}
+	}
 }
 
 static void



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201906220120.x5M1KjVs032914>