blob: 29f4a84ef54e5558a694e29c32e4c82989d45604 [file] [log] [blame]
/*
* Copyright © 2021 The Fuchsia Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
*/
#ifndef ADDRESS_SPACE_ALLOCATOR_H
#define ADDRESS_SPACE_ALLOCATOR_H
#include <assert.h>
#include <limits.h>
class AddressSpaceAllocator {
public:
// Constructs an address space ranging from address base to address base + size.
AddressSpaceAllocator(uint64_t base, size_t size) : base_(base), size_(size) {
assert(size > 0);
assert(size <= UINT64_MAX - base);
}
virtual ~AddressSpaceAllocator() = default;
uint64_t base() const { return base_; }
size_t size() const { return size_; }
// Allocates an address for a region of the given size and alignment, where alignment
// is specified by 2 << align_pow2.
// If alignment is less than a page than page alignment will be used.
// On success returns true and addr_out is set; otherwise returns false.
virtual bool Alloc(size_t size, uint8_t align_pow2, uint64_t* addr_out) = 0;
// Frees an address that was previously allocated.
virtual bool Free(uint64_t addr) = 0;
// Returns true and the size of the region if mapped; otherwise returns false.
virtual bool GetSize(uint64_t addr, size_t* size_out) = 0;
static inline uint32_t GetPageSize() { return PAGE_SIZE; }
static inline bool IsPageAligned(uint64_t val) { return (val & (GetPageSize() - 1)) == 0; }
template <class T>
static bool IsPow2(T v, T* exponent = nullptr) {
uint32_t pow = 0;
if (v == 0) {
return false;
}
for (uint32_t count = 0; v != 0; count += 1) {
if (v & 1) {
if (pow != 0) {
return false;
}
pow = count;
}
v >>= 1;
}
if (exponent != nullptr) {
*exponent = pow;
}
return true;
}
static inline uint32_t PageShift() {
uint32_t exponent = 0;
assert(IsPow2(GetPageSize(), &exponent));
return exponent;
}
// Note, alignment must be a power of 2
template <class T>
static inline T RoundUp(T val, T alignment) {
assert(IsPow2(alignment));
return ((val - 1) | (alignment - 1)) + 1;
}
private:
uint64_t base_;
size_t size_;
};
#endif // ADDRESS_SPACE_ALLOCATOR_H