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