Thanks! I tried scripts/run.py --virtio modern with network and disk, and it seems to be working, so I've committed this series.
-- Nadav Har'El [email protected] On Wed, Feb 6, 2019 at 3:29 PM Waldemar Kozaczuk <[email protected]> wrote: > This patch implements modern virtio PCI device > and makes necessary changes to virtio drivers > to behave slighlt differently whether it is > a modern or legacy device. > > Please note that QEMU can emulate virtio device > as legacy, modern or transitional (default) one. The transitional > means that device can act as either legacy or modern. > Currently OSv would detect transitional device > as legacy one and use it as such. In the future > we may change OSv to do the opposite once we feel > comfortable that modern virtio PCI implementation > in OSv is correct. > > You can run OSv with modern, legacy or transitional > devices simulated by QEMU by passing correct > value of a new '--virtio' parameter to scripts/run.py. > > Signed-off-by: Waldemar Kozaczuk <[email protected]> > --- > drivers/pci-function.cc | 16 ++- > drivers/pci-function.hh | 2 + > drivers/virtio-blk.cc | 22 ++++- > drivers/virtio-device.hh | 1 + > drivers/virtio-net.cc | 21 +++- > drivers/virtio-pci-device.cc | 184 ++++++++++++++++++++++++++++++++++- > drivers/virtio-pci-device.hh | 161 ++++++++++++++++++++++++++++++ > drivers/virtio-vring.cc | 15 +++ > drivers/virtio-vring.hh | 4 + > drivers/virtio.cc | 7 ++ > drivers/virtio.hh | 3 + > 11 files changed, 424 insertions(+), 12 deletions(-) > > diff --git a/drivers/pci-function.cc b/drivers/pci-function.cc > index eb12c452..ac585bc6 100644 > --- a/drivers/pci-function.cc > +++ b/drivers/pci-function.cc > @@ -100,6 +100,11 @@ namespace pci { > } > } > > + bool bar::is_mapped() > + { > + return _addr_mmio != mmio_nullptr; > + } > + > mmioaddr_t bar::get_mmio() > { > return _addr_mmio; > @@ -808,6 +813,11 @@ namespace pci { > } > > u8 function::find_capability(u8 cap_id) > + { > + return this->find_capability(cap_id, [](function *fun, u8 off) { > return true; } ); > + } > + > + u8 function::find_capability(u8 cap_id, std::function<bool > (function*, u8)> predicate) > { > u8 capabilities_base = pci_readb(PCI_CAPABILITIES_PTR); > u8 off = capabilities_base; > @@ -818,7 +828,7 @@ namespace pci { > while (off != 0) { > // Read capability > u8 capability = pci_readb(off + PCI_CAP_OFF_ID); > - if (capability == cap_id) { > + if (capability == cap_id && predicate(this, off)) { > return off; > } > > @@ -858,9 +868,9 @@ namespace pci { > for (int bar_idx = 1; bar_idx <= 6; bar_idx++) { > bar *bar = get_bar(bar_idx); > if (bar) { > - pci_d(" bar[%d]: %sbits addr=%p size=%x", > + pci_d(" bar[%d]: %sbits addr=%p size=%x, mmio=%d", > bar_idx, (bar->is_64() ? "64" : "32"), > - bar->get_addr64(), bar->get_size()); > + bar->get_addr64(), bar->get_size(), bar->is_mmio()); > } > } > > diff --git a/drivers/pci-function.hh b/drivers/pci-function.hh > index 13a9aa01..06ec96f6 100644 > --- a/drivers/pci-function.hh > +++ b/drivers/pci-function.hh > @@ -73,6 +73,7 @@ namespace pci { > // map mmio region > void map(); > void unmap(); > + bool is_mapped(); > mmioaddr_t get_mmio(); > > // Access the pio or mmio bar > @@ -343,6 +344,7 @@ namespace pci { > > // Capability parsing > u8 find_capability(u8 cap_id); > + u8 find_capability(u8 cap_id, std::function<bool (function*, u8)> > predicate); > > bar * get_bar(int idx); > void add_bar(int idx, bar* bar); > diff --git a/drivers/virtio-blk.cc b/drivers/virtio-blk.cc > index 6b439ada..0bc6fb0f 100644 > --- a/drivers/virtio-blk.cc > +++ b/drivers/virtio-blk.cc > @@ -174,8 +174,17 @@ blk::~blk() > > void blk::read_config() > { > - //read all of the block config (including size, mce, topology,..) in > one shot > - virtio_conf_read(0, &_config, sizeof(_config)); > + if (_dev.is_modern()) { > + //TODO: It may to do with legacy vs non-legacy device > + //but at least with latest spec we should check if individual > + //config fields are available vs reading whole config struct. For > example > + //firecracker reports memory read violation warnings > + virtio_conf_read(0, &_config, sizeof(_config.capacity)); > + } > + else { > + //read all of the block config (including size, mce, topology,..) > in one shot > + virtio_conf_read(0, &_config, sizeof(_config)); > + } > > trace_virtio_blk_read_config_capacity(_config.capacity); > > @@ -251,9 +260,12 @@ int blk::make_request(struct bio* bio) > > if (!bio) return EIO; > > - if (bio->bio_bcount/mmu::page_size + 1 > _config.seg_max) { > - trace_virtio_blk_make_request_seg_max(bio->bio_bcount, > _config.seg_max); > - return EIO; > + // TODO: Check if seg_max is unavailable if modern ... > + if (!_dev.is_modern()) { > + if (bio->bio_bcount/mmu::page_size + 1 > _config.seg_max) { > + trace_virtio_blk_make_request_seg_max(bio->bio_bcount, > _config.seg_max); > + return EIO; > + } > } > > auto* queue = get_virt_queue(0); > diff --git a/drivers/virtio-device.hh b/drivers/virtio-device.hh > index 93f65a4b..c4a9f180 100644 > --- a/drivers/virtio-device.hh > +++ b/drivers/virtio-device.hh > @@ -59,6 +59,7 @@ public: > virtual void select_queue(int queue) = 0; > virtual u16 get_queue_size() = 0; > virtual void setup_queue(vring *queue) = 0; > + virtual void activate_queue(int queue) = 0; > virtual void kick_queue(int queue) = 0; > > virtual u64 get_available_features() = 0; > diff --git a/drivers/virtio-net.cc b/drivers/virtio-net.cc > index 3f75cea5..ef2dff66 100644 > --- a/drivers/virtio-net.cc > +++ b/drivers/virtio-net.cc > @@ -250,7 +250,13 @@ net::net(virtio_device& dev) > > poll_task->set_priority(sched::thread::priority_infinity); > > - _hdr_size = _mergeable_bufs ? sizeof(net_hdr_mrg_rxbuf) : > sizeof(net_hdr); > + if (_dev.is_modern()) { > + //TODO: Legacy vs non-legacy -> the non-legacy header includes > one more field > + _hdr_size = sizeof(net_hdr_mrg_rxbuf); > + } > + else { > + _hdr_size = _mergeable_bufs ? sizeof(net_hdr_mrg_rxbuf) : > sizeof(net_hdr); > + } > > //initialize the BSD interface _if > _ifn = if_alloc(IFT_ETHER); > @@ -335,8 +341,17 @@ net::~net() > > void net::read_config() > { > - //read all of the net config in one shot > - virtio_conf_read(0, &_config, sizeof(_config)); > + if (_dev.is_modern()) { > + //TODO: It may to do with legacy vs non-legacy device > + //but at least with latest spec we should check if individual > + //config fields are available vs reading whole config struct. For > example > + //firecracker reports memory read violation warnings > + virtio_conf_read(0, &(_config.mac[0]), sizeof(_config.mac)); > + } > + else { > + //read all of the net config in one shot > + virtio_conf_read(0, &_config, sizeof(_config)); > + } > > if (get_guest_feature_bit(VIRTIO_NET_F_MAC)) > net_i("The mac addr of the device is %x:%x:%x:%x:%x:%x", > diff --git a/drivers/virtio-pci-device.cc b/drivers/virtio-pci-device.cc > index bfd20a04..dc444757 100644 > --- a/drivers/virtio-pci-device.cc > +++ b/drivers/virtio-pci-device.cc > @@ -163,8 +163,190 @@ bool virtio_legacy_pci_device::parse_pci_config() > return true; > } > > +virtio_modern_pci_device::virtio_modern_pci_device(pci::device *dev) > + : virtio_pci_device(dev) > +{ > +} > + > +void virtio_modern_pci_device::dump_config() > +{ > + virtio_pci_device::dump_config(); > + > + _common_cfg->print(" common cfg:"); > + _isr_cfg->print(" isr cfg:"); > + _notify_cfg->print(" notify cfg:"); > + _device_cfg->print(" device cfg:"); > +} > + > +void virtio_modern_pci_device::kick_queue(int queue) > +{ > + auto offset = _notify_offset_multiplier * > _queues_notify_offsets[queue]; > + _notify_cfg->virtio_conf_writew(offset, queue); > +} > + > +void virtio_modern_pci_device::setup_queue(vring *queue) > +{ > + auto queue_index = queue->index(); > + > + if (_dev->is_msix()) { > + // Setup queue_id:entry_id 1:1 correlation... > + > _common_cfg->virtio_conf_writew(COMMON_CFG_OFFSET_OF(queue_msix_vector), > queue_index); > + if > (_common_cfg->virtio_conf_readw(COMMON_CFG_OFFSET_OF(queue_msix_vector) != > queue_index)) { > + virtio_e("Setting MSIx entry for queue %d failed.", > queue_index); > + return; > + } > + } > + > + _queues_notify_offsets[queue_index] = > + > _common_cfg->virtio_conf_readw(COMMON_CFG_OFFSET_OF(queue_notify_off)); > + > + _common_cfg->virtio_conf_writew(COMMON_CFG_OFFSET_OF(queue_size), > queue->size()); > + // > + // Pass addresses > + _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(queue_desc_lo), > (u32)queue->get_desc_addr()); > + _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(queue_desc_hi), > (u32)(queue->get_desc_addr() >> 32)); > + > + _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(queue_avail_lo), > (u32)queue->get_avail_addr()); > + _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(queue_avail_hi), > (u32)(queue->get_avail_addr() >> 32)); > + > + _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(queue_used_lo), > (u32)queue->get_used_addr()); > + _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(queue_used_hi), > (u32)(queue->get_used_addr() >> 32)); > +} > + > +void virtio_modern_pci_device::activate_queue(int queue) > +{ > + select_queue(queue); > + _common_cfg->virtio_conf_writew(COMMON_CFG_OFFSET_OF(queue_enable), > 1); > +} > + > +void virtio_modern_pci_device::select_queue(int queue) > +{ > + _common_cfg->virtio_conf_writew(COMMON_CFG_OFFSET_OF(queue_select), > queue); > +} > + > +u16 virtio_modern_pci_device::get_queue_size() > +{ > + return > _common_cfg->virtio_conf_readw(COMMON_CFG_OFFSET_OF(queue_size)); > +} > + > +u64 virtio_modern_pci_device::get_available_features() > +{ > + u64 features; > + > + > _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(device_feature_select), > 0); > + features = > _common_cfg->virtio_conf_readl(COMMON_CFG_OFFSET_OF(device_feature)); > + > _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(device_feature_select), > 1); > + features |= > ((u64)_common_cfg->virtio_conf_readl(COMMON_CFG_OFFSET_OF(device_feature)) > << 32); > + > + return features; > +} > + > +bool virtio_modern_pci_device::get_available_feature_bit(int bit) > +{ > + return 0 != (get_available_features() & (1 << bit)); > +} > + > +void virtio_modern_pci_device::set_enabled_features(u64 features) > +{ > + > _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(driver_feature_select), > 0); > + _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(driver_feature), > (u32)features); > + > _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(driver_feature_select), > 1); > + _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(driver_feature), > features >> 32); > +} > + > +u64 virtio_modern_pci_device::get_enabled_features() > +{ > + u64 features; > + > + > _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(driver_feature_select), > 0); > + features = > _common_cfg->virtio_conf_readl(COMMON_CFG_OFFSET_OF(driver_feature)); > + > _common_cfg->virtio_conf_writel(COMMON_CFG_OFFSET_OF(driver_feature_select), > 1); > + features |= > ((u64)_common_cfg->virtio_conf_readl(COMMON_CFG_OFFSET_OF(driver_feature)) > << 32); > + > + return features; > +} > + > +bool virtio_modern_pci_device::get_enabled_feature_bit(int bit) > +{ > + return 0 != (get_enabled_features() & (1 << bit)); > +} > + > +u8 virtio_modern_pci_device::get_status() > +{ > + return > _common_cfg->virtio_conf_readb(COMMON_CFG_OFFSET_OF(device_status)); > +} > + > +void virtio_modern_pci_device::set_status(u8 status) > +{ > + _common_cfg->virtio_conf_writeb(COMMON_CFG_OFFSET_OF(device_status), > status); > +} > + > +u8 virtio_modern_pci_device::read_config(u32 offset) > +{ > + return _device_cfg->virtio_conf_readb(offset); > +} > + > +u8 virtio_modern_pci_device::read_and_ack_isr() > +{ > + return _isr_cfg->virtio_conf_readb(0); > +} > + > +bool virtio_modern_pci_device::parse_pci_config() > +{ > + // Check ABI version > + u8 rev = _dev->get_revision_id(); > + if (rev < VIRTIO_PCI_MODERN_ABI_VERSION) { > + virtio_e("Wrong virtio revision=%x", rev); > + return false; > + } > + > + // Check device ID > + u16 dev_id = _dev->get_device_id(); > + if ((dev_id < VIRTIO_PCI_MODERN_ID_MIN) || (dev_id > > VIRTIO_PCI_MODERN_ID_MAX)) { > + virtio_e("Wrong virtio dev id %x", dev_id); > + return false; > + } > + > + parse_virtio_capability(_common_cfg, VIRTIO_PCI_CAP_COMMON_CFG); > + parse_virtio_capability(_isr_cfg, VIRTIO_PCI_CAP_ISR_CFG); > + parse_virtio_capability(_notify_cfg, VIRTIO_PCI_CAP_NOTIFY_CFG); > + parse_virtio_capability(_device_cfg, VIRTIO_PCI_CAP_DEVICE_CFG); > + > + if (_notify_cfg) { > + _notify_offset_multiplier > =_dev->pci_readl(_notify_cfg->get_cfg_offset() + > + offsetof(virtio_pci_notify_cap, > notify_offset_multiplier)); > + } > + > + return _common_cfg && _isr_cfg && _notify_cfg && _device_cfg; > +} > + > +void > virtio_modern_pci_device::parse_virtio_capability(std::unique_ptr<virtio_capability> > &ptr, u8 type) > +{ > + u8 cfg_offset = _dev->find_capability(pci::function::PCI_CAP_VENDOR, > [type] (pci::function *fun, u8 offset) { > + u8 cfg_type = fun->pci_readb(offset + offsetof(struct > virtio_pci_cap, cfg_type)); > + return type == cfg_type; > + }); > + > + if (cfg_offset != 0xFF) { > + u8 bar_index = _dev->pci_readb(cfg_offset + offsetof(struct > virtio_pci_cap, bar)); > + u32 offset = _dev->pci_readl(cfg_offset + offsetof(struct > virtio_pci_cap, offset)); > + u32 length = _dev->pci_readl(cfg_offset + offsetof(struct > virtio_pci_cap, length)); > + > + auto bar_no = bar_index + 1; > + auto bar = _dev->get_bar(bar_no); > + if (bar && bar->is_mmio() && !bar->is_mapped()) { > + bar->map(); > + } > + > + ptr.reset(new > virtio_modern_pci_device::virtio_capability(cfg_offset, bar, bar_no, > offset, length)); > + } > +} > + > virtio_device* create_virtio_pci_device(pci::device *dev) { > - return new virtio_legacy_pci_device(dev); > + if (dev->get_device_id() >= VIRTIO_PCI_MODERN_ID_MIN && > dev->get_device_id() <= VIRTIO_PCI_MODERN_ID_MAX) > + return new virtio_modern_pci_device(dev); > + else > + return new virtio_legacy_pci_device(dev); > } > > } > diff --git a/drivers/virtio-pci-device.hh b/drivers/virtio-pci-device.hh > index 42b14934..e9554558 100644 > --- a/drivers/virtio-pci-device.hh > +++ b/drivers/virtio-pci-device.hh > @@ -57,6 +57,9 @@ enum VIRTIO_PCI_CONFIG { > VIRTIO_PCI_VRING_ALIGN = 4096, > VIRTIO_PCI_LEGACY_ID_MIN = 0x1000, > VIRTIO_PCI_LEGACY_ID_MAX = 0x103f, > + VIRTIO_PCI_MODERN_ABI_VERSION = 1, > + VIRTIO_PCI_MODERN_ID_MIN = 0x1040, > + VIRTIO_PCI_MODERN_ID_MAX = 0x107f, > }; > > class virtio_pci_device : public virtio_device { > @@ -100,6 +103,7 @@ public: > virtual void select_queue(int queue); > virtual u16 get_queue_size(); > virtual void setup_queue(vring *queue); > + virtual void activate_queue(int queue) {} > virtual void kick_queue(int queue); > > virtual u64 get_available_features(); > @@ -134,6 +138,163 @@ private: > pci::bar* _bar1; > }; > > +enum VIRTIO_MODERN_PCI_CONFIG { > + /* Common configuration */ > + VIRTIO_PCI_CAP_COMMON_CFG = 1, > + /* Notifications */ > + VIRTIO_PCI_CAP_NOTIFY_CFG = 2, > + /* ISR Status */ > + VIRTIO_PCI_CAP_ISR_CFG = 3, > + /* Device specific configuration */ > + VIRTIO_PCI_CAP_DEVICE_CFG = 4, > + /* PCI configuration access */ > + VIRTIO_PCI_CAP_PCI_CFG = 5, > +}; > + > +/* This is the PCI capability header: */ > +struct virtio_pci_cap { > + u8 cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */ > + u8 cap_next; /* Generic PCI field: next ptr. */ > + u8 cap_len; /* Generic PCI field: capability length */ > + u8 cfg_type; /* Identifies the structure. */ > + u8 bar; /* Where to find it. */ > + u8 padding[3]; /* Pad to full dword. */ > + u32 offset; /* Offset within bar. */ > + u32 length; /* Length of the structure, in bytes. */ > +}; > + > +/* The notification location is found using the VIRTIO_PCI_CAP_NOTIFY_CFG > capability. > + * This capability is immediately followed by an additional field, like > so:*/ > +struct virtio_pci_notify_cap { > + struct virtio_pci_cap cap; > + u32 notify_offset_multiplier; /* Multiplier for queue_notify_off. */ > +}; > + > +/* The common configuration structure is found at the bar and offset > within > + * the VIRTIO_PCI_CAP_COMMON_CFG capability; its layout is below. */ > +struct virtio_pci_common_cfg { > + /* About the whole device. */ > + u32 device_feature_select; /* read-write */ > + u32 device_feature; /* read-only for driver */ > + u32 driver_feature_select; /* read-write */ > + u32 driver_feature; /* read-write */ > + u16 msix_config; /* read-write */ > + u16 num_queues; /* read-only for driver */ > + u8 device_status; /* read-write */ > + u8 config_generation; /* read-only for driver */ > + > + /* About a specific virtqueue. */ > + u16 queue_select; /* read-write */ > + u16 queue_size; /* read-write, power of 2, or 0. */ > + u16 queue_msix_vector; /* read-write */ > + u16 queue_enable; /* read-write */ > + u16 queue_notify_off; /* read-only for driver */ > + u32 queue_desc_lo; /* read-write */ > + u32 queue_desc_hi; /* read-write */ > + u32 queue_avail_lo; /* read-write */ > + u32 queue_avail_hi; /* read-write */ > + u32 queue_used_lo; /* read-write */ > + u32 queue_used_hi; /* read-write */ > +}; > + > +#define COMMON_CFG_OFFSET_OF(field) offsetof(struct > virtio_pci_common_cfg, field) > + > +class virtio_modern_pci_device : public virtio_pci_device { > +public: > + struct virtio_capability { > + virtio_capability(u32 cfg_offset, pci::bar* bar, u32 bar_no, u32 > bar_offset, u32 length) : > + _cfg_offset(cfg_offset), > + _bar(bar), > + _bar_no(bar_no), > + _bar_offset(bar_offset), > + _length(length) { > + assert(_length > 0 && _bar_offset >= 0 && _bar_offset + > _length <= _bar->get_size()); > + } > + > + u8 virtio_conf_readb(u32 offset) { > + verify_offset(offset, sizeof(u8)); > + return _bar->readb(_bar_offset + offset); > + }; > + u16 virtio_conf_readw(u32 offset) { > + verify_offset(offset, sizeof(u16)); > + return _bar->readw(_bar_offset + offset); > + }; > + u32 virtio_conf_readl(u32 offset) { > + verify_offset(offset, sizeof(u32)); > + return _bar->readl(_bar_offset + offset); > + }; > + void virtio_conf_writeb(u32 offset, u8 val) { > + verify_offset(offset, sizeof(u8)); > + _bar->writeb(_bar_offset + offset, val); > + }; > + void virtio_conf_writew(u32 offset, u16 val) { > + verify_offset(offset, sizeof(u16)); > + _bar->writew(_bar_offset + offset, val); > + }; > + void virtio_conf_writel(u32 offset, u32 val) { > + verify_offset(offset, sizeof(u32)); > + _bar->writel(_bar_offset + offset, val); > + }; > + u32 get_cfg_offset() { return _cfg_offset; } > + > + void print(const char *prefix) { > + virtio_d("%s bar=%d, offset=%x, size=%x", prefix, _bar_no, > _bar_offset, _length); > + } > + private: > + inline void verify_offset(u32 offset, u32 size) { > + assert(offset >= 0 && offset + size <= _length); > + } > + > + u32 _cfg_offset; > + pci::bar* _bar; > + u32 _bar_no; > + u32 _bar_offset; > + u32 _length; > + }; > + > + explicit virtio_modern_pci_device(pci::device *dev); > + ~virtio_modern_pci_device() {} > + > + virtual const char *get_version() { return "modern"; } > + virtual u16 get_type_id() { return _dev->get_device_id() - > VIRTIO_PCI_MODERN_ID_MIN; }; > + > + virtual void dump_config(); > + > + virtual void select_queue(int queue); > + virtual u16 get_queue_size(); > + virtual void setup_queue(vring *queue); > + virtual void activate_queue(int queue); > + virtual void kick_queue(int queue); > + > + virtual u64 get_available_features(); > + virtual bool get_available_feature_bit(int bit); > + > + virtual void set_enabled_features(u64 features); > + virtual u64 get_enabled_features(); > + virtual bool get_enabled_feature_bit(int bit); > + > + virtual u8 get_status(); > + virtual void set_status(u8 status); > + > + virtual u8 read_config(u32 offset); > + virtual u8 read_and_ack_isr(); > + > + virtual bool is_modern() { return true; }; > + > +protected: > + virtual bool parse_pci_config(); > +private: > + void parse_virtio_capability(std::unique_ptr<virtio_capability> &ptr, > u8 type); > + > + std::unique_ptr<virtio_capability> _common_cfg; > + std::unique_ptr<virtio_capability> _isr_cfg; > + std::unique_ptr<virtio_capability> _notify_cfg; > + std::unique_ptr<virtio_capability> _device_cfg; > + > + u32 _notify_offset_multiplier; > + u32 _queues_notify_offsets[64]; > +}; > + > // Creates appropriate instance of virtio_pci_device > // by reading configuration from PCI device > virtio_device* create_virtio_pci_device(pci::device *dev); > diff --git a/drivers/virtio-vring.cc b/drivers/virtio-vring.cc > index 3f0e7e25..e619ef06 100644 > --- a/drivers/virtio-vring.cc > +++ b/drivers/virtio-vring.cc > @@ -87,6 +87,21 @@ namespace virtio { > return mmu::virt_to_phys(_vring_ptr); > } > > + u64 vring::get_desc_addr() > + { > + return mmu::virt_to_phys(_desc); > + } > + > + u64 vring::get_avail_addr() > + { > + return mmu::virt_to_phys(_avail); > + } > + > + u64 vring::get_used_addr() > + { > + return mmu::virt_to_phys(_used); > + } > + > unsigned vring::get_size(unsigned int num, unsigned long align) > { > return (((sizeof(vring_desc) * num + sizeof(u16) * (3 + num) > diff --git a/drivers/virtio-vring.hh b/drivers/virtio-vring.hh > index 74c4d8a1..59ad88c6 100644 > --- a/drivers/virtio-vring.hh > +++ b/drivers/virtio-vring.hh > @@ -128,6 +128,10 @@ class virtio_driver; > u64 get_paddr(); > static unsigned get_size(unsigned int num, unsigned long align); > > + u64 get_desc_addr(); > + u64 get_avail_addr(); > + u64 get_used_addr(); > + > // Ring operations > bool add_buf(void* cookie); > // Get the top item from the used ring > diff --git a/drivers/virtio.cc b/drivers/virtio.cc > index ef929820..5ef0f94d 100644 > --- a/drivers/virtio.cc > +++ b/drivers/virtio.cc > @@ -66,6 +66,10 @@ void virtio_driver::setup_features() > set_event_idx_cap(true); > > set_guest_features(subset); > + > + // Step 5 - confirm features (only applies to modern devices) > + if (_dev.is_modern()) > + add_dev_status(VIRTIO_CONFIG_S_FEATURES_OK); > } > > void virtio_driver::dump_config() > @@ -127,6 +131,9 @@ void virtio_driver::probe_virt_queues() > virtio_d("Queue[%d] -> size %d, paddr %x", (_num_queues-1), > qsize, queue->get_paddr()); > > } while (true); > + > + for (u32 _q = 0; _q < _num_queues; _q++) > + _dev.activate_queue(_q); > } > > vring* virtio_driver::get_virt_queue(unsigned idx) > diff --git a/drivers/virtio.hh b/drivers/virtio.hh > index 4718f286..ef915e1c 100644 > --- a/drivers/virtio.hh > +++ b/drivers/virtio.hh > @@ -23,6 +23,9 @@ enum VIRTIO_CONFIG { > VIRTIO_CONFIG_S_DRIVER = 2, > /* Driver has used its parts of the config, and is happy */ > VIRTIO_CONFIG_S_DRIVER_OK = 4, > + /* Indicates that the driver has acknowledged all the features it > understands, > + * and feature negotiation is complete */ > + VIRTIO_CONFIG_S_FEATURES_OK = 8, > /* We've given up on this device. */ > VIRTIO_CONFIG_S_FAILED = 0x80, > /* Some virtio feature bits (currently bits 28 through 31) are > reserved for the > -- > 2.19.1 > > -- > You received this message because you are subscribed to the Google Groups > "OSv Development" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
