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 "region.h"
11 #include "globals.h"
12 
13 #include <l4/sys/kip>
14 
15 #include <l4/re/dataspace>
16 #include <l4/re/rm>
17 #include <l4/re/env>
18 
19 #include <l4/cxx/iostream>
20 #include <l4/cxx/l4iostream>
21 
22 #include "dispatcher.h"
23 #include "debug.h"
24 
25 #include <stdio.h>
26 
27 using L4Re::Rm;
28 using L4Re::Dataspace;
29 using L4Re::Util::Region;
30 
Region_map()31 Region_map::Region_map()
32   : Base(0,0)
33 {}
34 
35 void
init()36 Region_map::init()
37 {
38   extern char __L4_KIP_ADDR__[];
39 
40   for (auto const &m: L4::Kip::Mem_desc::all(__L4_KIP_ADDR__))
41     {
42       if (!m.is_virtual())
43 	continue;
44 
45       l4_addr_t start = m.start();
46       l4_addr_t end = m.end();
47 
48       switch (m.type())
49 	{
50 	case L4::Kip::Mem_desc::Conventional:
51 	  set_limits(start, end);
52 	  break;
53 	case L4::Kip::Mem_desc::Reserved:
54 	  attach_area(start, end - start + 1, L4Re::Rm::F::Reserved);
55 	  break;
56 	default:
57 	  break;
58 	}
59     }
60 
61   // reserve page at 0
62   attach_area(0, L4_PAGESIZE);
63 }
64 
65 
66 int
map(Region_handler const * h,l4_addr_t local_addr,Region const & r,bool writable,l4_umword_t * result)67 Region_ops::map(Region_handler const *h, l4_addr_t local_addr,
68                 Region const &r, bool writable, l4_umword_t *result)
69 {
70   *result = 0;
71   auto r_flags = h->flags();
72   if (!writable)
73     r_flags = r_flags & ~L4Re::Rm::F::W;
74 
75   if ((r_flags & Rm::F::Reserved) || !h->memory().is_valid())
76     return -L4_ENOENT;
77 
78   if (r_flags & Rm::F::Pager)
79     {
80       L4::Ipc::Snd_fpage rfp;
81       L4::cap_reinterpret_cast<L4::Pager>(h->memory())
82         ->page_fault(local_addr, -3UL,
83                      L4::Ipc::Rcv_fpage::mem(0, L4_WHOLE_ADDRESS_SPACE, 0),
84                      rfp);
85       return L4_EOK;
86     }
87   else
88     {
89       // align to 16byte, some DS implementations are too picky about
90       // possible r/w etc. bits in the offset
91       local_addr &= ~0x0fUL;
92       l4_addr_t offset = local_addr - r.start() + h->offset();
93       L4::Cap<L4Re::Dataspace> ds = L4::cap_cast<L4Re::Dataspace>(h->memory());
94       L4Re::Dataspace::Flags flags = map_flags(r_flags);
95       return ds->map(offset, flags, local_addr, r.start(), r.end());
96     }
97 }
98 
99 void
free(Region_handler const * h,l4_addr_t start,unsigned long size)100 Region_ops::free(Region_handler const *h, l4_addr_t start, unsigned long size)
101 {
102   if ((h->flags() & Rm::F::Reserved) || !h->memory().is_valid())
103     return;
104 
105   if (h->flags() & Rm::F::Pager)
106     return;
107 
108   L4::Cap<L4Re::Dataspace> ds = L4::cap_cast<L4Re::Dataspace>(h->memory());
109   ds->clear(h->offset() + start, size);
110 }
111 
112 void
debug_dump(unsigned long) const113 Region_map::debug_dump(unsigned long /*function*/) const
114 {
115   printf("Region mapping: limits [%lx-%lx]\n", min_addr(), max_addr());
116   printf(" Area map:\n");
117   for (Region_map::Const_iterator i = area_begin(); i != area_end(); ++i)
118     printf("  [%10lx-%10lx] -> flags=%x\n",
119            i->first.start(), i->first.end(),
120 	   i->second.flags());
121   printf(" Region map:\n");
122   for (Region_map::Const_iterator i = begin(); i != end(); ++i)
123     printf("  [%10lx-%10lx] -> (offs=%llx, ds=%lx, flags=%x)\n",
124            i->first.start(), i->first.end(),
125 	   i->second.offset(), i->second.memory().cap(),
126 	   i->second.flags());
127 }
128 
129 int
op_exception(L4::Exception::Rights,l4_exc_regs_t & u,L4::Ipc::Opt<L4::Ipc::Snd_fpage> &)130 Region_map::op_exception(L4::Exception::Rights, l4_exc_regs_t &u,
131                          L4::Ipc::Opt<L4::Ipc::Snd_fpage> &)
132 {
133   Dbg w(Dbg::Warn);
134   w.printf("%s: Unhandled exception: PC=0x%lx PFA=0x%lx LdrFlgs=0x%lx\n",
135            Global::l4re_aux->binary, l4_utcb_exc_pc(&u), l4_utcb_exc_pfa(&u),
136            Global::l4re_aux->ldr_flags);
137 
138   return -L4_ENOREPLY;
139 }
140 
141 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> &)142 Region_map::op_io_page_fault(L4::Io_pager::Rights,
143                              l4_fpage_t io_pfa, l4_umword_t pc,
144                              L4::Ipc::Opt<L4::Ipc::Snd_fpage> &)
145 {
146   Err().printf("IO-port-fault: port=0x%lx size=%d pc=0x%lx\n",
147                l4_fpage_ioport(io_pfa), 1 << l4_fpage_size(io_pfa), pc);
148   return -L4_ENOMEM;
149 }
150 
151