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).

Reviewed by:	rgrimes, Patrick Mooney <pmooney@pfmooney.com>
Obtained from:	Joyent (Linux workaround)
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D18831
This commit is contained in:
John Baldwin 2019-05-02 22:46:37 +00:00
parent 05a179e83e
commit 8c74ade848
3 changed files with 21 additions and 4 deletions

View File

@ -65,7 +65,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,

View File

@ -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;

View File

@ -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,7 +56,9 @@ __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
@ -351,7 +354,15 @@ pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
/* 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;