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 "debug.h"
11 #include "region.h"
12 
13 #include <l4/sys/kip>
14 
15 #include <l4/re/rm>
16 
17 #include <l4/cxx/iostream>
18 #include <l4/cxx/exceptions>
19 
20 #include <l4/re/util/region_mapping_svr_2>
21 
Region_map()22 Region_map::Region_map()
23   : Base(Moe::Virt_limit::start, Moe::Virt_limit::end)
24 {
25   for (auto const &m: L4::Kip::Mem_desc::all(kip()))
26     {
27       if (m.type() != L4::Kip::Mem_desc::Reserved || !m.is_virtual())
28         continue;
29 
30       l4_addr_t start = m.start();
31       l4_addr_t end = m.end();
32 
33       attach_area(start, end - start + 1, L4Re::Rm::F::Reserved);
34     }
35 
36   attach_area(0, L4_PAGESIZE);
37 }
38 
map(Region_handler const * h,l4_addr_t adr,L4Re::Util::Region const & r,bool need_w,L4::Ipc::Snd_fpage * result)39 int Region_ops::map(Region_handler const *h, l4_addr_t adr,
40                     L4Re::Util::Region const &r, bool need_w,
41                     L4::Ipc::Snd_fpage *result)
42 {
43   if (!h->memory())
44     return -L4_EADDRNOTAVAIL;
45 
46   using L4::Ipc::Snd_fpage;
47   l4_addr_t offs = adr - r.start();
48   offs = l4_trunc_page(offs);
49   auto f = map_flags(h->flags());
50   if (!need_w)
51     f &= ~L4Re::Dataspace::F::W;
52 
53   static Snd_fpage::Cacheopt const cache_map[] =
54     { Snd_fpage::None, Snd_fpage::Buffered, Snd_fpage::Uncached,
55       Snd_fpage::None };
56 
57   auto ds_fpage = h->memory()->address(offs + h->offset(), f, adr,
58                                        r.start(), r.end());
59   if (ds_fpage.is_nil())
60     return -L4_EADDRNOTAVAIL;
61 
62   *result = Snd_fpage(ds_fpage.fp(), offs + r.start(), Snd_fpage::Map,
63                       cache_map[h->caching() >> L4Re::Rm::Caching_shift]);
64 
65   return L4_EOK;
66 }
67 
68 void
free(Region_handler const * h,l4_addr_t start,unsigned long size)69 Region_ops::free(Region_handler const *h, l4_addr_t start, unsigned long size)
70 {
71   if (h->is_ro() || !h->memory())
72     return;
73 
74   h->memory()->clear(h->offset() + start, size);
75 }
76 
77 int
validate_ds(void *,L4::Ipc::Snd_fpage const & ds_cap,L4Re::Rm::Region_flags flags,Dataspace * ds)78 Region_map::validate_ds(void *, L4::Ipc::Snd_fpage const &ds_cap,
79                         L4Re::Rm::Region_flags flags, Dataspace *ds)
80 {
81   if (flags & L4Re::Rm::F::Pager)
82     return -L4_EINVAL;
83 
84   if (!ds_cap.id_received())
85     return -L4_ENOENT;
86 
87   auto *moe_ds = dynamic_cast<Moe::Dataspace*>(object_pool.find(ds_cap.data()));
88 
89   if (!moe_ds)
90     return -L4_ENOENT;
91 
92   *ds = moe_ds;
93 
94   if ((map_flags(flags) & moe_ds->map_flags(ds_cap.data())) != map_flags(flags))
95     return -L4_EPERM;
96 
97   return L4_EOK;
98 }
99 
100 long
op_io_page_fault(L4::Io_pager::Rights,l4_fpage_t io_pfa,l4_umword_t pc,L4::Ipc::Opt<L4::Ipc::Snd_fpage> &)101 Region_map::op_io_page_fault(L4::Io_pager::Rights,
102                              l4_fpage_t io_pfa, l4_umword_t pc,
103                              L4::Ipc::Opt<L4::Ipc::Snd_fpage> &)
104 {
105   Dbg(Dbg::Warn).printf("IO-port-fault: port=0x%lx size=%d pc=0x%lx\n",
106                         l4_fpage_ioport(io_pfa), 1 << l4_fpage_size(io_pfa), pc);
107   return -L4_ENOMEM;
108 }
109