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/minmax>
27 #include <l4/re/dataspace>
28 #include <l4/re/dataspace-sys.h>
29 #include <l4/re/util/dataspace_svr>
30 
31 #if 0
32 inline
33 L4::Ipc::Ostream &operator << (L4::Ipc_ostream &s,
34                               L4Re::Dataspace::Stats const &st)
35 { s.put(st); return s; }
36 #endif
37 
38 namespace L4Re { namespace Util {
39 
40 int
map(Dataspace::Offset offs,Dataspace::Map_addr hot_spot,Dataspace::Flags flags,Dataspace::Map_addr min,Dataspace::Map_addr max,L4::Ipc::Snd_fpage & memory)41 Dataspace_svr::map(Dataspace::Offset offs,
42                    Dataspace::Map_addr hot_spot,
43                    Dataspace::Flags flags,
44                    Dataspace::Map_addr min,
45                    Dataspace::Map_addr max,
46                    L4::Ipc::Snd_fpage &memory)
47 {
48   int err = map_hook(offs, flags, min, max);
49   if (err < 0)
50     return err;
51 
52   memory = L4::Ipc::Snd_fpage();
53 
54   offs     = l4_trunc_page(offs);
55   hot_spot = l4_trunc_page(hot_spot);
56 
57   if (!check_limit(offs))
58     {
59 #if 0
60       printf("limit failed: off=%lx sz=%lx\n", offs, size());
61 #endif
62       return -L4_ERANGE;
63     }
64 
65   min = l4_trunc_page(min);
66   max = l4_round_page(max);
67 
68   l4_addr_t addr = _ds_start + offs;
69   unsigned char order = L4_PAGESHIFT;
70 
71   while (order < 30 /* limit to 1GB flexpage */)
72     {
73       l4_addr_t map_base = l4_trunc_size(addr, order + 1);
74       if (map_base < _ds_start)
75 	break;
76 
77       if (map_base + (1UL << (order + 1)) -1 > (_ds_start + round_size() - 1))
78 	break;
79 
80       map_base = l4_trunc_size(hot_spot, order + 1);
81       if (map_base < min)
82 	break;
83 
84       if (map_base + (1UL << (order + 1)) -1 > max -1)
85 	break;
86 
87       l4_addr_t mask = ~(~0UL << (order + 1));
88       if (hot_spot == ~0UL || ((addr ^ hot_spot) & mask))
89 	break;
90 
91       ++order;
92     }
93 
94   l4_addr_t map_base = l4_trunc_size(addr, order);
95   //l4_addr_t map_offs = addr & ~(~0UL << order);
96 
97   l4_fpage_t fpage = l4_fpage(map_base, order, flags.fpage_rights());
98 
99   memory = L4::Ipc::Snd_fpage(fpage, hot_spot, _map_flags, _cache_flags);
100 
101   return L4_EOK;
102 }
103 
104 long
clear(l4_addr_t offs,unsigned long ds_size) const105 Dataspace_svr::clear(l4_addr_t offs, unsigned long ds_size) const noexcept
106 {
107   if (!check_limit(offs))
108     return -L4_ERANGE;
109 
110   unsigned long sz = ds_size = cxx::min(ds_size, round_size() - offs);
111 
112   while (sz)
113     {
114       unsigned long b_addr = _ds_start + offs;
115       unsigned long b_sz = cxx::min(ds_size - offs, sz);
116 
117       memset((void *)b_addr, 0, b_sz);
118 
119       offs += b_sz;
120       sz -= b_sz;
121     }
122 
123   return ds_size;
124 }
125 
126 }}
127