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