blob: 1c5670a3fb8eceb901a882fa0e75dfc5b316edd6 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_ACPI_MEMORY_REGION_UTIL_H_
#define SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_ACPI_MEMORY_REGION_UTIL_H_
#include <lib/zircon-internal/align.h>
#include <zircon/assert.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>
#include <cstddef>
#include <limits>
#include <utility>
namespace i915 {
template <typename T>
std::pair<T, size_t> RoundToPageBoundaries(T region_start_address, size_t region_size) {
ZX_ASSERT(region_size > 0);
ZX_ASSERT(region_size < std::numeric_limits<T>::max());
ZX_ASSERT(std::numeric_limits<T>::max() - region_size >= region_start_address);
const T page_bits_mask = T{zx_system_get_page_size() - 1};
ZX_ASSERT_MSG((page_bits_mask & (page_bits_mask + 1)) == 0,
"zx_system_get_page_size() is not a power of two");
const T first_page_address = region_start_address & ~page_bits_mask;
ZX_ASSERT(first_page_address <= region_start_address);
const uint32_t page_offset = static_cast<uint32_t>(region_start_address & page_bits_mask);
ZX_ASSERT(page_offset == region_start_address - first_page_address);
const size_t page_region_size = ZX_PAGE_ALIGN(region_size + page_offset);
ZX_ASSERT(first_page_address + page_region_size >= region_start_address + region_size);
return {first_page_address, page_region_size};
}
} // namespace i915
#endif // SRC_GRAPHICS_DISPLAY_DRIVERS_INTEL_I915_ACPI_MEMORY_REGION_UTIL_H_