]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/map_util-mem.cpp
32110b5d2f4344ba160a153c9b45ccc997263e25
[l4.git] / kernel / fiasco / src / kern / map_util-mem.cpp
1 INTERFACE [debug]:
2
3 #include "mapdb.h"
4 #include "types.h"
5
6 extern Static_object<Mapdb> mapdb_mem;
7
8
9 IMPLEMENTATION:
10
11 #include "config.h"
12 #include "mapdb.h"
13
14 Static_object<Mapdb> mapdb_mem;
15
16 /** Map the region described by "fp_from" of address space "from" into
17     region "fp_to" at offset "offs" of address space "to", updating the
18     mapping database as we do so.
19     @param from source address space
20     @param fp_from_{page, size, write, grant} flexpage description for
21         virtual-address space range in source address space
22     @param to destination address space
23     @param fp_to_{page, size} flexpage descripton for virtual-address
24         space range in destination address space
25     @param offs sender-specified offset into destination flexpage
26     @return IPC error code that describes the status of the operation
27  */
28 L4_error __attribute__((nonnull(1, 3)))
29 mem_map(Space *from, L4_fpage const &fp_from,
30         Space *to, L4_fpage const &fp_to, L4_msg_item control)
31 {
32   typedef Map_traits<Mem_space> Mt;
33
34   if (EXPECT_FALSE(fp_from.order() < L4_fpage::Mem_addr::Shift
35                    || fp_to.order() < L4_fpage::Mem_addr::Shift))
36     return L4_error::None;
37
38   // loop variables
39   Mt::Addr rcv_addr = fp_to.mem_address();
40   Mt::Addr snd_addr = fp_from.mem_address();
41   Mt::Addr offs = Virt_addr(control.address());
42
43   Mt::Size snd_size = Mt::Size::from_shift(fp_from.order() - L4_fpage::Mem_addr::Shift);
44   Mt::Size rcv_size = Mt::Size::from_shift(fp_to.order() - L4_fpage::Mem_addr::Shift);
45
46   // calc size in bytes from power of tows
47   snd_addr = snd_addr.trunc(snd_size);
48   rcv_addr = rcv_addr.trunc(rcv_size);
49   Mt::constraint(snd_addr, snd_size, rcv_addr, rcv_size, offs);
50
51   if (snd_size == 0)
52     return L4_error::None;
53
54   unsigned long del_attribs, add_attribs;
55   Mt::attribs(control, fp_from, &del_attribs, &add_attribs);
56
57   return map<Mem_space>(mapdb_mem.get(),
58              from, from, snd_addr,
59              snd_size, to, to,
60              rcv_addr, control.is_grant(), add_attribs, del_attribs,
61              (Mem_space::Reap_list**)0);
62 }
63
64 /** Unmap the mappings in the region described by "fp" from the address
65     space "space" and/or the address spaces the mappings have been
66     mapped into.
67     @param space address space that should be flushed
68     @param fp    flexpage descriptor of address-space range that should
69                  be flushed
70     @param me_too If false, only flush recursive mappings.  If true,
71                  additionally flush the region in the given address space.
72     @param restriction Only flush specific task ID.
73     @param flush_mode determines which access privileges to remove.
74     @return combined (bit-ORed) access status of unmapped physical pages
75 */
76 unsigned __attribute__((nonnull(1)))
77 mem_fpage_unmap(Space *space, L4_fpage fp, L4_map_mask mask)
78 {
79   typedef Map_traits<Mem_space> Mt;
80   Mt::Size size = Mt::Size::from_shift(fp.order() - L4_fpage::Mem_addr::Shift);
81   Mt::Addr start = Mt::get_addr(fp);
82
83   start = start.trunc(size);
84
85   return unmap<Mem_space>(mapdb_mem.get(), space, space,
86                start, size,
87                fp.rights(), mask, (Mem_space::Reap_list**)0);
88 }
89
90 static inline
91 void
92 save_access_attribs(Mapdb* mapdb, const Mapdb::Frame& mapdb_frame,
93                     Mapping* mapping, Mem_space* space, unsigned page_rights, 
94                     Mem_space::Addr virt, Mem_space::Phys_addr phys,
95                     Mem_space::Size size,
96                     bool me_too)
97 {
98   typedef Mem_space::Size Size;
99   typedef Mem_space::Addr Addr;
100   typedef Mem_space::Phys_addr Phys_addr;
101
102   if (unsigned page_accessed
103       = page_rights & (Mem_space::Page_referenced | Mem_space::Page_dirty))
104     {
105       Mem_space::Status status;
106
107       // When flushing access attributes from our space as well,
108       // cache them in parent space, otherwise in our space.
109       if (! me_too || !mapping->parent())
110         {
111           status = space->v_insert(phys, virt, size,
112                                    page_accessed);
113         }
114       else
115         {
116           Mapping *parent = mapping->parent();
117
118           assert (parent->space());
119           Mem_space *parent_space = parent->space();
120
121           Address parent_shift = mapdb->shift(mapdb_frame, parent) + Mem_space::Page_shift;
122           Address parent_address = parent->page().value() << parent_shift;
123
124           status =
125             parent_space->v_insert(phys.trunc(Phys_addr::create(1UL << parent_shift)),
126                                    Addr::create(parent_address),
127                                    Size::create(1UL << parent_shift),
128                                    page_accessed, true);
129         }
130
131       assert (status == Mem_space::Insert_ok
132               || status == Mem_space::Insert_warn_exists
133               || status == Mem_space::Insert_warn_attrib_upgrade
134               /*|| s->is_sigma0()*/);
135       // Be forgiving to sigma0 because it's address
136       // space is not kept in sync with its mapping-db
137       // entries.
138     }
139 }
140
141 //---------------------------------------------------------------------------
142 IMPLEMENTATION[!64bit]:
143
144 /** The mapping database.
145     This is the system's instance of the mapping database.
146  */
147 void
148 init_mapdb_mem(Space *sigma0)
149 {
150   static size_t const page_sizes[]
151     = { Config::SUPERPAGE_SHIFT - Config::PAGE_SHIFT, 0 };
152
153   mapdb_mem.construct(sigma0,
154       Page_number::create(1U << (32 - Config::SUPERPAGE_SHIFT)),
155       page_sizes, 2);
156 }
157
158 //---------------------------------------------------------------------------
159 IMPLEMENTATION[amd64]:
160
161 #include "cpu.h"
162
163 /** The mapping database.
164     This is the system's instance of the mapping database.
165  */
166 void
167 init_mapdb_mem(Space *sigma0)
168 {
169   static size_t const amd64_page_sizes[] =
170   { Config::PML4E_SHIFT - Config::PAGE_SHIFT,
171     Config::PDPE_SHIFT - Config::PAGE_SHIFT,
172     Config::SUPERPAGE_SHIFT - Config::PAGE_SHIFT,
173     0};
174
175   unsigned const num_page_sizes = Cpu::boot_cpu()->phys_bits() >= 42 ?  4 : 3;
176
177   Address const largest_page_max_index = num_page_sizes == 4 ?
178     Config::PML4E_MASK + 1ULL
179     : 1ULL << (Cpu::boot_cpu()->phys_bits() - Config::PDPE_SHIFT);
180
181   size_t const *const page_sizes = num_page_sizes == 4 ? amd64_page_sizes : amd64_page_sizes + 1;
182
183   mapdb_mem.construct(sigma0, Page_number::create(largest_page_max_index),
184       page_sizes, num_page_sizes);
185 }
186