L4Re - L4 Runtime Environment
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 
29 namespace L4Re { namespace Util {
30 
31 template<typename DERIVED, typename Dbg>
32 struct Rm_server
33 {
34 private:
35  DERIVED *rm() { return static_cast<DERIVED*>(this); }
36  DERIVED const *rm() const { return static_cast<DERIVED const *>(this); }
37 
38 public:
39 
43  long op_attach(L4Re::Rm::Rights, l4_addr_t &_start,
44  unsigned long size, unsigned long flags,
45  L4::Ipc::Snd_fpage ds_cap, l4_addr_t offs,
46  unsigned char align, l4_cap_idx_t client_cap_idx)
47  {
48  typename DERIVED::Dataspace ds;
49 
50  if (!(flags & Rm::Reserved))
51  {
52  if (long r = rm()->validate_ds(static_cast<DERIVED*>(this)->server_iface(), ds_cap, 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  unsigned r_flags = flags & Rm::Region_flags;
63  unsigned a_flags = flags & Rm::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  unsigned &flags, l4_addr_t &offset,
93  {
94  if (!DERIVED::Have_find)
95  return -L4_EPERM;
96 
97  unsigned 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::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  return err;
130 
131  if (r.invalid())
132  return -L4_ENOENT;
133 
134  start = r.start();
135  rsize = r.size();
136  mem_cap = h.client_cap_idx();
137  return err;
138  }
139 
143  long op_reserve_area(L4Re::Rm::Rights, l4_addr_t &start, unsigned long size,
144  unsigned flags, unsigned char align)
145  {
146  start = rm()->attach_area(start, size, flags, align);
147  if (start == L4_INVALID_ADDR)
148  return -L4_EADDRNOTAVAIL;
149  return L4_EOK;
150  }
151 
155  long op_get_regions(L4Re::Rm::Rights, l4_addr_t addr,
157  {
158  typename DERIVED::Node r;
159  unsigned num = 0;
160  while ((r = rm()->lower_bound(Region(addr, addr +1))))
161  {
162  Rm::Region &x = regions.value[num];
163  x.start = r->first.start();
164  x.end = r->first.end();
165  x.offset = r->second.offset();
166 
167  if (++num >= regions.max)
168  break;
169 
170  if (x.end >= rm()->max_addr())
171  break;
172  addr = x.end + 1;
173  }
174  return num;
175  }
176 
180  long op_get_areas(L4Re::Rm::Rights, l4_addr_t addr,
182  {
183  typename DERIVED::Node r;
184  unsigned num = 0;
185  while ((r = rm()->lower_bound_area(Region(addr, addr +1))))
186  {
187  Rm::Area &x = areas.value[num];
188  x.start = r->first.start();
189  x.end = r->first.end();
190 
191  if (++num >= areas.max)
192  break;
193 
194  if (x.end >= rm()->max_addr())
195  break;
196 
197  addr = x.end + 1;
198  }
199  return num;
200  }
201 
202 private:
203  static void pager_set_result(L4::Ipc::Opt<l4_mword_t> *,
205  L4::Ipc::Snd_fpage const &f)
206  { *fp = f; }
207 
208  static void pager_set_result(L4::Ipc::Opt<l4_mword_t> *result,
210  { *result = 0; }
211 public:
212 
216  long op_io_page_fault(L4::Io_pager::Rights, l4_fpage_t, l4_umword_t,
217  L4::Ipc::Opt<l4_mword_t> &result,
219  {
220  // generate exception
221  result = ~0;
222  return L4_EOK;
223  }
224 
225  long op_page_fault(L4::Pager::Rights, l4_umword_t addr, l4_umword_t pc,
226  L4::Ipc::Opt<l4_mword_t> &result,
228  {
229  Dbg(Dbg::Server).printf("page fault: %lx pc=%lx\n", addr, pc);
230 
231  unsigned writable = addr & 2;
232  addr = addr & ~7UL;
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  writable ? "write" : "read", addr, pc);
240  // generate exception
241  result = ~0;
242  return L4_EOK;
243  }
244 
245  if (n->second.is_ro() && writable)
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  result = ~0;
251  return L4_EOK;
252  }
253 
254  typename DERIVED::Region_handler::Ops::Map_result map_res;
255  if (int err = n->second.map(addr, n->first, writable, &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  result = ~0;
261  return L4_EOK;
262  }
263 
264  pager_set_result(&result, &fp, map_res);
265  return L4_EOK;
266  }
267 };
268 
269 }}
No such entity.
Definition: err.h:45
No permission.
Definition: err.h:44
Invalid argument.
Definition: err.h:56
l4_addr_t l4_round_page(l4_addr_t address) L4_NOTHROW
Round address up to the next page.
Definition: consts.h:389
Common L4 ABI Data Types.
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:364
unsigned long l4_cap_idx_t
L4 Capability selector Type.
Definition: types.h:342
L4Re C++ Interfaces.
Definition: cmd_control:15
#define L4_PAGESIZE
Minimal page size (in bytes).
Definition: consts.h:307
Region mapper interface.
Ok.
Definition: err.h:43
unsigned long l4_umword_t
Unsigned machine word.
Definition: l4int.h:52
Attach_flags
Flags for attach operation.
Definition: rm:113
Attribute for defining an optional RPC argument.
Definition: ipc_types:147
Invalid address.
Definition: consts.h:409
Region is reserved (blocked)
Definition: rm:94
Region handling.
L4 flexpage type.
Definition: __l4_fpage.h:81
Region_flags
Flags for regions.
Definition: rm:88
unsigned long l4_addr_t
Address type.
Definition: l4int.h:45
Address not available.
Definition: err.h:62
Search only in area, or map into area.
Definition: rm:116
Generic RPC wrapper for L4 flex-pages.
Definition: ipc_types:321
Dynamically sized output array of type T.
Definition: ipc_ret_array:34