diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2015-02-13 01:43:42 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2015-02-13 01:45:51 -0500 |
commit | d761b0329108c73020a7c95b6fa0d7e82e35fe8b (patch) | |
tree | 2abab56c0ee04256082f4c171f8d01b1f2393604 /tools | |
parent | 3afe3e0f8db10a41a5923e1d7498318877473f33 (diff) |
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: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/lguest/lguest.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index 990671e61f87..4c7c2aa66c89 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c | |||
@@ -1688,16 +1688,15 @@ static void restore_vq_config(struct virtio_pci_common_cfg *cfg, | |||
1688 | } | 1688 | } |
1689 | 1689 | ||
1690 | /* | 1690 | /* |
1691 | * 4.1.4.3.2: | ||
1692 | * | ||
1693 | * The driver MUST configure the other virtqueue fields before | ||
1694 | * enabling the virtqueue with queue_enable. | ||
1695 | * | ||
1691 | * When they enable the virtqueue, we check that their setup is valid. | 1696 | * When they enable the virtqueue, we check that their setup is valid. |
1692 | */ | 1697 | */ |
1693 | static void enable_virtqueue(struct device *d, struct virtqueue *vq) | 1698 | static void check_virtqueue(struct device *d, struct virtqueue *vq) |
1694 | { | 1699 | { |
1695 | /* | ||
1696 | * Create stack for thread. Since the stack grows upwards, we point | ||
1697 | * the stack pointer to the end of this region. | ||
1698 | */ | ||
1699 | char *stack = malloc(32768); | ||
1700 | |||
1701 | /* Because lguest is 32 bit, all the descriptor high bits must be 0 */ | 1700 | /* Because lguest is 32 bit, all the descriptor high bits must be 0 */ |
1702 | if (vq->pci_config.queue_desc_hi | 1701 | if (vq->pci_config.queue_desc_hi |
1703 | || vq->pci_config.queue_avail_hi | 1702 | || vq->pci_config.queue_avail_hi |
@@ -1716,7 +1715,15 @@ static void enable_virtqueue(struct device *d, struct virtqueue *vq) | |||
1716 | sizeof(*vq->vring.used) | 1715 | sizeof(*vq->vring.used) |
1717 | + (sizeof(vq->vring.used->ring[0]) | 1716 | + (sizeof(vq->vring.used->ring[0]) |
1718 | * vq->vring.num)); | 1717 | * vq->vring.num)); |
1718 | } | ||
1719 | 1719 | ||
1720 | static void start_virtqueue(struct virtqueue *vq) | ||
1721 | { | ||
1722 | /* | ||
1723 | * Create stack for thread. Since the stack grows upwards, we point | ||
1724 | * the stack pointer to the end of this region. | ||
1725 | */ | ||
1726 | char *stack = malloc(32768); | ||
1720 | 1727 | ||
1721 | /* Create a zero-initialized eventfd. */ | 1728 | /* Create a zero-initialized eventfd. */ |
1722 | vq->eventfd = eventfd(0, 0); | 1729 | vq->eventfd = eventfd(0, 0); |
@@ -1732,6 +1739,16 @@ static void enable_virtqueue(struct device *d, struct virtqueue *vq) | |||
1732 | err(1, "Creating clone"); | 1739 | err(1, "Creating clone"); |
1733 | } | 1740 | } |
1734 | 1741 | ||
1742 | static void start_virtqueues(struct device *d) | ||
1743 | { | ||
1744 | struct virtqueue *vq; | ||
1745 | |||
1746 | for (vq = d->vq; vq; vq = vq->next) { | ||
1747 | if (vq->pci_config.queue_enable) | ||
1748 | start_virtqueue(vq); | ||
1749 | } | ||
1750 | } | ||
1751 | |||
1735 | static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) | 1752 | static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) |
1736 | { | 1753 | { |
1737 | struct virtqueue *vq; | 1754 | struct virtqueue *vq; |
@@ -1780,6 +1797,17 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) | |||
1780 | */ | 1797 | */ |
1781 | if (val == 0) | 1798 | if (val == 0) |
1782 | reset_device(d); | 1799 | reset_device(d); |
1800 | |||
1801 | /* | ||
1802 | * 2.1.2: | ||
1803 | * | ||
1804 | * The device MUST NOT consume buffers or notify the driver | ||
1805 | * before DRIVER_OK. | ||
1806 | */ | ||
1807 | if (val & VIRTIO_CONFIG_S_DRIVER_OK | ||
1808 | && !(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER_OK)) | ||
1809 | start_virtqueues(d); | ||
1810 | |||
1783 | goto write_through8; | 1811 | goto write_through8; |
1784 | case offsetof(struct virtio_pci_mmio, cfg.queue_select): | 1812 | case offsetof(struct virtio_pci_mmio, cfg.queue_select): |
1785 | vq = vq_by_num(d, val); | 1813 | vq = vq_by_num(d, val); |
@@ -1833,7 +1861,7 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) | |||
1833 | * The driver MUST configure the other virtqueue fields before | 1861 | * The driver MUST configure the other virtqueue fields before |
1834 | * enabling the virtqueue with queue_enable. | 1862 | * enabling the virtqueue with queue_enable. |
1835 | */ | 1863 | */ |
1836 | enable_virtqueue(d, vq_by_num(d, d->mmio->cfg.queue_select)); | 1864 | check_virtqueue(d, vq_by_num(d, d->mmio->cfg.queue_select)); |
1837 | goto write_through16; | 1865 | goto write_through16; |
1838 | case offsetof(struct virtio_pci_mmio, cfg.queue_notify_off): | 1866 | case offsetof(struct virtio_pci_mmio, cfg.queue_notify_off): |
1839 | errx(1, "%s: attempt to write to queue_notify_off", d->name); | 1867 | errx(1, "%s: attempt to write to queue_notify_off", d->name); |