Page MenuHomeFreeBSD

D36150.1775735916.diff
No OneTemporary

Size
5 KB
Referenced Files
None
Subscribers
None

D36150.1775735916.diff

diff --git a/sys/dev/virtio/mmio/virtio_mmio.c b/sys/dev/virtio/mmio/virtio_mmio.c
--- a/sys/dev/virtio/mmio/virtio_mmio.c
+++ b/sys/dev/virtio/mmio/virtio_mmio.c
@@ -74,6 +74,7 @@
static int vtmmio_read_ivar(device_t, device_t, int, uintptr_t *);
static int vtmmio_write_ivar(device_t, device_t, int, uintptr_t);
static uint64_t vtmmio_negotiate_features(device_t, uint64_t);
+static int vtmmio_finalize_features(device_t);
static int vtmmio_with_feature(device_t, uint64_t);
static void vtmmio_set_virtqueue(struct vtmmio_softc *sc,
struct virtqueue *vq, uint32_t size);
@@ -85,9 +86,11 @@
static int vtmmio_reinit(device_t, uint64_t);
static void vtmmio_reinit_complete(device_t);
static void vtmmio_notify_virtqueue(device_t, uint16_t, bus_size_t);
+static int vtmmio_config_generation(device_t);
static uint8_t vtmmio_get_status(device_t);
static void vtmmio_set_status(device_t, uint8_t);
static void vtmmio_read_dev_config(device_t, bus_size_t, void *, int);
+static uint64_t vtmmio_read_dev_config_8(struct vtmmio_softc *, bus_size_t);
static void vtmmio_write_dev_config(device_t, bus_size_t, const void *, int);
static void vtmmio_describe_features(struct vtmmio_softc *, const char *,
uint64_t);
@@ -152,6 +155,7 @@
/* VirtIO bus interface. */
DEVMETHOD(virtio_bus_negotiate_features, vtmmio_negotiate_features),
+ DEVMETHOD(virtio_bus_finalize_features, vtmmio_finalize_features),
DEVMETHOD(virtio_bus_with_feature, vtmmio_with_feature),
DEVMETHOD(virtio_bus_alloc_virtqueues, vtmmio_alloc_virtqueues),
DEVMETHOD(virtio_bus_setup_intr, vtmmio_setup_intr),
@@ -160,6 +164,7 @@
DEVMETHOD(virtio_bus_reinit, vtmmio_reinit),
DEVMETHOD(virtio_bus_reinit_complete, vtmmio_reinit_complete),
DEVMETHOD(virtio_bus_notify_vq, vtmmio_notify_virtqueue),
+ DEVMETHOD(virtio_bus_config_generation, vtmmio_config_generation),
DEVMETHOD(virtio_bus_read_device_config, vtmmio_read_dev_config),
DEVMETHOD(virtio_bus_write_device_config, vtmmio_write_dev_config),
@@ -461,6 +466,31 @@
return (features);
}
+static int
+vtmmio_finalize_features(device_t dev)
+{
+ struct vtmmio_softc *sc;
+ uint8_t status;
+
+ sc = device_get_softc(dev);
+
+ if (sc->vtmmio_version > 1) {
+ /*
+ * Must re-read the status after setting it to verify the
+ * negotiated features were accepted by the device.
+ */
+ vtmmio_set_status(dev, VIRTIO_CONFIG_S_FEATURES_OK);
+
+ status = vtmmio_get_status(dev);
+ if ((status & VIRTIO_CONFIG_S_FEATURES_OK) == 0) {
+ device_printf(dev, "desired features were not accepted\n");
+ return (ENOTSUP);
+ }
+ }
+
+ return (0);
+}
+
static int
vtmmio_with_feature(device_t dev, uint64_t feature)
{
@@ -540,8 +570,6 @@
vqx = &sc->vtmmio_vqs[idx];
info = &vq_info[idx];
- vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_SEL, idx);
-
vtmmio_select_virtqueue(sc, idx);
size = vtmmio_read_config_4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX);
@@ -605,7 +633,16 @@
vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_ACK);
vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER);
+ /*
+ * TODO: Check that features are not added as to what was
+ * originally negotiated.
+ */
vtmmio_negotiate_features(dev, features);
+ error = vtmmio_finalize_features(dev);
+ if (error) {
+ device_printf(dev, "cannot finalize features during reinit\n");
+ return (error);
+ }
if (sc->vtmmio_version == 1) {
vtmmio_write_config_4(sc, VIRTIO_MMIO_GUEST_PAGE_SIZE,
@@ -639,6 +676,22 @@
vtmmio_write_config_4(sc, offset, queue);
}
+static int
+vtmmio_config_generation(device_t dev)
+{
+ struct vtmmio_softc *sc;
+ uint32_t gen;
+
+ sc = device_get_softc(dev);
+
+ if (sc->vtmmio_version > 1)
+ gen = vtmmio_read_config_4(sc, VIRTIO_MMIO_CONFIG_GENERATION);
+ else
+ gen = 0;
+
+ return (gen);
+}
+
static uint8_t
vtmmio_get_status(device_t dev)
{
@@ -670,7 +723,6 @@
bus_size_t off;
uint8_t *d;
int size;
- uint64_t low32, high32;
sc = device_get_softc(dev);
off = VIRTIO_MMIO_CONFIG + offset;
@@ -707,9 +759,7 @@
le32toh(vtmmio_read_config_4(sc, off));
break;
case 8:
- low32 = le32toh(vtmmio_read_config_4(sc, off));
- high32 = le32toh(vtmmio_read_config_4(sc, off + 4));
- *(uint64_t *)dst = (high32 << 32) | low32;
+ *(uint64_t *)dst = vtmmio_read_dev_config_8(sc, off);
break;
default:
panic("%s: invalid length %d\n", __func__, length);
@@ -735,6 +785,24 @@
}
}
+static uint64_t
+vtmmio_read_dev_config_8(struct vtmmio_softc *sc, bus_size_t off)
+{
+ device_t dev;
+ int gen;
+ uint32_t val0, val1;
+
+ dev = sc->dev;
+
+ do {
+ gen = vtmmio_config_generation(dev);
+ val0 = le32toh(vtmmio_read_config_4(sc, off));
+ val1 = le32toh(vtmmio_read_config_4(sc, off + 4));
+ } while (gen != vtmmio_config_generation(dev));
+
+ return (((uint64_t) val1 << 32) | val0);
+}
+
static void
vtmmio_write_dev_config(device_t dev, bus_size_t offset,
const void *src, int length)
@@ -888,10 +956,11 @@
vqx = &sc->vtmmio_vqs[idx];
vtmmio_select_virtqueue(sc, idx);
- if (sc->vtmmio_version == 1)
- vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_PFN, 0);
- else
+ if (sc->vtmmio_version > 1) {
vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_READY, 0);
+ vtmmio_read_config_4(sc, VIRTIO_MMIO_QUEUE_READY);
+ } else
+ vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_PFN, 0);
virtqueue_free(vqx->vtv_vq);
vqx->vtv_vq = NULL;

File Metadata

Mime Type
text/plain
Expires
Thu, Apr 9, 11:58 AM (22 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28308952
Default Alt Text
D36150.1775735916.diff (5 KB)

Event Timeline