L4Re Operating System Framework – Interface and Usage Documentation
Loading...
Searching...
No Matches
virtio
1// vi:ft=cpp
2/* SPDX-License-Identifier: GPL-2.0-only or License-Ref-kk-custom */
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;
121 Request() = default;
122 private:
123 friend class Virtqueue;
124 Request(Virtqueue *r, unsigned i) : Head_desc(r, i), ring(r) {}
125 };
126
127
137 Request next_avail()
138 {
140 {
141 rmb();
142 unsigned head = _current_avail & _idx_mask;
144 return Request(this, _avail->ring[head]);
145 }
146 return Request();
147 }
148
154 bool desc_avail() const
155 {
156 return _current_avail != _avail->idx;
157 }
158
166 void consumed(Head_desc const &r, l4_uint32_t len = 0)
167 {
169 _used->ring[i] = Used_elem(r._d - _desc, len);
170 wmb();
171 ++_used->idx;
172 }
173
174 template<typename ITER>
175 void consumed(ITER const &begin, ITER const &end)
176 {
177 l4_uint16_t added = 0;
178 l4_uint16_t idx = _used->idx;
179
180 for (auto elem = begin ; elem != end; ++elem, ++added)
181 _used->ring[(idx + added) & _idx_mask]
182 = Used_elem(elem->first._d - _desc, elem->second);
183
184 wmb();
185 _used->idx += added;
186 }
187
188 template<typename QUEUE_OBSERVER>
189 void finish(Head_desc &d, QUEUE_OBSERVER *o, l4_uint32_t len = 0)
190 {
191 consumed(d, len);
192 o->notify_queue(this);
193 d._d = 0;
194 }
195
196 template<typename ITER, typename QUEUE_OBSERVER>
197 void finish(ITER const &begin, ITER const &end, QUEUE_OBSERVER *o)
198 {
199 consumed(begin, end);
200 o->notify_queue(this);
201 }
202
209 {
210 if (L4_LIKELY(ready()))
211 _used->flags.no_notify() = 1;
212 }
213
220 {
221 if (L4_LIKELY(ready()))
222 _used->flags.no_notify() = 0;
223 }
224
231 Desc const *desc(unsigned idx) const
232 { return _desc + idx; }
233
234};
235
240{
241 char *pos;
243
244 Data_buffer() = default;
245
254 template<typename T>
255 explicit Data_buffer(T *p)
256 : pos(reinterpret_cast<char *>(p)), left(sizeof(T))
257 {}
258
267 template<typename T>
268 void set(T *p)
269 {
270 pos = reinterpret_cast<char *>(p);
271 left = sizeof(T);
272 }
273
285 {
286 unsigned long bytes = cxx::min(cxx::min(left, dst->left), max);
287 memcpy(dst->pos, pos, bytes);
288 left -= bytes;
289 pos += bytes;
290 dst->left -= bytes;
291 dst->pos += bytes;
292 return bytes;
293 }
294
305 {
306 unsigned long b = cxx::min(left, bytes);
307 left -= b;
308 pos += b;
309 return b;
310 }
311
316 bool done() const
317 { return left == 0; }
318};
319
320class Request_processor;
321
326{
336
339
340 // The error code
341 Error error;
342
349 : proc(proc), error(e)
350 {}
351
357 char const *message() const
358 {
359 static char const *const err[] =
360 {
361 [Bad_address] = "Descriptor address cannot be translated",
362 [Bad_rights] = "Insufficient memory access rights",
363 [Bad_flags] = "Invalid descriptor flags",
364 [Bad_next] = "The descriptor's `next` index is invalid",
365 [Bad_size] = "Invalid size of the memory block"
366 };
367
368 if (error >= (sizeof(err) / sizeof(err[0])) || !err[error])
369 return "Unknown error";
370
371 return err[error];
372 }
373};
374
375
400{
401private:
403 Virtqueue::Desc const *_table;
404
406 Virtqueue::Desc _current;
407
409 l4_uint16_t _num;
410
411public:
427 template<typename DESC_MAN, typename ...ARGS>
428 void start(DESC_MAN *dm, Virtqueue *ring, Virtqueue::Head_desc const &request, ARGS... args)
429 {
430 _current = cxx::access_once(request.desc());
431
432 if (_current.flags.indirect())
433 {
434 dm->load_desc(_current, this, &_table);
435 _num = _current.len / sizeof(Virtqueue::Desc);
436 if (L4_UNLIKELY(!_num))
438
439 _current = cxx::access_once(_table);
440 }
441 else
442 {
443 _table = ring->desc(0);
444 _num = ring->num();
445 }
446
447 dm->load_desc(_current, this, cxx::forward<ARGS>(args)...);
448 }
449
458 template<typename DESC_MAN, typename ...ARGS>
459 Virtqueue::Request const &start(DESC_MAN *dm, Virtqueue::Request const &request, ARGS... args)
460 {
461 start(dm, request.ring, request, cxx::forward<ARGS>(args)...);
462 return request;
463 }
464
470 { return _current.flags; }
471
476 bool has_more() const
477 { return _current.flags.next(); }
478
492 template<typename DESC_MAN, typename ...ARGS>
493 bool next(DESC_MAN *dm, ARGS... args)
494 {
495 if (!_current.flags.next())
496 return false;
497
498 if (L4_UNLIKELY(_current.next >= _num))
500
501 _current = cxx::access_once(_table + _current.next);
502
503 if (0) // we ignore this for performance reasons
504 if (L4_UNLIKELY(_current.flags.indirect()))
506
507 // must throw an exception in case of a bad descriptor
508 dm->load_desc(_current, this, cxx::forward<ARGS>(args)...);
509 return true;
510 }
511};
512
513}
514}
Encapsulate the state for processing a VIRTIO request.
Definition virtio:400
bool next(DESC_MAN *dm, ARGS... args)
Switch to the next descriptor in a descriptor chain.
Definition virtio:493
Virtqueue::Desc::Flags current_flags() const
Get the flags of the currently processed descriptor.
Definition virtio:469
Virtqueue::Request const & start(DESC_MAN *dm, Virtqueue::Request const &request, ARGS... args)
Start processing a new request.
Definition virtio:459
bool has_more() const
Are there more chained descriptors?
Definition virtio:476
void start(DESC_MAN *dm, Virtqueue *ring, Virtqueue::Head_desc const &request, ARGS... args)
Start processing a new request.
Definition virtio:428
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:154
void enable_notify()
Clear the 'no notify' flag for this queue.
Definition virtio:219
Desc const * desc(unsigned idx) const
Get a descriptor from the descriptor list.
Definition virtio:231
Request next_avail()
Get the next available descriptor from the available ring.
Definition virtio:137
void disable_notify()
Set the 'no notify' flag for this queue.
Definition virtio:208
void consumed(Head_desc const &r, l4_uint32_t len=0)
Put the given descriptor into the used ring.
Definition virtio:166
l4_uint16_t ring[]
array of available descriptor indexes.
Definition virtqueue:163
l4_uint16_t idx
available index written by guest
Definition virtqueue:162
Descriptor in the descriptor table.
Definition virtqueue:103
l4_uint16_t next
Index of the next chained descriptor.
Definition virtqueue:127
l4_uint32_t len
Length of described buffer.
Definition virtqueue:125
Flags flags
Descriptor flags.
Definition virtqueue:126
Used_elem ring[]
array of used descriptors.
Definition virtqueue:208
l4_uint16_t idx
index of the last entry in the ring.
Definition virtqueue:207
Flags flags
flags of the used ring.
Definition virtqueue:206
Low-level Virtqueue.
Definition virtqueue:97
Used * _used
pointer to used ring.
Definition virtqueue:214
bool ready() const
Test if this queue is in working state.
Definition virtqueue:412
l4_uint16_t _idx_mask
mask used for indexing into the descriptor table and the rings.
Definition virtqueue:223
Desc * _desc
pointer to descriptor table, NULL if queue is off.
Definition virtqueue:212
Avail * _avail
pointer to available ring.
Definition virtqueue:213
l4_uint16_t _current_avail
The life counter for the queue.
Definition virtqueue:217
unsigned num() const
Definition virtqueue:416
T1 min(T1 a, T1 b)
Get the minimum of a and b.
Definition minmax:35
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:285
#define L4_LIKELY(x)
Expression is likely to execute.
Definition compiler.h:284
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:326
Request_processor const * proc
The processor that triggered the exception.
Definition virtio:338
Error
The error code.
Definition virtio:329
@ Bad_rights
Missing access rights on memory.
Definition virtio:331
@ Bad_address
Address cannot be translated.
Definition virtio:330
@ Bad_flags
Invalid combination of descriptor flags.
Definition virtio:332
@ Bad_next
Invalid next index.
Definition virtio:333
@ Bad_size
Invalid size of memory block.
Definition virtio:334
char const * message() const
Get a human readable description of the error code.
Definition virtio:357
Bad_descriptor(Request_processor const *proc, Error e)
Make a bad descriptor exception.
Definition virtio:348
Abstract data buffer.
Definition virtio:240
void set(T *p)
Set buffer for object p.
Definition virtio:268
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:284
l4_uint32_t left
Bytes left in buffer.
Definition virtio:242
char * pos
Current buffer position.
Definition virtio:241
l4_uint32_t skip(l4_uint32_t bytes)
Skip given number of bytes in this buffer.
Definition virtio:304
bool done() const
Check if there are no more bytes left in the buffer.
Definition virtio:316
Data_buffer(T *p)
Create buffer for object p.
Definition virtio:255
Type for device feature bitmap.
Definition virtio:67
l4_uint32_t raw
The raw value of the features bitmap.
Definition virtio:68
ring_indirect_desc_bfm_t::Val ring_indirect_desc() const
Get the ring_indirect_desc bits ( 28 to 28 ) of raw.
Definition virtio:74
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
device_needs_reset_bfm_t::Val device_needs_reset() const
Get the device_needs_reset bits ( 6 to 6 ) of raw.
Definition virtio:45
features_ok_bfm_t::Val features_ok() const
Get the features_ok bits ( 3 to 3 ) of raw.
Definition virtio:43
acked_bfm_t::Val acked() const
Get the acked bits ( 0 to 0 ) of raw.
Definition virtio:40
driver_ok_bfm_t::Val driver_ok() const
Get the driver_ok bits ( 2 to 2 ) of raw.
Definition virtio:42
bool running() const
Check if the device is in running state.
Definition virtio:57
fail_state_bfm_t::Val fail_state() const
Get the fail_state bits ( 6 to 7 ) of raw.
Definition virtio:44
driver_bfm_t::Val driver() const
Get the driver bits ( 1 to 1 ) of raw.
Definition virtio:41
Dev_status(l4_uint32_t v)
Make Status from raw value.
Definition virtio:38
failed_bfm_t::Val failed() const
Get the failed bits ( 7 to 7 ) of raw.
Definition virtio:46
unsigned char raw
Raw value of the VIRTIO device status register.
Definition virtio:34
Type for descriptor flags.
Definition virtqueue:109
next_bfm_t::Val next() const
Get the next bits ( 0 to 0 ) of raw.
Definition virtqueue:117
indirect_bfm_t::Val indirect() const
Get the indirect bits ( 2 to 2 ) of raw.
Definition virtqueue:121
no_notify_bfm_t::Val no_notify() const
Get the no_notify bits ( 0 to 0 ) of raw.
Definition virtqueue:203
Type of an element of the used ring.
Definition virtqueue:170