11#include <l4/cxx/bitmap>
12#include <l4/l4virtio/l4virtio>
13#include <l4/l4virtio/server/l4virtio>
14#include <l4/l4virtio/server/virtio>
15#include <l4/re/util/object_registry>
20namespace L4virtio {
namespace Svr {
namespace Scmi {
33 Invalid_parameters = -2,
48 CXX_BITFIELD_MEMBER(18, 27,
token, hdr_raw);
58 Power_domain_management_protocol = 0x11,
59 System_power_management_protocol = 0x12,
60 Performance_domain_management_protocol = 0x13,
61 Clock_management_protocol = 0x14,
62 Sensor_management_protocol = 0x15,
63 Reset_domain_management_protocol = 0x16,
64 Voltage_domain_management_protocol = 0x17
70 Protocol_version = 0x0,
71 Protocol_attributes = 0x1,
72 Protocol_message_attributes = 0x2,
78 Base_discover_vendor = 0x3,
79 Base_discover_sub_vendor = 0x4,
80 Base_discover_implementation_version = 0x5,
81 Base_discover_list_protocols = 0x6,
82 Base_discover_agent = 0x7,
83 Base_notify_errors = 0x8,
84 Base_set_device_permissions = 0x9,
85 Base_set_protocol_permissions = 0xa,
86 Base_reset_agent_configuration = 0xb
93 CXX_BITFIELD_MEMBER(8, 15,
nagents, attr_raw);
94 CXX_BITFIELD_MEMBER(0, 7,
nprots, attr_raw);
100 Performance_domain_attributes = 0x3,
101 Performance_describe_levels = 0x4,
102 Performance_limits_set = 0x5,
103 Performance_limits_get = 0x6,
104 Performance_level_set = 0x7,
105 Performance_level_get = 0x8,
106 Performance_notify_limits = 0x9,
107 Performance_notify_level = 0xa,
108 Performance_describe_fastchannel = 0xb,
115 CXX_BITFIELD_MEMBER(16, 16,
power, attr_raw);
116 CXX_BITFIELD_MEMBER( 0, 15,
domains, attr_raw);
138 char name[16] = { 0 };
158template<
typename OBSERV>
161 Queue_worker(OBSERV *o,
Virtqueue *queue)
167 auto r = q->next_avail();
172 head =
start(o->mem_info(), r, &req);
181 { q->finish(head, o, total); }
186 buf->pos =
reinterpret_cast<char *
>(data);
191 chunk += req.copy_to(buf);
205 buf->pos =
reinterpret_cast<char *
>(data);
210 chunk += buf->copy_to(&req);
233 Data_buffer buf = Data_buffer(&hdr);
234 if ((res = read(&buf, &hdr)) < 0)
238 auto proto = o->proto(hdr.protocol_id());
241 if ((res = proto->handle_request(hdr, buf,
this)) < 0)
247 if ((res = write(&buf, &hdr)) < 0)
252 if ((res = write(&buf, &status)) < 0)
259 head = Virtqueue::Head_desc();
272 struct Buffer : Data_buffer
275 Buffer(L4virtio::Svr::Driver_mem_region
const *r,
276 Virtqueue::Desc
const &d, Request_processor
const *)
278 pos =
static_cast<char *
>(r->local(d.addr));
284 Virtqueue::Head_desc head;
298template<
typename OBSERV>
303 Queue_worker<OBSERV> *qw) = 0;
340 Features() =
default;
347 explicit Host_irq(
Scmi_dev *c) : c(c) {}
348 void handle_irq() { c->kick(); }
361 _request_worker(
this, &_q[0])
366 "Register irq object");
369 hf.ring_indirect_desc() =
true;
371 _dev_config.host_features(0) = hf.raw;
374 _dev_config.reset_hdr();
381 { _protos.insert({id, proto}); }
385 if (_protos.find(
id) != _protos.end())
386 return _protos.at(
id);
396 _kick_guest_irq->trigger();
401 {
return L4::cap_cast<L4::Irq>(_host_irq.obj_cap()); }
403 void register_single_driver_irq()
override
406 L4Re::chkcap(server_iface()->
template rcv_cap<L4::Irq>(0)));
413 if (_request_worker.handle_request() < 0)
417 void reset()
override
419 for (Virtqueue &q : _q)
422 for (
l4_uint32_t i = 0; i < _dev_config.num_queues(); i++)
426 bool check_queues()
override
431 int reconfig_queue(
unsigned idx)
override
433 if (idx >=
sizeof(_q) /
sizeof(_q[0]))
439 void trigger_driver_config_irq()
override
442 _kick_guest_irq->trigger();
445 L4virtio::Svr::Dev_config_t<L4virtio::Svr::No_custom_data> _dev_config;
449 Queue_worker<Scmi_dev> _request_worker;
450 std::map<l4_uint32_t, Proto<Scmi_dev> *> _protos;
465 virtual std::vector<l4_uint32_t> prots()
const = 0;
468 Queue_worker<Scmi_dev> *qw)
override
474 case Protocol_version:
476 if ((res = qw->write(&buf, &hdr)) < 0)
485 if ((res = qw->write(&buf, &version)) < 0)
490 case Protocol_attributes:
492 if ((res = qw->write(&buf, &hdr)) < 0)
498 if ((res = qw->write(&buf, &status)) < 0)
501 if (status == Success)
503 if ((res = qw->write(&buf, &ba)) < 0)
509 case Protocol_message_attributes:
512 if ((res = qw->read(&buf, &msg_id)) < 0)
515 if ((res = qw->write(&buf, &hdr)) < 0)
524 if (msg_id >= Protocol_version &&
525 msg_id <= Base_discover_list_protocols)
526 attr.status = Success;
528 if ((res = qw->write(&buf, &attr)) < 0)
533 case Base_discover_vendor:
535 if ((res = qw->write(&buf, &hdr)) < 0)
542 l4_uint8_t vendor_identifier[16] = {
"L4Re" };
544 if ((res = qw->write(&buf, &vendor)) < 0)
549 case Base_discover_sub_vendor:
551 if ((res = qw->write(&buf, &hdr)) < 0)
558 l4_uint8_t vendor_identifier[16] = {
"Scmi" };
560 if ((res = qw->write(&buf, &vendor)) < 0)
565 case Base_discover_implementation_version:
567 if ((res = qw->write(&buf, &hdr)) < 0)
576 if ((res = qw->write(&buf, &version)) < 0)
581 case Base_discover_list_protocols:
584 if ((res = qw->read(&buf, &skip)) < 0)
587 if ((res = qw->write(&buf, &hdr)) < 0)
597 proto.num = p.size();
598 if ((res = qw->write(&buf, &proto)) < 0)
604 l4_uint8_t parr[(p.size() + 3) / 4 * 4] = { 0 };
608 if ((res = qw->write(&buf, parr,
sizeof(parr))) < 0)
615 if ((res = qw->write(&buf, &hdr)) < 0)
620 if ((res = qw->write(&buf, &status)) < 0)
694 Queue_worker<Scmi_dev> *qw)
override
700 case Protocol_version:
702 if ((res = qw->write(&buf, &hdr)) < 0)
711 if ((res = qw->write(&buf, &version)) < 0)
716 case Protocol_attributes:
718 if ((res = qw->write(&buf, &hdr)) < 0)
724 if ((res = qw->write(&buf, &status)) < 0)
727 if (status == Success)
729 if ((res = qw->write(&buf, &pa)) < 0)
735 case Protocol_message_attributes:
738 if ((res = qw->read(&buf, &msg_id)) < 0)
741 if ((res = qw->write(&buf, &hdr)) < 0)
750 CXX_BITFIELD_MEMBER(0, 0, fast_channel, attr_raw);
752 if ((msg_id >= Protocol_version &&
753 msg_id <= Performance_describe_levels) ||
754 (msg_id >= Performance_level_set &&
755 msg_id <= Performance_level_get))
756 attr.status = Success;
758 if ((res = qw->write(&buf, &attr)) < 0)
763 case Performance_domain_attributes:
766 if ((res = qw->read(&buf, &domain_id)) < 0)
769 if ((res = qw->write(&buf, &hdr)) < 0)
774 l4_int32_t status = fill_domain_attr(domain_id, &attr);
775 if ((res = qw->write(&buf, &status)) < 0)
778 if (status == Success)
780 if ((res = qw->write(&buf, &attr)) < 0)
786 case Performance_describe_levels:
793 if ((res = qw->read(&buf, ¶m)) < 0)
796 if ((res = qw->write(&buf, &hdr)) < 0)
802 l4_int32_t status = fill_describe_levels_n(param.domain_id, param.level_idx,
804 if (status != Success)
807 if ((res = qw->write(&buf, &status)) < 0)
815 status = fill_describe_levels(param.domain_id, param.level_idx,
817 if ((res = qw->write(&buf, &status)) < 0)
820 if (status == Success)
823 if ((res = qw->write(&buf, &attr)) < 0)
826 if ((res = qw->write(&buf, attr1,
sizeof(attr1))) < 0)
832 case Performance_level_set:
839 if ((res = qw->read(&buf, ¶m)) < 0)
842 if ((res = qw->write(&buf, &hdr)) < 0)
846 l4_int32_t status = level_set(param.domain_id, param.perf_level);
847 if ((res = qw->write(&buf, &status)) < 0)
852 case Performance_level_get:
855 if ((res = qw->read(&buf, &domain_id)) < 0)
858 if ((res = qw->write(&buf, &hdr)) < 0)
863 l4_int32_t status = level_get(domain_id, &perf_level);
864 if ((res = qw->write(&buf, &status)) < 0)
867 if (status == Success)
869 if ((res = qw->write(&buf, &perf_level)) < 0)
877 if ((res = qw->write(&buf, &hdr)) < 0)
882 if ((res = qw->write(&buf, &status)) < 0)
A registry that manages server objects and their attached IPC gates for a single server loop for a sp...
L4::Cap< L4::Irq > register_irq_obj(L4::Epiface *o) override
Register a handler for an interrupt.
C++ interface for capabilities.
Server-side L4-VIRTIO device stub.
void device_error()
Transition device into DEVICE_NEEDS_RESET state.
bool setup_queue(Virtqueue *q, unsigned qn, unsigned num_max)
Enable/disable the specified queue.
void init_mem_info(unsigned num)
Initialize the memory region list to the given maximum.
void reset_queue_config(unsigned idx, unsigned num_max, bool inc_generation=false)
Trigger reset for the configuration space for queue idx.
Encapsulate the state for processing a VIRTIO request.
bool next(DESC_MAN *dm, ARGS... args)
Switch to the next descriptor in a descriptor chain.
void start(DESC_MAN *dm, Virtqueue *ring, Virtqueue::Head_desc const &request, ARGS... args)
Start processing a new request.
Base class for the SCMI base protocol.
Base class for the SCMI performance protocol.
A server implementation of the virtio-scmi protocol.
void add_proto(l4_uint32_t id, Proto< Scmi_dev > *proto)
Add an actual protocol implementation with the given id to the server.
Virtqueue implementation for the device.
bool no_notify_guest() const
Get the no IRQ flag of this queue.
unsigned int l4_size_t
Unsigned size type.
signed int l4_int32_t
Signed 32bit value.
unsigned char l4_uint8_t
Unsigned 8bit value.
signed int l4_ssize_t
Signed size type.
unsigned int l4_uint32_t
Unsigned 32bit value.
unsigned short int l4_uint16_t
Unsigned 16bit value.
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
@ L4VIRTIO_FEATURE_VERSION_1
Virtio protocol version 1 supported. Must be 1 for L4virtio.
@ L4VIRTIO_ID_SCMI
Scmi device.
@ L4VIRTIO_IRQ_STATUS_VRING
VRING IRQ pending flag.
@ L4VIRTIO_IRQ_STATUS_CONFIG
CONFIG IRQ pending flag.
L4::Detail::Unique_cap_impl< T, Smart_cap_auto< L4_FP_ALL_SPACES > > Unique_cap
Unique capability that implements automatic free and unmap of the capability selector.
long chksys(long err, char const *extra="", long ret=0)
Generate C++ exception on error.
T chkcap(T &&cap, char const *extra="", long err=-L4_ENOMEM)
Check for valid capability or raise C++ exception.
L4-VIRTIO Transport C++ API.
Epiface implementation for interrupt handlers.
Exception used by Queue to indicate descriptor errors.
l4_uint32_t left
Bytes left in buffer.
char * pos
Current buffer position.
Type for device feature bitmap.
l4_uint32_t raw
The raw value of the features bitmap.
SCMI base protocol attributes.
constexpr nagents_bfm_t::Val nagents() const
Get the nagents bits ( 8 to 15 ) of attr_raw.
constexpr nprots_bfm_t::Val nprots() const
Get the nprots bits ( 0 to 7 ) of attr_raw.
SCMI performance domain protocol attributes.
constexpr perf_limits_change_notify_bfm_t::Val perf_limits_change_notify() const
Get the perf_limits_change_notify bits ( 29 to 29 ) of attr_raw.
constexpr set_perf_level_bfm_t::Val set_perf_level() const
Get the set_perf_level bits ( 30 to 30 ) of attr_raw.
constexpr fast_channel_bfm_t::Val fast_channel() const
Get the fast_channel bits ( 27 to 27 ) of attr_raw.
constexpr rate_limit_bfm_t::Val rate_limit() const
Get the rate_limit bits ( 0 to 19 ) of rate_limit_raw.
constexpr perf_level_change_notify_bfm_t::Val perf_level_change_notify() const
Get the perf_level_change_notify bits ( 28 to 28 ) of attr_raw.
constexpr set_limits_bfm_t::Val set_limits() const
Get the set_limits bits ( 31 to 31 ) of attr_raw.
Base class for all protocols.
constexpr token_bfm_t::Val token() const
Get the token bits ( 18 to 27 ) of hdr_raw.
constexpr message_type_bfm_t::Val message_type() const
Get the message_type bits ( 8 to 9 ) of hdr_raw.
constexpr message_id_bfm_t::Val message_id() const
Get the message_id bits ( 0 to 7 ) of hdr_raw.
constexpr protocol_id_bfm_t::Val protocol_id() const
Get the protocol_id bits ( 10 to 17 ) of hdr_raw.