1- // -*- C++ -*-
2- // This file is a part of the IncludeOS unikernel - www.includeos.org
3- //
4- // Copyright 2017 Oslo and Akershus University College of Applied Sciences
5- // and Alfred Bratterud
6- //
7- // Licensed under the Apache License, Version 2.0 (the "License");
8- // you may not use this file except in compliance with the License.
9- // You may obtain a copy of the License at
10- //
11- // http://www.apache.org/licenses/LICENSE-2.0
12- //
13- // Unless required by applicable law or agreed to in writing, software
14- // distributed under the License is distributed on an "AS IS" BASIS,
15- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16- // See the License for the specific language governing permissions and
17- // limitations under the License.
18-
19- #ifndef MEM_MEMORY_HPP
20- #define MEM_MEMORY_HPP
1+ #ifndef MEM_VMAP_HPP
2+ #define MEM_VMAP_HPP
213
224#include < util/bitops.hpp>
235#include < util/units.hpp>
24- #include < mem/alloc/buddy.hpp>
25- #include < mem/allocator.hpp>
266#include < mem/flags.hpp>
27- #include < sstream>
28- #include < expects>
297#include < mem/memmap.hpp>
8+ #include < expects>
9+ #include < algorithm>
10+ #include < cstdio>
11+ #include < stdexcept>
12+ #include < string>
3013
3114namespace os ::mem {
3215
33- using Raw_allocator = buddy::Alloc<false >;
34-
35- /* * Get default allocator for untyped allocations */
36- Raw_allocator& raw_allocator ();
37-
38- template <typename T>
39- using Typed_allocator = Allocator<T, Raw_allocator>;
40-
41- /* * Get default std::allocator for typed allocations */
42- template <typename T>
43- Typed_allocator<T> system_allocator () { return Typed_allocator<T>(raw_allocator ()); }
44-
4516 /* * Get bitfield with bit set for each supported page size */
4617 uintptr_t supported_page_sizes ();
4718
@@ -62,15 +33,14 @@ namespace os::mem {
6233 * For interfacing with the virtual memory API, e.g. mem::map / mem::protect.
6334 **/
6435 template <typename Fl = Access>
65- struct Mapping
66- {
36+ struct Mapping {
6737 static const size_t any_size;
6838
6939 uintptr_t lin = 0 ;
7040 uintptr_t phys = 0 ;
71- Fl flags {};
72- size_t size = 0 ;
73- size_t page_sizes = 0 ;
41+ Fl flags {};
42+ size_t size = 0 ;
43+ size_t page_sizes = 0 ;
7444
7545 // Constructors
7646 Mapping () = default ;
@@ -94,15 +64,13 @@ namespace os::mem {
9464 inline size_t max_psize () const noexcept ;
9565
9666 std::string to_string () const ;
97-
98- }; // struct Mapping<>
67+ };
9968
10069 using Map = Mapping<>;
10170
10271 /* * Exception class possibly used by various ::mem functions. **/
10372 class Memory_exception : public std ::runtime_error
104- { using runtime_error::runtime_error; };
105-
73+ { using std::runtime_error::runtime_error; };
10674
10775 /* *
10876 * Map linear address to physical memory, according to provided Mapping.
@@ -123,7 +91,9 @@ namespace os::mem {
12391
12492 /* * Determine active page size of a given linear address **/
12593 uintptr_t active_page_size (uintptr_t addr);
126- uintptr_t active_page_size (void * addr);
94+ inline uintptr_t active_page_size (void * addr) {
95+ return active_page_size ((uintptr_t ) addr);
96+ }
12797
12898 /* *
12999 * Set and return access flags for a given linear address range.
@@ -150,81 +120,70 @@ namespace os::mem {
150120 **/
151121 Access protect_page (uintptr_t linear, Access flags = Access::read);
152122
153-
154123 /* * Get the physical address to which linear address is mapped **/
155124 uintptr_t virt_to_phys (uintptr_t linear);
156125
157- void virtual_move (uintptr_t src, size_t size, uintptr_t dst, const char * label);
126+ inline void virtual_move (uintptr_t src, size_t size, uintptr_t dst, const char * label)
127+ {
128+ using namespace util ::bitops;
129+ const auto flags = os::mem::Access::read | os::mem::Access::write;
130+ // setup @dst as new virt area for @src
131+ os::mem::map ({dst, src, flags, size}, label);
132+ // unpresent @src
133+ os::mem::protect (src, size, os::mem::Access::none);
134+ }
158135
159136 /* * Virtual memory map **/
160137 inline Memory_map& vmmap () {
161138 // TODO Move to machine
162139 static Memory_map memmap;
163140 return memmap;
164- };
165-
166- bool heap_ready ();
167-
168- } // os::mem
169-
170-
171-
172-
141+ }
173142
174143
175- namespace os ::mem {
176144
177145 //
178- // mem:: Mapping implementation
146+ // Mapping implementation
179147 //
180-
181148 template <typename Fl>
182- Mapping<Fl>::Mapping(uintptr_t linear, uintptr_t physical, Fl fl, size_t sz)
183- : lin{linear}, phys{physical}, flags{fl}, size{sz},
184- page_sizes{any_size} {}
149+ inline Mapping<Fl>::Mapping(uintptr_t linear, uintptr_t physical, Fl fl, size_t sz)
150+ : lin{linear}, phys{physical}, flags{fl}, size{sz}, page_sizes{any_size} {}
185151
186152 template <typename Fl>
187- Mapping<Fl>::Mapping(uintptr_t linear, uintptr_t physical, Fl fl, size_t sz, size_t psz)
188- : lin{linear}, phys{physical}, flags{fl}, size{sz}, page_sizes{psz}
189- {}
153+ inline Mapping<Fl>::Mapping(uintptr_t linear, uintptr_t physical, Fl fl, size_t sz, size_t psz)
154+ : lin{linear}, phys{physical}, flags{fl}, size{sz}, page_sizes{psz} {}
190155
191156 template <typename Fl>
192- bool Mapping<Fl>::operator ==(const Mapping& rhs) const noexcept
193- { return lin == rhs.lin
194- && phys == rhs.phys
195- && flags == rhs.flags
196- && size == rhs.size
197- && page_sizes == rhs.page_sizes ; }
157+ inline bool Mapping<Fl>::operator ==(const Mapping& rhs) const noexcept {
158+ return lin == rhs.lin
159+ && phys == rhs.phys
160+ && flags == rhs.flags
161+ && size == rhs.size
162+ && page_sizes == rhs.page_sizes ;
163+ }
198164
199165 template <typename Fl>
200- Mapping<Fl>::operator bool () const noexcept
201- { return size != 0 && page_sizes !=0 ; }
166+ inline Mapping<Fl>::operator bool () const noexcept {
167+ return size != 0 && page_sizes != 0 ;
168+ }
202169
203170 template <typename Fl>
204- bool Mapping<Fl>::operator !=(const Mapping& rhs) const noexcept
205- { return ! (*this == rhs); }
171+ inline bool Mapping<Fl>::operator !=(const Mapping& rhs) const noexcept {
172+ return !(*this == rhs);
173+ }
206174
207175 template <typename Fl>
208- Mapping<Fl> Mapping<Fl>::operator +(const Mapping& rhs) noexcept
209- {
176+ inline Mapping<Fl> Mapping<Fl>::operator +(const Mapping& rhs) noexcept {
210177 using namespace util ::bitops;
211178 Mapping res;
212179
213180 // Adding with empty map behaves like 0 + x / x + 0.
214- if (! rhs) {
215- return *this ;
216- }
217-
218- if (! *this )
219- return rhs;
220-
221- if (res == rhs)
222- return res;
181+ if (not rhs) return *this ;
182+ if (not *this ) return rhs;
183+ if (res == rhs) return res;
223184
224185 // The mappings must have connecting ranges
225- if ((rhs.lin + rhs.size != lin)
226- and lin + size != rhs.lin )
227- {
186+ if ((rhs.lin + rhs.size != lin) and (lin + size != rhs.lin )) {
228187 Ensures (!res);
229188 return res;
230189 }
@@ -235,37 +194,35 @@ namespace os::mem {
235194
236195 // The mappings can span several page sizes
237196 res.page_sizes |= rhs.page_sizes ;
238- if (page_sizes && page_sizes != rhs.page_sizes )
239- {
197+ if (page_sizes && page_sizes != rhs.page_sizes ) {
240198 res.page_sizes |= page_sizes;
241199 }
242200
243- res.size = size + rhs.size ;
201+ res.size = size + rhs.size ;
244202 res.flags = flags & rhs.flags ;
245203
246- if (rhs)
247- Ensures (res);
248-
204+ if (rhs) Ensures (res);
249205 return res;
250206 }
251207
252208 template <typename Fl>
253- Mapping<Fl> Mapping<Fl>::operator +=(const Mapping& rhs) noexcept {
209+ inline Mapping<Fl> Mapping<Fl>::operator +=(const Mapping& rhs) noexcept {
254210 *this = *this + rhs;
255211 return *this ;
256212 }
257213
258214 template <typename Fl>
259- size_t Mapping<Fl>::min_psize() const noexcept
260- { return util::bits::keepfirst (page_sizes); }
215+ inline size_t Mapping<Fl>::min_psize() const noexcept {
216+ return util::bits::keepfirst (page_sizes);
217+ }
261218
262219 template <typename Fl>
263- size_t Mapping<Fl>::max_psize() const noexcept
264- { return util::bits::keeplast (page_sizes); }
220+ inline size_t Mapping<Fl>::max_psize() const noexcept {
221+ return util::bits::keeplast (page_sizes);
222+ }
265223
266224 template <typename Fl>
267- inline std::string Mapping<Fl>::to_string() const
268- {
225+ inline std::string Mapping<Fl>::to_string() const {
269226 using namespace util ::literals;
270227 char buffer[1024 ];
271228 int len = snprintf (buffer, sizeof (buffer),
@@ -281,47 +238,35 @@ namespace os::mem {
281238 " (%lu pages á %s)" ,
282239 size / page_sizes,
283240 util::Byte_r (page_sizes).to_string ().c_str ());
284- }
285- else {
241+ } else {
286242 len += snprintf (buffer + len, sizeof (buffer) - len,
287243 " (page sizes: %s)" , page_sizes_str (page_sizes).c_str ());
288244 }
289-
290245 return std::string (buffer, len);
291246 }
292247
293- inline std::string page_sizes_str (size_t bits)
294- {
248+ inline std::string page_sizes_str (size_t bits) {
295249 using namespace util ::literals;
296250 if (bits == 0 ) return " None" ;
297251
298252 std::string out;
299- while (bits){
300- auto ps = 1 << (__builtin_ffsl (bits) - 1 );
301- bits &= ~ps;
302- out += util::Byte_r (ps).to_string ();
303- if (bits)
304- out += " , " ;
305- }
253+ while (bits) {
254+ // index of lowest set bit (well-defined because bits != 0 here)
255+ const unsigned tz = std::countr_zero (bits);
306256
307- return out;
308- }
257+ // convert that bit to the corresponding power-of-two size
258+ const std:: size_t ps = 1 << tz;
309259
310- inline uintptr_t active_page_size (void * addr) {
311- return active_page_size ((uintptr_t ) addr);
312- }
260+ // and remove that bit from the input
261+ bits &= ~ps;
313262
314- inline void
315- virtual_move (uintptr_t src, size_t size, uintptr_t dst, const char * label)
316- {
317- using namespace util ::bitops;
318- const auto flags = os::mem::Access::read | os::mem::Access::write;
319- // setup @dst as new virt area for @src
320- os::mem::map ({dst, src, flags, size}, label);
321- // unpresent @src
322- os::mem::protect (src, size, os::mem::Access::none);
263+ // append formatted size; add a comma if there are more bits left
264+ std::format_to (std::back_inserter (out), " {}" , util::Byte_r (ps).to_string ());
265+ if (bits) out += " , " ;
266+ }
267+ return out;
323268 }
324- }
325269
270+ } // namespace os::mem
326271
327- #endif // MEM_MEMORY_HPP
272+ #endif // MEM_VMAP_HPP
0 commit comments