L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
virtio
1// vi:ft=cpp
2/* SPDX-License-Identifier: MIT */
3/*
4 * Copyright (C) 2014-2020 Kernkonzept GmbH.
5 * Author(s): Alexander Warg <alexander.warg@kernkonzept.com>
6 *
7 */
8#pragma once
9
10#include <l4/sys/types.h>
11#include <l4/cxx/bitfield>
12#include <l4/cxx/minmax>
13#include <l4/cxx/utils>
14
15#include <limits.h>
16#include <string.h>
17#include <stdio.h>
18
19#include "../virtqueue"
20
26namespace L4virtio {
27namespace Svr {
28
33{
34 unsigned char raw;
35 Dev_status() = default;
36
38 explicit Dev_status(l4_uint32_t v) : raw(v) {}
39
40 CXX_BITFIELD_MEMBER(0, 0, acked, raw);
41 CXX_BITFIELD_MEMBER(1, 1, driver, raw);
42 CXX_BITFIELD_MEMBER(2, 2, driver_ok, raw);
43 CXX_BITFIELD_MEMBER(3, 3, features_ok, raw);
44 CXX_BITFIELD_MEMBER(6, 7, fail_state, raw);
45 CXX_BITFIELD_MEMBER(6, 6, device_needs_reset, raw);
46 CXX_BITFIELD_MEMBER(7, 7, failed, raw);
47
57 bool running() const
58 {
59 return (raw == 0xf);
60 }
61};
62
67{
69 Dev_features() = default;
70
72 explicit Dev_features(l4_uint32_t v) : raw(v) {}
73
74 CXX_BITFIELD_MEMBER(28, 28, ring_indirect_desc, raw);
75 CXX_BITFIELD_MEMBER(29, 29, ring_event_idx, raw);
76};
77
78
88{
89public:
94 {
95 friend class Virtqueue;
96 private:
97 Virtqueue::Desc const *_d;
98 Head_desc(Virtqueue *r, unsigned i) : _d(r->desc(i)) {}
99
100 struct Null_ptr_check;
101
102 public:
104 Head_desc() : _d(0) {}
105
107 bool valid() const { return _d; }
108
110 operator Null_ptr_check const * () const
111 { return reinterpret_cast<Null_ptr_check const *>(_d); }
112
114 Desc const *desc() const
115 { return _d; }
116 };
117
118 struct Request : Head_desc
119 {
120 Virtqueue *ring = nullptr;
121 Request() = default;
122 private:
123 friend class Virtqueue;
124 Request(Virtqueue *r, unsigned i) : Head_desc(r, i), ring(r) {}
125 };
126
127
138 Request next_avail()
139 {
141 {
142 rmb();
143 unsigned head = _current_avail & _idx_mask;
145 return Request(this, _avail->ring[head]);
146 }
147 return Request();
148 }
149
156 bool desc_avail() const
157 {
158 return _current_avail != _avail->idx;
159 }
160
171 void consumed(Head_desc const &r, l4_uint32_t len = 0)
172 {
174 _used->ring[i] = Used_elem(r._d - _desc, len);
175 wmb();
176 ++_used->idx;
177 }
178
193 template<typename ITER>
194 void consumed(ITER const &begin, ITER const &end)
195 {
196 l4_uint16_t added = 0;
197 l4_uint16_t idx = _used->idx;
198
199 for (auto elem = begin ; elem != end; ++elem, ++added)
200 _used->ring[(idx + added) & _idx_mask]
201 = Used_elem(elem->first._d - _desc, elem->second);
202
203 wmb();
204 _used->idx += added;
205 }
206
220 template<typename QUEUE_OBSERVER>
221 void finish(Head_desc &d, QUEUE_OBSERVER *o, l4_uint32_t len = 0)
222 {
223 consumed(d, len);
224 o->notify_queue(this);
225 d._d = 0;
226 }
227
242 template<typename ITER, typename QUEUE_OBSERVER>
243 void finish(ITER const &begin, ITER const &end, QUEUE_OBSERVER *o)
244 {
245 consumed(begin, end);
246 o->notify_queue(this);
247 }
248
255 {
256 if (L4_LIKELY(ready()))
257 _used->flags.no_notify() = 1;
258 }
259
266 {
267 if (L4_LIKELY(ready()))
268 _used->flags.no_notify() = 0;
269 }
270
279 Desc const *desc(unsigned idx) const
280 { return _desc + idx; }
281
282};
283
288{
289 char *pos;
291
292 Data_buffer() = default;
293
303 template<typename T>
304 explicit Data_buffer(T *p)
305 : pos(reinterpret_cast<char *>(p)), left(sizeof(T))
306 {}
307
317 template<typename T>
318 void set(T *p)
319 {
320 pos = reinterpret_cast<char *>(p);
321 left = sizeof(T);
322 }
323
336 {
337 unsigned long bytes = cxx::min(cxx::min(left, dst->left), max);
338 memcpy(dst->pos, pos, bytes);
339 left -= bytes;
340 pos += bytes;
341 dst->left -= bytes;
342 dst->pos += bytes;
343 return bytes;
344 }
345
357 {
358 unsigned long b = cxx::min(left, bytes);
359 left -= b;
360 pos += b;
361 return b;
362 }
363
369 bool done() const
370 { return left == 0; }
371};
372
373class Request_processor;
374
379{
389
392
393 // The error code
394 Error error;
395
403 : proc(proc), error(e)
404 {}
405
411 char const *message() const
412 {
413 static char const *const err[] =
414 {
415 [Bad_address] = "Descriptor address cannot be translated",
416 [Bad_rights] = "Insufficient memory access rights",
417 [Bad_flags] = "Invalid descriptor flags",
418 [Bad_next] = "The descriptor's `next` index is invalid",
419 [Bad_size] = "Invalid size of the memory block"
420 };
421
422 if (error >= (sizeof(err) / sizeof(err[0])) || !err[error])
423 return "Unknown error";
424
425 return err[error];
426 }
427};
428
429
454{
455private:
457 Virtqueue::Desc const *_table;
458
460 Virtqueue::Desc _current;
461
463 l4_uint16_t _num;
464
465public:
481 template<typename DESC_MAN, typename ...ARGS>
482 void start(DESC_MAN *dm, Virtqueue *ring, Virtqueue::Head_desc const &request, ARGS... args)
483 {
484 _current = cxx::access_once(request.desc());
485
486 if (_current.flags.indirect())
487 {
488 dm->load_desc(_current, this, &_table);
489 _num = _current.len / sizeof(Virtqueue::Desc);
490 if (L4_UNLIKELY(!_num))
492
493 _current = cxx::access_once(_table);
494 }
495 else
496 {
497 _table = ring->desc(0);
498 _num = ring->num();
499 }
500
501 dm->load_desc(_current, this, cxx::forward<ARGS>(args)...);
502 }
503
514 template<typename DESC_MAN, typename ...ARGS>
515 Virtqueue::Request const &start(DESC_MAN *dm, Virtqueue::Request const &request, ARGS... args)
516 {
517 start(dm, request.ring, request, cxx::forward<ARGS>(args)...);
518 return request;
519 }
520
527 { return _current.flags; }
528
534 bool has_more() const
535 { return _current.flags.next(); }
536
550 template<typename DESC_MAN, typename ...ARGS>
551 bool next(DESC_MAN *dm, ARGS... args)
552 {
553 if (!_current.flags.next())
554 return false;
555
556 if (L4_UNLIKELY(_current.next >= _num))
558
559 _current = cxx::access_once(_table + _current.next);
560
561 if (0) // we ignore this for performance reasons
562 if (L4_UNLIKELY(_current.flags.indirect()))
564
565 // must throw an exception in case of a bad descriptor
566 dm->load_desc(_current, this, cxx::forward<ARGS>(args)...);
567 return true;
568 }
569};
570
571}
572}
Encapsulate the state for processing a VIRTIO request.
Definition virtio:454
bool next(DESC_MAN *dm, ARGS... args)
Switch to the next descriptor in a descriptor chain.
Definition virtio:551
Virtqueue::Desc::Flags current_flags() const
Get the flags of the currently processed descriptor.
Definition virtio:526
Virtqueue::Request const & start(DESC_MAN *dm, Virtqueue::Request const &request, ARGS... args)
Start processing a new request.
Definition virtio:515
bool has_more() const
Are there more chained descriptors?
Definition virtio:534
void start(DESC_MAN *dm, Virtqueue *ring, Virtqueue::Head_desc const &request, ARGS... args)
Start processing a new request.
Definition virtio:482
VIRTIO request, essentially a descriptor from the available ring.
Definition virtio:94
Desc const * desc() const
Definition virtio:114
Head_desc()
Make invalid (NULL) request.
Definition virtio:104
Virtqueue implementation for the device.
Definition virtio:88
bool desc_avail() const
Test for available descriptors.
Definition virtio:156
void enable_notify()
Clear the 'no notify' flag for this queue.
Definition virtio:265
void consumed(ITER const &begin, ITER const &end)
Put multiple descriptors into the used ring.
Definition virtio:194
Desc const * desc(unsigned idx) const
Get a descriptor from the descriptor list.
Definition virtio:279
Request next_avail()
Get the next available descriptor from the available ring.
Definition virtio:138
void finish(ITER const &begin, ITER const &end, QUEUE_OBSERVER *o)
Add a range of descriptors to the used ring, and notify an observer once.
Definition virtio:243
void disable_notify()
Set the 'no notify' flag for this queue.
Definition virtio:254
void finish(Head_desc &d, QUEUE_OBSERVER *o, l4_uint32_t len=0)
Add a descriptor to the used ring, and notify an observer.
Definition virtio:221
void consumed(Head_desc const &r, l4_uint32_t len=0)
Put the given descriptor into the used ring.
Definition virtio:171
l4_uint16_t ring[]
array of available descriptor indexes.
Definition virtqueue:155
l4_uint16_t idx
available index written by guest
Definition virtqueue:154
Descriptor in the descriptor table.
Definition virtqueue:94
l4_uint16_t next
Index of the next chained descriptor.
Definition virtqueue:118
l4_uint32_t len
Length of described buffer.
Definition virtqueue:116
Flags flags
Descriptor flags.
Definition virtqueue:117
Used_elem ring[]
array of used descriptors.
Definition virtqueue:200
l4_uint16_t idx
index of the last entry in the ring.
Definition virtqueue:199
Flags flags
flags of the used ring.
Definition virtqueue:198
Low-level Virtqueue.
Definition virtqueue:88
Used * _used
pointer to used ring.
Definition virtqueue:206
bool ready() const
Test if this queue is in working state.
Definition virtqueue:406
l4_uint16_t _idx_mask
mask used for indexing into the descriptor table and the rings.
Definition virtqueue:215
Desc * _desc
pointer to descriptor table, NULL if queue is off.
Definition virtqueue:204
Avail * _avail
pointer to available ring.
Definition virtqueue:205
l4_uint16_t _current_avail
The life counter for the queue.
Definition virtqueue:209
unsigned num() const
Definition virtqueue:410
unsigned int l4_uint32_t
Unsigned 32bit value.
Definition l4int.h:40
unsigned short int l4_uint16_t
Unsigned 16bit value.
Definition l4int.h:38
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:296
#define L4_LIKELY(x)
Expression is likely to execute.
Definition compiler.h:295
Common L4 ABI Data Types.
L4-VIRTIO Transport C++ API.
Definition l4virtio:26
T access_once(T const *a)
Read the value at an address at most once.
Definition utils:39
String.
Exception used by Queue to indicate descriptor errors.
Definition virtio:379
Request_processor const * proc
The processor that triggered the exception.
Definition virtio:391
Error
The error code.
Definition virtio:382
@ Bad_rights
Missing access rights on memory.
Definition virtio:384
@ Bad_address
Address cannot be translated.
Definition virtio:383
@ Bad_flags
Invalid combination of descriptor flags.
Definition virtio:385
@ Bad_next
Invalid next index.
Definition virtio:386
@ Bad_size
Invalid size of memory block.
Definition virtio:387
char const * message() const
Get a human readable description of the error code.
Definition virtio:411
Bad_descriptor(Request_processor const *proc, Error e)
Make a bad descriptor exception.
Definition virtio:402
Abstract data buffer.
Definition virtio:288
void set(T *p)
Set buffer for object p.
Definition virtio:318
l4_uint32_t copy_to(Data_buffer *dst, l4_uint32_t max=UINT_MAX)
Copy contents from this buffer to the destination buffer.
Definition virtio:335
l4_uint32_t left
Bytes left in buffer.
Definition virtio:290
char * pos
Current buffer position.
Definition virtio:289
l4_uint32_t skip(l4_uint32_t bytes)
Skip given number of bytes in this buffer.
Definition virtio:356
bool done() const
Check if there are no more bytes left in the buffer.
Definition virtio:369
Data_buffer(T *p)
Create buffer for object p.
Definition virtio:304
Type for device feature bitmap.
Definition virtio:67
l4_uint32_t raw
The raw value of the features bitmap.
Definition virtio:68
constexpr ring_indirect_desc_bfm_t::Val ring_indirect_desc() const
Get the ring_indirect_desc bits ( 28 to 28 ) of raw.
Definition virtio:74
constexpr ring_event_idx_bfm_t::Val ring_event_idx() const
Get the ring_event_idx bits ( 29 to 29 ) of raw.
Definition virtio:75
Dev_features(l4_uint32_t v)
Make Features from a raw bitmap.
Definition virtio:72
Type of the device status register.
Definition virtio:33
constexpr failed_bfm_t::Val failed() const
Get the failed bits ( 7 to 7 ) of raw.
Definition virtio:46
constexpr device_needs_reset_bfm_t::Val device_needs_reset() const
Get the device_needs_reset bits ( 6 to 6 ) of raw.
Definition virtio:45
bool running() const
Check if the device is in running state.
Definition virtio:57
constexpr driver_ok_bfm_t::Val driver_ok() const
Get the driver_ok bits ( 2 to 2 ) of raw.
Definition virtio:42
constexpr acked_bfm_t::Val acked() const
Get the acked bits ( 0 to 0 ) of raw.
Definition virtio:40
Dev_status(l4_uint32_t v)
Make Status from raw value.
Definition virtio:38
constexpr features_ok_bfm_t::Val features_ok() const
Get the features_ok bits ( 3 to 3 ) of raw.
Definition virtio:43
constexpr driver_bfm_t::Val driver() const
Get the driver bits ( 1 to 1 ) of raw.
Definition virtio:41
constexpr fail_state_bfm_t::Val fail_state() const
Get the fail_state bits ( 6 to 7 ) of raw.
Definition virtio:44
unsigned char raw
Raw value of the VIRTIO device status register.
Definition virtio:34
Type for descriptor flags.
Definition virtqueue:100
constexpr next_bfm_t::Val next() const
Get the next bits ( 0 to 0 ) of raw.
Definition virtqueue:108
constexpr indirect_bfm_t::Val indirect() const
Get the indirect bits ( 2 to 2 ) of raw.
Definition virtqueue:112
constexpr no_notify_bfm_t::Val no_notify() const
Get the no_notify bits ( 0 to 0 ) of raw.
Definition virtqueue:195
Type of an element of the used ring.
Definition virtqueue:162