L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
region_mapping_svr_2
1// vi:set ft=cpp: -*- Mode: C++ -*-
7/*
8 * (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com>
9 *
10 * License: see LICENSE.spdx (in this directory or the directories above)
11 */
12#pragma once
13
14#include <l4/sys/types.h>
15#include <l4/re/rm>
17
18namespace L4Re { namespace Util {
19
20template<typename DERIVED, typename Dbg>
21struct Rm_server
22{
23private:
24 DERIVED *rm() { return static_cast<DERIVED*>(this); }
25 DERIVED const *rm() const { return static_cast<DERIVED const *>(this); }
26
27public:
28
32 long op_attach(L4Re::Rm::Rights, l4_addr_t &_start,
33 unsigned long size, Rm::Flags flags,
34 L4::Ipc::Snd_fpage ds_cap, L4Re::Rm::Offset offs,
35 unsigned char align, l4_cap_idx_t client_cap_idx)
36 {
37 typename DERIVED::Dataspace ds;
38
39 if (!(flags & Rm::F::Reserved))
40 {
41 if (long r = rm()->validate_ds
42 (static_cast<DERIVED*>(this)->server_iface(), ds_cap,
43 flags.region_flags(), &ds))
44 return r;
45 }
46
47 size = l4_round_page(size);
48 l4_addr_t start = l4_trunc_page(_start);
49
50 if (size < L4_PAGESIZE)
51 return -L4_EINVAL;
52
53 Rm::Region_flags r_flags = flags.region_flags();
54 Rm::Attach_flags a_flags = flags.attach_flags();
55
56 typename DERIVED::Region_handler handler(ds, client_cap_idx, offs, r_flags);
57 start = l4_addr_t(rm()->attach(reinterpret_cast<void*>(start), size,
58 handler, a_flags, align));
59
60 if (start == L4_INVALID_ADDR)
61 return -L4_EADDRNOTAVAIL;
62
63 _start = start;
64 return L4_EOK;
65 }
66
70 long op_free_area(L4Re::Rm::Rights, l4_addr_t start)
71 {
72 if (!rm()->detach_area(start))
73 return -L4_ENOENT;
74
75 return L4_EOK;
76 }
77
81 long op_find(L4Re::Rm::Rights, l4_addr_t &addr, unsigned long &size,
82 L4Re::Rm::Flags &flags, L4Re::Rm::Offset &offset,
84 {
85 if (!DERIVED::Have_find)
86 return -L4_EPERM;
87
88 Rm::Flags flag_area { 0 };
89
90 typename DERIVED::Node r = rm()->find(Region(addr, addr + size -1));
91 if (!r)
92 {
93 r = rm()->area_find(Region(addr, addr + size - 1));
94 if (!r)
95 return -L4_ENOENT;
96 flag_area = Rm::F::In_area;
97 }
98
99 addr = r->first.start();
100 size = r->first.end() + 1 - addr;
101
102 flags = r->second.flags() | flag_area;
103 offset = r->second.offset();
104 m = L4::Cap<L4Re::Dataspace>(DERIVED::find_res(r->second.memory()));
105 return L4_EOK;
106 }
107
111 long op_detach(L4Re::Rm::Rights, l4_addr_t addr,
112 unsigned long size, unsigned flags,
113 l4_addr_t &start, l4_addr_t &rsize,
114 l4_cap_idx_t &mem_cap)
115 {
116 Region r;
117 typename DERIVED::Region_handler h;
118 int err = rm()->detach(reinterpret_cast<void*>(addr), size, flags, &r, &h);
119 if (err < 0)
120 {
121 start = rsize = 0;
122 mem_cap = L4_INVALID_CAP;
123 return err;
124 }
125
126 if (r.invalid())
127 {
128 start = rsize = 0;
129 mem_cap = L4_INVALID_CAP;
130 return -L4_ENOENT;
131 }
132
133 start = r.start();
134 rsize = r.size();
135 mem_cap = h.client_cap_idx();
136 return err;
137 }
138
142 long op_reserve_area(L4Re::Rm::Rights, l4_addr_t &start, unsigned long size,
143 L4Re::Rm::Flags flags, unsigned char align)
144 {
145 start = rm()->attach_area(start, size, flags, align);
146 if (start == L4_INVALID_ADDR)
147 return -L4_EADDRNOTAVAIL;
148 return L4_EOK;
149 }
150
154 long op_get_regions(L4Re::Rm::Rights, l4_addr_t addr,
156 {
157 typename DERIVED::Node r;
158 unsigned num = 0;
159 while ((r = rm()->lower_bound(Region(addr))))
160 {
161 Rm::Region &x = regions.value[num];
162 x.start = r->first.start();
163 x.end = r->first.end();
164
165 if (++num >= regions.max)
166 break;
167
168 if (x.end >= rm()->max_addr())
169 break;
170 addr = x.end + 1;
171 }
172 return num;
173 }
174
178 long op_get_areas(L4Re::Rm::Rights, l4_addr_t addr,
180 {
181 typename DERIVED::Node r;
182 unsigned num = 0;
183 while ((r = rm()->lower_bound_area(Region(addr))))
184 {
185 Rm::Area &x = areas.value[num];
186 x.start = r->first.start();
187 x.end = r->first.end();
188
189 if (++num >= areas.max)
190 break;
191
192 if (x.end >= rm()->max_addr())
193 break;
194
195 addr = x.end + 1;
196 }
197 return num;
198 }
199
200private:
201 static void pager_set_result(L4::Ipc::Opt<L4::Ipc::Snd_fpage> *fp,
202 L4::Ipc::Snd_fpage const &f)
203 { *fp = f; }
204
205 static void pager_set_result(L4::Ipc::Opt<L4::Ipc::Snd_fpage> *, ...)
206 {}
207public:
208
212 long op_io_page_fault(L4::Io_pager::Rights, l4_fpage_t, l4_umword_t,
214 {
215 // generate exception
216 return -L4_ENOMEM;
217 }
218
219 long op_page_fault(L4::Pager::Rights, l4_umword_t addr, l4_umword_t pc,
221 {
222 Dbg(Dbg::Server).printf("page fault: %lx pc=%lx\n", addr, pc);
223
224 bool need_w = addr & 2;
225 bool need_x = addr & 4;
226
227 typename DERIVED::Node n = rm()->find(addr);
228
229 if (!n || !n->second.memory())
230 {
231 Dbg(Dbg::Warn, "rm").printf("unhandled %s page fault at 0x%lx pc=0x%lx\n",
232 need_w ? "write" :
233 need_x ? "instruction" : "read", addr, pc);
234 // generate exception
235 return -L4_ENOMEM;
236 }
237
238 if (!(n->second.flags() & L4Re::Rm::F::W) && need_w)
239 {
240 Dbg(Dbg::Warn, "rm").printf("write page fault in readonly region at 0x%lx pc=0x%lx\n",
241 addr, pc);
242 // generate exception
243 return -L4_EACCESS;
244 }
245
246 if (!(n->second.flags() & L4Re::Rm::F::X) && need_x)
247 {
248 Dbg(Dbg::Warn, "rm").printf("instruction page fault in non-exec region at 0x%lx pc=0x%lx\n",
249 addr, pc);
250 // generate exception
251 return -L4_EACCESS;
252 }
253
254 typename DERIVED::Region_handler::Ops::Map_result map_res;
255 if (int err = n->second.map(addr, n->first, need_w, &map_res))
256 {
257 Dbg(Dbg::Warn, "rm").printf("mapping for page fault failed with error %d at 0x%lx pc=0x%lx\n",
258 err, addr, pc);
259 // generate exception
260 return -L4_ENOMEM;
261 }
262
263 pager_set_result(&fp, map_res);
264 return L4_EOK;
265 }
266};
267
268}}
Range Area
An area is a range of virtual addresses which is reserved, see L4Re::Rm::reserve_area().
Definition rm:690
Range Region
A region is a range of virtual addresses which is backed by a dataspace.
Definition rm:682
C++ interface for capabilities.
Definition capability.h:219
Send item or return item.
Definition ipc_types:324
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
unsigned long l4_addr_t
Address type.
Definition l4int.h:34
unsigned long l4_cap_idx_t
Capability selector type.
Definition types.h:335
@ L4_INVALID_CAP
Invalid capability selector.
Definition consts.h:157
@ L4_ENOENT
No such entity.
Definition err.h:34
@ L4_EACCESS
Permission denied.
Definition err.h:40
@ L4_EINVAL
Invalid argument.
Definition err.h:46
@ L4_EOK
Ok.
Definition err.h:32
@ L4_EADDRNOTAVAIL
Address not available.
Definition err.h:52
@ L4_EPERM
No permission.
Definition err.h:33
@ L4_ENOMEM
No memory.
Definition err.h:39
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:452
l4_addr_t l4_round_page(l4_addr_t address) L4_NOTHROW
Round address up to the next page.
Definition consts.h:477
#define L4_PAGESIZE
Minimal page size (in bytes).
Definition consts.h:395
@ L4_INVALID_ADDR
Invalid address.
Definition consts.h:509
Common L4 ABI Data Types.
L4Re C++ Interfaces.
Definition cmd_control:14
Region handling.
Region mapper interface.
@ Reserved
Region is reserved (blocked)
Definition rm:150
@ X
Executable region.
Definition rm:137
@ W
Writable region.
Definition rm:135
@ In_area
Search only in area, or map into area.
Definition rm:116
Attribute for defining an optional RPC argument.
Definition ipc_types:137
Dynamically sized output array of type T.
Definition ipc_ret_array:24
L4 flexpage type.
Definition __l4_fpage.h:76