]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/moe/server/src/dataspace.cc
update
[l4.git] / l4 / pkg / moe / server / src / dataspace.cc
1 /*
2  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *               Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10 #include "dataspace.h"
11 #include "dataspace_util.h"
12 #include "globals.h"
13 #include "page_alloc.h"
14
15 #include <l4/re/dataspace-sys.h>
16 #include <l4/re/protocols>
17 #include <l4/re/util/meta>
18
19 #include <l4/cxx/ipc_stream>
20 #include <l4/cxx/slab_alloc>
21 #include <l4/cxx/minmax>
22
23 #include <l4/sys/capability>
24 #include <l4/sys/err.h>
25
26 #include <cstring>
27 using cxx::min;
28
29 int
30 Moe::Dataspace::map(l4_addr_t offs, l4_addr_t hot_spot, bool _rw,
31                     l4_addr_t min, l4_addr_t max, L4::Snd_fpage &memory)
32 {
33   memory = L4::Snd_fpage();
34
35   offs     = l4_trunc_page(offs);
36   hot_spot = l4_trunc_page(hot_spot);
37
38   if (!check_limit(offs))
39     {
40 #if 1
41       L4::cout << "MOE: ds access out of bounds: offset=" << L4::n_hex(offs)
42                << " size=" << L4::n_hex(size()) << "\n";
43 #endif
44       return -L4_ERANGE;
45     }
46
47   Ds_rw rw = _rw ? Writable : Read_only;
48   Address adr = address(offs, rw, hot_spot, min, max);
49   if (adr.is_nil())
50     return -L4_EPERM;
51
52   memory = L4::Snd_fpage(adr.fp(), hot_spot, L4::Snd_fpage::Map,
53                          (L4::Snd_fpage::Cacheopt)((_flags >> 12) & (7 << 4)));
54
55   return L4_EOK;
56 }
57
58 inline
59 L4::Ipc_ostream &operator << (L4::Ipc_ostream &s,
60                               L4Re::Dataspace::Stats const &st)
61 { s.put(st); return s; }
62
63 int
64 Moe::Dataspace::dispatch(l4_umword_t obj, L4::Ipc_iostream &ios)
65 {
66   l4_msgtag_t tag;
67   ios >> tag;
68
69   if (tag.label() == L4::Meta::Protocol)
70     return L4Re::Util::handle_meta_request<L4Re::Dataspace>(ios);
71
72   if (tag.label() != L4Re::Protocol::Dataspace)
73     return -L4_EBADPROTO;
74
75   L4::Opcode op;
76   ios >> op;
77 #if 0
78   L4::cout << "MOE: DS: op=" << L4::n_hex(op) << "\n";
79 #endif
80
81   switch (op)
82     {
83     case L4Re::Dataspace_::Map:
84       {
85         // L4_FPAGE_X means writable for DSs!
86         bool read_only = !is_writable() || !(obj & L4_FPAGE_X);
87         l4_addr_t offset, spot;
88         unsigned long flags;
89         L4::Snd_fpage fp;
90         ios >> offset >> spot >> flags;
91 #if 0
92         L4::cout << "MAPrq: " << L4::hex << offset << ", " << spot << ", "
93                  << flags << "\n";
94 #endif
95
96         if (read_only && (flags & Writable))
97           return -L4_EPERM;
98
99         long int ret = map(offset, spot, flags & Writable, 0, ~0, fp);
100 #if 0
101         L4::cout << "MAP: " << L4::hex << reinterpret_cast<unsigned long *>(&fp)[0]
102                  << ", " << reinterpret_cast<unsigned long *>(&fp)[1]
103                  << ", " << flags << ", " << (!read_only && (flags & 1))
104                  << ", ret=" << ret << '\n';
105 #endif
106         if (ret == L4_EOK)
107           ios << fp;
108
109         return ret;
110       }
111     case L4Re::Dataspace_::Clear:
112       {
113         if (!(obj & L4_FPAGE_X) /* read only*/
114             || !is_writable())
115           return -L4_EACCESS;
116
117         l4_addr_t offs;
118         unsigned long sz;
119
120         ios >> offs >> sz;
121         return clear(offs, sz);
122       }
123     case L4Re::Dataspace_::Stats:
124       {
125         L4Re::Dataspace::Stats s;
126         s.size = size();
127         // only return writable if really writable
128         s.flags = flags() & ~Writable;
129         if ((obj & L4_FPAGE_X) && is_writable())
130           s.flags |= Writable;
131
132         ios << s;
133         return L4_EOK;
134       }
135     case L4Re::Dataspace_::Copy:
136       {
137         l4_addr_t dst_offs;
138         Moe::Dataspace *src = 0;
139         l4_addr_t src_offs;
140         unsigned long sz;
141         L4::Snd_fpage src_cap;
142
143         ios >> dst_offs >> src_offs >> sz >> src_cap;
144
145         if (src_cap.id_received())
146           src = dynamic_cast<Moe::Dataspace*>(object_pool.find(src_cap.data()));
147
148         if (!(obj & L4_FPAGE_X))
149           return -L4_EACCESS;
150
151         if (!src)
152           return -L4_EINVAL;
153
154         if (sz == 0)
155           return L4_EOK;
156
157         Dataspace_util::copy(this, dst_offs, src, src_offs, sz);
158
159         return L4_EOK;
160       }
161     case L4Re::Dataspace_::Phys:
162       {
163         l4_addr_t offset;
164         l4_addr_t phys_addr;
165         l4_size_t phys_size;
166
167         ios >> offset;
168
169         int ret = phys(offset, phys_addr, phys_size);
170         if (ret)
171           return -L4_EINVAL;
172
173         ios << phys_addr << phys_size;
174
175         return L4_EOK;
176       }
177     case L4Re::Dataspace_::Allocate:
178       {
179         l4_addr_t offset;
180         l4_size_t size;
181         ios >> offset >> size;
182         return pre_allocate(offset, size, obj & 3);
183       }
184     case L4Re::Dataspace_::Take:
185       take();
186       //L4::cout << "MOE: T[" << this << "]: refs=" << ref_cnt() << '\n';
187       return L4_EOK;
188     case L4Re::Dataspace_::Release:
189       if (release() == 0 && !is_static())
190         {
191           //L4::cout << "MOE: R[" << this << "]: refs=" << ref_cnt() << '\n';
192           delete this;
193           return 0;
194         }
195       //L4::cout << "MOE: R[" << this << "]: refs=" << ref_cnt() << '\n';
196
197       return 1;
198     default:
199       return -L4_ENOSYS;
200     }
201 }
202
203 long
204 Moe::Dataspace::clear(l4_addr_t offs, unsigned long _size) const throw()
205 {
206   if (!check_limit(offs))
207     return -L4_ERANGE;
208
209   unsigned long sz = _size = min(_size, round_size()-offs);
210
211   while (sz)
212     {
213       Address dst_a = address(offs, Writable);
214       unsigned long b_sz = min(dst_a.sz() - dst_a.of(), sz);
215
216       memset(dst_a.adr(), 0, b_sz);
217
218       offs += b_sz;
219       sz -= b_sz;
220     }
221
222   return _size;
223 }
224
225 int
226 Moe::Dataspace::phys(l4_addr_t /*offset*/, l4_addr_t &/*phys_addr*/, l4_size_t &/*phys_size*/) throw()
227 {
228   return -L4_EINVAL;
229 }