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