aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2015-02-13 01:43:42 -0500
committerRusty Russell <rusty@rustcorp.com.au>2015-02-13 01:45:49 -0500
commitc97eb679ef70dbb4482e66b9d192fc9e5bc6e0d6 (patch)
tree2b654642fd4920069e6c39ab3b4e513202e5af9e /tools
parent8dc425ffdd20b3462cfb43eb4f94a7ed8296dd63 (diff)
tools/lguest: insert driver references from the 1.0 spec (4.1 Virtio Over PCI)
As a demonstration, the lguest launcher is pretty strict, trying to catch badly behaved drivers. Document this precisely. A good implementation would *NOT* crash the guest when these happened! Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'tools')
-rw-r--r--tools/lguest/lguest.c59
1 files changed, 57 insertions, 2 deletions
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c
index 10a72b810127..80dc6346030e 100644
--- a/tools/lguest/lguest.c
+++ b/tools/lguest/lguest.c
@@ -1211,7 +1211,12 @@ static bool valid_bar_access(struct device *d,
1211 && cfg_access->cap.length != 4) 1211 && cfg_access->cap.length != 4)
1212 return false; 1212 return false;
1213 1213
1214 /* Offset must be multiple of length */ 1214 /*
1215 * 4.1.4.7.2:
1216 *
1217 * The driver MUST NOT write a cap.offset which is not a multiple of
1218 * cap.length (ie. all accesses MUST be aligned).
1219 */
1215 if (cfg_access->cap.offset % cfg_access->cap.length != 0) 1220 if (cfg_access->cap.offset % cfg_access->cap.length != 0)
1216 return false; 1221 return false;
1217 1222
@@ -1342,7 +1347,13 @@ static bool pci_data_iowrite(u16 port, u32 mask, u32 val)
1342 return true; 1347 return true;
1343 } 1348 }
1344 1349
1345 /* Complain about other writes. */ 1350 /*
1351 * 4.1.4.1:
1352 *
1353 * The driver MUST NOT write into any field of the capability
1354 * structure, with the exception of those with cap_type
1355 * VIRTIO_PCI_CAP_PCI_CFG...
1356 */
1346 return false; 1357 return false;
1347} 1358}
1348 1359
@@ -1789,6 +1800,12 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask)
1789 restore_vq_config(&d->mmio->cfg, vq); 1800 restore_vq_config(&d->mmio->cfg, vq);
1790 goto write_through16; 1801 goto write_through16;
1791 case offsetof(struct virtio_pci_mmio, cfg.queue_size): 1802 case offsetof(struct virtio_pci_mmio, cfg.queue_size):
1803 /*
1804 * 4.1.4.3.2:
1805 *
1806 * The driver MUST NOT write a value which is not a power of 2
1807 * to queue_size.
1808 */
1792 if (val & (val-1)) 1809 if (val & (val-1))
1793 errx(1, "%s: invalid queue size %u\n", d->name, val); 1810 errx(1, "%s: invalid queue size %u\n", d->name, val);
1794 if (d->mmio->cfg.queue_enable) 1811 if (d->mmio->cfg.queue_enable)
@@ -1799,11 +1816,22 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask)
1799 errx(1, "%s: attempt to set MSIX vector to %u", 1816 errx(1, "%s: attempt to set MSIX vector to %u",
1800 d->name, val); 1817 d->name, val);
1801 case offsetof(struct virtio_pci_mmio, cfg.queue_enable): 1818 case offsetof(struct virtio_pci_mmio, cfg.queue_enable):
1819 /*
1820 * 4.1.4.3.2:
1821 *
1822 * The driver MUST NOT write a 0 to queue_enable.
1823 */
1802 if (val != 1) 1824 if (val != 1)
1803 errx(1, "%s: setting queue_enable to %u", d->name, val); 1825 errx(1, "%s: setting queue_enable to %u", d->name, val);
1804 d->mmio->cfg.queue_enable = val; 1826 d->mmio->cfg.queue_enable = val;
1805 save_vq_config(&d->mmio->cfg, 1827 save_vq_config(&d->mmio->cfg,
1806 vq_by_num(d, d->mmio->cfg.queue_select)); 1828 vq_by_num(d, d->mmio->cfg.queue_select));
1829 /*
1830 * 4.1.4.3.2:
1831 *
1832 * The driver MUST configure the other virtqueue fields before
1833 * enabling the virtqueue with queue_enable.
1834 */
1807 enable_virtqueue(d, vq_by_num(d, d->mmio->cfg.queue_select)); 1835 enable_virtqueue(d, vq_by_num(d, d->mmio->cfg.queue_select));
1808 goto write_through16; 1836 goto write_through16;
1809 case offsetof(struct virtio_pci_mmio, cfg.queue_notify_off): 1837 case offsetof(struct virtio_pci_mmio, cfg.queue_notify_off):
@@ -1814,6 +1842,12 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask)
1814 case offsetof(struct virtio_pci_mmio, cfg.queue_avail_hi): 1842 case offsetof(struct virtio_pci_mmio, cfg.queue_avail_hi):
1815 case offsetof(struct virtio_pci_mmio, cfg.queue_used_lo): 1843 case offsetof(struct virtio_pci_mmio, cfg.queue_used_lo):
1816 case offsetof(struct virtio_pci_mmio, cfg.queue_used_hi): 1844 case offsetof(struct virtio_pci_mmio, cfg.queue_used_hi):
1845 /*
1846 * 4.1.4.3.2:
1847 *
1848 * The driver MUST configure the other virtqueue fields before
1849 * enabling the virtqueue with queue_enable.
1850 */
1817 if (d->mmio->cfg.queue_enable) 1851 if (d->mmio->cfg.queue_enable)
1818 errx(1, "%s: changing queue on live device", 1852 errx(1, "%s: changing queue on live device",
1819 d->name); 1853 d->name);
@@ -1837,9 +1871,23 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask)
1837 } 1871 }
1838 /* Fall through... */ 1872 /* Fall through... */
1839 default: 1873 default:
1874 /*
1875 * 4.1.4.3.2:
1876 *
1877 * The driver MUST NOT write to device_feature, num_queues,
1878 * config_generation or queue_notify_off.
1879 */
1840 errx(1, "%s: Unexpected write to offset %u", d->name, off); 1880 errx(1, "%s: Unexpected write to offset %u", d->name, off);
1841 } 1881 }
1842 1882
1883
1884 /*
1885 * 4.1.3.1:
1886 *
1887 * The driver MUST access each field using the “natural” access
1888 * method, i.e. 32-bit accesses for 32-bit fields, 16-bit accesses for
1889 * 16-bit fields and 8-bit accesses for 8-bit fields.
1890 */
1843write_through32: 1891write_through32:
1844 if (mask != 0xFFFFFFFF) { 1892 if (mask != 0xFFFFFFFF) {
1845 errx(1, "%s: non-32-bit write to offset %u (%#x)", 1893 errx(1, "%s: non-32-bit write to offset %u (%#x)",
@@ -1923,6 +1971,13 @@ static u32 emulate_mmio_read(struct device *d, u32 off, u32 mask)
1923 goto read_through8; 1971 goto read_through8;
1924 } 1972 }
1925 1973
1974 /*
1975 * 4.1.3.1:
1976 *
1977 * The driver MUST access each field using the “natural” access
1978 * method, i.e. 32-bit accesses for 32-bit fields, 16-bit accesses for
1979 * 16-bit fields and 8-bit accesses for 8-bit fields.
1980 */
1926read_through32: 1981read_through32:
1927 if (mask != 0xFFFFFFFF) 1982 if (mask != 0xFFFFFFFF)
1928 errx(1, "%s: non-32-bit read to offset %u (%#x)", 1983 errx(1, "%s: non-32-bit read to offset %u (%#x)",