aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2015-02-13 01:43:41 -0500
committerRusty Russell <rusty@rustcorp.com.au>2015-02-13 01:45:47 -0500
commit8dc425ffdd20b3462cfb43eb4f94a7ed8296dd63 (patch)
tree4cd6c61cfcc3f8150614d1e42949aa190e93fd00 /tools
parentb2ce1ea4427f0c752f8718a411435cc9527faa3d (diff)
tools/lguest: insert device references from the 1.0 spec (4.1 Virtio Over PCI)
There are some (optional) parts we don't implement, but this quotes all the device requirements from the spec (csd 03, but it should be the same across all released versions). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'tools')
-rw-r--r--tools/lguest/lguest.c140
1 files changed, 131 insertions, 9 deletions
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c
index b00263f5febb..10a72b810127 100644
--- a/tools/lguest/lguest.c
+++ b/tools/lguest/lguest.c
@@ -673,7 +673,13 @@ static void trigger_irq(struct virtqueue *vq)
673 return; 673 return;
674 } 674 }
675 675
676 /* Set isr to 1 (queue interrupt pending) */ 676 /*
677 * 4.1.4.5.1:
678 *
679 * If MSI-X capability is disabled, the device MUST set the Queue
680 * Interrupt bit in ISR status before sending a virtqueue notification
681 * to the driver.
682 */
677 vq->dev->mmio->isr = 0x1; 683 vq->dev->mmio->isr = 0x1;
678 684
679 /* Send the Guest an interrupt tell them we used something up. */ 685 /* Send the Guest an interrupt tell them we used something up. */
@@ -1304,11 +1310,19 @@ static bool pci_data_iowrite(u16 port, u32 mask, u32 val)
1304 } else if (&d->config_words[reg] == &d->config.cfg_access.pci_cfg_data) { 1310 } else if (&d->config_words[reg] == &d->config.cfg_access.pci_cfg_data) {
1305 u32 write_mask; 1311 u32 write_mask;
1306 1312
1313 /*
1314 * 4.1.4.7.1:
1315 *
1316 * Upon detecting driver write access to pci_cfg_data, the
1317 * device MUST execute a write access at offset cap.offset at
1318 * BAR selected by cap.bar using the first cap.length bytes
1319 * from pci_cfg_data.
1320 */
1321
1307 /* Must be bar 0 */ 1322 /* Must be bar 0 */
1308 if (!valid_bar_access(d, &d->config.cfg_access)) 1323 if (!valid_bar_access(d, &d->config.cfg_access))
1309 return false; 1324 return false;
1310 1325
1311 /* First copy what they wrote into the window */
1312 iowrite(portoff, val, mask, &d->config.cfg_access.pci_cfg_data); 1326 iowrite(portoff, val, mask, &d->config.cfg_access.pci_cfg_data);
1313 1327
1314 /* 1328 /*
@@ -1346,6 +1360,14 @@ static void pci_data_ioread(u16 port, u32 mask, u32 *val)
1346 if (&d->config_words[reg] == &d->config.cfg_access.pci_cfg_data) { 1360 if (&d->config_words[reg] == &d->config.cfg_access.pci_cfg_data) {
1347 u32 read_mask; 1361 u32 read_mask;
1348 1362
1363 /*
1364 * 4.1.4.7.1:
1365 *
1366 * Upon detecting driver read access to pci_cfg_data, the
1367 * device MUST execute a read access of length cap.length at
1368 * offset cap.offset at BAR selected by cap.bar and store the
1369 * first cap.length bytes in pci_cfg_data.
1370 */
1349 /* Must be bar 0 */ 1371 /* Must be bar 0 */
1350 if (!valid_bar_access(d, &d->config.cfg_access)) 1372 if (!valid_bar_access(d, &d->config.cfg_access))
1351 errx(1, "Invalid cfg_access to bar%u, offset %u len %u", 1373 errx(1, "Invalid cfg_access to bar%u, offset %u len %u",
@@ -1704,6 +1726,13 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask)
1704 1726
1705 switch (off) { 1727 switch (off) {
1706 case offsetof(struct virtio_pci_mmio, cfg.device_feature_select): 1728 case offsetof(struct virtio_pci_mmio, cfg.device_feature_select):
1729 /*
1730 * 4.1.4.3.1:
1731 *
1732 * The device MUST present the feature bits it is offering in
1733 * device_feature, starting at bit device_feature_select ∗ 32
1734 * for any device_feature_select written by the driver
1735 */
1707 if (val == 0) 1736 if (val == 0)
1708 d->mmio->cfg.device_feature = d->features; 1737 d->mmio->cfg.device_feature = d->features;
1709 else if (val == 1) 1738 else if (val == 1)
@@ -1731,12 +1760,23 @@ static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask)
1731 goto write_through32; 1760 goto write_through32;
1732 case offsetof(struct virtio_pci_mmio, cfg.device_status): 1761 case offsetof(struct virtio_pci_mmio, cfg.device_status):
1733 verbose("%s: device status -> %#x\n", d->name, val); 1762 verbose("%s: device status -> %#x\n", d->name, val);
1763 /*
1764 * 4.1.4.3.1:
1765 *
1766 * The device MUST reset when 0 is written to device_status,
1767 * and present a 0 in device_status once that is done.
1768 */
1734 if (val == 0) 1769 if (val == 0)
1735 reset_device(d); 1770 reset_device(d);
1736 goto write_through8; 1771 goto write_through8;
1737 case offsetof(struct virtio_pci_mmio, cfg.queue_select): 1772 case offsetof(struct virtio_pci_mmio, cfg.queue_select):
1738 vq = vq_by_num(d, val); 1773 vq = vq_by_num(d, val);
1739 /* Out of range? Return size 0 */ 1774 /*
1775 * 4.1.4.3.1:
1776 *
1777 * The device MUST present a 0 in queue_size if the virtqueue
1778 * corresponding to the current queue_select is unavailable.
1779 */
1740 if (!vq) { 1780 if (!vq) {
1741 d->mmio->cfg.queue_size = 0; 1781 d->mmio->cfg.queue_size = 0;
1742 goto write_through16; 1782 goto write_through16;
@@ -1841,6 +1881,17 @@ static u32 emulate_mmio_read(struct device *d, u32 off, u32 mask)
1841 goto read_through16; 1881 goto read_through16;
1842 case offsetof(struct virtio_pci_mmio, cfg.device_status): 1882 case offsetof(struct virtio_pci_mmio, cfg.device_status):
1843 case offsetof(struct virtio_pci_mmio, cfg.config_generation): 1883 case offsetof(struct virtio_pci_mmio, cfg.config_generation):
1884 /*
1885 * 4.1.4.3.1:
1886 *
1887 * The device MUST present a changed config_generation after
1888 * the driver has read a device-specific configuration value
1889 * which has changed since any part of the device-specific
1890 * configuration was last read.
1891 *
1892 * This is simple: none of our devices change config, so this
1893 * is always 0.
1894 */
1844 goto read_through8; 1895 goto read_through8;
1845 case offsetof(struct virtio_pci_mmio, notify): 1896 case offsetof(struct virtio_pci_mmio, notify):
1846 goto read_through16; 1897 goto read_through16;
@@ -1848,8 +1899,12 @@ static u32 emulate_mmio_read(struct device *d, u32 off, u32 mask)
1848 if (mask != 0xFF) 1899 if (mask != 0xFF)
1849 errx(1, "%s: non-8-bit read from offset %u (%#x)", 1900 errx(1, "%s: non-8-bit read from offset %u (%#x)",
1850 d->name, off, getreg(eip)); 1901 d->name, off, getreg(eip));
1851 /* Read resets the isr */
1852 isr = d->mmio->isr; 1902 isr = d->mmio->isr;
1903 /*
1904 * 4.1.4.5.1:
1905 *
1906 * The device MUST reset ISR status to 0 on driver read.
1907 */
1853 d->mmio->isr = 0; 1908 d->mmio->isr = 0;
1854 return isr; 1909 return isr;
1855 case offsetof(struct virtio_pci_mmio, padding): 1910 case offsetof(struct virtio_pci_mmio, padding):
@@ -2008,10 +2063,25 @@ static void set_device_config(struct device *dev, const void *conf, size_t len)
2008 dev->mmio = realloc(dev->mmio, dev->mmio_size); 2063 dev->mmio = realloc(dev->mmio, dev->mmio_size);
2009 memcpy(dev->mmio + 1, conf, len); 2064 memcpy(dev->mmio + 1, conf, len);
2010 2065
2066 /*
2067 * 4.1.4.6:
2068 *
2069 * The device MUST present at least one VIRTIO_PCI_CAP_DEVICE_CFG
2070 * capability for any device type which has a device-specific
2071 * configuration.
2072 */
2011 /* Hook up device cfg */ 2073 /* Hook up device cfg */
2012 dev->config.cfg_access.cap.cap_next 2074 dev->config.cfg_access.cap.cap_next
2013 = offsetof(struct pci_config, device); 2075 = offsetof(struct pci_config, device);
2014 2076
2077 /*
2078 * 4.1.4.6.1:
2079 *
2080 * The offset for the device-specific configuration MUST be 4-byte
2081 * aligned.
2082 */
2083 assert(dev->config.cfg_access.cap.cap_next % 4 == 0);
2084
2015 /* Fix up device cfg field length. */ 2085 /* Fix up device cfg field length. */
2016 dev->config.device.length = len; 2086 dev->config.device.length = len;
2017 2087
@@ -2041,7 +2111,12 @@ static void init_pci_config(struct pci_config *pci, u16 type,
2041{ 2111{
2042 size_t bar_offset, bar_len; 2112 size_t bar_offset, bar_len;
2043 2113
2044 /* Save typing: most thing are happy being zero. */ 2114 /*
2115 * 4.1.4.4.1:
2116 *
2117 * The device MUST either present notify_off_multiplier as an even
2118 * power of 2, or present notify_off_multiplier as 0.
2119 */
2045 memset(pci, 0, sizeof(*pci)); 2120 memset(pci, 0, sizeof(*pci));
2046 2121
2047 /* 4.1.2.1: Devices MUST have the PCI Vendor ID 0x1AF4 */ 2122 /* 4.1.2.1: Devices MUST have the PCI Vendor ID 0x1AF4 */
@@ -2058,14 +2133,18 @@ static void init_pci_config(struct pci_config *pci, u16 type,
2058 pci->subclass = subclass; 2133 pci->subclass = subclass;
2059 2134
2060 /* 2135 /*
2061 * 4.1.2.1 Non-transitional devices SHOULD have a PCI Revision 2136 * 4.1.2.1:
2062 * ID of 1 or higher 2137 *
2138 * Non-transitional devices SHOULD have a PCI Revision ID of 1 or
2139 * higher
2063 */ 2140 */
2064 pci->revid = 1; 2141 pci->revid = 1;
2065 2142
2066 /* 2143 /*
2067 * 4.1.2.1 Non-transitional devices SHOULD have a PCI 2144 * 4.1.2.1:
2068 * Subsystem Device ID of 0x40 or higher. 2145 *
2146 * Non-transitional devices SHOULD have a PCI Subsystem Device ID of
2147 * 0x40 or higher.
2069 */ 2148 */
2070 pci->subsystem_device_id = 0x40; 2149 pci->subsystem_device_id = 0x40;
2071 2150
@@ -2077,17 +2156,48 @@ static void init_pci_config(struct pci_config *pci, u16 type,
2077 pci->status = (1 << 4); 2156 pci->status = (1 << 4);
2078 2157
2079 /* Link them in. */ 2158 /* Link them in. */
2159 /*
2160 * 4.1.4.3.1:
2161 *
2162 * The device MUST present at least one common configuration
2163 * capability.
2164 */
2080 pci->capabilities = offsetof(struct pci_config, common); 2165 pci->capabilities = offsetof(struct pci_config, common);
2081 2166
2167 /* 4.1.4.3.1 ... offset MUST be 4-byte aligned. */
2168 assert(pci->capabilities % 4 == 0);
2169
2082 bar_offset = offsetof(struct virtio_pci_mmio, cfg); 2170 bar_offset = offsetof(struct virtio_pci_mmio, cfg);
2083 bar_len = sizeof(((struct virtio_pci_mmio *)0)->cfg); 2171 bar_len = sizeof(((struct virtio_pci_mmio *)0)->cfg);
2084 init_cap(&pci->common, sizeof(pci->common), VIRTIO_PCI_CAP_COMMON_CFG, 2172 init_cap(&pci->common, sizeof(pci->common), VIRTIO_PCI_CAP_COMMON_CFG,
2085 bar_offset, bar_len, 2173 bar_offset, bar_len,
2086 offsetof(struct pci_config, notify)); 2174 offsetof(struct pci_config, notify));
2087 2175
2176 /*
2177 * 4.1.4.4.1:
2178 *
2179 * The device MUST present at least one notification capability.
2180 */
2088 bar_offset += bar_len; 2181 bar_offset += bar_len;
2089 bar_len = sizeof(((struct virtio_pci_mmio *)0)->notify); 2182 bar_len = sizeof(((struct virtio_pci_mmio *)0)->notify);
2183
2184 /*
2185 * 4.1.4.4.1:
2186 *
2187 * The cap.offset MUST be 2-byte aligned.
2188 */
2189 assert(pci->common.cap_next % 2 == 0);
2190
2090 /* FIXME: Use a non-zero notify_off, for per-queue notification? */ 2191 /* FIXME: Use a non-zero notify_off, for per-queue notification? */
2192 /*
2193 * 4.1.4.4.1:
2194 *
2195 * The value cap.length presented by the device MUST be at least 2 and
2196 * MUST be large enough to support queue notification offsets for all
2197 * supported queues in all possible configurations.
2198 */
2199 assert(bar_len >= 2);
2200
2091 init_cap(&pci->notify.cap, sizeof(pci->notify), 2201 init_cap(&pci->notify.cap, sizeof(pci->notify),
2092 VIRTIO_PCI_CAP_NOTIFY_CFG, 2202 VIRTIO_PCI_CAP_NOTIFY_CFG,
2093 bar_offset, bar_len, 2203 bar_offset, bar_len,
@@ -2095,11 +2205,23 @@ static void init_pci_config(struct pci_config *pci, u16 type,
2095 2205
2096 bar_offset += bar_len; 2206 bar_offset += bar_len;
2097 bar_len = sizeof(((struct virtio_pci_mmio *)0)->isr); 2207 bar_len = sizeof(((struct virtio_pci_mmio *)0)->isr);
2208 /*
2209 * 4.1.4.5.1:
2210 *
2211 * The device MUST present at least one VIRTIO_PCI_CAP_ISR_CFG
2212 * capability.
2213 */
2098 init_cap(&pci->isr, sizeof(pci->isr), 2214 init_cap(&pci->isr, sizeof(pci->isr),
2099 VIRTIO_PCI_CAP_ISR_CFG, 2215 VIRTIO_PCI_CAP_ISR_CFG,
2100 bar_offset, bar_len, 2216 bar_offset, bar_len,
2101 offsetof(struct pci_config, cfg_access)); 2217 offsetof(struct pci_config, cfg_access));
2102 2218
2219 /*
2220 * 4.1.4.7.1:
2221 *
2222 * The device MUST present at least one VIRTIO_PCI_CAP_PCI_CFG
2223 * capability.
2224 */
2103 /* This doesn't have any presence in the BAR */ 2225 /* This doesn't have any presence in the BAR */
2104 init_cap(&pci->cfg_access.cap, sizeof(pci->cfg_access), 2226 init_cap(&pci->cfg_access.cap, sizeof(pci->cfg_access),
2105 VIRTIO_PCI_CAP_PCI_CFG, 2227 VIRTIO_PCI_CAP_PCI_CFG,