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/util/meta>
16
17 #include <l4/cxx/iostream>
18 #include <l4/cxx/minmax>
19
20 #include <l4/sys/capability>
21 #include <l4/sys/err.h>
22 #include <l4/sys/cache.h>
23
24 #include <cstring>
25 using cxx::min;
26
27 int
map(l4_addr_t offs,l4_addr_t hot_spot,Flags flags,l4_addr_t min,l4_addr_t max,L4::Ipc::Snd_fpage & memory)28 Moe::Dataspace::map(l4_addr_t offs, l4_addr_t hot_spot, Flags flags,
29 l4_addr_t min, l4_addr_t max, L4::Ipc::Snd_fpage &memory)
30 {
31 using L4Re::Dataspace;
32 using L4::Ipc::Snd_fpage;
33
34 memory = L4::Ipc::Snd_fpage();
35
36 offs = l4_trunc_page(offs);
37 hot_spot = l4_trunc_page(hot_spot);
38
39 if (!check_limit(offs))
40 {
41 if (1)
42 L4::cout << "MOE: ds access out of bounds: offset=" << L4::n_hex(offs)
43 << " size=" << L4::n_hex(size()) << "\n";
44
45 return -L4_ERANGE;
46 }
47
48 Address adr = address(offs, flags, hot_spot, min, max);
49 if (adr.is_nil())
50 return adr.error();
51
52 unsigned long cache_opt = cxx::max((_flags & Dataspace::F::Caching_mask).raw,
53 (flags & Dataspace::F::Caching_mask).raw);
54
55 static Snd_fpage::Cacheopt cache_map[] =
56 { Snd_fpage::None, Snd_fpage::Buffered, Snd_fpage::Uncached,
57 Snd_fpage::None };
58
59 memory = Snd_fpage(adr.fp(), hot_spot, Snd_fpage::Map,
60 cache_map[cache_opt >> Dataspace::F::Caching_shift]);
61
62 return L4_EOK;
63 }
64
65 long
op_map(L4Re::Dataspace::Rights rights,L4Re::Dataspace::Offset offset,L4Re::Dataspace::Map_addr spot,L4Re::Dataspace::Flags flags,L4::Ipc::Snd_fpage & fp)66 Moe::Dataspace::op_map(L4Re::Dataspace::Rights rights,
67 L4Re::Dataspace::Offset offset,
68 L4Re::Dataspace::Map_addr spot,
69 L4Re::Dataspace::Flags flags,
70 L4::Ipc::Snd_fpage &fp)
71 {
72 auto mf = map_flags(rights);
73
74 if (0)
75 L4::cout << "MAPrq: " << L4::hex << offset << ", " << spot << ", "
76 << flags.raw << "\n";
77
78 if (!mf.w() && flags.w())
79 return -L4_EPERM;
80
81 if (!mf.x() && flags.x())
82 return -L4_EPERM;
83
84 long ret = map(offset, spot, flags & mf, 0, ~0, fp);
85
86 if (0)
87 L4::cout << "MAP: " << L4::hex << reinterpret_cast<unsigned long *>(&fp)[0]
88 << ", " << reinterpret_cast<unsigned long *>(&fp)[1]
89 << ", " << flags.raw << ", " << (mf.w() && flags.w())
90 << ", ret=" << ret << '\n';
91
92 return ret;
93 };
94
95 long
op_copy_in(L4Re::Dataspace::Rights obj,L4Re::Dataspace::Offset dst_offs,L4::Ipc::Snd_fpage const & src_cap,L4Re::Dataspace::Offset src_offs,L4Re::Dataspace::Size sz)96 Moe::Dataspace::op_copy_in(L4Re::Dataspace::Rights obj,
97 L4Re::Dataspace::Offset dst_offs,
98 L4::Ipc::Snd_fpage const &src_cap,
99 L4Re::Dataspace::Offset src_offs,
100 L4Re::Dataspace::Size sz)
101 {
102 Moe::Dataspace *src = 0;
103
104 if (src_cap.id_received())
105 src = dynamic_cast<Moe::Dataspace*>(object_pool.find(src_cap.data()));
106
107 if (!map_flags(obj).w())
108 return -L4_EACCESS;
109
110 if (!src)
111 return -L4_EINVAL;
112
113 if (sz == 0)
114 return L4_EOK;
115
116 Dataspace_util::copy(this, dst_offs, src, src_offs, sz);
117
118 return L4_EOK;
119 }
120
121 long
clear(l4_addr_t offs,unsigned long size) const122 Moe::Dataspace::clear(l4_addr_t offs, unsigned long size) const throw()
123 {
124 if (!check_limit(offs))
125 return -L4_ERANGE;
126
127 unsigned long sz = min(size, round_size() - offs);
128
129 while (sz)
130 {
131 Address dst_a = address(offs);
132 unsigned long b_sz = min(dst_a.sz() - dst_a.of(), sz);
133
134 memset(dst_a.adr(), 0, b_sz);
135
136 // No need for I cache coherence, as we just zero fill and assume that
137 // this is no executable code
138 l4_cache_clean_data((l4_addr_t)dst_a.adr(),
139 (l4_addr_t)dst_a.adr() + b_sz);
140
141 offs += b_sz;
142 sz -= b_sz;
143 }
144
145 return 0;
146 }
147
148 int
dma_map(Dma_space *,l4_addr_t,l4_size_t *,Dma_attribs,Dma_space::Direction,Dma_space::Dma_addr *)149 Moe::Dataspace::dma_map(Dma_space *, l4_addr_t, l4_size_t *,
150 Dma_attribs, Dma_space::Direction,
151 Dma_space::Dma_addr *)
152 {
153 return -L4_EINVAL;
154 }
155