L4Re - L4 Runtime Environment
region_mapping_svr
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /**
3  * \internal
4  * \file
5  * \brief Region mapper server template.
6  */
7 /*
8  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
9  * Alexander Warg <warg@os.inf.tu-dresden.de>
10  * economic rights: Technische Universit├Ąt Dresden (Germany)
11  *
12  * This file is part of TUD:OS and distributed under the terms of the
13  * GNU General Public License 2.
14  * Please see the COPYING-GPL-2 file for details.
15  *
16  * As a special exception, you may use this file as part of a free software
17  * library without restriction. Specifically, if other files instantiate
18  * templates or use macros or inline functions from this file, or you compile
19  * this file and link it with other files to produce an executable, this
20  * file does not by itself cause the resulting executable to be covered by
21  * the GNU General Public License. This exception does not however
22  * invalidate any other reasons why the executable file might be covered by
23  * the GNU General Public License.
24  */
25 #pragma once
26 
27 #include <l4/sys/types.h>
28 #include <l4/re/rm-sys.h>
29 
30 #include <l4/re/util/region_mapping>
31 
32 namespace L4Re { namespace Util {
33 
34 template<typename Rm_server, typename SVR_DATA, typename RM, typename IOS>
35 int region_map_server(SVR_DATA *sdata, RM *rm, IOS &ios)
36 {
37  L4::Opcode op;
38  ios >> op;
39  switch (op)
40  {
41  case Rm_::Attach:
42  {
43  unsigned long size;
44  l4_addr_t start;
45  unsigned long flags;
46  l4_cap_idx_t client_cap_idx = L4_INVALID_CAP;
47  L4::Ipc::Snd_fpage ds_cap;
48  typename Rm_server::Dataspace ds = typename Rm_server::Dataspace();
49  l4_addr_t offs;
50  unsigned char align;
51 
52  ios >> start >> size >> flags >> offs >> align;
53  if (!(flags & Rm::Reserved))
54  {
55  ios >> client_cap_idx >> ds_cap;
56 
57  if (int r = Rm_server::validate_ds(sdata, ds_cap, flags, &ds))
58  return r;
59  }
60 
61  size = l4_round_page(size);
62  start = l4_trunc_page(start);
63 
64  if (size < L4_PAGESIZE)
65  return -L4_EINVAL;
66 
67  unsigned r_flags = flags & Rm::Region_flags;
68  unsigned a_flags = flags & Rm::Attach_flags;
69 
70  start = l4_addr_t(rm->attach((void*)start, size,
71  typename RM::Region_handler(ds, client_cap_idx, offs, r_flags),
72  a_flags, align));
73 
74  if (start == L4_INVALID_ADDR)
75  return -L4_EADDRNOTAVAIL;
76 
77  ios << start;
78  return L4_EOK;
79  }
80  case Rm_::Detach:
81  {
82  l4_addr_t addr;
83  unsigned long size;
84  unsigned flags;
85  ios >> addr >> size >> flags;
86 
87  Region r;
88  typename RM::Region_handler h;
89  int err = rm->detach((void*)addr, size, flags, &r, &h);
90  if (err < 0)
91  return err;
92 
93  if (r.invalid())
94  return -L4_ENOENT;
95 
96  ios << l4_addr_t(r.start()) << (unsigned long)r.size()
97  << h.client_cap_idx();
98 
99  return err;
100  }
101  case Rm_::Attach_area:
102  {
103  l4_addr_t start;
104  unsigned long size;
105  unsigned flags;
106  unsigned char align;
107 
108  ios >> start >> size >> flags >> align;
109  start = rm->attach_area(start, size, flags, align);
110  if (start == L4_INVALID_ADDR)
111  return -L4_EADDRNOTAVAIL;
112 
113  ios << start;
114 
115  return L4_EOK;
116  }
117  case Rm_::Detach_area:
118  {
119  l4_addr_t start;
120  ios >> start;
121  if (!rm->detach_area(start))
122  return -L4_ENOENT;
123 
124  return L4_EOK;
125  }
126  case Rm_::Find:
127  {
128  if (!Rm_server::Have_find)
129  return -L4_EPERM;
130 
131  l4_addr_t addr;
132  unsigned flag_area = 0;
133  unsigned long size;
134  ios >> addr >> size;
135 
136  typename RM::Node r = rm->find(Region(addr, addr + size -1));
137  if (!r)
138  {
139  r = rm->area_find(Region(addr, addr + size - 1));
140  if (!r)
141  return -L4_ENOENT;
142  flag_area = Rm::In_area;
143  }
144 
145  addr = r->first.start();
146  size = r->first.end() + 1 - addr;
147 
148  unsigned flags = r->second.flags() | flag_area;
149 
150  ios << addr << size << flags << r->second.offset()
151  << Rm_server::find_res(r->second.memory());
152 
153  return L4_EOK;
154  }
155  case Rm_::Get_regions:
156  {
157  l4_addr_t addr;
158  ios >> addr;
159  typename RM::Node r;
160  int num = 0;
161  while ((r = rm->lower_bound(Region(addr, addr +1))))
162  {
163  Rm::Region x;
164  x.start = r->first.start();
165  x.end = r->first.end();
166  x.offset = r->second.offset();
167 
168  if (!ios.put(x))
169  break;
170 
171  num++;
172  if (x.end >= rm->max_addr())
173  break;
174  addr = x.end + 1;
175  }
176 
177  return num;
178  }
179  case Rm_::Get_areas:
180  {
181  l4_addr_t addr;
182  ios >> addr;
183  typename RM::Node r;
184  int num = 0;
185  while ((r = rm->lower_bound_area(Region(addr, addr +1))))
186  {
187  Rm::Area x;
188  x.start = r->first.start();
189  x.end = r->first.end();
190 
191  if (!ios.put(x))
192  break;
193 
194  num++;
195  if (x.end >= rm->max_addr())
196  break;
197  addr = x.end + 1;
198  }
199 
200  return num;
201  }
202  default:
203  return -L4_ENOSYS;
204  }
205 }
206 
207 template<typename Dbg, typename RM, typename IOS>
208 int region_pf_handler(RM *rm, IOS &ios)
209 {
210  l4_umword_t addr, pc, sp;
211  ios >> addr >> pc >> sp;
212  Dbg(Dbg::Server).printf("page fault: %lx pc=%lx\n", addr, pc);
213 
214  unsigned writable = addr & 2;
215  addr = addr & ~7UL;
216 
217  typename RM::Node n = rm->find(addr);
218 
219  if (!n || !n->second.memory())
220  {
221  Dbg(Dbg::Warn, "rm").printf("unhandled %s page fault at 0x%lx pc=0x%lx\n",
222  writable ? "write" : "read", addr, pc);
223 
224  // generate exception
225  ios << (l4_umword_t)~0;
226  return L4_EOK;
227  }
228 
229  if (n->second.is_ro() && writable)
230  {
231  Dbg(Dbg::Warn, "rm").printf("write page fault in readonly region at 0x%lx pc=0x%lx\n",
232  addr, pc);
233  // generate exception
234  ios << (l4_umword_t)~0;
235  return L4_EOK;
236  }
237 
238  typename RM::Region_handler::Ops::Map_result result;
239  if (int err = n->second.map(addr, n->first, writable, &result))
240  {
241  Dbg(Dbg::Warn, "rm").printf("mapping for page fault failed with error %d at 0x%lx pc=0x%lx\n",
242  err, addr, pc);
243  // generate exception
244  ios << (l4_umword_t)~0;
245  return L4_EOK;
246  }
247 
248  ios << result;
249  return L4_EOK;
250 }
251 
252 }}