L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
virtio-scmi-device
1// vi:ft=cpp
2/* SPDX-License-Identifier: MIT */
3/*
4 * Copyright (C) 2024 Kernkonzept GmbH.
5 * Author(s): Christian Pötzsch <christian.poetzsch@kernkonzept.com>
6 *
7 * License: see LICENSE.spdx (in this directory or the directories above)
8 */
9#pragma once
10
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>
16
17#include <map>
18#include <vector>
19
20namespace L4virtio { namespace Svr { namespace Scmi {
21
23enum
24{
25 Version = 0x20000
26};
27
29enum
30{
31 Success = 0,
32 Not_supported = -1,
33 Invalid_parameters = -2,
34 Denied = -3,
35 Not_found = -4,
36 Out_of_range = -5,
37 Busy = -6,
38 Comms_error = -7,
39 Generic_error = -8,
40 Hardware_error = -9,
41 Protocol_error = -10
42};
43
46{
47 l4_uint32_t hdr_raw = 0;
48 CXX_BITFIELD_MEMBER(18, 27, token, hdr_raw);
49 CXX_BITFIELD_MEMBER(10, 17, protocol_id, hdr_raw);
50 CXX_BITFIELD_MEMBER( 8, 9, message_type, hdr_raw);
51 CXX_BITFIELD_MEMBER( 0, 7, message_id, hdr_raw);
52};
53
55enum
56{
57 Base_protocol = 0x10,
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
65};
66
68enum
69{
70 Protocol_version = 0x0,
71 Protocol_attributes = 0x1,
72 Protocol_message_attributes = 0x2,
73};
74
76enum
77{
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
87};
88
91{
92 l4_uint32_t attr_raw = 0;
93 CXX_BITFIELD_MEMBER(8, 15, nagents, attr_raw);
94 CXX_BITFIELD_MEMBER(0, 7, nprots, attr_raw);
95};
96
98enum
99{
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,
109};
110
113{
114 l4_uint32_t attr_raw = 0;
115 CXX_BITFIELD_MEMBER(16, 16, power, attr_raw);
116 CXX_BITFIELD_MEMBER( 0, 15, domains, attr_raw);
117
118 l4_uint32_t stat_addr_low = 0;
119 l4_uint32_t stat_addr_high = 0;
120 l4_uint32_t stat_len = 0;
121};
122
125{
126 l4_uint32_t attr_raw = 0;
127 CXX_BITFIELD_MEMBER(31, 31, set_limits, attr_raw);
128 CXX_BITFIELD_MEMBER(30, 30, set_perf_level, attr_raw);
129 CXX_BITFIELD_MEMBER(29, 29, perf_limits_change_notify, attr_raw);
130 CXX_BITFIELD_MEMBER(28, 28, perf_level_change_notify, attr_raw);
131 CXX_BITFIELD_MEMBER(27, 27, fast_channel, attr_raw);
132
133 l4_uint32_t rate_limit_raw = 0;
134 CXX_BITFIELD_MEMBER( 0, 19, rate_limit, rate_limit_raw);
135
136 l4_uint32_t sustained_freq = 0;
137 l4_uint32_t sustained_perf_level = 0;
138 char name[16] = { 0 };
139};
140
143{
144 l4_uint32_t num_levels_raw = 0;
145 CXX_BITFIELD_MEMBER(16, 31, nremain_perf_levels, num_levels_raw);
146 CXX_BITFIELD_MEMBER( 0, 11, nperf_levels, num_levels_raw);
147};
148
151{
152 l4_uint32_t perf_level = 0;
153 l4_uint32_t power_cost = 0;
154 l4_uint16_t trans_latency = 0;
155 l4_uint16_t res0 = 0;
156};
157
158template<typename OBSERV>
159struct Queue_worker : Request_processor
160{
161 Queue_worker(OBSERV *o, Virtqueue *queue)
162 : o(o), q(queue)
163 {}
164
165 bool init_queue()
166 {
167 auto r = q->next_avail();
168
169 if (L4_UNLIKELY(!r))
170 return false;
171
172 head = start(o->mem_info(), r, &req);
173
174 return true;
175 }
176
177 bool next()
178 { return Request_processor::next(o->mem_info(), &req); }
179
180 void finish(l4_uint32_t total)
181 { q->finish(head, o, total); }
182
183 template<typename T>
184 l4_ssize_t read(Data_buffer *buf, T *data, l4_size_t s = sizeof(T))
185 {
186 buf->pos = reinterpret_cast<char *>(data);
187 buf->left = s;
188 l4_size_t chunk = 0;
189 for (;;)
190 {
191 chunk += req.copy_to(buf);
192 if (req.done() && !next())
193 break;
194 if (!buf->left)
195 break;
196 }
197 if (chunk != s)
198 return -1;
199 return chunk;
200 }
201
202 template<typename T>
203 l4_ssize_t write(Data_buffer *buf, T *data, l4_size_t s = sizeof(T))
204 {
205 buf->pos = reinterpret_cast<char *>(data);
206 buf->left = s;
207 l4_size_t chunk = 0;
208 for (;;)
209 {
210 chunk += buf->copy_to(&req);
211 if (req.done() && !next())
212 break;
213 if (!buf->left)
214 break;
215 }
216 if (chunk != s)
217 return -1;
218 return chunk;
219 }
220
221 l4_ssize_t handle_request()
222 {
223 if (!q->ready())
224 return 0;
225
226 try
227 {
228 if (!head && L4_UNLIKELY(!init_queue()))
229 return 0;
230
231 for (;;)
232 {
233 l4_ssize_t total = 0;
234 l4_ssize_t res = 0;
235 Scmi_hdr_t hdr;
236 Data_buffer buf = Data_buffer(&hdr);
237 if ((res = read(&buf, &hdr)) < 0)
238 return res;
239
240 // Search/execute handler for given protocol
241 auto proto = o->proto(hdr.protocol_id());
242 if (proto)
243 {
244 if ((res = proto->handle_request(hdr, buf, this)) < 0)
245 return res;
246 total += res;
247 }
248 else
249 {
250 if ((res = write(&buf, &hdr)) < 0)
251 return res;
252 total += res;
253
254 l4_int32_t status = Not_supported;
255 if ((res = write(&buf, &status)) < 0)
256 return res;
257 total += res;
258 }
259
260 finish(total);
261
262 head = Virtqueue::Head_desc();
263 if (L4_UNLIKELY(!init_queue()))
264 return 0;
265 }
266 }
267 catch (L4virtio::Svr::Bad_descriptor const &e)
268 {
269 return e.error;
270 }
271 return 0;
272 }
273
274private:
275 struct Buffer : Data_buffer
276 {
277 Buffer() = default;
278 Buffer(L4virtio::Svr::Driver_mem_region const *r,
279 Virtqueue::Desc const &d, Request_processor const *)
280 {
281 pos = static_cast<char *>(r->local(d.addr));
282 left = d.len;
283 }
284 };
285
287 Virtqueue::Head_desc head;
288 Buffer req;
289
291 OBSERV *o;
292 Virtqueue *q;
293};
294
301template<typename OBSERV>
302struct Proto
303{
304 virtual l4_ssize_t handle_request(Scmi_hdr_t &hdr,
305 Data_buffer &buf,
306 Queue_worker<OBSERV> *qw) = 0;
307};
308
339class Scmi_dev : public L4virtio::Svr::Device
340{
341 struct Features : L4virtio::Svr::Dev_config::Features
342 {
343 Features() = default;
344 Features(l4_uint32_t raw) : L4virtio::Svr::Dev_config::Features(raw) {}
345 };
346
347 struct Host_irq : public L4::Irqep_t<Host_irq>
348 {
349 Scmi_dev *c;
350 explicit Host_irq(Scmi_dev *c) : c(c) {}
351 void handle_irq() { c->kick(); }
352 };
353
354 enum
355 {
356 Queue_size = 0x10
357 };
358
359public:
360 Scmi_dev(L4Re::Util::Object_registry *registry)
361 : L4virtio::Svr::Device(&_dev_config),
362 _dev_config(L4VIRTIO_VENDOR_KK, L4VIRTIO_ID_SCMI, 1),
363 _host_irq(this),
364 _request_worker(this, &_q[0])
365 {
366 init_mem_info(2);
367
368 L4Re::chkcap(registry->register_irq_obj(&_host_irq),
369 "Register irq object");
370
371 Features hf(0);
372 hf.ring_indirect_desc() = true;
373
374 _dev_config.host_features(0) = hf.raw;
375
376 _dev_config.set_host_feature(L4VIRTIO_FEATURE_VERSION_1);
377 _dev_config.reset_hdr();
378
379 reset();
380 }
381
384 { _protos.insert({id, proto}); }
385
386 Proto<Scmi_dev> *proto(l4_uint32_t id) const
387 {
388 if (_protos.find(id) != _protos.end())
389 return _protos.at(id);
390 return nullptr;
391 }
392
393 void notify_queue(L4virtio::Virtqueue *queue)
394 {
395 if (queue->no_notify_guest())
396 return;
397
399 _kick_guest_irq->trigger();
400 }
401
402private:
403 L4::Cap<L4::Irq> device_notify_irq() const override
404 { return L4::cap_cast<L4::Irq>(_host_irq.obj_cap()); }
405
406 void register_single_driver_irq() override
407 {
408 _kick_guest_irq = L4Re::Util::Unique_cap<L4::Irq>(
409 L4Re::chkcap(server_iface()->template rcv_cap<L4::Irq>(0)));
410
411 L4Re::chksys(server_iface()->realloc_rcv_cap(0));
412 }
413
414 void kick()
415 {
416 if (_request_worker.handle_request() < 0)
417 device_error();
418 }
419
420 void reset() override
421 {
422 for (Virtqueue &q : _q)
423 q.disable();
424
425 for (l4_uint32_t i = 0; i < _dev_config.num_queues(); i++)
426 reset_queue_config(i, Queue_size);
427 }
428
429 bool check_queues() override
430 {
431 for (Virtqueue &q : _q)
432 if (!q.ready())
433 return false;
434
435 return true;
436 }
437
438 int reconfig_queue(unsigned idx) override
439 {
440 if (idx >= sizeof(_q) / sizeof(_q[0]))
441 return -L4_ERANGE;
442
443 if (!setup_queue(_q + idx, idx, Queue_size))
444 return -L4_EINVAL;
445
446 return L4_EOK;
447 }
448
449 void trigger_driver_config_irq() override
450 {
451 _dev_config.add_irq_status(L4VIRTIO_IRQ_STATUS_CONFIG);
452 _kick_guest_irq->trigger();
453 }
454
455 L4virtio::Svr::Dev_config_t<L4virtio::Svr::No_custom_data> _dev_config;
456 Host_irq _host_irq;
457 L4Re::Util::Unique_cap<L4::Irq> _kick_guest_irq;
458 Virtqueue _q[1];
459 Queue_worker<Scmi_dev> _request_worker;
460 std::map<l4_uint32_t, Proto<Scmi_dev> *> _protos;
461};
462
468class Base_proto : public Proto<Scmi_dev>
469{
472 virtual l4_int32_t fill_attr(Base_attr_t *attr) const = 0;
473
475 virtual std::vector<l4_uint32_t> prots() const = 0;
476
477 l4_ssize_t handle_request(Scmi_hdr_t &hdr, Data_buffer &buf,
478 Queue_worker<Scmi_dev> *qw) override
479 {
480 l4_ssize_t total = 0;
481 l4_ssize_t res = 0;
482 switch (hdr.message_id())
483 {
484 case Protocol_version:
485 {
486 if ((res = qw->write(&buf, &hdr)) < 0)
487 return res;
488 total += res;
489
490 struct
491 {
492 l4_int32_t status = Success;
493 l4_uint32_t version = Version;
494 } version;
495 if ((res = qw->write(&buf, &version)) < 0)
496 return res;
497 total += res;
498 break;
499 }
500 case Protocol_attributes:
501 {
502 if ((res = qw->write(&buf, &hdr)) < 0)
503 return res;
504 total += res;
505
506 Base_attr_t ba;
507 l4_int32_t status = fill_attr(&ba);
508 if ((res = qw->write(&buf, &status)) < 0)
509 return res;
510 total += res;
511 if (status == Success)
512 {
513 if ((res = qw->write(&buf, &ba)) < 0)
514 return res;
515 total += res;
516 }
517 break;
518 }
519 case Protocol_message_attributes:
520 {
521 l4_uint32_t msg_id = 0;
522 if ((res = qw->read(&buf, &msg_id)) < 0)
523 return res;
524
525 if ((res = qw->write(&buf, &hdr)) < 0)
526 return res;
527 total += res;
528
529 struct
530 {
531 l4_int32_t status = Not_found;
532 l4_uint32_t attr = 0;
533 } attr;
534 if (msg_id >= Protocol_version &&
535 msg_id <= Base_discover_list_protocols)
536 attr.status = Success;
537
538 if ((res = qw->write(&buf, &attr)) < 0)
539 return res;
540 total += res;
541 break;
542 }
543 case Base_discover_vendor:
544 {
545 if ((res = qw->write(&buf, &hdr)) < 0)
546 return res;
547 total += res;
548
549 struct
550 {
551 l4_int32_t status = Success;
552 l4_uint8_t vendor_identifier[16] = { "L4Re" };
553 } vendor;
554 if ((res = qw->write(&buf, &vendor)) < 0)
555 return res;
556 total += res;
557 break;
558 }
559 case Base_discover_sub_vendor:
560 {
561 if ((res = qw->write(&buf, &hdr)) < 0)
562 return res;
563 total += res;
564
565 struct
566 {
567 l4_int32_t status = Success;
568 l4_uint8_t vendor_identifier[16] = { "Scmi" };
569 } vendor;
570 if ((res = qw->write(&buf, &vendor)) < 0)
571 return res;
572 total += res;
573 break;
574 }
575 case Base_discover_implementation_version:
576 {
577 if ((res = qw->write(&buf, &hdr)) < 0)
578 return res;
579 total += res;
580
581 struct
582 {
583 l4_int32_t status = Success;
584 l4_uint32_t version = 1;
585 } version;
586 if ((res = qw->write(&buf, &version)) < 0)
587 return res;
588 total += res;
589 break;
590 }
591 case Base_discover_list_protocols:
592 {
593 l4_uint32_t skip = 0;
594 if ((res = qw->read(&buf, &skip)) < 0)
595 return res;
596
597 if ((res = qw->write(&buf, &hdr)) < 0)
598 return res;
599 total += res;
600
601 auto p = prots();
602 struct
603 {
604 l4_int32_t status = Success;
605 l4_uint32_t num;
606 } proto;
607 proto.num = p.size();
608 if ((res = qw->write(&buf, &proto)) < 0)
609 return res;
610 total += res;
611
612 // Array of uint32 where 4 protos are packed into one uint32. So
613 // round up to 4 bytes and fill the array byte by byte.
614 l4_uint8_t parr[(p.size() + 3) / 4 * 4] = { 0 };
615 for (l4_size_t i = 0; i < p.size(); i++)
616 parr[i] = p.at(i);
617
618 if ((res = qw->write(&buf, parr, sizeof(parr))) < 0)
619 return res;
620 total += res;
621 break;
622 }
623 default:
624 {
625 if ((res = qw->write(&buf, &hdr)) < 0)
626 return res;
627 total += res;
628
629 l4_int32_t status = Not_supported;
630 if ((res = qw->write(&buf, &status)) < 0)
631 return res;
632 total += res;
633 break;
634 }
635 }
636
637 return total;
638 }
639};
640
672class Perf_proto : public Proto<Scmi_dev>
673{
676 virtual l4_int32_t fill_attr(Performance_attr_t *attr) const = 0;
677
680 virtual l4_int32_t fill_domain_attr(l4_uint32_t domain_id,
681 Performance_domain_attr_t *attr) const = 0;
682
684 virtual l4_int32_t fill_describe_levels_n(l4_uint32_t domain_id,
685 l4_uint32_t level_idx,
686 Performance_describe_levels_n_t *attr) const = 0;
687
690 virtual l4_int32_t fill_describe_levels(l4_uint32_t domain_id,
691 l4_uint32_t level_idx,
692 l4_uint32_t num,
693 Performance_describe_level_t *attr) const = 0;
694
696 virtual l4_int32_t level_set(l4_uint32_t domain_id,
697 l4_uint32_t perf_level) = 0;
698
700 virtual l4_int32_t level_get(l4_uint32_t domain_id,
701 l4_uint32_t *perf_level) const = 0;
702
703 l4_ssize_t handle_request(Scmi_hdr_t &hdr, Data_buffer &buf,
704 Queue_worker<Scmi_dev> *qw) override
705 {
706 l4_ssize_t total = 0;
707 l4_ssize_t res = 0;
708 switch (hdr.message_id())
709 {
710 case Protocol_version:
711 {
712 if ((res = qw->write(&buf, &hdr)) < 0)
713 return res;
714 total += res;
715
716 struct
717 {
718 l4_int32_t status = Success;
719 l4_uint32_t version = Version;
720 } version;
721 if ((res = qw->write(&buf, &version)) < 0)
722 return res;
723 total += res;
724 break;
725 }
726 case Protocol_attributes:
727 {
728 if ((res = qw->write(&buf, &hdr)) < 0)
729 return res;
730 total += res;
731
733 l4_int32_t status = fill_attr(&pa);
734 if ((res = qw->write(&buf, &status)) < 0)
735 return res;
736 total += res;
737 if (status == Success)
738 {
739 if ((res = qw->write(&buf, &pa)) < 0)
740 return res;
741 total += res;
742 }
743 break;
744 }
745 case Protocol_message_attributes:
746 {
747 l4_uint32_t msg_id = 0;
748 if ((res = qw->read(&buf, &msg_id)) < 0)
749 return res;
750
751 if ((res = qw->write(&buf, &hdr)) < 0)
752 return res;
753 total += res;
754
755 struct
756 {
757 l4_int32_t status = Not_found;
758
759 l4_uint32_t attr_raw = 0;
760 CXX_BITFIELD_MEMBER(0, 0, fast_channel, attr_raw); // ignored
761 } attr;
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;
767
768 if ((res = qw->write(&buf, &attr)) < 0)
769 return res;
770 total += res;
771 break;
772 }
773 case Performance_domain_attributes:
774 {
775 l4_uint32_t domain_id = 0;
776 if ((res = qw->read(&buf, &domain_id)) < 0)
777 return res;
778
779 if ((res = qw->write(&buf, &hdr)) < 0)
780 return res;
781 total += res;
782
784 l4_int32_t status = fill_domain_attr(domain_id, &attr);
785 if ((res = qw->write(&buf, &status)) < 0)
786 return res;
787 total += res;
788 if (status == Success)
789 {
790 if ((res = qw->write(&buf, &attr)) < 0)
791 return res;
792 total += res;
793 }
794 break;
795 }
796 case Performance_describe_levels:
797 {
798 struct
799 {
800 l4_uint32_t domain_id = 0;
801 l4_uint32_t level_idx = 0;
802 } param;
803 if ((res = qw->read(&buf, &param)) < 0)
804 return res;
805
806 if ((res = qw->write(&buf, &hdr)) < 0)
807 return res;
808 total += res;
809
810 // First figure out how many levels we support
812 l4_int32_t status = fill_describe_levels_n(param.domain_id, param.level_idx,
813 &attr);
814 if (status != Success)
815 {
816 // On error bail out early
817 if ((res = qw->write(&buf, &status)) < 0)
818 return res;
819 total += res;
820 break;
821 }
822
823 // Now fetch the actual levels
824 Performance_describe_level_t attr1[attr.nperf_levels().get()];
825 status = fill_describe_levels(param.domain_id, param.level_idx,
826 attr.nperf_levels(), attr1);
827 if ((res = qw->write(&buf, &status)) < 0)
828 return res;
829 total += res;
830 if (status == Success)
831 {
832 // Write both answers to the client
833 if ((res = qw->write(&buf, &attr)) < 0)
834 return res;
835 total += res;
836 if ((res = qw->write(&buf, attr1, sizeof(attr1))) < 0)
837 return res;
838 total += res;
839 }
840 break;
841 }
842 case Performance_level_set:
843 {
844 struct
845 {
846 l4_uint32_t domain_id;
847 l4_uint32_t perf_level;
848 } param;
849 if ((res = qw->read(&buf, &param)) < 0)
850 return res;
851
852 if ((res = qw->write(&buf, &hdr)) < 0)
853 return res;
854 total += res;
855
856 l4_int32_t status = level_set(param.domain_id, param.perf_level);
857 if ((res = qw->write(&buf, &status)) < 0)
858 return res;
859 total += res;
860 break;
861 }
862 case Performance_level_get:
863 {
864 l4_uint32_t domain_id = 0;
865 if ((res = qw->read(&buf, &domain_id)) < 0)
866 return res;
867
868 if ((res = qw->write(&buf, &hdr)) < 0)
869 return res;
870 total += res;
871
872 l4_uint32_t perf_level;
873 l4_int32_t status = level_get(domain_id, &perf_level);
874 if ((res = qw->write(&buf, &status)) < 0)
875 return res;
876 total += res;
877 if (status == Success)
878 {
879 if ((res = qw->write(&buf, &perf_level)) < 0)
880 return res;
881 total += res;
882 }
883 break;
884 }
885 default:
886 {
887 if ((res = qw->write(&buf, &hdr)) < 0)
888 return res;
889 total += res;
890
891 l4_int32_t status = Not_supported;
892 if ((res = qw->write(&buf, &status)) < 0)
893 return res;
894 total += res;
895 break;
896 }
897 }
898 return total;
899 }
900};
901
902} /* Scmi */ } /* Svr */ } /* L4virtio */
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.
Definition capability.h:249
void add_irq_status(l4_uint32_t status)
Adds irq status bit.
Definition l4virtio:285
bool setup_queue(Virtqueue *q, unsigned qn, unsigned num_max)
Definition l4virtio:1091
void reset_queue_config(unsigned idx, unsigned num_max, bool inc_generation=false, unsigned device_notify_index=0)
Definition l4virtio:1044
virtual L4::Cap< L4::Irq > device_notify_irq() const
Definition l4virtio:878
T * local(Ptr< T > p) const
Get the local address for driver address p.
Definition l4virtio:640
Encapsulate the state for processing a VIRTIO request.
Definition virtio:473
bool next(DESC_MAN *dm, ARGS... args)
Switch to the next descriptor in a descriptor chain.
Definition virtio:575
void start(DESC_MAN *dm, Virtqueue *ring, Virtqueue::Head_desc const &request, ARGS... args)
Start processing a new request.
Definition virtio:503
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.
Definition virtio:88
Request next_avail()
Get the next available descriptor from the available ring.
Definition virtio:136
void finish(Head_desc &d, QUEUE_OBSERVER *o, l4_uint32_t len=0)
Add a descriptor to the used ring, and notify an observer.
Definition virtio:240
l4_uint32_t len
Length of described buffer.
Definition virtqueue:115
Ptr< void > addr
Address stored in descriptor.
Definition virtqueue:114
Low-level Virtqueue.
Definition virtqueue:87
bool no_notify_guest() const
Get the no IRQ flag of this queue.
Definition virtqueue:433
unsigned int l4_size_t
Unsigned size type.
Definition l4int.h:22
signed int l4_int32_t
Signed 32bit value.
Definition l4int.h:28
unsigned char l4_uint8_t
Unsigned 8bit value.
Definition l4int.h:25
signed int l4_ssize_t
Signed size type.
Definition l4int.h:23
unsigned int l4_uint32_t
Unsigned 32bit value.
Definition l4int.h:29
unsigned short int l4_uint16_t
Unsigned 16bit value.
Definition l4int.h:27
@ L4_ERANGE
Range error.
Definition err.h:49
@ L4_EINVAL
Invalid argument.
Definition err.h:47
@ L4_EOK
Ok.
Definition err.h:33
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:295
@ L4VIRTIO_FEATURE_VERSION_1
Virtio protocol version 1 supported. Must be 1 for L4virtio.
Definition virtio.h:110
@ L4VIRTIO_ID_SCMI
Scmi device.
Definition virtio.h:80
@ L4VIRTIO_IRQ_STATUS_VRING
VRING IRQ pending flag.
Definition virtio.h:121
@ L4VIRTIO_IRQ_STATUS_CONFIG
CONFIG IRQ pending flag.
Definition virtio.h:122
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.
Definition unique_cap:43
T chkcap(T &&cap, char const *extra="", l4_ret_t err=-L4_ENOMEM)
Check for valid capability or raise C++ exception.
Definition error_helper:149
l4_ret_t chksys(l4_ret_t err, char const *extra="", l4_ret_t ret=0)
Generate C++ exception on error.
Definition error_helper:72
Cap< T > cap_cast(Cap< F > const &c) noexcept
static_cast for capabilities.
Definition capability.h:437
L4-VIRTIO Transport C++ API.
Definition l4virtio:26
Epiface implementation for interrupt handlers.
Definition ipc_epiface:401
Cap< L4::Irq > obj_cap() const
Get the (typed) capability to this object.
Definition ipc_epiface:412
Abstract data buffer.
Definition virtio:307
l4_uint32_t left
Bytes left in buffer.
Definition virtio:309
char * pos
Current buffer position.
Definition virtio:308
l4_uint32_t raw
The raw value of the features bitmap.
Definition virtio:68
constexpr ring_indirect_desc_bfm_t::Val ring_indirect_desc() const
Get the ring_indirect_desc bits (28 to 28) of raw.
Definition virtio:74
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 protocol attributes.
constexpr power_bfm_t::Val power() const
Get the power bits (16 to 16) of attr_raw.
constexpr domains_bfm_t::Val domains() const
Get the domains bits (0 to 15) of attr_raw.
SCMI performance describe levels numbers.
constexpr nperf_levels_bfm_t::Val nperf_levels() const
Get the nperf_levels bits (0 to 11) of num_levels_raw.
constexpr nremain_perf_levels_bfm_t::Val nremain_perf_levels() const
Get the nremain_perf_levels bits (16 to 31) of num_levels_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.