L4Re - L4 Runtime Environment
l4virtio
1 // vi:ft=cpp
2 /*
3  * (c) 2014 Alexander Warg <warg@os.inf.tu-dresden.de>
4  *
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU General Public License 2.
7  * Please see the COPYING-GPL-2 file for details.
8  *
9  * As a special exception, you may use this file as part of a free software
10  * library without restriction. Specifically, if other files instantiate
11  * templates or use macros or inline functions from this file, or you compile
12  * this file and link it with other files to produce an executable, this
13  * file does not by itself cause the resulting executable to be covered by
14  * the GNU General Public License. This exception does not however
15  * invalidate any other reasons why the executable file might be covered by
16  * the GNU General Public License.
17  */
18 #pragma once
19 
20 #include <limits.h>
21 
22 #include <l4/re/dataspace>
23 #include <l4/re/env>
24 #include <l4/re/error_helper>
25 #include <l4/re/rm>
26 #include <l4/re/util/cap_alloc>
27 
28 #include <l4/sys/types.h>
29 #include <l4/re/util/meta>
30 
31 #include <l4/cxx/bitfield>
32 #include <l4/cxx/utils>
33 #include <l4/cxx/unique_ptr>
34 
35 #include <l4/sys/cxx/ipc_legacy>
36 
37 #include "../l4virtio"
38 #include "virtio"
39 
43 namespace L4virtio {
44 namespace Svr {
45 
56 {
57 public:
58  typedef Dev_status Status;
59  typedef Dev_features Features;
60 
61 private:
62  typedef L4Re::Rm::Auto_region< l4virtio_config_hdr_t*> Cfg_region;
64 
65  l4_uint32_t _vendor, _device, _qoffset, _nqueues;
66  l4_uint32_t _host_features[sizeof(l4virtio_config_hdr_t::dev_features_map)
67  / sizeof(l4_uint32_t)];
68  Cfg_cap _ds;
69  Cfg_region _config;
70 
71  Status _status; // status shadow, can be trusted by the device model
72 
73  static l4_uint32_t align(l4_uint32_t x)
74  { return (x + 0xfU) & ~0xfU; }
75 
76 protected:
77  void volatile *get_priv_config() const
78  {
79  return l4virtio_device_config(_config.get());
80  }
81 
82 public:
83 
96  unsigned cfg_size, l4_uint32_t num_queues = 0)
97  : _vendor(vendor), _device(device),
98  _qoffset(0x100 + align(cfg_size)),
99  _nqueues(num_queues)
100  {
101  using L4Re::Dataspace;
102  using L4Re::chkcap;
103  using L4Re::chksys;
104 
105  //if (_cfg_offset + align(cfg_size) >= L4_PAGESIZE)
106  // hm what to do
107 
108  if (sizeof(l4virtio_config_queue_t) * _nqueues + _qoffset > L4_PAGESIZE)
109  {
110  // too many queues does not fit into our page
111  _qoffset = 0;
112  _nqueues = 0;
113  }
114 
115  Cfg_cap cfg = chkcap(L4Re::Util::cap_alloc.alloc<Dataspace>());
116  chksys(L4Re::Env::env()->mem_alloc()->alloc(L4_PAGESIZE, cfg.get()));
117  chksys(L4Re::Env::env()->rm()->attach(&_config, L4_PAGESIZE,
119  L4::Ipc::make_cap_rw(cfg.get())));
120  _ds = cfg;
121  _config->generation = 0;
122  memset(_config->driver_features_map, 0, sizeof (_config->driver_features_map));
123  memset(_host_features, 0, sizeof(_host_features));
124  _host_features[1] = 1; // virtio 1
125  reset_hdr();
126  }
127 
128  void set_host_feature(unsigned feature)
129  { l4virtio_set_feature(_host_features, feature); }
130 
131  void clear_host_feature(unsigned feature)
132  { l4virtio_clear_feature(_host_features, feature); }
133 
134  bool get_host_feature(unsigned feature)
135  { return l4virtio_get_feature(_host_features, feature); }
136 
137  l4_uint32_t &host_features(unsigned idx)
138  { return _host_features[idx]; }
139 
140  l4_uint32_t host_features(unsigned idx) const
141  { return _host_features[idx]; }
142 
150  Status status() const { return _status; }
151 
159  {
160  return hdr()->cmd;
161  }
162 
169  void reset_cmd()
170  {
171  const_cast<l4_uint32_t volatile &>(hdr()->cmd) = 0;
172  }
173 
181  void set_status(Status status)
182  {
183  _status = status;
184  const_cast<l4_uint32_t volatile &>(hdr()->status) = status.raw;
185  }
186 
193  void set_failed()
194  {
195  _status.failed() = 1;
196  const_cast<l4_uint32_t volatile &>(hdr()->status) = _status.raw;
197  }
198 
204  {
205  if (sizeof(l4virtio_config_queue_t) * num_queues + _qoffset > L4_PAGESIZE)
206  // too many queues does not fit into our page
207  return false;
208 
209  _nqueues = num_queues;
210  reset_hdr(true);
211  return true;
212  }
213 
220  l4virtio_config_queue_t volatile const *qconfig(unsigned index) const
221  {
222  if (L4_UNLIKELY(_qoffset < sizeof (l4virtio_config_hdr_t)))
223  return 0;
224 
225  if (L4_UNLIKELY(index >= _nqueues))
226  return 0;
227 
228  return reinterpret_cast<l4virtio_config_queue_t const *>
229  (reinterpret_cast<char *>(_config.get()) + _qoffset) + index;
230  }
231 
235  void reset_hdr(bool inc_generation = false) const
236  {
237  _config->magic = L4VIRTIO_MAGIC;
238  _config->version = 2;
239  _config->device = _device;
240  _config->vendor = _vendor;
241  _config->status = 0;
242  _config->irq_status = 0;
243  _config->num_queues = _nqueues;
244  _config->queues_offset = _qoffset;
245 
246  memcpy(_config->dev_features_map, _host_features,
247  sizeof(_config->dev_features_map));
248  wmb();
249  if (inc_generation)
250  ++_config->generation;
251 
252  }
253 
262  bool reset_queue(unsigned index, unsigned num_max,
263  bool inc_generation = false) const
264  {
265  l4virtio_config_queue_t volatile *qc;
266  // this function is allowed to write to the device config
267  qc = const_cast<l4virtio_config_queue_t volatile *>(qconfig(index));
268  if (L4_UNLIKELY(qc == 0))
269  return false;
270 
271  qc->num_max = num_max;
272  qc->num = 0;
273  qc->ready = 0;
274  wmb();
275  if (inc_generation)
276  ++_config->generation;
277 
278  return true;
279  }
280 
285  l4virtio_config_hdr_t const volatile *hdr() const
286  { return _config.get(); }
287 
292  L4::Cap<L4Re::Dataspace> ds() const { return _ds.get(); }
293 };
294 
295 
296 template<typename PRIV_CONFIG>
297 class Dev_config_t : public Dev_config
298 {
299 public:
301  typedef PRIV_CONFIG Priv_config;
302 
313  Dev_config_t(l4_uint32_t vendor, l4_uint32_t device,
314  l4_uint32_t num_queues = 0)
315  : Dev_config(vendor, device, sizeof(PRIV_CONFIG), num_queues)
316  {}
317 
327  Priv_config volatile *priv_config() const
328  {
329  return static_cast<Priv_config volatile *>(get_priv_config());
330  }
331 
332 };
333 
334 struct No_custom_data {};
335 
341 template <typename DATA>
342 class Driver_mem_region_t : public DATA
343 {
344 public:
345  struct Flags
346  {
347  l4_uint32_t raw;
348  CXX_BITFIELD_MEMBER(0, 0, rw, raw);
349  };
350 
351 private:
354 
355  l4_uint64_t _drv_base;
356  l4_uint64_t _trans_offset;
357  l4_umword_t _size;
358  Flags _flags;
359 
360  Ds_cap _ds;
361  l4_addr_t _ds_offset;
362 
364  L4Re::Rm::Auto_region<l4_addr_t> _local_base;
365 
366  template<typename T>
367  T _local(l4_uint64_t addr) const
368  {
369  return (T)(addr - _trans_offset);
370  }
371 
372 public:
374  Driver_mem_region_t() : _size(0) {}
375 
388  l4_addr_t offset, Ds_cap &&ds)
389  : _drv_base(l4_trunc_page(drv_base)), _size(0),
390  _ds_offset(l4_trunc_page(offset))
391  {
392  using L4Re::chksys;
393  using L4Re::Env;
394 
396  chksys(ds->info(&ds_info), "getting data-space infos");
397 
398  l4_addr_t ds_size = l4_round_page(ds_info.size);
399 
400  if (ds_size < L4_PAGESIZE)
401  chksys(-L4_EINVAL, "DS too small");
402 
403  if (_ds_offset >= ds_size)
404  chksys(-L4_ERANGE, "offset larger than DS size");
405 
406  size = l4_round_page(size);
407  if (size > ds_size)
408  chksys(-L4_EINVAL, "size larger than DS size");
409 
410  if (_ds_offset > ds_size - size)
411  chksys(-L4_EINVAL, "invalid offset or size");
412 
413  // overflow check
414  if ((ULLONG_MAX - size) < _drv_base)
415  chksys(-L4_EINVAL, "invalid size");
416 
417  _flags.rw() = ds_info.flags & L4Re::Dataspace::Map_rw;
418 
419  chksys(Env::env()->rm()->attach(&_local_base, size,
420  L4Re::Rm::Search_addr | (_flags.rw() ? 0 : L4Re::Rm::Read_only),
421  L4::Ipc::make_cap(ds.get(), _flags.rw()
423  : L4_CAP_FPAGE_RO), _ds_offset));
424 
425  _size = size;
426  _ds = cxx::move(ds);
427  _trans_offset = _drv_base - _local_base.get();
428  }
429 
431  bool is_writable() const { return _flags.rw(); }
432 
434  Flags flags() const { return _flags; }
435 
437  bool empty() const
438  { return _size == 0; }
439 
441  l4_uint64_t drv_base() const { return _drv_base; }
442 
444  void *local_base() const { return (void*)_local_base.get(); }
445 
447  l4_umword_t size() const { return _size; }
448 
450  l4_addr_t ds_offset() const { return _ds_offset; }
451 
453  L4::Cap<L4Re::Dataspace> ds() const { return _ds.get(); }
454 
462  bool contains(l4_uint64_t base, l4_umword_t size) const
463  {
464  if (base < _drv_base)
465  return false;
466 
467  if (base > _drv_base + _size - 1)
468  return false;
469 
470  if (size > _size)
471  return false;
472 
473  if (base - _drv_base > _size - size)
474  return false;
475 
476  return true;
477  }
478 
485  template<typename T>
486  T *local(Ptr<T> p) const
487  { return _local<T*>(p.get()); }
488 };
489 
491 
498 template <typename DATA>
500 {
501 public:
503 
504 private:
505  cxx::unique_ptr<Mem_region[]> _l;
506  unsigned _max;
507  unsigned _free;
508 
509 public:
512 
514  Driver_mem_list_t() : _max(0), _free(0) {}
515 
520  void init(unsigned max)
521  {
522  _l = cxx::make_unique<Driver_mem_region_t<DATA>[]>(max);
523  _max = max;
524  _free = 0;
525  }
526 
528  bool full() const
529  { return _free == _max; }
530 
539  Mem_region const *add(l4_uint64_t drv_base, l4_umword_t size,
540  l4_addr_t offset, Ds_cap &&ds)
541  {
542  if (full())
544 
545  _l[_free++] = Mem_region(drv_base, size, offset, cxx::move(ds));
546  return &_l[_free - 1];
547  }
548 
553  void remove(Mem_region const *r)
554  {
555  if (r < &_l[0] || r >= &_l[_free])
557 
558  unsigned idx = r - &_l[0];
559 
560  for (unsigned i = idx + 1; i < _free - 1; ++i)
561  _l[i] = cxx::move(_l[i + 1]);
562 
563  _l[--_free] = Mem_region();
564  }
565 
573  Mem_region *find(l4_uint64_t base, l4_umword_t size) const
574  {
575  return _find(base, size);
576  }
577 
584  void load_desc(Virtqueue::Desc const &desc, Request_processor const *p,
585  Virtqueue::Desc const **table) const
586  {
587  Mem_region const *r = find(desc.addr.get(), desc.len);
588  if (L4_UNLIKELY(!r))
590 
591  *table = static_cast<Virtqueue::Desc const *>(r->local(desc.addr));
592  }
593 
601  void load_desc(Virtqueue::Desc const &desc, Request_processor const *p,
602  Mem_region const **data) const
603  {
604  Mem_region const *r = find(desc.addr.get(), desc.len);
605  if (L4_UNLIKELY(!r))
607 
608  *data = r;
609  }
610 
623  template<typename ARG>
624  void load_desc(Virtqueue::Desc const &desc, Request_processor const *p,
625  ARG *data) const
626  {
627  Mem_region *r = find(desc.addr.get(), desc.len);
628  if (L4_UNLIKELY(!r))
630 
631  *data = ARG(r, desc, p);
632  }
633 
634 private:
635  Mem_region *_find(l4_uint64_t base, l4_umword_t size) const
636  {
637  for (unsigned i = 0; i < _free; ++i)
638  if (_l[i].contains(base, size))
639  return &_l[i];
640  return 0;
641  }
642 
643 
644 };
645 
647 
651 template<typename DATA>
652 class Device_t
653 {
654 public:
656 
657 protected:
658  Mem_list _mem_info;
659 
660 private:
661  Dev_config *_device_config;
662 
663 public:
664  L4_RPC_LEGACY_DISPATCH(L4virtio::Device);
665  template<typename IOS> int virtio_dispatch(unsigned r, IOS &ios)
666  { return dispatch(r, ios); }
667 
669  virtual void reset() = 0;
670 
672  virtual bool check_queues() = 0;
673 
675  virtual int reconfig_queue(unsigned idx) = 0;
676 
678  virtual void register_single_driver_irq() = 0;
679 
681  virtual L4::Cap<L4::Irq> device_notify_irq() const = 0;
682 
683  virtual L4::Ipc_svr::Server_iface *server_iface() const = 0;
684 
688  Device_t(Dev_config *dev_config)
689  : _device_config(dev_config)
690  {}
691 
695  Mem_list const *mem_info() const
696  { return &_mem_info; };
697 
698  long op_set_status(L4virtio::Device::Rights, unsigned status)
699  { return _set_status(status); }
700 
701  long op_config_queue(L4virtio::Device::Rights, unsigned queue)
702  {
703  Dev_config::Status status = _device_config->status();
704  if (status.failed())
705  return -L4_EIO;
706 
707  if (!status.acked() || !status.driver())
708  return -L4_EIO;
709 
710  return reconfig_queue(queue);
711  }
712 
713  long op_register_ds(L4virtio::Device::Rights,
714  L4::Ipc::Snd_fpage ds_cap_fp, l4_uint64_t ds_base,
715  l4_umword_t offset, l4_umword_t sz)
716  {
717  printf("Registering dataspace from 0x%llx with %lu KiB, offset 0x%lx\n",
718  ds_base, sz >> 10, offset);
719 
720  _check_n_init_shm(ds_cap_fp, ds_base, sz, offset);
721 
722  return 0;
723  }
724 
725  long op_register_iface(L4virtio::Device::Rights,
726  L4::Ipc::Snd_fpage irq_cap_fp,
729  {
730  if (!irq_cap_fp.cap_received())
731  return -L4_EINVAL;
732 
733  register_single_driver_irq();
734 
735  printf("register client: host IRQ: %lx config DS: %lx\n",
736  device_notify_irq().cap(), _device_config->ds().cap());
737 
738  host_irq = L4::Ipc::make_cap(device_notify_irq(), L4_CAP_FPAGE_RO);
739  config_ds = L4::Ipc::make_cap(_device_config->ds(), L4_CAP_FPAGE_RW);
740  return 0;
741  }
742 
754  void reset_queue_config(unsigned idx, unsigned num_max,
755  bool inc_generation = false)
756  {
757  _device_config->reset_queue(idx, num_max, inc_generation);
758  }
759 
764  void init_mem_info(unsigned num)
765  {
766  _mem_info.init(num);
767  }
768 
778  {
779  reset();
780  _device_config->set_failed();
781  }
782 
796  bool setup_queue(Virtqueue *q, unsigned qn, unsigned num_max)
797  {
798  l4virtio_config_queue_t volatile const *qc;
799  qc = _device_config->qconfig(qn);
800 
801  if (!qc->ready)
802  {
803  q->disable();
804  return true;
805  }
806 
807  // read to local variables before check
808  l4_uint32_t num = qc->num;
809  l4_uint64_t desc = qc->desc_addr;
810  l4_uint64_t avail = qc->avail_addr;
811  l4_uint64_t used = qc->used_addr;
812 
813  if (0)
814  printf("%p: setup queue: num=0x%x max_num=0x%x desc=0x%llx avail=0x%llx used=0x%llx\n",
815  this, num, num_max, desc, avail, used);
816 
817  if (!num || num > num_max)
818  return false;
819 
820  // num must be power of two
821  if (num & (num - 1))
822  return false;
823 
824  if (desc & 0xf)
825  return false;
826 
827  if (avail & 0x1)
828  return false;
829 
830  if (used & 0x3)
831  return false;
832 
833  auto const *desc_info = _mem_info.find(desc, Virtqueue::desc_size(num));
834  if (L4_UNLIKELY(!desc_info))
835  return false;
836 
837  auto const *avail_info = _mem_info.find(avail, Virtqueue::avail_size(num));
838  if (L4_UNLIKELY(!avail_info))
839  return false;
840 
841  auto const *used_info = _mem_info.find(used, Virtqueue::used_size(num));
842  if (L4_UNLIKELY(!used_info || !used_info->is_writable()))
843  return false;
844 
845  printf("shm=[%llx-%llx] local=[%lx-%lx] desc=[%llx-%llx] (%p-%p)\n",
846  desc_info->drv_base(), desc_info->drv_base() + desc_info->size() - 1,
847  (unsigned long)desc_info->local_base(),
848  (unsigned long)desc_info->local_base() + desc_info->size() - 1,
849  desc, desc + Virtqueue::desc_size(num),
850  desc_info->local(Ptr<char>(desc)),
851  desc_info->local(Ptr<char>(desc)) + Virtqueue::desc_size(num));
852 
853  printf("shm=[%llx-%llx] local=[%lx-%lx] avail=[%llx-%llx] (%p-%p)\n",
854  avail_info->drv_base(), avail_info->drv_base() + avail_info->size() - 1,
855  (unsigned long)avail_info->local_base(),
856  (unsigned long)avail_info->local_base() + avail_info->size() - 1,
857  avail, avail + Virtqueue::avail_size(num),
858  avail_info->local(Ptr<char>(avail)),
859  avail_info->local(Ptr<char>(avail)) + Virtqueue::avail_size(num));
860 
861  printf("shm=[%llx-%llx] local=[%lx-%lx] used=[%llx-%llx] (%p-%p)\n",
862  used_info->drv_base(), used_info->drv_base() + used_info->size() - 1,
863  (unsigned long)used_info->local_base(),
864  (unsigned long)used_info->local_base() + used_info->size() - 1,
865  used, used + Virtqueue::used_size(num),
866  used_info->local(Ptr<char>(used)),
867  used_info->local(Ptr<char>(used)) + Virtqueue::used_size(num));
868 
869  q->setup(num, desc_info->local(Ptr<void>(desc)),
870  avail_info->local(Ptr<void>(avail)),
871  used_info->local(Ptr<void>(used)));
872  return true;
873  }
874 
875  void check_n_init_shm(L4Re::Util::Auto_cap<L4Re::Dataspace>::Cap &&shm,
876  l4_uint64_t base, l4_umword_t size, l4_addr_t offset)
877  {
878  if (_mem_info.full())
880 
881  auto const *i = _mem_info.add(base, size, offset, cxx::move(shm));
882  printf("PORT[%p]: DMA guest [%llx-%llx] local [%lx-%lx] offset %lx\n",
883  this, i->drv_base(), i->drv_base() + i->size() - 1,
884  (unsigned long)i->local_base(),
885  (unsigned long)i->local_base() + i->size() - 1,
886  i->ds_offset());
887  }
888 
898  {
899  l4_uint32_t cmd = _device_config->get_cmd();
900  if (L4_LIKELY(!(cmd & L4VIRTIO_CMD_MASK)))
901  return false;
902 
903  switch (cmd & L4VIRTIO_CMD_MASK)
904  {
906  _set_status(cmd & ~L4VIRTIO_CMD_MASK);
907  break;
908 
910  reconfig_queue(cmd & ~L4VIRTIO_CMD_MASK);
911  break;
912 
913  default:
914  // unknown command
915  break;
916  }
917 
918  _device_config->reset_cmd();
919 
920  return true;
921  }
922 
923 private:
924  void _check_n_init_shm(L4::Ipc::Snd_fpage shm_cap_fp,
925  l4_uint64_t base, l4_umword_t size, l4_addr_t offset)
926  {
927  if (!shm_cap_fp.cap_received())
929 
931  ds = L4Re::chkcap(server_iface()->template rcv_cap<L4Re::Dataspace>(0));
932  L4Re::chksys(server_iface()->realloc_rcv_cap(0));
933 
934  check_n_init_shm(cxx::move(ds), base, size, offset);
935  }
936 
937  int _set_status(unsigned _status)
938  {
939  Dev_config::Status status(_status);
940 
941  if (_status == 0)
942  {
943  printf("Resetting device\n");
944  reset();
945  }
946 
947  // do nothing if 'failed' is set
948  if (status.failed())
949  return 0;
950 
951  if (status.running() && !check_queues())
952  status.failed() = 1;
953 
954  _device_config->set_status(status);
955  return 0;
956  }
957 
958 };
959 
961 
962 } // namespace Svr
963 
964 }
965 
l4_umword_t size() const
Definition: l4virtio:447
l4_uint32_t get_cmd() const
Get the value from the cmd register.
Definition: l4virtio:158
Request writable mapping.
Definition: dataspace:71
Capability type for RPC interfaces (see L4::Cap<T>).
Definition: ipc_types:541
Set the status register.
Definition: virtio.h:119
unsigned long size
size
Definition: dataspace:86
Descriptor in the descriptor table.
Definition: virtqueue:93
Pointer used in virtio descriptors.
Definition: virtqueue:56
Read and interface specific &#39;W&#39; right for capability flex-pages.
Definition: __l4_fpage.h:176
Smart capability class.
l4_uint32_t status
Device status register (read-only).
Definition: virtio.h:166
Virtqueue implementation for the device.
Definition: virtio:93
Abstraction for L4-Virtio device config memory.
Definition: l4virtio:55
Invalid argument.
Definition: err.h:56
Status status() const
Get current device status (trusted).
Definition: l4virtio:150
Server-side L4-VIRTIO device stub.
Definition: l4virtio:652
void l4virtio_set_feature(l4_uint32_t *feature_map, unsigned feat)
Set the given feature bit in a feature map.
Definition: virtio.h:257
bool handle_mem_cmd_write()
Check for a value in the cmd register and handle a write.
Definition: l4virtio:897
Dev_config(l4_uint32_t vendor, l4_uint32_t device, unsigned cfg_size, l4_uint32_t num_queues=0)
Setup/Create a L4-Virtio config data space.
Definition: l4virtio:95
bool change_queue_config(l4_uint32_t num_queues)
Setup new queue configuration.
Definition: l4virtio:203
Interface for server-loop related functions.
Definition: ipc_epiface:45
bool cap_received() const
Check if the capability has been mapped.
Definition: ipc_types:438
l4virtio_config_queue_t volatile const * qconfig(unsigned index) const
Get queue read-only config data for queue with the given index.
Definition: l4virtio:220
l4_addr_t l4_round_page(l4_addr_t address) L4_NOTHROW
Round address up to the next page.
Definition: consts.h:359
void reset_hdr(bool inc_generation=false) const
Reset the config header to the initial contents.
Definition: l4virtio:235
void load_desc(Virtqueue::Desc const &desc, Request_processor const *p, Mem_region const **data) const
Default implementation returning the Driver_mem_region.
Definition: l4virtio:601
Common L4 ABI Data Types.
Driver_mem_list_t()
Make an empty, zero capacity list.
Definition: l4virtio:514
l4_uint32_t cmd
L4 specific command register polled by the driver iff supported.
Definition: virtio.h:187
Address cannot be translated.
Definition: virtio:334
Information about the dataspace.
Definition: dataspace:85
void reset_queue_config(unsigned idx, unsigned num_max, bool inc_generation=false)
Trigger reset for the configuration space for queue idx.
Definition: l4virtio:754
Cap< T > make_cap(L4::Cap< T > cap, unsigned rights)
Make an L4::Ipc::Cap<T> for the given capability and rights.
Definition: ipc_types:621
L4::Cap< L4Re::Dataspace > ds() const
Get data-space capability for the shared config data space.
Definition: l4virtio:292
C++ interface of the initial environment that is provided to an L4 task.
Definition: env:82
Exception used by Queue to indicate descriptor errors.
Definition: virtio:329
l4_addr_t l4_trunc_page(l4_addr_t address) L4_NOTHROW
Round an address down to the next lower page boundary.
Definition: consts.h:334
Driver_mem_region_t(l4_uint64_t drv_base, l4_umword_t size, l4_addr_t offset, Ds_cap &&ds)
Make a local memory region for the given driver values.
Definition: l4virtio:387
Type of the device status register.
Definition: virtio:43
l4_uint64_t used_addr
W: address of used ring.
Definition: virtio.h:223
void disable()
Completely disable the queue.
Definition: virtqueue:228
l4_uint64_t drv_base() const
Definition: l4virtio:441
Search for a suitable address range.
Definition: rm:113
Mem_region * find(l4_uint64_t base, l4_umword_t size) const
Find memory region containing the given driver address region.
Definition: l4virtio:573
void device_error()
Transition device into failed state.
Definition: l4virtio:777
Mem_list _mem_info
Memory region list.
Definition: l4virtio:658
Encapsulate the state for processing a VIRTIO request.
Definition: virtio:381
l4_uint16_t num
RW: number of descriptors configured for this queue.
Definition: virtio.h:213
Environment interface.
Read right for capability flex-pages.
Definition: __l4_fpage.h:160
Interface for memory-like objects.
Definition: dataspace:59
T1 max(T1 a, T1 b)
Get the maximum of a and b.
Definition: minmax:45
l4virtio_config_hdr_t const volatile * hdr() const
Get a read-only pointer to the config header.
Definition: l4virtio:285
Error helper.
long info(Stats *stats)
Get information on the dataspace.
#define L4_PAGESIZE
Minimal page size (in bytes).
Definition: consts.h:277
driver_bfm_t::Val driver() const
Get the driver bits ( 1 to 1 ) of raw .
Definition: virtio:52
void * l4virtio_device_config(l4virtio_config_hdr_t const *cfg)
Get the pointer to the device configuration.
Definition: virtio.h:248
Region mapper interface.
bool contains(l4_uint64_t base, l4_umword_t size) const
Test if the given driver address range is within this region.
Definition: l4virtio:462
bool running() const
Check if the device is in running state.
Definition: virtio:65
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition: compiler.h:234
static Env const * env()
Returns the initial environment for the current task.
Definition: env:100
unsigned long flags
flags
Definition: dataspace:87
Configure a queue.
Definition: virtio.h:120
L4-VIRTIO config header, provided in shared data space.
Definition: virtio.h:127
unsigned l4virtio_get_feature(l4_uint32_t *feature_map, unsigned feat)
Check if the given bit in a feature map is set.
Definition: virtio.h:281
l4_cap_idx_t cap() const
Return capability selector.
Definition: capability.h:51
_Cap_alloc & cap_alloc
Capability allocator.
Cap< T > make_cap_rw(L4::Cap< T > cap)
Make an L4::Ipc::Cap<T> for the given capability with L4_CAP_FPAGE_RW rights.
Definition: ipc_types:631
unsigned long l4_umword_t
Unsigned machine word.
Definition: l4int.h:52
l4_uint16_t num_max
R: maximum number of descriptors supported by this queue.
Definition: virtio.h:211
Ptr< void > addr
Address stored in descriptor.
Definition: virtqueue:115
T chkcap(T &&cap, char const *extra="", long err=-L4_ENOMEM)
Check for valid capability or raise C++ exception.
Definition: error_helper:139
List of driver memory regions assigned to a single L4-VIRTIO transport instance.
Definition: l4virtio:499
void init(unsigned max)
Make a fresh list with capacity max.
Definition: l4virtio:520
L4::Cap< L4Re::Dataspace > ds() const
Definition: l4virtio:453
No memory.
Definition: err.h:50
#define L4_LIKELY(x)
Expression is likely to execute.
Definition: compiler.h:233
unsigned char raw
Raw value of the VIRTIO device status register.
Definition: virtio:45
l4_uint16_t ready
RW: queue ready flag (read-write)
Definition: virtio.h:216
l4_uint64_t get() const
Definition: virtqueue:71
I/O error.
Definition: err.h:46
void set_status(Status status)
Set device status register.
Definition: l4virtio:181
void setup(unsigned num, void *desc, void *avail, void *used)
Enable this queue.
Definition: virtqueue:353
T * local(Ptr< T > p) const
Get the local address for driver address p.
Definition: l4virtio:486
void set_failed()
Set device status failed bit.
Definition: l4virtio:193
Mem_list const * mem_info() const
Get the memory region list used for this device.
Definition: l4virtio:695
failed_bfm_t::Val failed() const
Get the failed bits ( 7 to 7 ) of raw .
Definition: virtio:55
long chksys(long err, char const *extra="", long ret=0)
Generate C++ exception on error.
Definition: error_helper:62
Type for device feature bitmap.
Definition: virtio:74
static unsigned long avail_size(unsigned num)
Calculate the size of the available ring for num entries.
Definition: virtqueue:283
Queue configuration entry.
Definition: virtio.h:208
Region of driver memory, that shall be managed locally.
Definition: l4virtio:342
void init_mem_info(unsigned num)
Initialize the memory region list to the given maximum.
Definition: l4virtio:764
void reset_cmd()
Reset the cmd register after execution of a command.
Definition: l4virtio:169
Region is read-only.
Definition: rm:88
void load_desc(Virtqueue::Desc const &desc, Request_processor const *p, ARG *data) const
Default implementation returning generic information.
Definition: l4virtio:624
bool reset_queue(unsigned index, unsigned num_max, bool inc_generation=false) const
Reset queue config for the given queue.
Definition: l4virtio:262
Dataspace interface.
Capability allocator.
Range error.
Definition: err.h:58
void load_desc(Virtqueue::Desc const &desc, Request_processor const *p, Virtqueue::Desc const **table) const
Default implementation for loading an indirect descriptor.
Definition: l4virtio:584
Device_t(Dev_config *dev_config)
Make a device for the given config.
Definition: l4virtio:688
static unsigned long desc_size(unsigned num)
Calculate the size of the descriptor table for num entries.
Definition: virtqueue:265
unsigned long long l4_uint64_t
Unsigned 64bit value.
Definition: l4int.h:42
bool setup_queue(Virtqueue *q, unsigned qn, unsigned num_max)
Enable/disable the specified queue.
Definition: l4virtio:796
L4-VIRTIO Transport C++ API.
Definition: l4virtio:29
Mem_region const * add(l4_uint64_t drv_base, l4_umword_t size, l4_addr_t offset, Ds_cap &&ds)
Add a new region to the list.
Definition: l4virtio:539
l4_uint32_t len
Length of described buffer.
Definition: virtqueue:116
L4Re::Util::Auto_cap< L4Re::Dataspace >::Cap Ds_cap
type for storing a data-space capability internally
Definition: l4virtio:511
Mask to get command bits.
Definition: virtio.h:121
unsigned long l4_addr_t
Address type.
Definition: l4int.h:45
l4_uint64_t desc_addr
W: address of descriptor table.
Definition: virtio.h:221
acked_bfm_t::Val acked() const
Get the acked bits ( 0 to 0 ) of raw .
Definition: virtio:51
void l4virtio_clear_feature(l4_uint32_t *feature_map, unsigned feat)
Clear the given feature bit in a feature map.
Definition: virtio.h:269
l4_uint64_t avail_addr
W: address of available ring.
Definition: virtio.h:222
unsigned int l4_uint32_t
Unsigned 32bit value.
Definition: l4int.h:40
Driver_mem_region_t()
Make default empty memroy region.
Definition: l4virtio:374
Generic RPC wrapper for L4 flex-pages.
Definition: ipc_types:321
static unsigned long used_size(unsigned num)
Calculate the size of the used ring for num entries.
Definition: virtqueue:302
l4_addr_t ds_offset() const
Definition: l4virtio:450