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 * This file is part of TUD:OS and distributed under the terms of the
11 * GNU General Public License 2.
12 * Please see the COPYING-GPL-2 file for details.
13 *
14 * As a special exception, you may use this file as part of a free software
15 * library without restriction. Specifically, if other files instantiate
16 * templates or use macros or inline functions from this file, or you compile
17 * this file and link it with other files to produce an executable, this
18 * file does not by itself cause the resulting executable to be covered by
19 * the GNU General Public License. This exception does not however
20 * invalidate any other reasons why the executable file might be covered by
21 * the GNU General Public License.
22 */
23#pragma once
24
25#include <l4/sys/types.h>
26#include <l4/re/rm>
28
29namespace L4Re { namespace Util {
30
31template<typename DERIVED, typename Dbg>
32struct Rm_server
33{
34private:
35 DERIVED *rm() { return static_cast<DERIVED*>(this); }
36 DERIVED const *rm() const { return static_cast<DERIVED const *>(this); }
37
38public:
39
43 long op_attach(L4Re::Rm::Rights, l4_addr_t &_start,
44 unsigned long size, Rm::Flags flags,
45 L4::Ipc::Snd_fpage ds_cap, L4Re::Rm::Offset offs,
46 unsigned char align, l4_cap_idx_t client_cap_idx)
47 {
48 typename DERIVED::Dataspace ds;
49
50 if (!(flags & Rm::F::Reserved))
51 {
52 if (long r = rm()->validate_ds(static_cast<DERIVED*>(this)->server_iface(), ds_cap, flags.region_flags(), &ds))
53 return r;
54 }
55
56 size = l4_round_page(size);
57 l4_addr_t start = l4_trunc_page(_start);
58
59 if (size < L4_PAGESIZE)
60 return -L4_EINVAL;
61
62 Rm::Region_flags r_flags = flags.region_flags();
63 Rm::Attach_flags a_flags = flags.attach_flags();
64
65 start = l4_addr_t(rm()->attach((void*)start, size,
66 typename DERIVED::Region_handler(ds, client_cap_idx, offs, r_flags),
67 a_flags, align));
68
69 if (start == L4_INVALID_ADDR)
70 return -L4_EADDRNOTAVAIL;
71
72 _start = start;
73 return L4_EOK;
74 }
75
79 long op_free_area(L4Re::Rm::Rights, l4_addr_t start)
80 {
81 if (!rm()->detach_area(start))
82 return -L4_ENOENT;
83
84 return L4_EOK;
85 }
86
90 long op_find(L4Re::Rm::Rights, l4_addr_t &addr, unsigned long &size,
91 L4Re::Rm::Flags &flags, L4Re::Rm::Offset &offset,
93 {
94 if (!DERIVED::Have_find)
95 return -L4_EPERM;
96
97 Rm::Flags flag_area { 0 };
98
99 typename DERIVED::Node r = rm()->find(Region(addr, addr + size -1));
100 if (!r)
101 {
102 r = rm()->area_find(Region(addr, addr + size - 1));
103 if (!r)
104 return -L4_ENOENT;
105 flag_area = Rm::F::In_area;
106 }
107
108 addr = r->first.start();
109 size = r->first.end() + 1 - addr;
110
111 flags = r->second.flags() | flag_area;
112 offset = r->second.offset();
113 m = L4::Cap<L4Re::Dataspace>(DERIVED::find_res(r->second.memory()));
114 return L4_EOK;
115 }
116
120 long op_detach(L4Re::Rm::Rights, l4_addr_t addr,
121 unsigned long size, unsigned flags,
122 l4_addr_t &start, l4_addr_t &rsize,
123 l4_cap_idx_t &mem_cap)
124 {
125 Region r;
126 typename DERIVED::Region_handler h;
127 int err = rm()->detach((void*)addr, size, flags, &r, &h);
128 if (err < 0)
129 {
130 start = rsize = mem_cap = 0;
131 return err;
132 }
133
134 if (r.invalid())
135 {
136 start = rsize = mem_cap = 0;
137 return -L4_ENOENT;
138 }
139
140 start = r.start();
141 rsize = r.size();
142 mem_cap = h.client_cap_idx();
143 return err;
144 }
145
149 long op_reserve_area(L4Re::Rm::Rights, l4_addr_t &start, unsigned long size,
150 L4Re::Rm::Flags flags, unsigned char align)
151 {
152 start = rm()->attach_area(start, size, flags, align);
153 if (start == L4_INVALID_ADDR)
154 return -L4_EADDRNOTAVAIL;
155 return L4_EOK;
156 }
157
161 long op_get_regions(L4Re::Rm::Rights, l4_addr_t addr,
163 {
164 typename DERIVED::Node r;
165 unsigned num = 0;
166 while ((r = rm()->lower_bound(Region(addr))))
167 {
168 Rm::Region &x = regions.value[num];
169 x.start = r->first.start();
170 x.end = r->first.end();
171
172 if (++num >= regions.max)
173 break;
174
175 if (x.end >= rm()->max_addr())
176 break;
177 addr = x.end + 1;
178 }
179 return num;
180 }
181
185 long op_get_areas(L4Re::Rm::Rights, l4_addr_t addr,
187 {
188 typename DERIVED::Node r;
189 unsigned num = 0;
190 while ((r = rm()->lower_bound_area(Region(addr))))
191 {
192 Rm::Area &x = areas.value[num];
193 x.start = r->first.start();
194 x.end = r->first.end();
195
196 if (++num >= areas.max)
197 break;
198
199 if (x.end >= rm()->max_addr())
200 break;
201
202 addr = x.end + 1;
203 }
204 return num;
205 }
206
207private:
208 static void pager_set_result(L4::Ipc::Opt<L4::Ipc::Snd_fpage> *fp,
209 L4::Ipc::Snd_fpage const &f)
210 { *fp = f; }
211
212 static void pager_set_result(L4::Ipc::Opt<L4::Ipc::Snd_fpage> *, ...)
213 {}
214public:
215
219 long op_io_page_fault(L4::Io_pager::Rights, l4_fpage_t, l4_umword_t,
221 {
222 // generate exception
223 return -L4_ENOMEM;
224 }
225
226 long op_page_fault(L4::Pager::Rights, l4_umword_t addr, l4_umword_t pc,
228 {
229 Dbg(Dbg::Server).printf("page fault: %lx pc=%lx\n", addr, pc);
230
231 bool need_w = addr & 2;
232 bool need_x = addr & 4;
233
234 typename DERIVED::Node n = rm()->find(addr);
235
236 if (!n || !n->second.memory())
237 {
238 Dbg(Dbg::Warn, "rm").printf("unhandled %s page fault at 0x%lx pc=0x%lx\n",
239 need_w ? "write" :
240 need_x ? "instruction" : "read", addr, pc);
241 // generate exception
242 return -L4_ENOMEM;
243 }
244
245 if (!(n->second.flags() & L4Re::Rm::F::W) && need_w)
246 {
247 Dbg(Dbg::Warn, "rm").printf("write page fault in readonly region at 0x%lx pc=0x%lx\n",
248 addr, pc);
249 // generate exception
250 return -L4_EACCESS;
251 }
252
253 if (!(n->second.flags() & L4Re::Rm::F::X) && need_x)
254 {
255 Dbg(Dbg::Warn, "rm").printf("instruction page fault in non-exec region at 0x%lx pc=0x%lx\n",
256 addr, pc);
257 // generate exception
258 return -L4_EACCESS;
259 }
260
261 typename DERIVED::Region_handler::Ops::Map_result map_res;
262 if (int err = n->second.map(addr, n->first, need_w, &map_res))
263 {
264 Dbg(Dbg::Warn, "rm").printf("mapping for page fault failed with error %d at 0x%lx pc=0x%lx\n",
265 err, addr, pc);
266 // generate exception
267 return -L4_ENOMEM;
268 }
269
270 pager_set_result(&fp, map_res);
271 return L4_EOK;
272 }
273};
274
275}}
Range Area
An area is a range of virtual addresses which is reserved, see L4Re::Rm::reserve_area().
Definition rm:677
Range Region
A region is a range of virtual addresses which is backed by a dataspace.
Definition rm:669
C++ interface for capabilities.
Definition capability.h:222
Generic RPC wrapper for L4 flex-pages.
Definition ipc_types:322
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:51
unsigned long l4_addr_t
Address type.
Definition l4int.h:45
unsigned long l4_cap_idx_t
Capability selector type.
Definition types.h:358
@ L4_ENOENT
No such entity.
Definition err.h:45
@ L4_EACCESS
Permission denied.
Definition err.h:51
@ L4_EINVAL
Invalid argument.
Definition err.h:56
@ L4_EOK
Ok.
Definition err.h:43
@ L4_EADDRNOTAVAIL
Address not available.
Definition err.h:62
@ L4_EPERM
No permission.
Definition err.h:44
@ L4_ENOMEM
No memory.
Definition err.h:50
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:437
l4_addr_t l4_round_page(l4_addr_t address) L4_NOTHROW
Round address up to the next page.
Definition consts.h:462
#define L4_PAGESIZE
Minimal page size (in bytes).
Definition consts.h:380
@ L4_INVALID_ADDR
Invalid address.
Definition consts.h:494
Common L4 ABI Data Types.
L4Re C++ Interfaces.
Definition cmd_control:15
Region handling.
Region mapper interface.
@ Reserved
Region is reserved (blocked)
Definition rm:151
@ X
Executable region.
Definition rm:138
@ W
Writable region.
Definition rm:136
@ In_area
Search only in area, or map into area.
Definition rm:120
Attribute for defining an optional RPC argument.
Definition ipc_types:148
Dynamically sized output array of type T.
Definition ipc_ret_array:35
L4 flexpage type.
Definition __l4_fpage.h:85