Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 29 May 2019 23:05:27 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r348374 - stable/12/usr.sbin/bhyve
Message-ID:  <201905292305.x4TN5R5b014057@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Wed May 29 23:05:26 2019
New Revision: 348374
URL: https://svnweb.freebsd.org/changeset/base/348374

Log:
  MFC 347033:
  Increase the VirtIO segment count to support modern Windows guests.
  
  The Windows virtio driver ignores the advertized seg_max field and
  assumes the host can accept up to 67 segments in indirect descriptors,
  triggering an assert in the bhyve process.
  
  This brings back r282922 but with a couple of changes:
  - It raises the block interface segment limit to 128 instead of 67.
  - Linux's virtio driver assumes that the segment limit is no
    larger than the ring size.  To avoid breaking Linux guests,
    raise the VirtIO ring size to 128, and cap the VirtIO segment
    limit at ring size - 2 (effectively 126).

Modified:
  stable/12/usr.sbin/bhyve/block_if.c
  stable/12/usr.sbin/bhyve/block_if.h
  stable/12/usr.sbin/bhyve/pci_virtio_block.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/usr.sbin/bhyve/block_if.c
==============================================================================
--- stable/12/usr.sbin/bhyve/block_if.c	Wed May 29 22:33:37 2019	(r348373)
+++ stable/12/usr.sbin/bhyve/block_if.c	Wed May 29 23:05:26 2019	(r348374)
@@ -62,7 +62,7 @@ __FBSDID("$FreeBSD$");
 #define BLOCKIF_SIG	0xb109b109
 
 #define BLOCKIF_NUMTHR	8
-#define BLOCKIF_MAXREQ	(64 + BLOCKIF_NUMTHR)
+#define BLOCKIF_MAXREQ	(BLOCKIF_RING_MAX + BLOCKIF_NUMTHR)
 
 enum blockop {
 	BOP_READ,

Modified: stable/12/usr.sbin/bhyve/block_if.h
==============================================================================
--- stable/12/usr.sbin/bhyve/block_if.h	Wed May 29 22:33:37 2019	(r348373)
+++ stable/12/usr.sbin/bhyve/block_if.h	Wed May 29 23:05:26 2019	(r348374)
@@ -41,7 +41,13 @@
 #include <sys/uio.h>
 #include <sys/unistd.h>
 
-#define BLOCKIF_IOV_MAX		33	/* not practical to be IOV_MAX */
+/*
+ * BLOCKIF_IOV_MAX is the maximum number of scatter/gather entries in
+ * a single request.  BLOCKIF_RING_MAX is the maxmimum number of
+ * pending requests that can be queued.
+ */
+#define	BLOCKIF_IOV_MAX		128	/* not practical to be IOV_MAX */
+#define	BLOCKIF_RING_MAX	128
 
 struct blockif_req {
 	int		br_iovcnt;

Modified: stable/12/usr.sbin/bhyve/pci_virtio_block.c
==============================================================================
--- stable/12/usr.sbin/bhyve/pci_virtio_block.c	Wed May 29 22:33:37 2019	(r348373)
+++ stable/12/usr.sbin/bhyve/pci_virtio_block.c	Wed May 29 23:05:26 2019	(r348374)
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2011 NetApp, Inc.
  * All rights reserved.
+ * Copyright (c) 2019 Joyent, Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -55,8 +56,10 @@ __FBSDID("$FreeBSD$");
 #include "virtio.h"
 #include "block_if.h"
 
-#define VTBLK_RINGSZ	64
+#define VTBLK_RINGSZ	128
 
+_Static_assert(VTBLK_RINGSZ <= BLOCKIF_RING_MAX, "Each ring entry must be able to queue a request");
+
 #define VTBLK_S_OK	0
 #define VTBLK_S_IOERR	1
 #define	VTBLK_S_UNSUPP	2
@@ -351,7 +354,15 @@ pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *
 	/* setup virtio block config space */
 	sc->vbsc_cfg.vbc_capacity = size / DEV_BSIZE; /* 512-byte units */
 	sc->vbsc_cfg.vbc_size_max = 0;	/* not negotiated */
-	sc->vbsc_cfg.vbc_seg_max = BLOCKIF_IOV_MAX;
+
+	/*
+	 * If Linux is presented with a seg_max greater than the virtio queue
+	 * size, it can stumble into situations where it violates its own
+	 * invariants and panics.  For safety, we keep seg_max clamped, paying
+	 * heed to the two extra descriptors needed for the header and status
+	 * of a request.
+	 */
+	sc->vbsc_cfg.vbc_seg_max = MIN(VTBLK_RINGSZ - 2, BLOCKIF_IOV_MAX);
 	sc->vbsc_cfg.vbc_geometry.cylinders = 0;	/* no geometry */
 	sc->vbsc_cfg.vbc_geometry.heads = 0;
 	sc->vbsc_cfg.vbc_geometry.sectors = 0;



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