summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
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,