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)
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);
192 if (req.done() && !next())
205 buf->pos =
reinterpret_cast<char *
>(data);
210 chunk += buf->copy_to(&req);
211 if (req.done() && !next())
236 Data_buffer buf = Data_buffer(&hdr);
237 if ((res = read(&buf, &hdr)) < 0)
241 auto proto = o->proto(hdr.protocol_id());
244 if ((res = proto->handle_request(hdr, buf,
this)) < 0)
250 if ((res = write(&buf, &hdr)) < 0)
255 if ((res = write(&buf, &status)) < 0)
262 head = Virtqueue::Head_desc();
267 catch (L4virtio::Svr::Bad_descriptor
const &e)
275 struct Buffer : Data_buffer
278 Buffer(L4virtio::Svr::Driver_mem_region
const *r,
279 Virtqueue::Desc
const &d, Request_processor
const *)
287 Virtqueue::Head_desc head;
301template<
typename OBSERV>
306 Queue_worker<OBSERV> *qw) = 0;
339class Scmi_dev :
public L4virtio::Svr::Device
341 struct Features : L4virtio::Svr::Dev_config::Features
343 Features() =
default;
350 explicit Host_irq(Scmi_dev *c) : c(c) {}
351 void handle_irq() { c->kick(); }
361 : L4virtio::Svr::Device(&_dev_config),
364 _request_worker(
this, &_q[0])
369 "Register irq object");
374 _dev_config.host_features(0) = hf.
raw;
377 _dev_config.reset_hdr();
384 { _protos.insert({id, proto}); }
388 if (_protos.find(
id) != _protos.end())
389 return _protos.at(
id);
399 _kick_guest_irq->trigger();
409 L4Re::chkcap(server_iface()->
template rcv_cap<L4::Irq>(0)));
416 if (_request_worker.handle_request() < 0)
420 void reset()
override
422 for (Virtqueue &q : _q)
425 for (
l4_uint32_t i = 0; i < _dev_config.num_queues(); i++)
431 for (Virtqueue &q : _q)
438 int reconfig_queue(
unsigned idx)
override
440 if (idx >=
sizeof(_q) /
sizeof(_q[0]))
452 _kick_guest_irq->trigger();
455 L4virtio::Svr::Dev_config_t<L4virtio::Svr::No_custom_data> _dev_config;
459 Queue_worker<Scmi_dev> _request_worker;
460 std::map<l4_uint32_t, Proto<Scmi_dev> *> _protos;
475 virtual std::vector<l4_uint32_t> prots()
const = 0;
478 Queue_worker<Scmi_dev> *qw)
override
484 case Protocol_version:
486 if ((res = qw->write(&buf, &hdr)) < 0)
495 if ((res = qw->write(&buf, &version)) < 0)
500 case Protocol_attributes:
502 if ((res = qw->write(&buf, &hdr)) < 0)
508 if ((res = qw->write(&buf, &status)) < 0)
511 if (status == Success)
513 if ((res = qw->write(&buf, &ba)) < 0)
519 case Protocol_message_attributes:
522 if ((res = qw->read(&buf, &msg_id)) < 0)
525 if ((res = qw->write(&buf, &hdr)) < 0)
534 if (msg_id >= Protocol_version &&
535 msg_id <= Base_discover_list_protocols)
536 attr.status = Success;
538 if ((res = qw->write(&buf, &attr)) < 0)
543 case Base_discover_vendor:
545 if ((res = qw->write(&buf, &hdr)) < 0)
552 l4_uint8_t vendor_identifier[16] = {
"L4Re" };
554 if ((res = qw->write(&buf, &vendor)) < 0)
559 case Base_discover_sub_vendor:
561 if ((res = qw->write(&buf, &hdr)) < 0)
568 l4_uint8_t vendor_identifier[16] = {
"Scmi" };
570 if ((res = qw->write(&buf, &vendor)) < 0)
575 case Base_discover_implementation_version:
577 if ((res = qw->write(&buf, &hdr)) < 0)
586 if ((res = qw->write(&buf, &version)) < 0)
591 case Base_discover_list_protocols:
594 if ((res = qw->read(&buf, &skip)) < 0)
597 if ((res = qw->write(&buf, &hdr)) < 0)
607 proto.num = p.size();
608 if ((res = qw->write(&buf, &proto)) < 0)
614 l4_uint8_t parr[(p.size() + 3) / 4 * 4] = { 0 };
618 if ((res = qw->write(&buf, parr,
sizeof(parr))) < 0)
625 if ((res = qw->write(&buf, &hdr)) < 0)
630 if ((res = qw->write(&buf, &status)) < 0)
704 Queue_worker<Scmi_dev> *qw)
override
710 case Protocol_version:
712 if ((res = qw->write(&buf, &hdr)) < 0)
721 if ((res = qw->write(&buf, &version)) < 0)
726 case Protocol_attributes:
728 if ((res = qw->write(&buf, &hdr)) < 0)
734 if ((res = qw->write(&buf, &status)) < 0)
737 if (status == Success)
739 if ((res = qw->write(&buf, &pa)) < 0)
745 case Protocol_message_attributes:
748 if ((res = qw->read(&buf, &msg_id)) < 0)
751 if ((res = qw->write(&buf, &hdr)) < 0)
760 CXX_BITFIELD_MEMBER(0, 0, fast_channel, attr_raw);
762 if ((msg_id >= Protocol_version &&
763 msg_id <= Performance_describe_levels) ||
764 (msg_id >= Performance_level_set &&
765 msg_id <= Performance_level_get))
766 attr.status = Success;
768 if ((res = qw->write(&buf, &attr)) < 0)
773 case Performance_domain_attributes:
776 if ((res = qw->read(&buf, &domain_id)) < 0)
779 if ((res = qw->write(&buf, &hdr)) < 0)
784 l4_int32_t status = fill_domain_attr(domain_id, &attr);
785 if ((res = qw->write(&buf, &status)) < 0)
788 if (status == Success)
790 if ((res = qw->write(&buf, &attr)) < 0)
796 case Performance_describe_levels:
803 if ((res = qw->read(&buf, ¶m)) < 0)
806 if ((res = qw->write(&buf, &hdr)) < 0)
812 l4_int32_t status = fill_describe_levels_n(param.domain_id, param.level_idx,
814 if (status != Success)
817 if ((res = qw->write(&buf, &status)) < 0)
825 status = fill_describe_levels(param.domain_id, param.level_idx,
827 if ((res = qw->write(&buf, &status)) < 0)
830 if (status == Success)
833 if ((res = qw->write(&buf, &attr)) < 0)
836 if ((res = qw->write(&buf, attr1,
sizeof(attr1))) < 0)
842 case Performance_level_set:
849 if ((res = qw->read(&buf, ¶m)) < 0)
852 if ((res = qw->write(&buf, &hdr)) < 0)
856 l4_int32_t status = level_set(param.domain_id, param.perf_level);
857 if ((res = qw->write(&buf, &status)) < 0)
862 case Performance_level_get:
865 if ((res = qw->read(&buf, &domain_id)) < 0)
868 if ((res = qw->write(&buf, &hdr)) < 0)
873 l4_int32_t status = level_get(domain_id, &perf_level);
874 if ((res = qw->write(&buf, &status)) < 0)
877 if (status == Success)
879 if ((res = qw->write(&buf, &perf_level)) < 0)
887 if ((res = qw->write(&buf, &hdr)) < 0)
892 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.
void add_irq_status(l4_uint32_t status)
Adds irq status bit.
virtual void trigger_driver_config_irq()=0
virtual void register_single_driver_irq()
bool setup_queue(Virtqueue *q, unsigned qn, unsigned num_max)
void init_mem_info(unsigned num)
void reset_queue_config(unsigned idx, unsigned num_max, bool inc_generation=false, unsigned device_notify_index=0)
virtual L4::Cap< L4::Irq > device_notify_irq() const
virtual bool check_queues()=0
T * local(Ptr< T > p) const
Get the local address for driver address p.
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.
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.
Request next_avail()
Get the next available descriptor from the available ring.
void finish(Head_desc &d, QUEUE_OBSERVER *o, l4_uint32_t len=0)
Add a descriptor to the used ring, and notify an observer.
l4_uint32_t len
Length of described buffer.
Ptr< void > addr
Address stored in descriptor.
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.
@ L4_EINVAL
Invalid argument.
#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, L4Re::Util::Smart_cap_auto< L4_FP_ALL_SPACES > > Unique_cap
Unique capability that implements automatic free and unmap of the capability slot.
T chkcap(T &&cap, char const *extra="", l4_ret_t err=-L4_ENOMEM)
Check for valid capability or raise C++ exception.
l4_ret_t chksys(l4_ret_t err, char const *extra="", l4_ret_t ret=0)
Generate C++ exception on error.
Cap< T > cap_cast(Cap< F > const &c) noexcept
static_cast for capabilities.
L4-VIRTIO Transport C++ API.
Epiface implementation for interrupt handlers.
Cap< L4::Irq > obj_cap() const
Get the (typed) capability to this object.
l4_uint32_t left
Bytes left in buffer.
char * pos
Current buffer position.
l4_uint32_t raw
The raw value of the features bitmap.
constexpr ring_indirect_desc_bfm_t::Val ring_indirect_desc() const
Get the ring_indirect_desc bits (28 to 28) of raw.
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.