diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/lguest/lguest.c | 492 |
1 files changed, 490 insertions, 2 deletions
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index 0f29657fc065..eafdaf2a14c4 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c | |||
@@ -63,12 +63,16 @@ typedef uint16_t u16; | |||
63 | typedef uint8_t u8; | 63 | typedef uint8_t u8; |
64 | /*:*/ | 64 | /*:*/ |
65 | 65 | ||
66 | #include <linux/virtio_config.h> | 66 | #define VIRTIO_PCI_NO_LEGACY |
67 | |||
68 | /* Use in-kernel ones, which defines VIRTIO_F_VERSION_1 */ | ||
69 | #include "../../include/uapi/linux/virtio_config.h" | ||
67 | #include <linux/virtio_net.h> | 70 | #include <linux/virtio_net.h> |
68 | #include <linux/virtio_blk.h> | 71 | #include <linux/virtio_blk.h> |
69 | #include <linux/virtio_console.h> | 72 | #include <linux/virtio_console.h> |
70 | #include <linux/virtio_rng.h> | 73 | #include <linux/virtio_rng.h> |
71 | #include <linux/virtio_ring.h> | 74 | #include <linux/virtio_ring.h> |
75 | #include "../../include/uapi/linux/virtio_pci.h" | ||
72 | #include <asm/bootparam.h> | 76 | #include <asm/bootparam.h> |
73 | #include "../../include/linux/lguest_launcher.h" | 77 | #include "../../include/linux/lguest_launcher.h" |
74 | 78 | ||
@@ -126,6 +130,19 @@ struct device_list { | |||
126 | /* The list of Guest devices, based on command line arguments. */ | 130 | /* The list of Guest devices, based on command line arguments. */ |
127 | static struct device_list devices; | 131 | static struct device_list devices; |
128 | 132 | ||
133 | struct virtio_pci_cfg_cap { | ||
134 | struct virtio_pci_cap cap; | ||
135 | u32 window; /* Data for BAR access. */ | ||
136 | }; | ||
137 | |||
138 | struct virtio_pci_mmio { | ||
139 | struct virtio_pci_common_cfg cfg; | ||
140 | u16 notify; | ||
141 | u8 isr; | ||
142 | u8 padding; | ||
143 | /* Device-specific configuration follows this. */ | ||
144 | }; | ||
145 | |||
129 | /* This is the layout (little-endian) of the PCI config space. */ | 146 | /* This is the layout (little-endian) of the PCI config space. */ |
130 | struct pci_config { | 147 | struct pci_config { |
131 | u16 vendor_id, device_id; | 148 | u16 vendor_id, device_id; |
@@ -139,6 +156,14 @@ struct pci_config { | |||
139 | u8 capabilities, reserved1[3]; | 156 | u8 capabilities, reserved1[3]; |
140 | u32 reserved2; | 157 | u32 reserved2; |
141 | u8 irq_line, irq_pin, min_grant, max_latency; | 158 | u8 irq_line, irq_pin, min_grant, max_latency; |
159 | |||
160 | /* Now, this is the linked capability list. */ | ||
161 | struct virtio_pci_cap common; | ||
162 | struct virtio_pci_notify_cap notify; | ||
163 | struct virtio_pci_cap isr; | ||
164 | struct virtio_pci_cap device; | ||
165 | /* FIXME: Implement this! */ | ||
166 | struct virtio_pci_cfg_cap cfg_access; | ||
142 | }; | 167 | }; |
143 | 168 | ||
144 | /* The device structure describes a single device. */ | 169 | /* The device structure describes a single device. */ |
@@ -168,6 +193,9 @@ struct device { | |||
168 | u32 config_words[sizeof(struct pci_config) / sizeof(u32)]; | 193 | u32 config_words[sizeof(struct pci_config) / sizeof(u32)]; |
169 | }; | 194 | }; |
170 | 195 | ||
196 | /* Features we offer, and those accepted. */ | ||
197 | u64 features, features_accepted; | ||
198 | |||
171 | /* Device-specific config hangs off the end of this. */ | 199 | /* Device-specific config hangs off the end of this. */ |
172 | struct virtio_pci_mmio *mmio; | 200 | struct virtio_pci_mmio *mmio; |
173 | 201 | ||
@@ -192,6 +220,9 @@ struct virtqueue { | |||
192 | /* The actual ring of buffers. */ | 220 | /* The actual ring of buffers. */ |
193 | struct vring vring; | 221 | struct vring vring; |
194 | 222 | ||
223 | /* The information about this virtqueue (we only use queue_size on) */ | ||
224 | struct virtio_pci_common_cfg pci_config; | ||
225 | |||
195 | /* Last available index we saw. */ | 226 | /* Last available index we saw. */ |
196 | u16 last_avail_idx; | 227 | u16 last_avail_idx; |
197 | 228 | ||
@@ -680,6 +711,10 @@ static void trigger_irq(struct virtqueue *vq) | |||
680 | return; | 711 | return; |
681 | } | 712 | } |
682 | 713 | ||
714 | /* For a PCI device, set isr to 1 (queue interrupt pending) */ | ||
715 | if (vq->dev->mmio) | ||
716 | vq->dev->mmio->isr = 0x1; | ||
717 | |||
683 | /* Send the Guest an interrupt tell them we used something up. */ | 718 | /* Send the Guest an interrupt tell them we used something up. */ |
684 | if (write(lguest_fd, buf, sizeof(buf)) != 0) | 719 | if (write(lguest_fd, buf, sizeof(buf)) != 0) |
685 | err(1, "Triggering irq %i", vq->config.irq); | 720 | err(1, "Triggering irq %i", vq->config.irq); |
@@ -1616,13 +1651,264 @@ static struct device *find_mmio_region(unsigned long paddr, u32 *off) | |||
1616 | return NULL; | 1651 | return NULL; |
1617 | } | 1652 | } |
1618 | 1653 | ||
1654 | /* FIXME: Use vq array. */ | ||
1655 | static struct virtqueue *vq_by_num(struct device *d, u32 num) | ||
1656 | { | ||
1657 | struct virtqueue *vq = d->vq; | ||
1658 | |||
1659 | while (num-- && vq) | ||
1660 | vq = vq->next; | ||
1661 | |||
1662 | return vq; | ||
1663 | } | ||
1664 | |||
1665 | static void save_vq_config(const struct virtio_pci_common_cfg *cfg, | ||
1666 | struct virtqueue *vq) | ||
1667 | { | ||
1668 | vq->pci_config = *cfg; | ||
1669 | } | ||
1670 | |||
1671 | static void restore_vq_config(struct virtio_pci_common_cfg *cfg, | ||
1672 | struct virtqueue *vq) | ||
1673 | { | ||
1674 | /* Only restore the per-vq part */ | ||
1675 | size_t off = offsetof(struct virtio_pci_common_cfg, queue_size); | ||
1676 | |||
1677 | memcpy((void *)cfg + off, (void *)&vq->pci_config + off, | ||
1678 | sizeof(*cfg) - off); | ||
1679 | } | ||
1680 | |||
1681 | /* | ||
1682 | * When they enable the virtqueue, we check that their setup is valid. | ||
1683 | */ | ||
1684 | static void enable_virtqueue(struct device *d, struct virtqueue *vq) | ||
1685 | { | ||
1686 | /* | ||
1687 | * Create stack for thread. Since the stack grows upwards, we point | ||
1688 | * the stack pointer to the end of this region. | ||
1689 | */ | ||
1690 | char *stack = malloc(32768); | ||
1691 | |||
1692 | /* Because lguest is 32 bit, all the descriptor high bits must be 0 */ | ||
1693 | if (vq->pci_config.queue_desc_hi | ||
1694 | || vq->pci_config.queue_avail_hi | ||
1695 | || vq->pci_config.queue_used_hi) | ||
1696 | errx(1, "%s: invalid 64-bit queue address", d->name); | ||
1697 | |||
1698 | /* Initialize the virtqueue and check they're all in range. */ | ||
1699 | vq->vring.num = vq->pci_config.queue_size; | ||
1700 | vq->vring.desc = check_pointer(vq->pci_config.queue_desc_lo, | ||
1701 | sizeof(*vq->vring.desc) * vq->vring.num); | ||
1702 | vq->vring.avail = check_pointer(vq->pci_config.queue_avail_lo, | ||
1703 | sizeof(*vq->vring.avail) | ||
1704 | + (sizeof(vq->vring.avail->ring[0]) | ||
1705 | * vq->vring.num)); | ||
1706 | vq->vring.used = check_pointer(vq->pci_config.queue_used_lo, | ||
1707 | sizeof(*vq->vring.used) | ||
1708 | + (sizeof(vq->vring.used->ring[0]) | ||
1709 | * vq->vring.num)); | ||
1710 | |||
1711 | |||
1712 | /* Create a zero-initialized eventfd. */ | ||
1713 | vq->eventfd = eventfd(0, 0); | ||
1714 | if (vq->eventfd < 0) | ||
1715 | err(1, "Creating eventfd"); | ||
1716 | |||
1717 | /* | ||
1718 | * CLONE_VM: because it has to access the Guest memory, and SIGCHLD so | ||
1719 | * we get a signal if it dies. | ||
1720 | */ | ||
1721 | vq->thread = clone(do_thread, stack + 32768, CLONE_VM | SIGCHLD, vq); | ||
1722 | if (vq->thread == (pid_t)-1) | ||
1723 | err(1, "Creating clone"); | ||
1724 | } | ||
1725 | |||
1726 | static void reset_pci_device(struct device *dev) | ||
1727 | { | ||
1728 | /* FIXME */ | ||
1729 | } | ||
1730 | |||
1619 | static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) | 1731 | static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) |
1620 | { | 1732 | { |
1733 | struct virtqueue *vq; | ||
1734 | |||
1735 | switch (off) { | ||
1736 | case offsetof(struct virtio_pci_mmio, cfg.device_feature_select): | ||
1737 | if (val == 0) | ||
1738 | d->mmio->cfg.device_feature = d->features; | ||
1739 | else if (val == 1) | ||
1740 | d->mmio->cfg.device_feature = (d->features >> 32); | ||
1741 | else | ||
1742 | d->mmio->cfg.device_feature = 0; | ||
1743 | goto write_through32; | ||
1744 | case offsetof(struct virtio_pci_mmio, cfg.guest_feature_select): | ||
1745 | if (val > 1) | ||
1746 | errx(1, "%s: Unexpected driver select %u", | ||
1747 | d->name, val); | ||
1748 | goto write_through32; | ||
1749 | case offsetof(struct virtio_pci_mmio, cfg.guest_feature): | ||
1750 | if (d->mmio->cfg.guest_feature_select == 0) { | ||
1751 | d->features_accepted &= ~((u64)0xFFFFFFFF); | ||
1752 | d->features_accepted |= val; | ||
1753 | } else { | ||
1754 | assert(d->mmio->cfg.guest_feature_select == 1); | ||
1755 | d->features_accepted &= ((u64)0xFFFFFFFF << 32); | ||
1756 | d->features_accepted |= ((u64)val) << 32; | ||
1757 | } | ||
1758 | if (d->features_accepted & ~d->features) | ||
1759 | errx(1, "%s: over-accepted features %#llx of %#llx", | ||
1760 | d->name, d->features_accepted, d->features); | ||
1761 | goto write_through32; | ||
1762 | case offsetof(struct virtio_pci_mmio, cfg.device_status): | ||
1763 | verbose("%s: device status -> %#x\n", d->name, val); | ||
1764 | if (val == 0) | ||
1765 | reset_pci_device(d); | ||
1766 | goto write_through8; | ||
1767 | case offsetof(struct virtio_pci_mmio, cfg.queue_select): | ||
1768 | vq = vq_by_num(d, val); | ||
1769 | /* Out of range? Return size 0 */ | ||
1770 | if (!vq) { | ||
1771 | d->mmio->cfg.queue_size = 0; | ||
1772 | goto write_through16; | ||
1773 | } | ||
1774 | /* Save registers for old vq, if it was a valid vq */ | ||
1775 | if (d->mmio->cfg.queue_size) | ||
1776 | save_vq_config(&d->mmio->cfg, | ||
1777 | vq_by_num(d, d->mmio->cfg.queue_select)); | ||
1778 | /* Restore the registers for the queue they asked for */ | ||
1779 | restore_vq_config(&d->mmio->cfg, vq); | ||
1780 | goto write_through16; | ||
1781 | case offsetof(struct virtio_pci_mmio, cfg.queue_size): | ||
1782 | if (val & (val-1)) | ||
1783 | errx(1, "%s: invalid queue size %u\n", d->name, val); | ||
1784 | if (d->mmio->cfg.queue_enable) | ||
1785 | errx(1, "%s: changing queue size on live device", | ||
1786 | d->name); | ||
1787 | goto write_through16; | ||
1788 | case offsetof(struct virtio_pci_mmio, cfg.queue_msix_vector): | ||
1789 | errx(1, "%s: attempt to set MSIX vector to %u", | ||
1790 | d->name, val); | ||
1791 | case offsetof(struct virtio_pci_mmio, cfg.queue_enable): | ||
1792 | if (val != 1) | ||
1793 | errx(1, "%s: setting queue_enable to %u", d->name, val); | ||
1794 | d->mmio->cfg.queue_enable = val; | ||
1795 | save_vq_config(&d->mmio->cfg, | ||
1796 | vq_by_num(d, d->mmio->cfg.queue_select)); | ||
1797 | enable_virtqueue(d, vq_by_num(d, d->mmio->cfg.queue_select)); | ||
1798 | goto write_through16; | ||
1799 | case offsetof(struct virtio_pci_mmio, cfg.queue_notify_off): | ||
1800 | errx(1, "%s: attempt to write to queue_notify_off", d->name); | ||
1801 | case offsetof(struct virtio_pci_mmio, cfg.queue_desc_lo): | ||
1802 | case offsetof(struct virtio_pci_mmio, cfg.queue_desc_hi): | ||
1803 | case offsetof(struct virtio_pci_mmio, cfg.queue_avail_lo): | ||
1804 | case offsetof(struct virtio_pci_mmio, cfg.queue_avail_hi): | ||
1805 | case offsetof(struct virtio_pci_mmio, cfg.queue_used_lo): | ||
1806 | case offsetof(struct virtio_pci_mmio, cfg.queue_used_hi): | ||
1807 | if (d->mmio->cfg.queue_enable) | ||
1808 | errx(1, "%s: changing queue on live device", | ||
1809 | d->name); | ||
1810 | goto write_through32; | ||
1811 | case offsetof(struct virtio_pci_mmio, notify): | ||
1812 | vq = vq_by_num(d, val); | ||
1813 | if (!vq) | ||
1814 | errx(1, "Invalid vq notification on %u", val); | ||
1815 | /* Notify the process handling this vq by adding 1 to eventfd */ | ||
1816 | write(vq->eventfd, "\1\0\0\0\0\0\0\0", 8); | ||
1817 | goto write_through16; | ||
1818 | case offsetof(struct virtio_pci_mmio, isr): | ||
1819 | errx(1, "%s: Unexpected write to isr", d->name); | ||
1820 | default: | ||
1821 | errx(1, "%s: Unexpected write to offset %u", d->name, off); | ||
1822 | } | ||
1823 | |||
1824 | write_through32: | ||
1825 | if (mask != 0xFFFFFFFF) { | ||
1826 | errx(1, "%s: non-32-bit write to offset %u (%#x)", | ||
1827 | d->name, off, getreg(eip)); | ||
1828 | return; | ||
1829 | } | ||
1830 | memcpy((char *)d->mmio + off, &val, 4); | ||
1831 | return; | ||
1832 | |||
1833 | write_through16: | ||
1834 | if (mask != 0xFFFF) | ||
1835 | errx(1, "%s: non-16-bit (%#x) write to offset %u (%#x)", | ||
1836 | d->name, mask, off, getreg(eip)); | ||
1837 | memcpy((char *)d->mmio + off, &val, 2); | ||
1838 | return; | ||
1839 | |||
1840 | write_through8: | ||
1841 | if (mask != 0xFF) | ||
1842 | errx(1, "%s: non-8-bit write to offset %u (%#x)", | ||
1843 | d->name, off, getreg(eip)); | ||
1844 | memcpy((char *)d->mmio + off, &val, 1); | ||
1845 | return; | ||
1621 | } | 1846 | } |
1622 | 1847 | ||
1623 | static u32 emulate_mmio_read(struct device *d, u32 off, u32 mask) | 1848 | static u32 emulate_mmio_read(struct device *d, u32 off, u32 mask) |
1624 | { | 1849 | { |
1625 | return 0xFFFFFFFF; | 1850 | u8 isr; |
1851 | u32 val = 0; | ||
1852 | |||
1853 | switch (off) { | ||
1854 | case offsetof(struct virtio_pci_mmio, cfg.device_feature_select): | ||
1855 | case offsetof(struct virtio_pci_mmio, cfg.device_feature): | ||
1856 | case offsetof(struct virtio_pci_mmio, cfg.guest_feature_select): | ||
1857 | case offsetof(struct virtio_pci_mmio, cfg.guest_feature): | ||
1858 | goto read_through32; | ||
1859 | case offsetof(struct virtio_pci_mmio, cfg.msix_config): | ||
1860 | errx(1, "%s: read of msix_config", d->name); | ||
1861 | case offsetof(struct virtio_pci_mmio, cfg.num_queues): | ||
1862 | goto read_through16; | ||
1863 | case offsetof(struct virtio_pci_mmio, cfg.device_status): | ||
1864 | case offsetof(struct virtio_pci_mmio, cfg.config_generation): | ||
1865 | goto read_through8; | ||
1866 | case offsetof(struct virtio_pci_mmio, notify): | ||
1867 | goto read_through16; | ||
1868 | case offsetof(struct virtio_pci_mmio, isr): | ||
1869 | if (mask != 0xFF) | ||
1870 | errx(1, "%s: non-8-bit read from offset %u (%#x)", | ||
1871 | d->name, off, getreg(eip)); | ||
1872 | /* Read resets the isr */ | ||
1873 | isr = d->mmio->isr; | ||
1874 | d->mmio->isr = 0; | ||
1875 | return isr; | ||
1876 | case offsetof(struct virtio_pci_mmio, padding): | ||
1877 | errx(1, "%s: read from padding (%#x)", | ||
1878 | d->name, getreg(eip)); | ||
1879 | default: | ||
1880 | /* Read from device config space, beware unaligned overflow */ | ||
1881 | if (off > d->mmio_size - 4) | ||
1882 | errx(1, "%s: read past end (%#x)", | ||
1883 | d->name, getreg(eip)); | ||
1884 | if (mask == 0xFFFFFFFF) | ||
1885 | goto read_through32; | ||
1886 | else if (mask == 0xFFFF) | ||
1887 | goto read_through16; | ||
1888 | else | ||
1889 | goto read_through8; | ||
1890 | } | ||
1891 | |||
1892 | read_through32: | ||
1893 | if (mask != 0xFFFFFFFF) | ||
1894 | errx(1, "%s: non-32-bit read to offset %u (%#x)", | ||
1895 | d->name, off, getreg(eip)); | ||
1896 | memcpy(&val, (char *)d->mmio + off, 4); | ||
1897 | return val; | ||
1898 | |||
1899 | read_through16: | ||
1900 | if (mask != 0xFFFF) | ||
1901 | errx(1, "%s: non-16-bit read to offset %u (%#x)", | ||
1902 | d->name, off, getreg(eip)); | ||
1903 | memcpy(&val, (char *)d->mmio + off, 2); | ||
1904 | return val; | ||
1905 | |||
1906 | read_through8: | ||
1907 | if (mask != 0xFF) | ||
1908 | errx(1, "%s: non-8-bit read to offset %u (%#x)", | ||
1909 | d->name, off, getreg(eip)); | ||
1910 | memcpy(&val, (char *)d->mmio + off, 1); | ||
1911 | return val; | ||
1626 | } | 1912 | } |
1627 | 1913 | ||
1628 | static void emulate_mmio(unsigned long paddr, const u8 *insn) | 1914 | static void emulate_mmio(unsigned long paddr, const u8 *insn) |
@@ -1783,6 +2069,42 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, | |||
1783 | *i = vq; | 2069 | *i = vq; |
1784 | } | 2070 | } |
1785 | 2071 | ||
2072 | static void add_pci_virtqueue(struct device *dev, | ||
2073 | void (*service)(struct virtqueue *)) | ||
2074 | { | ||
2075 | struct virtqueue **i, *vq = malloc(sizeof(*vq)); | ||
2076 | |||
2077 | /* Initialize the virtqueue */ | ||
2078 | vq->next = NULL; | ||
2079 | vq->last_avail_idx = 0; | ||
2080 | vq->dev = dev; | ||
2081 | |||
2082 | /* | ||
2083 | * This is the routine the service thread will run, and its Process ID | ||
2084 | * once it's running. | ||
2085 | */ | ||
2086 | vq->service = service; | ||
2087 | vq->thread = (pid_t)-1; | ||
2088 | |||
2089 | /* Initialize the configuration. */ | ||
2090 | vq->pci_config.queue_size = VIRTQUEUE_NUM; | ||
2091 | vq->pci_config.queue_enable = 0; | ||
2092 | vq->pci_config.queue_notify_off = 0; | ||
2093 | |||
2094 | /* Add one to the number of queues */ | ||
2095 | vq->dev->mmio->cfg.num_queues++; | ||
2096 | |||
2097 | /* FIXME: Do irq per virtqueue, not per device. */ | ||
2098 | vq->config.irq = vq->dev->config.irq_line; | ||
2099 | |||
2100 | /* | ||
2101 | * Add to tail of list, so dev->vq is first vq, dev->vq->next is | ||
2102 | * second. | ||
2103 | */ | ||
2104 | for (i = &dev->vq; *i; i = &(*i)->next); | ||
2105 | *i = vq; | ||
2106 | } | ||
2107 | |||
1786 | /* | 2108 | /* |
1787 | * The first half of the feature bitmask is for us to advertise features. The | 2109 | * The first half of the feature bitmask is for us to advertise features. The |
1788 | * second half is for the Guest to accept features. | 2110 | * second half is for the Guest to accept features. |
@@ -1800,6 +2122,11 @@ static void add_feature(struct device *dev, unsigned bit) | |||
1800 | features[bit / CHAR_BIT] |= (1 << (bit % CHAR_BIT)); | 2122 | features[bit / CHAR_BIT] |= (1 << (bit % CHAR_BIT)); |
1801 | } | 2123 | } |
1802 | 2124 | ||
2125 | static void add_pci_feature(struct device *dev, unsigned bit) | ||
2126 | { | ||
2127 | dev->features |= (1ULL << bit); | ||
2128 | } | ||
2129 | |||
1803 | /* | 2130 | /* |
1804 | * This routine sets the configuration fields for an existing device's | 2131 | * This routine sets the configuration fields for an existing device's |
1805 | * descriptor. It only works for the last device, but that's OK because that's | 2132 | * descriptor. It only works for the last device, but that's OK because that's |
@@ -1819,6 +2146,139 @@ static void set_config(struct device *dev, unsigned len, const void *conf) | |||
1819 | assert(dev->desc->config_len == len); | 2146 | assert(dev->desc->config_len == len); |
1820 | } | 2147 | } |
1821 | 2148 | ||
2149 | /* For devices with no config. */ | ||
2150 | static void no_device_config(struct device *dev) | ||
2151 | { | ||
2152 | dev->mmio_addr = get_mmio_region(dev->mmio_size); | ||
2153 | |||
2154 | dev->config.bar[0] = dev->mmio_addr; | ||
2155 | /* Bottom 4 bits must be zero */ | ||
2156 | assert(~(dev->config.bar[0] & 0xF)); | ||
2157 | } | ||
2158 | |||
2159 | /* This puts the device config into BAR0 */ | ||
2160 | static void set_device_config(struct device *dev, const void *conf, size_t len) | ||
2161 | { | ||
2162 | /* Set up BAR 0 */ | ||
2163 | dev->mmio_size += len; | ||
2164 | dev->mmio = realloc(dev->mmio, dev->mmio_size); | ||
2165 | memcpy(dev->mmio + 1, conf, len); | ||
2166 | |||
2167 | /* Hook up device cfg */ | ||
2168 | dev->config.cfg_access.cap.cap_next | ||
2169 | = offsetof(struct pci_config, device); | ||
2170 | |||
2171 | /* Fix up device cfg field length. */ | ||
2172 | dev->config.device.length = len; | ||
2173 | |||
2174 | /* The rest is the same as the no-config case */ | ||
2175 | no_device_config(dev); | ||
2176 | } | ||
2177 | |||
2178 | static void init_cap(struct virtio_pci_cap *cap, size_t caplen, int type, | ||
2179 | size_t bar_offset, size_t bar_bytes, u8 next) | ||
2180 | { | ||
2181 | cap->cap_vndr = PCI_CAP_ID_VNDR; | ||
2182 | cap->cap_next = next; | ||
2183 | cap->cap_len = caplen; | ||
2184 | cap->cfg_type = type; | ||
2185 | cap->bar = 0; | ||
2186 | memset(cap->padding, 0, sizeof(cap->padding)); | ||
2187 | cap->offset = bar_offset; | ||
2188 | cap->length = bar_bytes; | ||
2189 | } | ||
2190 | |||
2191 | /* | ||
2192 | * This sets up the pci_config structure, as defined in the virtio 1.0 | ||
2193 | * standard (and PCI standard). | ||
2194 | */ | ||
2195 | static void init_pci_config(struct pci_config *pci, u16 type, | ||
2196 | u8 class, u8 subclass) | ||
2197 | { | ||
2198 | size_t bar_offset, bar_len; | ||
2199 | |||
2200 | /* Save typing: most thing are happy being zero. */ | ||
2201 | memset(pci, 0, sizeof(*pci)); | ||
2202 | |||
2203 | /* 4.1.2.1: Devices MUST have the PCI Vendor ID 0x1AF4 */ | ||
2204 | pci->vendor_id = 0x1AF4; | ||
2205 | /* 4.1.2.1: ... PCI Device ID calculated by adding 0x1040 ... */ | ||
2206 | pci->device_id = 0x1040 + type; | ||
2207 | |||
2208 | /* | ||
2209 | * PCI have specific codes for different types of devices. | ||
2210 | * Linux doesn't care, but it's a good clue for people looking | ||
2211 | * at the device. | ||
2212 | * | ||
2213 | * eg : | ||
2214 | * VIRTIO_ID_CONSOLE: class = 0x07, subclass = 0x00 | ||
2215 | * VIRTIO_ID_NET: class = 0x02, subclass = 0x00 | ||
2216 | * VIRTIO_ID_BLOCK: class = 0x01, subclass = 0x80 | ||
2217 | * VIRTIO_ID_RNG: class = 0xff, subclass = 0 | ||
2218 | */ | ||
2219 | pci->class = class; | ||
2220 | pci->subclass = subclass; | ||
2221 | |||
2222 | /* | ||
2223 | * 4.1.2.1 Non-transitional devices SHOULD have a PCI Revision | ||
2224 | * ID of 1 or higher | ||
2225 | */ | ||
2226 | pci->revid = 1; | ||
2227 | |||
2228 | /* | ||
2229 | * 4.1.2.1 Non-transitional devices SHOULD have a PCI | ||
2230 | * Subsystem Device ID of 0x40 or higher. | ||
2231 | */ | ||
2232 | pci->subsystem_device_id = 0x40; | ||
2233 | |||
2234 | /* We use our dummy interrupt controller, and irq_line is the irq */ | ||
2235 | pci->irq_line = devices.next_irq++; | ||
2236 | pci->irq_pin = 0; | ||
2237 | |||
2238 | /* Support for extended capabilities. */ | ||
2239 | pci->status = (1 << 4); | ||
2240 | |||
2241 | /* Link them in. */ | ||
2242 | pci->capabilities = offsetof(struct pci_config, common); | ||
2243 | |||
2244 | bar_offset = offsetof(struct virtio_pci_mmio, cfg); | ||
2245 | bar_len = sizeof(((struct virtio_pci_mmio *)0)->cfg); | ||
2246 | init_cap(&pci->common, sizeof(pci->common), VIRTIO_PCI_CAP_COMMON_CFG, | ||
2247 | bar_offset, bar_len, | ||
2248 | offsetof(struct pci_config, notify)); | ||
2249 | |||
2250 | bar_offset += bar_len; | ||
2251 | bar_len = sizeof(((struct virtio_pci_mmio *)0)->notify); | ||
2252 | /* FIXME: Use a non-zero notify_off, for per-queue notification? */ | ||
2253 | init_cap(&pci->notify.cap, sizeof(pci->notify), | ||
2254 | VIRTIO_PCI_CAP_NOTIFY_CFG, | ||
2255 | bar_offset, bar_len, | ||
2256 | offsetof(struct pci_config, isr)); | ||
2257 | |||
2258 | bar_offset += bar_len; | ||
2259 | bar_len = sizeof(((struct virtio_pci_mmio *)0)->isr); | ||
2260 | init_cap(&pci->isr, sizeof(pci->isr), | ||
2261 | VIRTIO_PCI_CAP_ISR_CFG, | ||
2262 | bar_offset, bar_len, | ||
2263 | offsetof(struct pci_config, cfg_access)); | ||
2264 | |||
2265 | /* This doesn't have any presence in the BAR */ | ||
2266 | init_cap(&pci->cfg_access.cap, sizeof(pci->cfg_access), | ||
2267 | VIRTIO_PCI_CAP_PCI_CFG, | ||
2268 | 0, 0, 0); | ||
2269 | |||
2270 | bar_offset += bar_len + sizeof(((struct virtio_pci_mmio *)0)->padding); | ||
2271 | assert(bar_offset == sizeof(struct virtio_pci_mmio)); | ||
2272 | |||
2273 | /* | ||
2274 | * This gets sewn in and length set in set_device_config(). | ||
2275 | * Some devices don't have a device configuration interface, so | ||
2276 | * we never expose this if we don't call set_device_config(). | ||
2277 | */ | ||
2278 | init_cap(&pci->device, sizeof(pci->device), VIRTIO_PCI_CAP_DEVICE_CFG, | ||
2279 | bar_offset, 0, 0); | ||
2280 | } | ||
2281 | |||
1822 | /* | 2282 | /* |
1823 | * This routine does all the creation and setup of a new device, including | 2283 | * This routine does all the creation and setup of a new device, including |
1824 | * calling new_dev_desc() to allocate the descriptor and device memory. We | 2284 | * calling new_dev_desc() to allocate the descriptor and device memory. We |
@@ -1854,6 +2314,34 @@ static struct device *new_device(const char *name, u16 type) | |||
1854 | return dev; | 2314 | return dev; |
1855 | } | 2315 | } |
1856 | 2316 | ||
2317 | static struct device *new_pci_device(const char *name, u16 type, | ||
2318 | u8 class, u8 subclass) | ||
2319 | { | ||
2320 | struct device *dev = malloc(sizeof(*dev)); | ||
2321 | |||
2322 | /* Now we populate the fields one at a time. */ | ||
2323 | dev->desc = NULL; | ||
2324 | dev->name = name; | ||
2325 | dev->vq = NULL; | ||
2326 | dev->feature_len = 0; | ||
2327 | dev->num_vq = 0; | ||
2328 | dev->running = false; | ||
2329 | dev->next = NULL; | ||
2330 | dev->mmio_size = sizeof(struct virtio_pci_mmio); | ||
2331 | dev->mmio = calloc(1, dev->mmio_size); | ||
2332 | dev->features = (u64)1 << VIRTIO_F_VERSION_1; | ||
2333 | dev->features_accepted = 0; | ||
2334 | |||
2335 | if (devices.device_num + 1 >= 32) | ||
2336 | errx(1, "Can only handle 31 PCI devices"); | ||
2337 | |||
2338 | init_pci_config(&dev->config, type, class, subclass); | ||
2339 | assert(!devices.pci[devices.device_num+1]); | ||
2340 | devices.pci[++devices.device_num] = dev; | ||
2341 | |||
2342 | return dev; | ||
2343 | } | ||
2344 | |||
1857 | /* | 2345 | /* |
1858 | * Our first setup routine is the console. It's a fairly simple device, but | 2346 | * Our first setup routine is the console. It's a fairly simple device, but |
1859 | * UNIX tty handling makes it uglier than it could be. | 2347 | * UNIX tty handling makes it uglier than it could be. |