L4Re – L4 Runtime Environment
l4virtio
1 // vi:ft=cpp
2 /* SPDX-License-Identifier: GPL-2.0-only or License-Ref-kk-custom */
3 /*
4  * Copyright (C) 2013-2020 Kernkonzept GmbH.
5  * Author(s): Alexander Warg <alexander.warg@kernkonzept.com>
6  * Matthias Lange <matthias.lange@kernkonzept.com>
7  *
8  */
9 #pragma once
10 
11 #include "virtio.h"
12 #include <l4/sys/capability>
13 #include <l4/sys/cxx/ipc_client>
14 #include <l4/re/dataspace>
15 #include <l4/sys/irq>
16 #include <l4/cxx/utils>
17 
18 namespace L4virtio {
39 class Device :
40  public L4::Kobject_t<Device, L4::Icu, L4VIRTIO_PROTOCOL,
41  L4::Type_info::Demand_t<1> >
42 {
43 public:
45  struct Config_hdr : l4virtio_config_hdr_t
46  {
47  Config_queue *queues() const
48  { return l4virtio_config_queues(this); }
49 
50  template <typename T>
51  T *device_config() const
52  {
53  return static_cast<T*>(l4virtio_device_config(this));
54  }
55 
56  int config_queue(unsigned num, L4::Cap<L4::Triggerable> out_notify,
57  L4::Cap<L4::Triggerable> in_notify,
58  l4_timeout_s to = L4_IPC_TIMEOUT_NEVER)
59  {
60  return send_cmd(L4VIRTIO_CMD_CFG_QUEUE | num,
61  out_notify, in_notify, to);
62  }
63 
72  bool fail_state() const
73  {
74  auto cfg_status = cxx::access_once(&status);
75  return cfg_status
77  }
78 
79  int set_status(unsigned new_status, L4::Cap<L4::Triggerable> out_notify,
80  L4::Cap<L4::Triggerable> in_notify,
81  l4_timeout_s to = L4_IPC_TIMEOUT_NEVER)
82  {
83  return send_cmd(L4VIRTIO_CMD_SET_STATUS | new_status,
84  out_notify, in_notify, to);
85  }
86 
87  int send_cmd(unsigned command, L4::Cap<L4::Triggerable> out_notify,
88  L4::Cap<L4::Triggerable> in_notify,
89  l4_timeout_s to = L4_IPC_TIMEOUT_NEVER)
90  {
91  cxx::write_now(&cmd, command);
92 
93  if (out_notify)
94  out_notify->trigger();
95 
96  auto utcb = l4_utcb();
97  auto ipc_to = l4_timeout(L4_IPC_TIMEOUT_0, to);
98 
99  do
100  {
101  if (in_notify)
102  if (l4_ipc_error(l4_ipc_receive(in_notify.cap(), utcb, ipc_to),
103  utcb) == L4_IPC_RETIMEOUT)
104  break;
105  }
106  while (cxx::access_once(&cmd));
107 
108  return cxx::access_once(&cmd) ? -L4_EBUSY : L4_EOK;
109  }
110  };
111 
121  L4_INLINE_RPC(long, set_status, (unsigned status));
122 
138  L4_INLINE_RPC(long, config_queue, (unsigned queue));
139 
154  l4_uint64_t base, l4_umword_t offset,
155  l4_umword_t size));
156 
177 
187  l4_addr_t *ds_offset));
188 
208  (unsigned index, L4::Ipc::Out<L4::Cap<L4::Triggerable> > irq));
209 
210 
211  typedef L4::Typeid::Rpcs<set_status_t, config_queue_t, register_iface_t,
212  register_ds_t, device_config_t,
213  device_notification_irq_t> Rpcs;
214 };
215 
216 }
L4::Cap related definitions.
l4_cap_idx_t cap() const noexcept
Return capability selector.
Definition: capability.h:52
C++ interface for capabilities.
Definition: capability.h:219
Capability type for RPC interfaces (see L4::Cap<T>).
Definition: ipc_types:542
Helper class to create an L4Re interface class that is derived from a single base class.
Definition: __typeinfo.h:760
IPC interface for virtio over L4 IPC.
Definition: l4virtio:42
long register_ds(L4::Ipc::Cap< L4Re::Dataspace > ds_cap, l4_uint64_t base, l4_umword_t offset, l4_umword_t size)
Register a shared data space with VIRTIO host.
long device_notification_irq(unsigned index, L4::Ipc::Out< L4::Cap< L4::Triggerable > > irq)
Get the notification interrupt corresponding to the given index.
long config_queue(unsigned queue)
Trigger queue configuration of the given queue.
long device_config(L4::Ipc::Out< L4::Cap< L4Re::Dataspace > > config_ds, l4_addr_t *ds_offset)
Get the dataspace with the L4virtio configuration page.
long register_iface(L4::Ipc::Cap< L4::Triggerable > guest_irq, L4::Ipc::Out< L4::Cap< L4::Triggerable > > host_irq, L4::Ipc::Out< L4::Cap< L4Re::Dataspace > > config_ds)
Register client to the L4-VIRTIO device.
long set_status(unsigned status)
Write the VIRTIO status register.
Dataspace interface.
unsigned long l4_umword_t
Unsigned machine word.
Definition: l4int.h:51
unsigned long l4_addr_t
Address type.
Definition: l4int.h:45
unsigned long long l4_uint64_t
Unsigned 64bit value.
Definition: l4int.h:42
@ L4_EBUSY
Object currently busy, try later.
Definition: err.h:53
@ L4_EOK
Ok.
Definition: err.h:43
l4_msgtag_t l4_ipc_receive(l4_cap_idx_t object, l4_utcb_t *utcb, l4_timeout_t timeout) L4_NOTHROW
Wait for a message from a specific source.
Definition: ipc.h:505
l4_umword_t l4_ipc_error(l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW
Get the error code for an object invocation.
Definition: ipc.h:518
@ L4_IPC_RETIMEOUT
Timeout during receive operation.
Definition: ipc.h:83
#define L4_IPC_TIMEOUT_0
Timeout constants.
Definition: __timeout.h:79
l4_timeout_t l4_timeout(l4_timeout_s snd, l4_timeout_s rcv) L4_NOTHROW
Combine send and receive timeout in a timeout.
Definition: __timeout.h:198
l4_utcb_t * l4_utcb(void) L4_NOTHROW L4_PURE
Get the UTCB address.
Definition: utcb.h:340
l4virtio_config_queue_t * l4virtio_config_queues(l4virtio_config_hdr_t const *cfg)
Get the pointer to the first queue config.
Definition: virtio.h:232
void * l4virtio_device_config(l4virtio_config_hdr_t const *cfg)
Get the pointer to the device configuration.
Definition: virtio.h:243
@ L4VIRTIO_STATUS_FAILED
Driver detected fatal error.
Definition: virtio.h:86
@ L4VIRTIO_STATUS_DEVICE_NEEDS_RESET
Device detected fatal error.
Definition: virtio.h:85
@ L4VIRTIO_CMD_SET_STATUS
Set the status register.
Definition: virtio.h:114
@ L4VIRTIO_CMD_CFG_QUEUE
Configure a queue.
Definition: virtio.h:115
#define L4_INLINE_RPC(res, name, args, attr...)
Define an inline RPC call (type and callable).
Definition: ipc_iface:469
C++ Irq interface.
L4-VIRTIO Transport C++ API.
Definition: virtio-block:29
Mark an argument as a output value in an RPC signature.
Definition: ipc_types:42
Standard list of RPCs of an interface.
Definition: __typeinfo.h:438
Basic timeout specification.
Definition: __timeout.h:47
L4-VIRTIO config header, provided in shared data space.
Definition: virtio.h:123
Queue configuration entry.
Definition: virtio.h:204