]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/map_util-objs.cpp
d8b0c27a61e16b15d89a74a04b0ef0f6a92f90fc
[l4.git] / kernel / fiasco / src / kern / map_util-objs.cpp
1 INTERFACE:
2
3 #include "kobject_mapdb.h"
4
5
6 IMPLEMENTATION:
7
8 #include "assert.h"
9 #include "assert_opt.h"
10
11 #include "obj_space.h"
12 #include "l4_types.h"
13 #include "mappable.h"
14
15 inline NEEDS["assert_opt.h"]
16 void
17 save_access_attribs (Kobject_mapdb* /*mapdb*/,
18     const Kobject_mapdb::Frame& /*mapdb_frame*/,
19     Kobject_mapdb::Mapping* /*mapping*/, Obj_space* /*space*/,
20     unsigned /*page_rights*/,
21     Obj_space::Addr /*virt*/, Obj_space::Phys_addr /*phys*/, Obj_space::Size /*size*/,
22     bool /*me_too*/)
23 {}
24
25 L4_error
26 obj_map(Space *from, L4_fpage const &fp_from,
27         Space *to, L4_fpage const &fp_to, L4_msg_item control,
28         Kobject ***reap_list)
29 {
30   assert_opt (from);
31   assert_opt (to);
32
33   typedef Map_traits<Obj_space> Mt;
34   Mt::Addr rcv_addr = Mt::get_addr(fp_to);
35   Mt::Addr snd_addr = Mt::get_addr(fp_from);
36   Mt::Size snd_size = Mt::Size::from_shift(fp_from.order());
37   Mt::Size rcv_size = Mt::Size::from_shift(fp_to.order());
38   Mt::Addr offs(control.index());
39
40   snd_addr = snd_addr.trunc(snd_size);
41   rcv_addr = rcv_addr.trunc(rcv_size);
42
43   Mt::constraint(snd_addr, snd_size, rcv_addr, rcv_size, offs);
44
45   if (snd_size == 0)
46     return L4_error::None;
47
48   unsigned long del_attribs, add_attribs;
49   Mt::attribs(control, fp_from, &del_attribs, &add_attribs);
50
51   return map<Obj_space>((Kobject_mapdb*)0,
52               from, from, snd_addr,
53               snd_size,
54               to, to, rcv_addr,
55               control.is_grant(), add_attribs, del_attribs,
56               reap_list);
57 }
58
59 unsigned __attribute__((nonnull(1)))
60 obj_fpage_unmap(Space * space, L4_fpage fp, L4_map_mask mask,
61                 Kobject ***reap_list)
62 {
63   assert_opt (space);
64   typedef Map_traits<Obj_space> Mt;
65   Mt::Size size = Mt::Size::from_shift(fp.order());
66   Mt::Addr addr = Mt::get_addr(fp);
67   addr = addr.trunc(size);
68
69   // XXX prevent unmaps when a task has no caps enabled
70
71   return unmap<Obj_space>((Kobject_mapdb*)0, space, space,
72                addr, size,
73                fp.rights(), mask, reap_list);
74 }
75
76
77 L4_error
78 obj_map(Space *from, unsigned long snd_addr, unsigned long snd_size,
79         Space *to, unsigned long rcv_addr,
80         Kobject ***reap_list, bool grant = false,
81         unsigned attrib_add = 0, unsigned attrib_del = 0)
82 {
83   assert_opt (from);
84   assert_opt (to);
85   typedef Map_traits<Obj_space> Mt;
86
87   return map<Obj_space>((Kobject_mapdb*)0,
88              from, from, Mt::Addr(snd_addr),
89              Mt::Size(snd_size),
90              to, to, Mt::Addr(rcv_addr),
91              grant, attrib_add, attrib_del, reap_list);
92 }
93
94 bool
95 map(Kobject_iface *o, Obj_space* to, Space *to_id, Address _rcv_addr,
96     Kobject ***reap_list, unsigned attribs = L4_fpage::CRWSD)
97 {
98   assert_opt (o);
99   assert_opt (to);
100   assert_opt (to_id);
101
102   typedef Obj_space SPACE;
103   typedef Obj_space::Addr Addr;
104   typedef Obj_space::Size Size;
105
106   Page_number const rcv_addr = Page_number::create(_rcv_addr);
107
108   if (EXPECT_FALSE(rcv_addr >= to->map_max_address()))
109     return 0;
110
111   // Receiver lookup.
112   Obj_space::Phys_addr r_phys;
113   Size r_size;
114   unsigned r_attribs;
115
116   Addr ra(rcv_addr);
117   if (to->v_lookup(ra, &r_phys, &r_size, &r_attribs))
118     unmap((Kobject_mapdb*)0, to, to_id, ra, r_size,
119           L4_fpage::RWX, L4_map_mask::full(), reap_list);
120
121   attribs &= L4_fpage::WX;
122   // Do the actual insertion.
123   Obj_space::Status status
124     = to->v_insert(o, ra, Size::create(1), attribs);
125
126   switch (status)
127     {
128     case SPACE::Insert_warn_exists:
129     case SPACE::Insert_warn_attrib_upgrade:
130     case SPACE::Insert_ok:
131
132       if (status == SPACE::Insert_ok)
133         {
134           if (! o->map_root()->insert(0, to_id, ra))
135             {
136               to->v_delete(rcv_addr, Obj_space::Size::create(1));
137               return 0;
138             }
139         }
140       break;
141
142     case SPACE::Insert_err_nomem:
143       return 0;
144
145     case SPACE::Insert_err_exists:
146       // Do not flag an error here -- because according to L4
147       // semantics, it isn't.
148       break;
149     }
150
151   return 1;
152 }