diff options
| author | Rusty Russell <rusty@rustcorp.com.au> | 2015-02-13 01:43:43 -0500 |
|---|---|---|
| committer | Rusty Russell <rusty@rustcorp.com.au> | 2015-02-13 01:45:52 -0500 |
| commit | d39a6785f40af658224bc3ff3d4c4a5a2f7c9eda (patch) | |
| tree | 8882a1116659a2efcd512f226cafe77eab9b7fe4 | |
| parent | 55c2d7884e9a97c2f2d46d5818f783bf3dcc5314 (diff) | |
tools/lguest: more documentation and checking of virtio 1.0 compliance.
This is from all the non-PCI parts of the spec.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
| -rw-r--r-- | tools/lguest/lguest.c | 307 |
1 files changed, 293 insertions, 14 deletions
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index 4c7c2aa66c89..bc444aff2333 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c | |||
| @@ -170,6 +170,9 @@ struct device { | |||
| 170 | /* Is it operational */ | 170 | /* Is it operational */ |
| 171 | bool running; | 171 | bool running; |
| 172 | 172 | ||
| 173 | /* Has it written FEATURES_OK but not re-checked it? */ | ||
| 174 | bool wrote_features_ok; | ||
| 175 | |||
| 173 | /* PCI configuration */ | 176 | /* PCI configuration */ |
| 174 | union { | 177 | union { |
| 175 | struct pci_config config; | 178 | struct pci_config config; |
| @@ -668,7 +671,26 @@ static void trigger_irq(struct virtqueue *vq) | |||
| 668 | return; | 671 | return; |
| 669 | vq->pending_used = 0; | 672 | vq->pending_used = 0; |
| 670 | 673 | ||
| 671 | /* If they don't want an interrupt, don't send one... */ | 674 | /* |
| 675 | * 2.4.7.1: | ||
| 676 | * | ||
| 677 | * If the VIRTIO_F_EVENT_IDX feature bit is not negotiated: | ||
| 678 | * The driver MUST set flags to 0 or 1. | ||
| 679 | */ | ||
| 680 | if (vq->vring.avail->flags > 1) | ||
| 681 | errx(1, "%s: avail->flags = %u\n", | ||
| 682 | vq->dev->name, vq->vring.avail->flags); | ||
| 683 | |||
| 684 | /* | ||
| 685 | * 2.4.7.2: | ||
| 686 | * | ||
| 687 | * If the VIRTIO_F_EVENT_IDX feature bit is not negotiated: | ||
| 688 | * | ||
| 689 | * - The device MUST ignore the used_event value. | ||
| 690 | * - After the device writes a descriptor index into the used ring: | ||
| 691 | * - If flags is 1, the device SHOULD NOT send an interrupt. | ||
| 692 | * - If flags is 0, the device MUST send an interrupt. | ||
| 693 | */ | ||
| 672 | if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) { | 694 | if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) { |
| 673 | return; | 695 | return; |
| 674 | } | 696 | } |
| @@ -703,6 +725,14 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq, | |||
| 703 | struct vring_desc *desc; | 725 | struct vring_desc *desc; |
| 704 | u16 last_avail = lg_last_avail(vq); | 726 | u16 last_avail = lg_last_avail(vq); |
| 705 | 727 | ||
| 728 | /* | ||
| 729 | * 2.4.7.1: | ||
| 730 | * | ||
| 731 | * The driver MUST handle spurious interrupts from the device. | ||
| 732 | * | ||
| 733 | * That's why this is a while loop. | ||
| 734 | */ | ||
| 735 | |||
| 706 | /* There's nothing available? */ | 736 | /* There's nothing available? */ |
| 707 | while (last_avail == vq->vring.avail->idx) { | 737 | while (last_avail == vq->vring.avail->idx) { |
| 708 | u64 event; | 738 | u64 event; |
| @@ -776,12 +806,62 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq, | |||
| 776 | * descriptor chain. | 806 | * descriptor chain. |
| 777 | */ | 807 | */ |
| 778 | if (desc[i].flags & VRING_DESC_F_INDIRECT) { | 808 | if (desc[i].flags & VRING_DESC_F_INDIRECT) { |
| 809 | /* 2.4.5.3.1: | ||
| 810 | * | ||
| 811 | * The driver MUST NOT set the VIRTQ_DESC_F_INDIRECT | ||
| 812 | * flag unless the VIRTIO_F_INDIRECT_DESC feature was | ||
| 813 | * negotiated. | ||
| 814 | */ | ||
| 815 | if (!(vq->dev->features_accepted & | ||
| 816 | (1<<VIRTIO_RING_F_INDIRECT_DESC))) | ||
| 817 | errx(1, "%s: vq indirect not negotiated", | ||
| 818 | vq->dev->name); | ||
| 819 | |||
| 820 | /* | ||
| 821 | * 2.4.5.3.1: | ||
| 822 | * | ||
| 823 | * The driver MUST NOT set the VIRTQ_DESC_F_INDIRECT | ||
| 824 | * flag within an indirect descriptor (ie. only one | ||
| 825 | * table per descriptor). | ||
| 826 | */ | ||
| 827 | if (desc != vq->vring.desc) | ||
| 828 | errx(1, "%s: Indirect within indirect", | ||
| 829 | vq->dev->name); | ||
| 830 | |||
| 831 | /* | ||
| 832 | * Proposed update VIRTIO-134 spells this out: | ||
| 833 | * | ||
| 834 | * A driver MUST NOT set both VIRTQ_DESC_F_INDIRECT | ||
| 835 | * and VIRTQ_DESC_F_NEXT in flags. | ||
| 836 | */ | ||
| 837 | if (desc[i].flags & VRING_DESC_F_NEXT) | ||
| 838 | errx(1, "%s: indirect and next together", | ||
| 839 | vq->dev->name); | ||
| 840 | |||
| 779 | if (desc[i].len % sizeof(struct vring_desc)) | 841 | if (desc[i].len % sizeof(struct vring_desc)) |
| 780 | errx(1, "Invalid size for indirect buffer table"); | 842 | errx(1, "Invalid size for indirect buffer table"); |
| 843 | /* | ||
| 844 | * 2.4.5.3.2: | ||
| 845 | * | ||
| 846 | * The device MUST ignore the write-only flag | ||
| 847 | * (flags&VIRTQ_DESC_F_WRITE) in the descriptor that | ||
| 848 | * refers to an indirect table. | ||
| 849 | * | ||
| 850 | * We ignore it here: :) | ||
| 851 | */ | ||
| 781 | 852 | ||
| 782 | max = desc[i].len / sizeof(struct vring_desc); | 853 | max = desc[i].len / sizeof(struct vring_desc); |
| 783 | desc = check_pointer(desc[i].addr, desc[i].len); | 854 | desc = check_pointer(desc[i].addr, desc[i].len); |
| 784 | i = 0; | 855 | i = 0; |
| 856 | |||
| 857 | /* 2.4.5.3.1: | ||
| 858 | * | ||
| 859 | * A driver MUST NOT create a descriptor chain longer | ||
| 860 | * than the Queue Size of the device. | ||
| 861 | */ | ||
| 862 | if (max > vq->pci_config.queue_size) | ||
| 863 | errx(1, "%s: indirect has too many entries", | ||
| 864 | vq->dev->name); | ||
| 785 | } | 865 | } |
| 786 | 866 | ||
| 787 | /* Grab the first descriptor, and check it's OK. */ | 867 | /* Grab the first descriptor, and check it's OK. */ |
| @@ -1082,6 +1162,7 @@ static void reset_device(struct device *dev) | |||
| 1082 | } | 1162 | } |
| 1083 | } | 1163 | } |
| 1084 | dev->running = false; | 1164 | dev->running = false; |
| 1165 | dev->wrote_features_ok = false; | ||
| 1085 | 1166 | ||
| 1086 | /* Now we care if threads die. */ | 1167 | /* Now we care if threads die. */ |
| 1087 | signal(SIGCHLD, (void *)kill_launcher); | 1168 | signal(SIGCHLD, (void *)kill_launcher); |
| @@ -1703,6 +1784,18 @@ static void check_virtqueue(struct device *d, struct virtqueue *vq) | |||
| 1703 | || vq->pci_config.queue_used_hi) | 1784 | || vq->pci_config.queue_used_hi) |
| 1704 | errx(1, "%s: invalid 64-bit queue address", d->name); | 1785 | errx(1, "%s: invalid 64-bit queue address", d->name); |
| 1705 | 1786 | ||
| 1787 | /* | ||
| 1788 | * 2.4.1: | ||
| 1789 | * | ||
| 1790 | * The driver MUST ensure that the physical address of the first byte | ||
| 1791 | * of each virtqueue part is a multiple of the specified alignment | ||
| 1792 | * value in the above table. | ||
| 1793 | */ | ||
| 1794 | if (vq->pci_config.queue_desc_lo % 16 | ||
| 1795 | || vq->pci_config.queue_avail_lo % 2 | ||
| 1796 | || vq->pci_config.queue_used_lo % 4) | ||
| 1797 | errx(1, "%s: invalid alignment in queue addresses", d->name); | ||
| 1798 | |||
| 1706 | /* Initialize the virtqueue and check they're all in range. */ | 1799 | /* Initialize the virtqueue and check they're all in range. */ |
| 1707 | vq->vring.num = vq->pci_config.queue_size; | 1800 | vq->vring.num = vq->pci_config.queue_size; |
| 1708 | vq->vring.desc = check_pointer(vq->pci_config.queue_desc_lo, | 1801 | vq->vring.desc = check_pointer(vq->pci_config.queue_desc_lo, |
| @@ -1715,6 +1808,16 @@ static void check_virtqueue(struct device *d, struct virtqueue *vq) | |||
| 1715 | sizeof(*vq->vring.used) | 1808 | sizeof(*vq->vring.used) |
| 1716 | + (sizeof(vq->vring.used->ring[0]) | 1809 | + (sizeof(vq->vring.used->ring[0]) |
| 1717 | * vq->vring.num)); | 1810 | * vq->vring.num)); |
| 1811 | |||
| 1812 | /* | ||
| 1813 | * 2.4.9.1: | ||
| 1814 | * | ||
| 1815 | * The driver MUST initialize flags in the used ring to 0 | ||
| 1816 | * when allocating the used ring. | ||
| 1817 | */ | ||
| 1818 | if (vq->vring.used->flags != 0) | ||
| 1819 | errx(1, "%s: invalid initial used.flags %#x", | ||
| 1820 | d->name, vq->vring.used->flags); | ||
| 1718 | } | 1821 | } |
| 1719 | 1822 | ||
| 1720 | static void start_virtqueue(struct virtqueue *vq) | 1823 | static void start_virtqueue(struct virtqueue *vq) |
| @@ -1768,12 +1871,12 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) | |||
| 1768 | d->mmio->cfg.device_feature = (d->features >> 32); | 1871 | d->mmio->cfg.device_feature = (d->features >> 32); |
| 1769 | else | 1872 | else |
| 1770 | d->mmio->cfg.device_feature = 0; | 1873 | d->mmio->cfg.device_feature = 0; |
| 1771 | goto write_through32; | 1874 | goto feature_write_through32; |
| 1772 | case offsetof(struct virtio_pci_mmio, cfg.guest_feature_select): | 1875 | case offsetof(struct virtio_pci_mmio, cfg.guest_feature_select): |
| 1773 | if (val > 1) | 1876 | if (val > 1) |
| 1774 | errx(1, "%s: Unexpected driver select %u", | 1877 | errx(1, "%s: Unexpected driver select %u", |
| 1775 | d->name, val); | 1878 | d->name, val); |
| 1776 | goto write_through32; | 1879 | goto feature_write_through32; |
| 1777 | case offsetof(struct virtio_pci_mmio, cfg.guest_feature): | 1880 | case offsetof(struct virtio_pci_mmio, cfg.guest_feature): |
| 1778 | if (d->mmio->cfg.guest_feature_select == 0) { | 1881 | if (d->mmio->cfg.guest_feature_select == 0) { |
| 1779 | d->features_accepted &= ~((u64)0xFFFFFFFF); | 1882 | d->features_accepted &= ~((u64)0xFFFFFFFF); |
| @@ -1783,11 +1886,19 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) | |||
| 1783 | d->features_accepted &= 0xFFFFFFFF; | 1886 | d->features_accepted &= 0xFFFFFFFF; |
| 1784 | d->features_accepted |= ((u64)val) << 32; | 1887 | d->features_accepted |= ((u64)val) << 32; |
| 1785 | } | 1888 | } |
| 1889 | /* | ||
| 1890 | * 2.2.1: | ||
| 1891 | * | ||
| 1892 | * The driver MUST NOT accept a feature which the device did | ||
| 1893 | * not offer | ||
| 1894 | */ | ||
| 1786 | if (d->features_accepted & ~d->features) | 1895 | if (d->features_accepted & ~d->features) |
| 1787 | errx(1, "%s: over-accepted features %#llx of %#llx", | 1896 | errx(1, "%s: over-accepted features %#llx of %#llx", |
| 1788 | d->name, d->features_accepted, d->features); | 1897 | d->name, d->features_accepted, d->features); |
| 1789 | goto write_through32; | 1898 | goto feature_write_through32; |
| 1790 | case offsetof(struct virtio_pci_mmio, cfg.device_status): | 1899 | case offsetof(struct virtio_pci_mmio, cfg.device_status): { |
| 1900 | u8 prev; | ||
| 1901 | |||
| 1791 | verbose("%s: device status -> %#x\n", d->name, val); | 1902 | verbose("%s: device status -> %#x\n", d->name, val); |
| 1792 | /* | 1903 | /* |
| 1793 | * 4.1.4.3.1: | 1904 | * 4.1.4.3.1: |
| @@ -1795,8 +1906,15 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) | |||
| 1795 | * The device MUST reset when 0 is written to device_status, | 1906 | * The device MUST reset when 0 is written to device_status, |
| 1796 | * and present a 0 in device_status once that is done. | 1907 | * and present a 0 in device_status once that is done. |
| 1797 | */ | 1908 | */ |
| 1798 | if (val == 0) | 1909 | if (val == 0) { |
| 1799 | reset_device(d); | 1910 | reset_device(d); |
| 1911 | goto write_through8; | ||
| 1912 | } | ||
| 1913 | |||
| 1914 | /* 2.1.1: The driver MUST NOT clear a device status bit. */ | ||
| 1915 | if (d->mmio->cfg.device_status & ~val) | ||
| 1916 | errx(1, "%s: unset of device status bit %#x -> %#x", | ||
| 1917 | d->name, d->mmio->cfg.device_status, val); | ||
| 1800 | 1918 | ||
| 1801 | /* | 1919 | /* |
| 1802 | * 2.1.2: | 1920 | * 2.1.2: |
| @@ -1808,7 +1926,67 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) | |||
| 1808 | && !(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER_OK)) | 1926 | && !(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER_OK)) |
| 1809 | start_virtqueues(d); | 1927 | start_virtqueues(d); |
| 1810 | 1928 | ||
| 1929 | /* | ||
| 1930 | * 3.1.1: | ||
| 1931 | * | ||
| 1932 | * The driver MUST follow this sequence to initialize a device: | ||
| 1933 | * - Reset the device. | ||
| 1934 | * - Set the ACKNOWLEDGE status bit: the guest OS has | ||
| 1935 | * notice the device. | ||
| 1936 | * - Set the DRIVER status bit: the guest OS knows how | ||
| 1937 | * to drive the device. | ||
| 1938 | * - Read device feature bits, and write the subset | ||
| 1939 | * of feature bits understood by the OS and driver | ||
| 1940 | * to the device. During this step the driver MAY | ||
| 1941 | * read (but MUST NOT write) the device-specific | ||
| 1942 | * configuration fields to check that it can | ||
| 1943 | * support the device before accepting it. | ||
| 1944 | * - Set the FEATURES_OK status bit. The driver | ||
| 1945 | * MUST not accept new feature bits after this | ||
| 1946 | * step. | ||
| 1947 | * - Re-read device status to ensure the FEATURES_OK | ||
| 1948 | * bit is still set: otherwise, the device does | ||
| 1949 | * not support our subset of features and the | ||
| 1950 | * device is unusable. | ||
| 1951 | * - Perform device-specific setup, including | ||
| 1952 | * discovery of virtqueues for the device, | ||
| 1953 | * optional per-bus setup, reading and possibly | ||
| 1954 | * writing the device’s virtio configuration | ||
| 1955 | * space, and population of virtqueues. | ||
| 1956 | * - Set the DRIVER_OK status bit. At this point the | ||
| 1957 | * device is “live”. | ||
| 1958 | */ | ||
| 1959 | prev = 0; | ||
| 1960 | switch (val & ~d->mmio->cfg.device_status) { | ||
| 1961 | case VIRTIO_CONFIG_S_DRIVER_OK: | ||
| 1962 | prev |= VIRTIO_CONFIG_S_FEATURES_OK; /* fall thru */ | ||
| 1963 | case VIRTIO_CONFIG_S_FEATURES_OK: | ||
| 1964 | prev |= VIRTIO_CONFIG_S_DRIVER; /* fall thru */ | ||
| 1965 | case VIRTIO_CONFIG_S_DRIVER: | ||
| 1966 | prev |= VIRTIO_CONFIG_S_ACKNOWLEDGE; /* fall thru */ | ||
| 1967 | case VIRTIO_CONFIG_S_ACKNOWLEDGE: | ||
| 1968 | break; | ||
| 1969 | default: | ||
| 1970 | errx(1, "%s: unknown device status bit %#x -> %#x", | ||
| 1971 | d->name, d->mmio->cfg.device_status, val); | ||
| 1972 | } | ||
| 1973 | if (d->mmio->cfg.device_status != prev) | ||
| 1974 | errx(1, "%s: unexpected status transition %#x -> %#x", | ||
| 1975 | d->name, d->mmio->cfg.device_status, val); | ||
| 1976 | |||
| 1977 | /* If they just wrote FEATURES_OK, we make sure they read */ | ||
| 1978 | switch (val & ~d->mmio->cfg.device_status) { | ||
| 1979 | case VIRTIO_CONFIG_S_FEATURES_OK: | ||
| 1980 | d->wrote_features_ok = true; | ||
| 1981 | break; | ||
| 1982 | case VIRTIO_CONFIG_S_DRIVER_OK: | ||
| 1983 | if (d->wrote_features_ok) | ||
| 1984 | errx(1, "%s: did not re-read FEATURES_OK", | ||
| 1985 | d->name); | ||
| 1986 | break; | ||
| 1987 | } | ||
| 1811 | goto write_through8; | 1988 | goto write_through8; |
| 1989 | } | ||
| 1812 | case offsetof(struct virtio_pci_mmio, cfg.queue_select): | 1990 | case offsetof(struct virtio_pci_mmio, cfg.queue_select): |
| 1813 | vq = vq_by_num(d, val); | 1991 | vq = vq_by_num(d, val); |
| 1814 | /* | 1992 | /* |
| @@ -1844,7 +2022,9 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) | |||
| 1844 | case offsetof(struct virtio_pci_mmio, cfg.queue_msix_vector): | 2022 | case offsetof(struct virtio_pci_mmio, cfg.queue_msix_vector): |
| 1845 | errx(1, "%s: attempt to set MSIX vector to %u", | 2023 | errx(1, "%s: attempt to set MSIX vector to %u", |
| 1846 | d->name, val); | 2024 | d->name, val); |
| 1847 | case offsetof(struct virtio_pci_mmio, cfg.queue_enable): | 2025 | case offsetof(struct virtio_pci_mmio, cfg.queue_enable): { |
| 2026 | struct virtqueue *vq = vq_by_num(d, d->mmio->cfg.queue_select); | ||
| 2027 | |||
| 1848 | /* | 2028 | /* |
| 1849 | * 4.1.4.3.2: | 2029 | * 4.1.4.3.2: |
| 1850 | * | 2030 | * |
| @@ -1852,17 +2032,27 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) | |||
| 1852 | */ | 2032 | */ |
| 1853 | if (val != 1) | 2033 | if (val != 1) |
| 1854 | errx(1, "%s: setting queue_enable to %u", d->name, val); | 2034 | errx(1, "%s: setting queue_enable to %u", d->name, val); |
| 1855 | d->mmio->cfg.queue_enable = val; | 2035 | |
| 1856 | save_vq_config(&d->mmio->cfg, | ||
| 1857 | vq_by_num(d, d->mmio->cfg.queue_select)); | ||
| 1858 | /* | 2036 | /* |
| 1859 | * 4.1.4.3.2: | 2037 | * 3.1.1: |
| 1860 | * | 2038 | * |
| 1861 | * The driver MUST configure the other virtqueue fields before | 2039 | * 7. Perform device-specific setup, including discovery of |
| 1862 | * enabling the virtqueue with queue_enable. | 2040 | * virtqueues for the device, optional per-bus setup, |
| 2041 | * reading and possibly writing the device’s virtio | ||
| 2042 | * configuration space, and population of virtqueues. | ||
| 2043 | * 8. Set the DRIVER_OK status bit. | ||
| 2044 | * | ||
| 2045 | * All our devices require all virtqueues to be enabled, so | ||
| 2046 | * they should have done that before setting DRIVER_OK. | ||
| 1863 | */ | 2047 | */ |
| 1864 | check_virtqueue(d, vq_by_num(d, d->mmio->cfg.queue_select)); | 2048 | if (d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER_OK) |
| 2049 | errx(1, "%s: enabling vs after DRIVER_OK", d->name); | ||
| 2050 | |||
| 2051 | d->mmio->cfg.queue_enable = val; | ||
| 2052 | save_vq_config(&d->mmio->cfg, vq); | ||
| 2053 | check_virtqueue(d, vq); | ||
| 1865 | goto write_through16; | 2054 | goto write_through16; |
| 2055 | } | ||
| 1866 | case offsetof(struct virtio_pci_mmio, cfg.queue_notify_off): | 2056 | case offsetof(struct virtio_pci_mmio, cfg.queue_notify_off): |
| 1867 | errx(1, "%s: attempt to write to queue_notify_off", d->name); | 2057 | errx(1, "%s: attempt to write to queue_notify_off", d->name); |
| 1868 | case offsetof(struct virtio_pci_mmio, cfg.queue_desc_lo): | 2058 | case offsetof(struct virtio_pci_mmio, cfg.queue_desc_lo): |
| @@ -1880,6 +2070,26 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) | |||
| 1880 | if (d->mmio->cfg.queue_enable) | 2070 | if (d->mmio->cfg.queue_enable) |
| 1881 | errx(1, "%s: changing queue on live device", | 2071 | errx(1, "%s: changing queue on live device", |
| 1882 | d->name); | 2072 | d->name); |
| 2073 | |||
| 2074 | /* | ||
| 2075 | * 3.1.1: | ||
| 2076 | * | ||
| 2077 | * The driver MUST follow this sequence to initialize a device: | ||
| 2078 | *... | ||
| 2079 | * 5. Set the FEATURES_OK status bit. The driver MUST not | ||
| 2080 | * accept new feature bits after this step. | ||
| 2081 | */ | ||
| 2082 | if (!(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_FEATURES_OK)) | ||
| 2083 | errx(1, "%s: enabling vs before FEATURES_OK", d->name); | ||
| 2084 | |||
| 2085 | /* | ||
| 2086 | * 6. Re-read device status to ensure the FEATURES_OK bit is | ||
| 2087 | * still set... | ||
| 2088 | */ | ||
| 2089 | if (d->wrote_features_ok) | ||
| 2090 | errx(1, "%s: didn't re-read FEATURES_OK before setup", | ||
| 2091 | d->name); | ||
| 2092 | |||
| 1883 | goto write_through32; | 2093 | goto write_through32; |
| 1884 | case offsetof(struct virtio_pci_mmio, notify): | 2094 | case offsetof(struct virtio_pci_mmio, notify): |
| 1885 | vq = vq_by_num(d, val); | 2095 | vq = vq_by_num(d, val); |
| @@ -1909,6 +2119,27 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) | |||
| 1909 | errx(1, "%s: Unexpected write to offset %u", d->name, off); | 2119 | errx(1, "%s: Unexpected write to offset %u", d->name, off); |
| 1910 | } | 2120 | } |
| 1911 | 2121 | ||
| 2122 | feature_write_through32: | ||
| 2123 | /* | ||
| 2124 | * 3.1.1: | ||
| 2125 | * | ||
| 2126 | * The driver MUST follow this sequence to initialize a device: | ||
| 2127 | *... | ||
| 2128 | * - Set the DRIVER status bit: the guest OS knows how | ||
| 2129 | * to drive the device. | ||
| 2130 | * - Read device feature bits, and write the subset | ||
| 2131 | * of feature bits understood by the OS and driver | ||
| 2132 | * to the device. | ||
| 2133 | *... | ||
| 2134 | * - Set the FEATURES_OK status bit. The driver MUST not | ||
| 2135 | * accept new feature bits after this step. | ||
| 2136 | */ | ||
| 2137 | if (!(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER)) | ||
| 2138 | errx(1, "%s: feature write before VIRTIO_CONFIG_S_DRIVER", | ||
| 2139 | d->name); | ||
| 2140 | if (d->mmio->cfg.device_status & VIRTIO_CONFIG_S_FEATURES_OK) | ||
| 2141 | errx(1, "%s: feature write after VIRTIO_CONFIG_S_FEATURES_OK", | ||
| 2142 | d->name); | ||
| 1912 | 2143 | ||
| 1913 | /* | 2144 | /* |
| 1914 | * 4.1.3.1: | 2145 | * 4.1.3.1: |
| @@ -1951,12 +2182,29 @@ static u32 emulate_mmio_read(struct device *d, u32 off, u32 mask) | |||
| 1951 | case offsetof(struct virtio_pci_mmio, cfg.device_feature): | 2182 | case offsetof(struct virtio_pci_mmio, cfg.device_feature): |
| 1952 | case offsetof(struct virtio_pci_mmio, cfg.guest_feature_select): | 2183 | case offsetof(struct virtio_pci_mmio, cfg.guest_feature_select): |
| 1953 | case offsetof(struct virtio_pci_mmio, cfg.guest_feature): | 2184 | case offsetof(struct virtio_pci_mmio, cfg.guest_feature): |
| 2185 | /* | ||
| 2186 | * 3.1.1: | ||
| 2187 | * | ||
| 2188 | * The driver MUST follow this sequence to initialize a device: | ||
| 2189 | *... | ||
| 2190 | * - Set the DRIVER status bit: the guest OS knows how | ||
| 2191 | * to drive the device. | ||
| 2192 | * - Read device feature bits, and write the subset | ||
| 2193 | * of feature bits understood by the OS and driver | ||
| 2194 | * to the device. | ||
| 2195 | */ | ||
| 2196 | if (!(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER)) | ||
| 2197 | errx(1, "%s: feature read before VIRTIO_CONFIG_S_DRIVER", | ||
| 2198 | d->name); | ||
| 1954 | goto read_through32; | 2199 | goto read_through32; |
| 1955 | case offsetof(struct virtio_pci_mmio, cfg.msix_config): | 2200 | case offsetof(struct virtio_pci_mmio, cfg.msix_config): |
| 1956 | errx(1, "%s: read of msix_config", d->name); | 2201 | errx(1, "%s: read of msix_config", d->name); |
| 1957 | case offsetof(struct virtio_pci_mmio, cfg.num_queues): | 2202 | case offsetof(struct virtio_pci_mmio, cfg.num_queues): |
| 1958 | goto read_through16; | 2203 | goto read_through16; |
| 1959 | case offsetof(struct virtio_pci_mmio, cfg.device_status): | 2204 | case offsetof(struct virtio_pci_mmio, cfg.device_status): |
| 2205 | /* As they did read, any write of FEATURES_OK is now fine. */ | ||
| 2206 | d->wrote_features_ok = false; | ||
| 2207 | goto read_through8; | ||
| 1960 | case offsetof(struct virtio_pci_mmio, cfg.config_generation): | 2208 | case offsetof(struct virtio_pci_mmio, cfg.config_generation): |
| 1961 | /* | 2209 | /* |
| 1962 | * 4.1.4.3.1: | 2210 | * 4.1.4.3.1: |
| @@ -1971,6 +2219,15 @@ static u32 emulate_mmio_read(struct device *d, u32 off, u32 mask) | |||
| 1971 | */ | 2219 | */ |
| 1972 | goto read_through8; | 2220 | goto read_through8; |
| 1973 | case offsetof(struct virtio_pci_mmio, notify): | 2221 | case offsetof(struct virtio_pci_mmio, notify): |
| 2222 | /* | ||
| 2223 | * 3.1.1: | ||
| 2224 | * | ||
| 2225 | * The driver MUST NOT notify the device before setting | ||
| 2226 | * DRIVER_OK. | ||
| 2227 | */ | ||
| 2228 | if (!(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER_OK)) | ||
| 2229 | errx(1, "%s: notify before VIRTIO_CONFIG_S_DRIVER_OK", | ||
| 2230 | d->name); | ||
| 1974 | goto read_through16; | 2231 | goto read_through16; |
| 1975 | case offsetof(struct virtio_pci_mmio, isr): | 2232 | case offsetof(struct virtio_pci_mmio, isr): |
| 1976 | if (mask != 0xFF) | 2233 | if (mask != 0xFF) |
| @@ -1992,6 +2249,23 @@ static u32 emulate_mmio_read(struct device *d, u32 off, u32 mask) | |||
| 1992 | if (off > d->mmio_size - 4) | 2249 | if (off > d->mmio_size - 4) |
| 1993 | errx(1, "%s: read past end (%#x)", | 2250 | errx(1, "%s: read past end (%#x)", |
| 1994 | d->name, getreg(eip)); | 2251 | d->name, getreg(eip)); |
| 2252 | |||
| 2253 | /* | ||
| 2254 | * 3.1.1: | ||
| 2255 | * The driver MUST follow this sequence to initialize a device: | ||
| 2256 | *... | ||
| 2257 | * 3. Set the DRIVER status bit: the guest OS knows how to | ||
| 2258 | * drive the device. | ||
| 2259 | * 4. Read device feature bits, and write the subset of | ||
| 2260 | * feature bits understood by the OS and driver to the | ||
| 2261 | * device. During this step the driver MAY read (but MUST NOT | ||
| 2262 | * write) the device-specific configuration fields to check | ||
| 2263 | * that it can support the device before accepting it. | ||
| 2264 | */ | ||
| 2265 | if (!(d->mmio->cfg.device_status & VIRTIO_CONFIG_S_DRIVER)) | ||
| 2266 | errx(1, "%s: config read before VIRTIO_CONFIG_S_DRIVER", | ||
| 2267 | d->name); | ||
| 2268 | |||
| 1995 | if (mask == 0xFFFFFFFF) | 2269 | if (mask == 0xFFFFFFFF) |
| 1996 | goto read_through32; | 2270 | goto read_through32; |
| 1997 | else if (mask == 0xFFFF) | 2271 | else if (mask == 0xFFFF) |
| @@ -2200,6 +2474,10 @@ static void init_pci_config(struct pci_config *pci, u16 type, | |||
| 2200 | * | 2474 | * |
| 2201 | * The device MUST either present notify_off_multiplier as an even | 2475 | * The device MUST either present notify_off_multiplier as an even |
| 2202 | * power of 2, or present notify_off_multiplier as 0. | 2476 | * power of 2, or present notify_off_multiplier as 0. |
| 2477 | * | ||
| 2478 | * 2.1.2: | ||
| 2479 | * | ||
| 2480 | * The device MUST initialize device status to 0 upon reset. | ||
| 2203 | */ | 2481 | */ |
| 2204 | memset(pci, 0, sizeof(*pci)); | 2482 | memset(pci, 0, sizeof(*pci)); |
| 2205 | 2483 | ||
| @@ -2340,6 +2618,7 @@ static struct device *new_pci_device(const char *name, u16 type, | |||
| 2340 | dev->name = name; | 2618 | dev->name = name; |
| 2341 | dev->vq = NULL; | 2619 | dev->vq = NULL; |
| 2342 | dev->running = false; | 2620 | dev->running = false; |
| 2621 | dev->wrote_features_ok = false; | ||
| 2343 | dev->mmio_size = sizeof(struct virtio_pci_mmio); | 2622 | dev->mmio_size = sizeof(struct virtio_pci_mmio); |
| 2344 | dev->mmio = calloc(1, dev->mmio_size); | 2623 | dev->mmio = calloc(1, dev->mmio_size); |
| 2345 | dev->features = (u64)1 << VIRTIO_F_VERSION_1; | 2624 | dev->features = (u64)1 << VIRTIO_F_VERSION_1; |
