L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
vfs_impl.h
1/*
2 * (c) 2008-2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3 * Alexander Warg <warg@os.inf.tu-dresden.de>,
4 * Björn Döbel <doebel@os.inf.tu-dresden.de>
5 * economic rights: Technische Universität Dresden (Germany)
6 *
7 * License: see LICENSE.spdx (in this directory or the directories above)
8 */
9
10#include "fd_store.h"
11#include "vcon_stream.h"
12#include "ns_fs.h"
13
14#include <l4/bid_config.h>
15#include <l4/re/env>
16#include <l4/re/rm>
17#include <l4/re/dataspace>
18#include <l4/sys/assert.h>
19#include <l4/cxx/hlist>
20#include <l4/cxx/pair>
21#include <l4/cxx/std_alloc>
22
23#include <l4/l4re_vfs/backend>
24#include <l4/re/shared_cap>
25
26#include <unistd.h>
27#include <stdarg.h>
28#include <errno.h>
29#include <sys/uio.h>
30#include <sys/mman.h>
31
32#if 0
33#include <l4/sys/kdebug.h>
34static int debug_mmap = 1;
35#define DEBUG_LOG(level, dbg...) do { if (level) dbg } while (0)
36#else
37#define DEBUG_LOG(level, dbg...) do { } while (0)
38#endif
39
45#define USE_BIG_ANON_DS
46
47using L4Re::Rm;
48
49namespace {
50
51using cxx::Ref_ptr;
52
53class Fd_store : public L4Re::Core::Fd_store
54{
55public:
56 Fd_store() noexcept;
57};
58
59// for internal Vcon_streams we want to have a placement new operator, so
60// inherit and add one
61class Std_stream : public L4Re::Core::Vcon_stream
62{
63public:
64 Std_stream(L4::Cap<L4::Vcon> c) : L4Re::Core::Vcon_stream(c) {}
65};
66
67Fd_store::Fd_store() noexcept
68{
69 // use this strange way to prevent deletion of the stdio object
70 // this depends on Fd_store to being a singleton !!!
71 static char m[sizeof(Std_stream)] __attribute__((aligned(sizeof(long))));
72 if (auto log = L4Re::Env::env()->log())
73 {
74 Std_stream *s = new (m) Std_stream(log);
75 set(0, cxx::ref_ptr(s)); // stdin
76 set(1, cxx::ref_ptr(s)); // stdout
77 set(2, cxx::ref_ptr(s)); // stderr
78
79 // make sure that we never delete the static io stream thing
80 s->add_ref();
81 }
82}
83
84class Root_mount_tree : public L4Re::Vfs::Mount_tree
85{
86public:
87 Root_mount_tree() : L4Re::Vfs::Mount_tree(0) {}
88 void operator delete (void *) {}
89};
90
91class Vfs : public L4Re::Vfs::Ops
92{
93private:
94 bool _early_oom;
95
96public:
97 Vfs()
98 : _early_oom(true), _root_mount(), _root(L4Re::Env::env())
99 {
100 _root_mount.add_ref();
101 _root.add_ref();
102 _root_mount.mount(cxx::ref_ptr(&_root));
103 _cwd = cxx::ref_ptr(&_root);
104
105#if 0
106 Ref_ptr<L4Re::Vfs::File> rom;
107 _root.openat("rom", 0, 0, &rom);
108
109 _root_mount.create_tree("lib/foo", rom);
110
111 _root.openat("lib", 0, 0, &_cwd);
112
113#endif
114 }
115
116 int alloc_fd(Ref_ptr<L4Re::Vfs::File> const &f) noexcept override;
117 Ref_ptr<L4Re::Vfs::File> free_fd(int fd) noexcept override;
118 Ref_ptr<L4Re::Vfs::File> get_root() noexcept override;
119 Ref_ptr<L4Re::Vfs::File> get_cwd() noexcept override;
120 void set_cwd(Ref_ptr<L4Re::Vfs::File> const &dir) noexcept override;
121 Ref_ptr<L4Re::Vfs::File> get_file(int fd) noexcept override;
122 cxx::Pair<Ref_ptr<L4Re::Vfs::File>, int>
123 set_fd(int fd, Ref_ptr<L4Re::Vfs::File> const &f = Ref_ptr<>::Nil) noexcept
124 override;
125
126 int mmap2(void *start, size_t len, int prot, int flags, int fd,
127 off_t offset, void **ptr) noexcept override;
128
129 int munmap(void *start, size_t len) noexcept override;
130 int mprotect(const void *a, size_t sz, int prot) noexcept override;
131 int msync(void *addr, size_t len, int flags) noexcept override;
132 int madvise(void *addr, size_t len, int advice) noexcept override;
133
134 int register_file_system(L4Re::Vfs::File_system *f) noexcept override;
135 int unregister_file_system(L4Re::Vfs::File_system *f) noexcept override;
136 L4Re::Vfs::File_system *get_file_system(char const *fstype) noexcept override;
137 L4Re::Vfs::File_system_list file_system_list() noexcept override;
138
139 int register_file_factory(cxx::Ref_ptr<L4Re::Vfs::File_factory> f) noexcept override;
140 int unregister_file_factory(cxx::Ref_ptr<L4Re::Vfs::File_factory> f) noexcept override;
141 Ref_ptr<L4Re::Vfs::File_factory> get_file_factory(int proto) noexcept override;
142 Ref_ptr<L4Re::Vfs::File_factory> get_file_factory(char const *proto_name) noexcept override;
143 int mount(char const *path, cxx::Ref_ptr<L4Re::Vfs::File> const &dir) noexcept override;
144
145 void operator delete (void *) {}
146
147 void *malloc(size_t size) noexcept override { return Vfs_config::malloc(size); }
148 void free(void *m) noexcept override { Vfs_config::free(m); }
149
150private:
151 Root_mount_tree _root_mount;
152 L4Re::Core::Env_dir _root;
153 Ref_ptr<L4Re::Vfs::File> _cwd;
154 Fd_store fds;
155
156 L4Re::Vfs::File_system *_fs_registry;
157
158 struct File_factory_item : cxx::H_list_item_t<File_factory_item>
159 {
160 cxx::Ref_ptr<L4Re::Vfs::File_factory> f;
161 explicit File_factory_item(cxx::Ref_ptr<L4Re::Vfs::File_factory> const &f)
162 : f(f) {};
163
164 File_factory_item() = default;
165 File_factory_item(File_factory_item const &) = delete;
166 File_factory_item &operator = (File_factory_item const &) = delete;
167 };
168
169 cxx::H_list_t<File_factory_item> _file_factories;
170
171 void align_mmap_start_and_length(void **start, size_t *length);
172 int munmap_regions(void *start, size_t len);
173
174 L4Re::Vfs::File_system *find_fs_from_type(char const *fstype) noexcept;
175};
176
177static inline bool strequal(char const *a, char const *b)
178{
179 for (;*a && *a == *b; ++a, ++b)
180 ;
181 return *a == *b;
182}
183
184int
185Vfs::register_file_system(L4Re::Vfs::File_system *f) noexcept
186{
187 using L4Re::Vfs::File_system;
188
189 if (!f)
190 return -EINVAL;
191
192 for (File_system *c = _fs_registry; c; c = c->next())
193 if (strequal(c->type(), f->type()))
194 return -EEXIST;
195
196 f->next(_fs_registry);
197 _fs_registry = f;
198
199 return 0;
200}
201
202int
203Vfs::unregister_file_system(L4Re::Vfs::File_system *f) noexcept
204{
205 using L4Re::Vfs::File_system;
206
207 if (!f)
208 return -EINVAL;
209
210 File_system **p = &_fs_registry;
211
212 for (; *p; p = &(*p)->next())
213 if (*p == f)
214 {
215 *p = f->next();
216 f->next() = 0;
217 return 0;
218 }
219
220 return -ENOENT;
221}
222
223L4Re::Vfs::File_system *
224Vfs::find_fs_from_type(char const *fstype) noexcept
225{
226 L4Re::Vfs::File_system_list fsl(_fs_registry);
227 for (L4Re::Vfs::File_system_list::Iterator c = fsl.begin();
228 c != fsl.end(); ++c)
229 if (strequal(c->type(), fstype))
230 return *c;
231 return 0;
232}
233
234L4Re::Vfs::File_system_list
235Vfs::file_system_list() noexcept
236{
237 return L4Re::Vfs::File_system_list(_fs_registry);
238}
239
240L4Re::Vfs::File_system *
241Vfs::get_file_system(char const *fstype) noexcept
242{
243 L4Re::Vfs::File_system *fs;
244 if ((fs = find_fs_from_type(fstype)))
245 return fs;
246
247 // Try to load a file system module dynamically
248 int res = Vfs_config::load_module(fstype);
249 if (res < 0)
250 return 0;
251
252 // Try again
253 return find_fs_from_type(fstype);
254}
255
256int
257Vfs::register_file_factory(cxx::Ref_ptr<L4Re::Vfs::File_factory> f) noexcept
258{
259 if (!f)
260 return -EINVAL;
261
262 void *x = this->malloc(sizeof(File_factory_item));
263 if (!x)
264 return -ENOMEM;
265
266 auto ff = new (x, cxx::Nothrow()) File_factory_item(f);
267 _file_factories.push_front(ff);
268 return 0;
269}
270
271int
272Vfs::unregister_file_factory(cxx::Ref_ptr<L4Re::Vfs::File_factory> f) noexcept
273{
274 for (auto p: _file_factories)
275 {
276 if (p->f == f)
277 {
278 _file_factories.remove(p);
279 p->~File_factory_item();
280 this->free(p);
281 return 0;
282 }
283 }
284 return -ENOENT;
285}
286
287Ref_ptr<L4Re::Vfs::File_factory>
288Vfs::get_file_factory(int proto) noexcept
289{
290 for (auto p: _file_factories)
291 if (p->f->proto() == proto)
292 return p->f;
293
294 return Ref_ptr<L4Re::Vfs::File_factory>();
295}
296
297Ref_ptr<L4Re::Vfs::File_factory>
298Vfs::get_file_factory(char const *proto_name) noexcept
299{
300 for (auto p: _file_factories)
301 {
302 auto n = p->f->proto_name();
303 if (n)
304 {
305 char const *a = n;
306 char const *b = proto_name;
307 for (; *a && *b && *a == *b; ++a, ++b)
308 ;
309
310 if ((*a == 0) && (*b == 0))
311 return p->f;
312 }
313 }
314
315 return Ref_ptr<L4Re::Vfs::File_factory>();
316}
317
318int
319Vfs::alloc_fd(Ref_ptr<L4Re::Vfs::File> const &f) noexcept
320{
321 int fd = fds.alloc();
322 if (fd < 0)
323 return -EMFILE;
324
325 if (f)
326 fds.set(fd, f);
327
328 return fd;
329}
330
331Ref_ptr<L4Re::Vfs::File>
332Vfs::free_fd(int fd) noexcept
333{
334 Ref_ptr<L4Re::Vfs::File> f = fds.get(fd);
335
336 if (!f)
337 return Ref_ptr<>::Nil;
338
339 fds.free(fd);
340 return f;
341}
342
343
344Ref_ptr<L4Re::Vfs::File>
345Vfs::get_root() noexcept
346{
347 return cxx::ref_ptr(&_root);
348}
349
350Ref_ptr<L4Re::Vfs::File>
351Vfs::get_cwd() noexcept
352{
353 return _cwd;
354}
355
356void
357Vfs::set_cwd(Ref_ptr<L4Re::Vfs::File> const &dir) noexcept
358{
359 // FIXME: check for is dir
360 if (dir)
361 _cwd = dir;
362}
363
364Ref_ptr<L4Re::Vfs::File>
365Vfs::get_file(int fd) noexcept
366{
367 return fds.get(fd);
368}
369
370cxx::Pair<Ref_ptr<L4Re::Vfs::File>, int>
371Vfs::set_fd(int fd, Ref_ptr<L4Re::Vfs::File> const &f) noexcept
372{
373 if (!fds.check_fd(fd))
374 return cxx::pair(Ref_ptr<L4Re::Vfs::File>(Ref_ptr<>::Nil), EBADF);
375
376 Ref_ptr<L4Re::Vfs::File> old = fds.get(fd);
377 fds.set(fd, f);
378 return cxx::pair(old, 0);
379}
380
381
382#define GET_FILE_DBG(fd, err) \
383 Ref_ptr<L4Re::Vfs::File> fi = fds.get(fd); \
384 if (!fi) \
385 { \
386 return -err; \
387 }
388
389#define GET_FILE(fd, err) \
390 Ref_ptr<L4Re::Vfs::File> fi = fds.get(fd); \
391 if (!fi) \
392 return -err;
393
394void
395Vfs::align_mmap_start_and_length(void **start, size_t *length)
396{
397 l4_addr_t const s = reinterpret_cast<l4_addr_t>(*start);
398 size_t const o = s & (L4_PAGESIZE - 1);
399
400 *start = reinterpret_cast<void *>(l4_trunc_page(s));
401 *length = l4_round_page(*length + o);
402}
403
404int
405Vfs::munmap_regions(void *start, size_t len)
406{
407 using namespace L4;
408 using namespace L4Re;
409
410 int err;
411 Cap<Rm> r = Env::env()->rm();
412
413 if (l4_addr_t(start) & (L4_PAGESIZE - 1))
414 return -EINVAL;
415
416 align_mmap_start_and_length(&start, &len);
417
418 while (1)
419 {
420 DEBUG_LOG(debug_mmap, {
421 l4_kd_outstring("DETACH: start = 0x");
423 l4_kd_outstring(" len = 0x");
424 l4_kd_outhex32(len);
425 l4_kd_outstring("\n");
426 });
427 err = r->detach(l4_addr_t(start), len, nullptr, This_task);
428 if (err < 0)
429 return err;
430
431 if (!(err & Rm::Detach_again))
432 return 0;
433 }
434}
435
436int
437Vfs::munmap(void *start, size_t len) L4_NOTHROW
438{
439 using namespace L4;
440 using namespace L4Re;
441
442 int err = 0;
443 Cap<Rm> r = Env::env()->rm();
444
445 // Fields for obtaining a list of areas for the calling process
446 long area_cnt = -1; // No. of areas in this process
447 L4::Ipc::Array_ref<Rm::Area> areas_in_utcb;
448 bool matches_area = false; // true if unmap parameters match an area
449
450 // First check if there are any areas matching the munmap request. Those
451 // might have been created by an mmap call using PROT_NONE as protection
452 // modifier.
453
454 area_cnt = r->get_areas((l4_addr_t) start, areas_in_utcb);
455
456 // It is enough to check for the very first entry, since get_areas will
457 // only return areas with a starting address equal or greater to <start>.
458 // However, we intend to unmap at most the area starting exactly at
459 // <start>.
460 if (area_cnt > 0)
461 {
462 Rm::Area const &first_area = areas_in_utcb.data[0];
463 size_t area_size = first_area.end - first_area.start + 1;
464
465 // Only free the area if the munmap parameters describe it exactly.
466 if (first_area.start == (l4_addr_t) start && area_size == len)
467 {
468 r->free_area((l4_addr_t) start);
469 matches_area = true;
470 }
471 }
472
473 // After clearing possible area reservations from PROT_NONE mappings, clear
474 // any regions in the address range specified. Note that errors shall be
475 // suppressed if an area was freed but no regions were found.
476 err = munmap_regions(start, len);
477 if (err == -ENOENT && matches_area)
478 return 0;
479
480 return err;
481}
482
483int
484Vfs::mmap2(void *start, size_t len, int prot, int flags, int fd, off_t page4k_offset,
485 void **resptr) L4_NOTHROW
486{
487 DEBUG_LOG(debug_mmap, {
488 l4_kd_outstring("MMAP params: ");
489 l4_kd_outstring("start = 0x");
491 l4_kd_outstring(", len = 0x");
492 l4_kd_outhex32(len);
493 l4_kd_outstring(", prot = 0x");
494 l4_kd_outhex32(prot);
495 l4_kd_outstring(", flags = 0x");
496 l4_kd_outhex32(flags);
497 l4_kd_outstring(", offset = 0x");
498 l4_kd_outhex32(page4k_offset);
499 l4_kd_outstring("\n");
500 });
501
502 using namespace L4Re;
503 off64_t offset = l4_trunc_page(page4k_offset << 12);
504
505 if (flags & MAP_FIXED)
506 if (l4_addr_t(start) & (L4_PAGESIZE - 1))
507 return -EINVAL;
508
509 align_mmap_start_and_length(&start, &len);
510
511 // special code to just reserve an area of the virtual address space
512 // Same behavior should be exposed when mapping with PROT_NONE. Mind that
513 // PROT_NONE can only be specified exclusively, since it is defined to 0x0.
514 if ((flags & 0x1000000) || (prot == PROT_NONE))
515 {
516 int err;
517 L4::Cap<Rm> r = Env::env()->rm();
518 l4_addr_t area = reinterpret_cast<l4_addr_t>(start);
519 err = r->reserve_area(&area, len, L4Re::Rm::F::Search_addr);
520 if (err < 0)
521 return err;
522
523 *resptr = reinterpret_cast<void*>(area);
524
525 DEBUG_LOG(debug_mmap, {
526 l4_kd_outstring(" MMAP reserved area: 0x");
527 l4_kd_outhex32(area);
528 l4_kd_outstring(" length= 0x");
529 l4_kd_outhex32(len);
530 l4_kd_outstring("\n");
531 });
532
533 return 0;
534 }
535
536 L4::Cap<L4Re::Dataspace> ds;
537 L4Re::Rm::Flags rm_flags(0);
538 char const *region_name = "[unknown]";
539 l4_addr_t file_offset = 0;
540
541 if (flags & MAP_PRIVATE)
542 rm_flags |= L4Re::Rm::F::Private;
543
544 if (flags & MAP_ANONYMOUS)
545 {
546 rm_flags |= L4Re::Rm::F::Anonymous;
547 offset = 0; // Or should we return EINVAL?
548 region_name = "[anon]";
549 }
550 else
551 {
552 Ref_ptr<L4Re::Vfs::File> fi = fds.get(fd);
553 if (!fi)
554 return -EBADF;
555
556 region_name = fi->path();
557
558 ds = fi->data_space();
559 if (!ds.is_valid())
560 return -EINVAL;
561
562 if (len + offset > l4_round_page(ds->size()))
563 return -EINVAL;
564 }
565
566
567 if (!(flags & MAP_FIXED) && start == 0)
568 start = reinterpret_cast<void*>(L4_PAGESIZE);
569
570 char *data = static_cast<char *>(start);
571 L4::Cap<Rm> r = Env::env()->rm();
572 l4_addr_t overmap_area = L4_INVALID_ADDR;
573
574 int err;
575 if (flags & MAP_FIXED)
576 {
577 overmap_area = l4_addr_t(start);
578
579 err = r->reserve_area(&overmap_area, len);
580 if (err < 0)
581 overmap_area = L4_INVALID_ADDR;
582
583 rm_flags |= Rm::F::In_area;
584
585 // Make sure to remove old mappings residing at the respective address
586 // range. If none exists, we are fine as well, allowing us to ignore
587 // ENOENT here.
588 err = munmap_regions(start, len);
589 if (err && err != -ENOENT)
590 return err;
591 }
592
593 if (!(flags & MAP_FIXED))
594 rm_flags |= Rm::F::Search_addr;
595 if (prot & PROT_READ)
596 rm_flags |= Rm::F::R;
597 if (prot & PROT_WRITE)
598 rm_flags |= Rm::F::W;
599 if (prot & PROT_EXEC)
600 rm_flags |= Rm::F::X;
601
602 // Region manager takes a reference to the ds cap...
603 err = r->attach(&data, len, rm_flags,
604 L4::Ipc::make_cap(ds, (prot & PROT_WRITE)
608 region_name, file_offset);
609
610 DEBUG_LOG(debug_mmap, {
611 l4_kd_outstring(" MAPPED: 0x");
612 l4_kd_outhex32(ds.cap());
613 l4_kd_outstring(" addr: 0x");
615 l4_kd_outstring(" bytes: 0x");
616 l4_kd_outhex32(len);
617 l4_kd_outstring(" offset: 0x");
618 l4_kd_outhex32(offset);
619 l4_kd_outstring(" err = ");
620 l4_kd_outdec(err);
621 l4_kd_outstring("\n");
622 });
623
624
625 if (overmap_area != L4_INVALID_ADDR)
626 r->free_area(overmap_area);
627
628 if (err < 0)
629 return err;
630
631 l4_assert (!(start && !data));
632
633 *resptr = data;
634
635 return 0;
636}
637
638int
639Vfs::mprotect(const void * /* a */, size_t /* sz */, int prot) L4_NOTHROW
640{
641 return (prot & PROT_WRITE) ? -ENOSYS : 0;
642}
643
644int
645Vfs::msync(void *, size_t, int) L4_NOTHROW
646{ return 0; }
647
648int
649Vfs::madvise(void *, size_t, int) L4_NOTHROW
650{ return 0; }
651
652}
653
654L4Re::Vfs::Ops *__rtld_l4re_env_posix_vfs_ops;
655extern void *l4re_env_posix_vfs_ops __attribute__((alias("__rtld_l4re_env_posix_vfs_ops"), visibility("default")));
656
657namespace {
658 class Real_mount_tree : public L4Re::Vfs::Mount_tree
659 {
660 public:
661 explicit Real_mount_tree(char *n) : Mount_tree(n) {}
662
663 void *operator new (size_t size)
664 { return __rtld_l4re_env_posix_vfs_ops->malloc(size); }
665
666 void operator delete (void *mem)
667 { __rtld_l4re_env_posix_vfs_ops->free(mem); }
668 };
669}
670
672int
673Vfs::mount(char const *path, cxx::Ref_ptr<L4Re::Vfs::File> const &dir) noexcept
674{
675 using L4Re::Vfs::File;
676 using L4Re::Vfs::Mount_tree;
677 using L4Re::Vfs::Path;
678
679 cxx::Ref_ptr<Mount_tree> root = get_root()->mount_tree();
680 if (!root)
681 return -EINVAL;
682
684 Path p = root->lookup(Path(path), &base);
685
686 while (!p.empty())
687 {
688 Path f = p.strip_first();
689
690 if (f.empty())
691 return -EEXIST;
692
693 char *name = __rtld_l4re_env_posix_vfs_ops->strndup(f.path(), f.length());
694 if (!name)
695 return -ENOMEM;
696
697 auto nt = cxx::make_ref_obj<Real_mount_tree>(name);
698 if (!nt)
699 {
700 __rtld_l4re_env_posix_vfs_ops->free(name);
701 return -ENOMEM;
702 }
703
704 base->add_child_node(nt);
705 base = nt;
706
707 if (p.empty())
708 {
709 nt->mount(dir);
710 return 0;
711 }
712 }
713
714 return -EINVAL;
715}
716
717#undef DEBUG_LOG
718#undef GET_FILE_DBG
719#undef GET_FILE
static Env const * env() noexcept
Returns the initial environment for the current task.
Definition env:96
Region map.
Definition rm:84
@ Detach_again
Detached data space, more to do.
Definition rm:96
The basic interface for an open POSIX file.
Definition vfs.h:461
Interface for the POSIX backends of an application.
Definition vfs.h:1107
l4_cap_idx_t cap() const noexcept
Return capability selector.
Definition capability.h:49
bool is_valid() const noexcept
Test whether the capability is a valid capability index (i.e., not L4_INVALID_CAP).
Definition capability.h:57
@ Invalid
Invalid capability selector.
Definition capability.h:42
A reference-counting pointer with automatic cleanup.
Definition ref_ptr:71
Dataspace interface.
Environment interface.
unsigned long l4_addr_t
Address type.
Definition l4int.h:34
@ L4_CAP_FPAGE_RO
Read right for capability flexpages.
Definition __l4_fpage.h:176
@ L4_CAP_FPAGE_RW
Read and interface specific 'W' right for capability flexpages.
Definition __l4_fpage.h:192
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:459
l4_addr_t l4_round_page(l4_addr_t address) L4_NOTHROW
Round address up to the next page.
Definition consts.h:484
#define L4_PAGESIZE
Minimal page size (in bytes).
Definition consts.h:402
#define L4_PAGESHIFT
Size of a page, log2-based.
Definition consts.h:26
@ L4_INVALID_ADDR
Invalid address.
Definition consts.h:516
#define L4_NOTHROW
Mark a function declaration and definition as never throwing an exception.
Definition compiler.h:167
Functionality for invoking the kernel debugger.
void l4_kd_outdec(l4_mword_t number)
Output a decimal unsigned machine word via the kernel debugger.
Definition kdebug.h:334
void l4_kd_outhex32(l4_uint32_t number)
Output a 32-bit unsigned hexadecimal number via the kernel debugger.
Definition kdebug.h:284
void l4_kd_outstring(char const *text)
Output a string via the kernel debugger.
Definition kdebug.h:237
Cap< T > make_cap(L4::Cap< T > cap, unsigned rights) noexcept
Make an L4::Ipc::Cap<T> for the given capability and rights.
Definition ipc_types:845
Pair implementation.
Region mapper interface.
Shared_cap / Shared_del_cap.
An area is a range of virtual addresses which is reserved, see L4Re::Rm::reserve_area().
Definition rm:705
@ Private
Attach the dataspace privately with copy-on-write semantics.
Definition rm:156
@ X
Executable region.
Definition rm:139
@ R
Readable region.
Definition rm:135
@ W
Writable region.
Definition rm:137
@ Anonymous
Attach anonymous memory in the region.
Definition rm:160
@ Search_addr
Search for a suitable address range.
Definition rm:115
@ In_area
Search only in area, or map into area.
Definition rm:117
Low-level assert implementation.
#define l4_assert(expr)
Low-level assert.
Definition assert.h:32