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