7#include <l4/re/util/debug>
10#include <l4/cxx/bitfield>
19#if defined(__ARM_ARCH_7A__) \
20 || ( defined(__ARM_ARCH) && __ARM_ARCH == 7 \
21 && defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE >= 'A')
22static inline void wmb() {
asm volatile (
"dmb" : : :
"memory"); }
23static inline void rmb() {
asm volatile (
"dmb" : : :
"memory"); }
25#elif defined(__ARM_ARCH_8A) \
26 || ( defined(__ARM_ARCH) && __ARM_ARCH == 8 \
27 && defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE >= 'A') \
28 || (defined(__ARM_ARCH) && __ARM_ARCH > 8)
29static inline void wmb() {
asm volatile (
"dsb ishst" : : :
"memory"); }
30static inline void rmb() {
asm volatile (
"dsb ishld" : : :
"memory"); }
31#elif defined(__mips__)
32static inline void wmb() {
asm volatile (
"sync" : : :
"memory"); }
33static inline void rmb() {
asm volatile (
"sync" : : :
"memory"); }
34#elif defined(__amd64__) || defined(__i386__) || defined(__i686__)
35static inline void wmb() {
asm volatile (
"sfence" : : :
"memory"); }
36static inline void rmb() {
asm volatile (
"lfence" : : :
"memory"); }
38static inline void wmb() {
asm volatile (
"fence ow, ow" : : :
"memory"); }
39static inline void rmb() {
asm volatile (
"fence ir, ir" : : :
"memory"); }
41#warning Missing proper memory write barrier
42static inline void wmb() {
asm volatile (
"" : : :
"memory"); }
43static inline void rmb() {
asm volatile (
"" : : :
"memory"); }
125 L4Re::Util::Dbg().printf(
"D[%04x]: %08llx (%x) f=%04x n=%04x\n",
128 static_cast<unsigned>(
next));
253 static_assert(Desc_align >= Avail_align,
254 "virtqueue alignment assumptions broken");
276 {
return Desc_align; }
286 {
return 2 *
num + 6; }
294 {
return Avail_align; }
305 {
return 8 *
num + 6; }
313 {
return Used_align; }
322 return (
reinterpret_cast<char *
>(
_used) -
reinterpret_cast<char *
>(
_desc))
330 {
return reinterpret_cast<char *
>(
_avail) -
reinterpret_cast<char *
>(
_desc); }
336 {
return reinterpret_cast<char *
>(
_used) -
reinterpret_cast<char *
>(
_desc); }
355 void setup(
unsigned num,
void *desc,
void *avail,
void *used)
367 L4Re::Util::Dbg().printf(
"VQ[%p]: num=%d d:%p a:%p u:%p\n",
388 void *used =
reinterpret_cast<void *
>(
390 setup(
num, ring,
reinterpret_cast<void *
>(avail), used);
507 _desc[d].next = d + 1;
601 return _desc[descno];
Exception for an abstract runtime error.
Driver-side implementation of a Virtqueue.
void free_descriptor(l4_uint16_t head, l4_uint16_t tail)
Free a chained list of descriptors in the descriptor queue.
void enqueue_descriptor(l4_uint16_t descno)
Enqueue a descriptor in the available ring.
void init_queue(unsigned num, void *base)
Initialize this virtqueue.
l4_uint16_t alloc_descriptor()
Allocate and return an unused descriptor from the descriptor table.
l4_uint16_t find_next_used(l4_uint32_t *len=nullptr)
Return the next finished block.
void init_queue(unsigned num, void *desc, void *avail, void *used)
Initialize this virtqueue.
Desc & desc(l4_uint16_t descno)
Return a reference to a descriptor in the descriptor table.
void initialize_rings(unsigned num)
Initialize the descriptor table and the index structures of this queue.
Pointer used in virtio descriptors.
Ptr(l4_uint64_t vm_addr)
Make a Ptr from a raw 64bit address.
Invalid_type
Type for making an invalid (NULL) Ptr.
@ Invalid
Use to set a Ptr to invalid (NULL)
Ptr(Invalid_type)
Make and invalid Ptr.
Type of available ring, this is read-only for the host.
l4_uint16_t ring[]
array of available descriptor indexes.
Flags flags
flags of available ring
l4_uint16_t idx
available index written by guest
Descriptor in the descriptor table.
l4_uint16_t next
Index of the next chained descriptor.
l4_uint32_t len
Length of described buffer.
Flags flags
Descriptor flags.
void dump(unsigned idx) const
Dump a single descriptor.
Ptr< void > addr
Address stored in descriptor.
Used_elem ring[]
array of used descriptors.
l4_uint16_t idx
index of the last entry in the ring.
Flags flags
flags of the used ring.
void no_notify_host(bool value)
Set the no-notify flag for this queue.
void disable()
Completely disable the queue.
void setup(unsigned num, void *desc, void *avail, void *used)
Enable this queue.
static unsigned long desc_size(unsigned num)
Calculate the size of the descriptor table for num entries.
l4_uint16_t get_tail_avail_idx() const
Get tail-available index stored in local state (for debugging).
Used * _used
pointer to used ring.
bool no_notify_guest() const
Get the no IRQ flag of this queue.
static unsigned long avail_align()
Get the alignment in zero LSBs needed for the available ring.
void dump(Desc const *d) const
Dump descriptors for this queue.
void setup_simple(unsigned num, void *ring)
Enable this queue.
unsigned long avail_offset() const
Get the offset of the available ring from the descriptor table.
static unsigned long used_align()
Get the alignment in zero LSBs needed for the used ring.
static unsigned long total_size(unsigned num)
Calculate the total size for a virtqueue of the given dimensions.
static unsigned long desc_align()
Get the alignment in zero LSBs needed for the descriptor table.
static unsigned long used_size(unsigned num)
Calculate the size of the used ring for num entries.
Virtqueue()=default
Create a disabled virtqueue.
unsigned long used_offset() const
Get the offset of the used ring from the descriptor table.
static unsigned long avail_size(unsigned num)
Calculate the size of the available ring for num entries.
unsigned long total_size() const
Calculate the total size of this virtqueue.
bool ready() const
Test if this queue is in working state.
l4_uint16_t _idx_mask
mask used for indexing into the descriptor table and the rings.
Desc * _desc
pointer to descriptor table, NULL if queue is off.
l4_uint16_t get_avail_idx() const
Get available index from available ring (for debugging).
bool no_notify_host() const
Get the no notify flag of this queue.
Avail * _avail
pointer to available ring.
l4_uint16_t _current_avail
The life counter for the queue.
unsigned long l4_addr_t
Address type.
unsigned int l4_uint32_t
Unsigned 32bit value.
unsigned short int l4_uint16_t
Unsigned 16bit value.
unsigned long long l4_uint64_t
Unsigned 64bit value.
@ L4_EINVAL
Invalid argument.
l4_addr_t l4_round_size(l4_addr_t value, unsigned char bits) L4_NOTHROW
Round value up to the next alignment with bits size.
#define L4_LIKELY(x)
Expression is likely to execute.
Common L4 ABI Data Types.
L4-VIRTIO Transport C++ API.
Flags of the available ring.
constexpr no_irq_bfm_t::Val no_irq() const
Get the no_irq bits ( 0 to 0 ) of raw.
Flags(l4_uint16_t v)
Make Flags from the raw value.
l4_uint16_t raw
raw 16bit flags value of the available ring.
Type for descriptor flags.
constexpr next_bfm_t::Val next() const
Get the next bits ( 0 to 0 ) of raw.
constexpr write_bfm_t::Val write() const
Get the write bits ( 1 to 1 ) of raw.
Flags(l4_uint16_t v)
Make Flags from raw 16bit value.
l4_uint16_t raw
raw flags value of a virtio descriptor.
constexpr indirect_bfm_t::Val indirect() const
Get the indirect bits ( 2 to 2 ) of raw.
constexpr no_notify_bfm_t::Val no_notify() const
Get the no_notify bits ( 0 to 0 ) of raw.
l4_uint16_t raw
raw flags value as specified by virtio.
Flags(l4_uint16_t v)
make Flags from raw value
Type of an element of the used ring.
l4_uint32_t id
descriptor index
l4_uint32_t len
length field
Used_elem(l4_uint16_t id, l4_uint32_t len)
Initialize a used ring element.