]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re/util/libs/dataspace_svr.cc
f0f3170a10923973cb560608cbc438214e0d8f67
[l4.git] / l4 / pkg / l4re / util / libs / dataspace_svr.cc
1 // vi:ft=cpp
2 /*
3  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
4  *               Alexander Warg <warg@os.inf.tu-dresden.de>,
5  *               Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
6  *     economic rights: Technische Universität Dresden (Germany)
7  *
8  * This file is part of TUD:OS and distributed under the terms of the
9  * GNU General Public License 2.
10  * Please see the COPYING-GPL-2 file for details.
11  *
12  * As a special exception, you may use this file as part of a free software
13  * library without restriction.  Specifically, if other files instantiate
14  * templates or use macros or inline functions from this file, or you compile
15  * this file and link it with other files to produce an executable, this
16  * file does not by itself cause the resulting executable to be covered by
17  * the GNU General Public License.  This exception does not however
18  * invalidate any other reasons why the executable file might be covered by
19  * the GNU General Public License.
20  */
21 #include <cstring>
22 #include <cstddef>
23 #include <cstdio>
24 #include <l4/sys/types.h>
25 #include <l4/cxx/list>
26 #include <l4/cxx/ipc_server>
27 #include <l4/cxx/ipc_stream>
28 #include <l4/cxx/minmax>
29 #include <l4/re/dataspace>
30 #include <l4/re/dataspace-sys.h>
31 #include <l4/re/protocols>
32 #include <l4/re/util/dataspace_svr>
33
34 #if 0
35 inline
36 L4::Ipc_ostream &operator << (L4::Ipc_ostream &s,
37                               L4Re::Dataspace::Stats const &st)
38 { s.put(st); return s; }
39 #endif
40
41 namespace L4Re { namespace Util {
42
43 int
44 Dataspace_svr::map(l4_addr_t offs, l4_addr_t hot_spot, unsigned long flags,
45                     l4_addr_t min, l4_addr_t max, L4::Snd_fpage &memory)
46 {
47   int err = map_hook(offs, flags, min, max);
48   if (err < 0)
49     return err;
50
51   memory = L4::Snd_fpage();
52
53   offs     = l4_trunc_page(offs);
54   hot_spot = l4_trunc_page(hot_spot);
55
56   if (!check_limit(offs))
57     {
58 #if 0
59       printf("limit failed: off=%lx sz=%lx\n", offs, size());
60 #endif
61       return -L4_ERANGE;
62     }
63
64   min = l4_trunc_page(min);
65   max = l4_round_page(max);
66
67   l4_addr_t adr = _ds_start + offs;
68   unsigned char order = L4_PAGESHIFT;
69
70   while (order < 30 /* limit to 1GB flexpage */)
71     {
72       l4_addr_t map_base = l4_trunc_size(adr, order + 1);
73       if (map_base < _ds_start)
74         break;
75
76       if (map_base + (1UL << (order + 1)) -1 > (_ds_start + round_size() - 1))
77         break;
78
79       map_base = l4_trunc_size(hot_spot, order + 1);
80       if (map_base < min)
81         break;
82
83       if (map_base + (1UL << (order + 1)) -1 > max -1)
84         break;
85
86       l4_addr_t mask = ~(~0UL << (order + 1));
87       if (hot_spot == ~0UL || ((adr ^ hot_spot) & mask))
88         break;
89
90       ++order;
91     }
92
93   l4_addr_t map_base = l4_trunc_size(adr, order);
94   //l4_addr_t map_offs = adr & ~(~0UL << order);
95
96   l4_fpage_t fpage = l4_fpage(map_base, order, flags && is_writable() ?  L4_FPAGE_RWX : L4_FPAGE_RX);
97   
98   memory = L4::Snd_fpage(fpage, hot_spot, _map_flags, _cache_flags);
99
100   return L4_EOK;
101 }
102
103 long
104 Dataspace_svr::clear(l4_addr_t offs, unsigned long _size) const throw()
105 {
106   if (!check_limit(offs))
107     return -L4_ERANGE;
108
109   unsigned long sz = _size = cxx::min(_size, round_size()-offs);
110
111   while (sz)
112     {
113       unsigned long b_adr = _ds_start + offs;
114       unsigned long b_sz = cxx::min(_size - offs, sz);
115
116       memset((void *)b_adr, 0, b_sz);
117
118       offs += b_sz;
119       sz -= b_sz;
120     }
121
122   return _size;
123 }
124
125 int
126 Dataspace_svr::phys(l4_addr_t /*offset*/, l4_addr_t &/*phys_addr*/, l4_size_t &/*phys_size*/) throw()
127 {
128   return -L4_EINVAL;
129 }
130
131 int
132 Dataspace_svr::dispatch(l4_umword_t obj, L4::Ipc_iostream &ios)
133 {
134   L4::Opcode op;
135   ios >> op;
136 #if 0
137   L4::cout << "Dataspace_svr: DS: op=" << L4::n_hex(op) << "\n";
138 #endif
139   l4_msgtag_t tag;
140   ios >> tag;
141
142   if (tag.label() != L4Re::Protocol::Dataspace)
143     return -L4_EBADPROTO;
144
145   switch (op)
146     {
147     case L4Re::Dataspace_::Map:
148       {
149         // L4_FPAGE_X means writable for DSs!
150         bool read_only = !is_writable() || !(obj & L4_FPAGE_X);
151         l4_addr_t offset, spot;
152         unsigned long flags;
153         L4::Snd_fpage fp;
154         ios >> offset >> spot >> flags;
155 #if 0
156         L4::cout << "MAPrq: " << L4::hex << offset << ", " << spot << ", "
157                  << flags << "\n";
158 #endif
159
160         if (read_only && (flags & 1))
161           return -L4_EPERM;
162
163         long int ret = map(offset, spot, flags & 1, 0, ~0, fp);
164 #if 0
165         L4::cout << "MAP: " << L4::hex << reinterpret_cast<unsigned long *>(&fp)[0]
166                  << ", " << reinterpret_cast<unsigned long *>(&fp)[1]
167                  << ", " << flags << ", " << (!read_only && (flags & 1))
168                  << ", ret=" << ret << '\n';
169 #endif
170         if (ret == L4_EOK)
171           ios << fp;
172
173         return ret;
174       }
175     case L4Re::Dataspace_::Clear:
176       {
177         if ((obj & 1) /* read only*/
178             || is_static() || !is_writable())
179           return -L4_EACCESS;
180
181         l4_addr_t offs;
182         unsigned long sz;
183
184         ios >> offs >> sz;
185         return clear(offs, sz);
186       }
187     case L4Re::Dataspace_::Stats:
188       {
189         L4Re::Dataspace::Stats s;
190         s.size = size();
191         // only return writable if really writable
192         s.flags = (rw_flags() & ~Writable) | (!(obj & 1) && is_writable());
193         ios << s;
194         return L4_EOK;
195       }
196     case L4Re::Dataspace_::Copy:
197       {
198         l4_addr_t dst_offs;
199         l4_addr_t src_offs;
200         unsigned long sz;
201         L4::Snd_fpage src_cap;
202
203         ios >> dst_offs >> src_offs >> sz >> src_cap;
204
205         if (!src_cap.id_received())
206           return -L4_EINVAL;
207
208         if (!(obj & 1))
209           return -L4_EACCESS;
210
211         if (sz == 0)
212           return L4_EOK;
213
214         copy(dst_offs, src_cap.data(), src_offs, sz);
215
216         return L4_EOK;
217       }
218     case L4Re::Dataspace_::Phys:
219       {
220         l4_addr_t offset;
221         l4_addr_t phys_addr;
222         l4_size_t phys_size;
223
224         ios >> offset;
225
226         int ret = phys(offset, phys_addr, phys_size);
227         if (ret)
228           return -L4_EINVAL;
229
230         ios << phys_addr << phys_size;
231
232         return L4_EOK;
233       }
234     case L4Re::Dataspace_::Take:
235       take();
236       //L4::cout << "Dataspace_svr: T[" << this << "]: refs=" << ref_cnt() << '\n';
237       return L4_EOK;
238     case L4Re::Dataspace_::Release:
239       if ((release() == 0) && !is_static())
240         {
241           //L4::cout << "Dataspace_svr: R[" << this << "]: refs=" << ref_cnt() << '\n';
242           delete this;
243           return 0;
244         }
245       //L4::cout << "Dataspace_svr: R[" << this << "]: refs=" << ref_cnt() << '\n';
246
247       return 1;
248     default:
249       return -L4_ENOSYS;
250     }
251 }
252
253 }}