]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re/util/include/region_mapping_svr
update
[l4.git] / l4 / pkg / l4re / util / include / region_mapping_svr
1 // vi:ft=cpp
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 RM, typename IOS>
35 int region_map_server(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::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(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       default:
156         return -L4_ENOSYS;
157     }
158 }
159
160 template<typename Dbg, typename RM, typename IOS>
161 int region_pf_handler(RM *rm, IOS &ios)
162 {
163   l4_umword_t addr, pc;
164   ios >> addr >> pc;
165   Dbg(Dbg::Server).printf("page fault: %lx pc=%lx\n", addr, pc);
166
167   register unsigned writable = addr & 2;
168   addr = addr & ~3UL;
169
170   typename RM::Node n = rm->find(addr);
171
172   if (!n || !n->second.memory())
173     {
174       Dbg(Dbg::Warn, "rm").printf("unhandled %s page fault @%lx pc=%lx\n",
175                                   writable ? "write" : "read", addr, pc);
176
177       // generate exception
178       ios << (l4_umword_t)~0;
179       return L4_EOK;
180     }
181
182   if (n->second.is_ro() && writable)
183     {
184       Dbg(Dbg::Warn, "rm").printf("write page fault in readonly region @%lx pc=%lx\n",
185                                   addr, pc);
186       // generate exception
187       ios << (l4_umword_t)~0;
188       return L4_EOK;
189     }
190
191   typename RM::Region_handler::Ops::Map_result result;
192   if (int err = n->second.map(addr, n->first, writable, &result))
193     {
194       Dbg(Dbg::Warn, "rm").printf("mapping for pf failed with %d @%lx pc=%lx\n",
195                                   err, addr, pc);
196       // generate exception
197       ios << (l4_umword_t)~0;
198       return L4_EOK;
199     }
200
201   ios << result;
202   return L4_EOK;
203 }
204
205 }}