diff --git a/drivers/virtio-vring.cc b/drivers/virtio-vring.cc index c96c3446dd2d9bb258c125a306ecec8c5af68445..4df787c71111d3c752164dc4d5297e39fb4911cd 100644 --- a/drivers/virtio-vring.cc +++ b/drivers/virtio-vring.cc @@ -29,12 +29,22 @@ namespace virtio { sizeof(u16) + VIRTIO_PCI_VRING_ALIGN-1) & ~(VIRTIO_PCI_VRING_ALIGN-1)); // initialize the next pointer within the available ring - for (int i=0;i<num;i++) _avail->_ring[i] = i+1; + for (int i=0;i<num;i++) _desc[i]._next = i+1; + _desc[num-1]._next = 0; + + _cookie = new void*[num]; + + _avail_head = 0; + _used_guest_head = 0; + _avail_added = 0; + _avail_count = num; + } vring::~vring() { free(_vring_ptr); + delete [] _cookie; } u64 vring::get_paddr(void) @@ -61,27 +71,30 @@ namespace virtio { bool vring::add_buf(sglist* sg, u16 out, u16 in, void* cookie) { - //if (_avail->count() < (in+out)) { - // what should I do? - //} + if (_avail_count < (in+out)) { + //make sure the interrupts get there + kick(); + return false; + } - int i = 0; - vring_desc* desc = &_desc[_avail->_ring[_avail->_idx]]; + int i = 0, idx, prev_idx; + idx = prev_idx = _avail_head; for (auto ii = sg->_nodes.begin();i<in+out;ii++) { - desc->_flags = vring_desc::VRING_DESC_F_NEXT | (i>in)? vring_desc::VRING_DESC_F_WRITE:0; - desc->_paddr = (*ii)._paddr; - desc->_len = (*ii)._len; - desc->_next = _avail->_ring[_avail->_idx]; - _avail->_idx++; - desc = &_desc[_avail->_ring[desc->_next]]; - i++; + _desc[idx]._flags = vring_desc::VRING_DESC_F_NEXT; + _desc[idx]._flags |= (i++>in)? vring_desc::VRING_DESC_F_WRITE:0; + _desc[idx]._paddr = (*ii)._paddr; + _desc[idx]._len = (*ii)._len; + prev_idx = idx; + idx = _avail->_ring[_desc[idx]._next]; } - desc->_flags &= ~vring_desc::VRING_DESC_F_NEXT; - + _desc[prev_idx]._flags &= ~vring_desc::VRING_DESC_F_NEXT; + _avail->_idx = _avail_head; + _cookie[_avail_head] = cookie; - //_avail->add(sg, in, out, cookie); - //used idx math + _avail_added += i; + _avail_count -= i; + _avail_head = idx; return true; } diff --git a/drivers/virtio-vring.hh b/drivers/virtio-vring.hh index 82ba3578d1300b9b6765a60e5386340cb419e2fd..3d62869c36071871271815f361643775d2fde2aa 100644 --- a/drivers/virtio-vring.hh +++ b/drivers/virtio-vring.hh @@ -129,12 +129,23 @@ class virtio_driver; // Total number of descriptors in ring unsigned int _num; + + // Position of the next available descriptor + u16 _avail_head; + // Position of the used descriptor we've last seen + u16 _used_guest_head; + // The amount of avail descriptors we've added since last kick + u16 _avail_added; + u16 _avail_count; + // Flat list of chained descriptors vring_desc *_desc; // Available for host consumption vring_avail *_avail; // Available for guest consumption vring_used *_used; + // cookies to store access to the upper layer pointers + void** _cookie; };