blob: 611d07327606c653167032ccf262366a4c1ed379 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#ifndef ZIRCON_KERNEL_PHYS_LIB_MEMALLOC_INCLUDE_LIB_MEMALLOC_RANGE_H_
#define ZIRCON_KERNEL_PHYS_LIB_MEMALLOC_INCLUDE_LIB_MEMALLOC_RANGE_H_
#include <lib/fit/function.h>
#include <lib/stdcompat/span.h>
#include <zircon/boot/image.h>
#include <algorithm>
#include <array>
#include <string_view>
namespace memalloc {
constexpr uint64_t kMinExtendedTypeValue =
static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()) + 1;
// The type of a physical memory range. Represented by 64 bits, the lower 2^32
// values in the space are reserved for memory range types defined in the ZBI
// spec, the "base types"; the types in the upper half are referred to as
// "extended types", and increment from kMinExtendedTypeValue in value.
//
// As is detailed in the ZBI spec regarding overlaps, among the base types,
// kReserved and kPeripheral ranges have the highest precedence, in that order.
// Further, by definition here, an extended type is only permitted to overlap
// with kFreeRam or the same type.
enum class Type : uint64_t {
//
// ZBI memory range types:
//
kFreeRam = ZBI_MEM_RANGE_RAM,
kPeripheral = ZBI_MEM_RANGE_PERIPHERAL,
kReserved = ZBI_MEM_RANGE_RESERVED,
//
// Extended types:
//
// Reserved for internal bookkeeping.
kPoolBookkeeping = kMinExtendedTypeValue,
// The phys kernel memory image.
kPhysKernel,
// The kernel memory image.
kKernel,
// The kernel memory image at a fixed address of 1MiB.
kFixedAddressKernel,
// A (decompressed) STORAGE_KERNEL ZBI payload.
kKernelStorage,
// The data ZBI, as placed by the bootloader.
kDataZbi,
// Data structures related to legacy boot protocols.
kLegacyBootData,
// Identity-mapping page tables.
kIdentityPageTables,
// General scratch space used by the phys kernel, but that which is free for
// the next kernel as of hand-off.
kPhysScratch,
// A generic allocated type for Pool tests.
kPoolTestPayload,
// A generic allocated type for ZBI tests.
kZbiTestPayload,
// Memory carved out for the kernel.test.ram.reserve boot option.
kTestRamReserve,
// Memory carved out for the ZBI_TYPE_NVRAM region.
kNvram,
// A placeholder value signifying the last extended type. It must not be used
// as an actual type value.
kMaxExtended,
};
static_assert(static_cast<uint64_t>(Type::kFreeRam) < kMinExtendedTypeValue);
static_assert(static_cast<uint64_t>(Type::kPeripheral) < kMinExtendedTypeValue);
static_assert(static_cast<uint64_t>(Type::kReserved) < kMinExtendedTypeValue);
constexpr uint64_t kMaxExtendedTypeValue = static_cast<uint64_t>(Type::kMaxExtended);
constexpr size_t kNumExtendedTypes = kMaxExtendedTypeValue - kMinExtendedTypeValue;
constexpr size_t kNumBaseTypes = 3;
std::string_view ToString(Type type);
constexpr bool IsExtendedType(Type type) {
return static_cast<uint64_t>(type) >= kMinExtendedTypeValue;
}
// A memory range type that is layout-compatible to zbi_mem_range_t, but with
// the benefit of being able to use extended types.
struct Range {
uint64_t addr;
uint64_t size;
Type type;
// The end of the memory range. This method may only be called if addr + size
// has been normalized to not overflow.
constexpr uint64_t end() const { return addr + size; }
constexpr bool operator==(const Range& other) const {
return addr == other.addr && size == other.size && type == other.type;
}
constexpr bool operator!=(const Range& other) const { return !(*this == other); }
// Gives a lexicographic order on Range.
constexpr bool operator<(const Range& other) const {
return addr < other.addr || (addr == other.addr && size < other.size);
}
};
// We have constrained Type so that the ZBI memory type's value space
// identically embeds into the lower 2^32 values of Type; the upper 2^32 values
// is reserved for Type's extensions. Accordingly, in order to coherently
// recast a zbi_mem_range_t as a Range, the former's `reserved` field -
// which, layout-wise, corresponds to the upper half of Type - must be zeroed
// out.
cpp20::span<Range> AsRanges(cpp20::span<zbi_mem_range_t> ranges);
namespace internal {
// Effectively just a span and an iterator. This is used internally to iterate
// over a variable number of range arrays.
struct RangeIterationContext {
RangeIterationContext() = default;
// Lexicographically sorts the ranges on construction.
explicit RangeIterationContext(cpp20::span<Range> ranges) : ranges_(ranges), it_(ranges.begin()) {
std::sort(ranges_.begin(), ranges_.end());
}
cpp20::span<Range> ranges_;
typename cpp20::span<Range>::iterator it_;
};
} // namespace internal
} // namespace memalloc
#endif // ZIRCON_KERNEL_PHYS_LIB_MEMALLOC_INCLUDE_LIB_MEMALLOC_RANGE_H_