Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d761b032 authored by Rusty Russell's avatar Rusty Russell
Browse files

tools/lguest: don't start devices until DRIVER_OK status set.



We were activating them with the virtqueues, and that's not allowed.

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 3afe3e0f
Loading
Loading
Loading
Loading
+36 −8
Original line number Original line Diff line number Diff line
@@ -1688,16 +1688,15 @@ static void restore_vq_config(struct virtio_pci_common_cfg *cfg,
}
}


/*
/*
 * 4.1.4.3.2:
 *
 *  The driver MUST configure the other virtqueue fields before
 *  enabling the virtqueue with queue_enable.
 *
 * When they enable the virtqueue, we check that their setup is valid.
 * When they enable the virtqueue, we check that their setup is valid.
 */
 */
static void enable_virtqueue(struct device *d, struct virtqueue *vq)
static void check_virtqueue(struct device *d, struct virtqueue *vq)
{
{
	/*
	 * Create stack for thread.  Since the stack grows upwards, we point
	 * the stack pointer to the end of this region.
	 */
	char *stack = malloc(32768);

	/* Because lguest is 32 bit, all the descriptor high bits must be 0 */
	/* Because lguest is 32 bit, all the descriptor high bits must be 0 */
	if (vq->pci_config.queue_desc_hi
	if (vq->pci_config.queue_desc_hi
	    || vq->pci_config.queue_avail_hi
	    || vq->pci_config.queue_avail_hi
@@ -1716,7 +1715,15 @@ static void enable_virtqueue(struct device *d, struct virtqueue *vq)
				       sizeof(*vq->vring.used)
				       sizeof(*vq->vring.used)
				       + (sizeof(vq->vring.used->ring[0])
				       + (sizeof(vq->vring.used->ring[0])
					  * vq->vring.num));
					  * vq->vring.num));
}


static void start_virtqueue(struct virtqueue *vq)
{
	/*
	 * Create stack for thread.  Since the stack grows upwards, we point
	 * the stack pointer to the end of this region.
	 */
	char *stack = malloc(32768);


	/* Create a zero-initialized eventfd. */
	/* Create a zero-initialized eventfd. */
	vq->eventfd = eventfd(0, 0);
	vq->eventfd = eventfd(0, 0);
@@ -1732,6 +1739,16 @@ static void enable_virtqueue(struct device *d, struct virtqueue *vq)
		err(1, "Creating clone");
		err(1, "Creating clone");
}
}


static void start_virtqueues(struct device *d)
{
	struct virtqueue *vq;

	for (vq = d->vq; vq; vq = vq->next) {
		if (vq->pci_config.queue_enable)
			start_virtqueue(vq);
	}
}

static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask)
static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask)
{
{
	struct virtqueue *vq;
	struct virtqueue *vq;
@@ -1780,6 +1797,17 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask)
		 */
		 */
		if (val == 0)
		if (val == 0)
			reset_device(d);
			reset_device(d);

		/*
		 * 2.1.2:
		 *
		 *  The device MUST NOT consume buffers or notify the driver
		 *  before DRIVER_OK.
		 */
		if (val & VIRTIO_CONFIG_S_DRIVER_OK
		    && !(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER_OK))
			start_virtqueues(d);

		goto write_through8;
		goto write_through8;
	case offsetof(struct virtio_pci_mmio, cfg.queue_select):
	case offsetof(struct virtio_pci_mmio, cfg.queue_select):
		vq = vq_by_num(d, val);
		vq = vq_by_num(d, val);
@@ -1833,7 +1861,7 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask)
		 *  The driver MUST configure the other virtqueue fields before
		 *  The driver MUST configure the other virtqueue fields before
		 *  enabling the virtqueue with queue_enable.
		 *  enabling the virtqueue with queue_enable.
		 */
		 */
		enable_virtqueue(d, vq_by_num(d, d->mmio->cfg.queue_select));
		check_virtqueue(d, vq_by_num(d, d->mmio->cfg.queue_select));
		goto write_through16;
		goto write_through16;
	case offsetof(struct virtio_pci_mmio, cfg.queue_notify_off):
	case offsetof(struct virtio_pci_mmio, cfg.queue_notify_off):
		errx(1, "%s: attempt to write to queue_notify_off", d->name);
		errx(1, "%s: attempt to write to queue_notify_off", d->name);