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;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to