aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/lguest/lguest.c492
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;
63typedef uint8_t u8; 63typedef 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. */
127static struct device_list devices; 131static struct device_list devices;
128 132
133struct virtio_pci_cfg_cap {
134 struct virtio_pci_cap cap;
135 u32 window; /* Data for BAR access. */
136};
137
138struct 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. */
130struct pci_config { 147struct 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. */
1655static 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
1665static void save_vq_config(const struct virtio_pci_common_cfg *cfg,
1666 struct virtqueue *vq)
1667{
1668 vq->pci_config = *cfg;
1669}
1670
1671static 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 */
1684static 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
1726static void reset_pci_device(struct device *dev)
1727{
1728 /* FIXME */
1729}
1730
1619static void emulate_mmio_write(struct device *d, u32 off, u32 val, u32 mask) 1731static 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
1824write_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
1833write_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
1840write_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
1623static u32 emulate_mmio_read(struct device *d, u32 off, u32 mask) 1848static 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
1892read_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
1899read_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
1906read_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
1628static void emulate_mmio(unsigned long paddr, const u8 *insn) 1914static 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
2072static 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
2125static 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. */
2150static 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 */
2160static 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
2178static 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 */
2195static 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
2317static 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.