core: hle: kernel: k_dynamic_page_manager: Refresh.

This commit is contained in:
bunnei 2022-10-29 14:39:44 -07:00
parent 6f941121e6
commit b7b47f3099
1 changed files with 50 additions and 17 deletions

View File

@ -3,6 +3,8 @@
#pragma once #pragma once
#include <vector>
#include "common/alignment.h" #include "common/alignment.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/kernel/k_page_bitmap.h" #include "core/hle/kernel/k_page_bitmap.h"
@ -33,28 +35,36 @@ public:
return reinterpret_cast<T*>(m_backing_memory.data() + (addr - m_address)); return reinterpret_cast<T*>(m_backing_memory.data() + (addr - m_address));
} }
Result Initialize(VAddr addr, size_t sz) { Result Initialize(VAddr memory, size_t size, size_t align) {
// We need to have positive size. // We need to have positive size.
R_UNLESS(sz > 0, ResultOutOfMemory); R_UNLESS(size > 0, ResultOutOfMemory);
m_backing_memory.resize(sz); m_backing_memory.resize(size);
// Calculate management overhead. // Set addresses.
const size_t management_size = m_address = memory;
KPageBitmap::CalculateManagementOverheadSize(sz / sizeof(PageBuffer)); m_aligned_address = Common::AlignDown(memory, align);
const size_t allocatable_size = sz - management_size;
// Calculate extents.
const size_t managed_size = m_address + size - m_aligned_address;
const size_t overhead_size = Common::AlignUp(
KPageBitmap::CalculateManagementOverheadSize(managed_size / sizeof(PageBuffer)),
sizeof(PageBuffer));
R_UNLESS(overhead_size < size, ResultOutOfMemory);
// Set tracking fields. // Set tracking fields.
m_address = addr; m_size = Common::AlignDown(size - overhead_size, sizeof(PageBuffer));
m_size = Common::AlignDown(allocatable_size, sizeof(PageBuffer)); m_count = m_size / sizeof(PageBuffer);
m_count = allocatable_size / sizeof(PageBuffer);
R_UNLESS(m_count > 0, ResultOutOfMemory);
// Clear the management region. // Clear the management region.
u64* management_ptr = GetPointer<u64>(m_address + allocatable_size); u64* management_ptr = GetPointer<u64>(m_address + size - overhead_size);
std::memset(management_ptr, 0, management_size); std::memset(management_ptr, 0, overhead_size);
// Initialize the bitmap. // Initialize the bitmap.
m_page_bitmap.Initialize(management_ptr, m_count); const size_t allocatable_region_size =
(m_address + size - overhead_size) - m_aligned_address;
ASSERT(allocatable_region_size >= sizeof(PageBuffer));
m_page_bitmap.Initialize(management_ptr, allocatable_region_size / sizeof(PageBuffer));
// Free the pages to the bitmap. // Free the pages to the bitmap.
for (size_t i = 0; i < m_count; i++) { for (size_t i = 0; i < m_count; i++) {
@ -62,7 +72,8 @@ public:
std::memset(GetPointer<PageBuffer>(m_address) + i, 0, PageSize); std::memset(GetPointer<PageBuffer>(m_address) + i, 0, PageSize);
// Set the bit for the free page. // Set the bit for the free page.
m_page_bitmap.SetBit(i); m_page_bitmap.SetBit((m_address + (i * sizeof(PageBuffer)) - m_aligned_address) /
sizeof(PageBuffer));
} }
R_SUCCEED(); R_SUCCEED();
@ -101,7 +112,28 @@ public:
m_page_bitmap.ClearBit(offset); m_page_bitmap.ClearBit(offset);
m_peak = std::max(m_peak, (++m_used)); m_peak = std::max(m_peak, (++m_used));
return GetPointer<PageBuffer>(m_address) + offset; return GetPointer<PageBuffer>(m_aligned_address) + offset;
}
PageBuffer* Allocate(size_t count) {
// Take the lock.
// TODO(bunnei): We should disable interrupts here via KScopedInterruptDisable.
KScopedSpinLock lk(m_lock);
// Find a random free block.
s64 soffset = m_page_bitmap.FindFreeRange(count);
if (soffset < 0) [[likely]] {
return nullptr;
}
const size_t offset = static_cast<size_t>(soffset);
// Update our tracking.
m_page_bitmap.ClearRange(offset, count);
m_used += count;
m_peak = std::max(m_peak, m_used);
return GetPointer<PageBuffer>(m_aligned_address) + offset;
} }
void Free(PageBuffer* pb) { void Free(PageBuffer* pb) {
@ -113,7 +145,7 @@ public:
KScopedSpinLock lk(m_lock); KScopedSpinLock lk(m_lock);
// Set the bit for the free page. // Set the bit for the free page.
size_t offset = (reinterpret_cast<uintptr_t>(pb) - m_address) / sizeof(PageBuffer); size_t offset = (reinterpret_cast<uintptr_t>(pb) - m_aligned_address) / sizeof(PageBuffer);
m_page_bitmap.SetBit(offset); m_page_bitmap.SetBit(offset);
// Decrement our used count. // Decrement our used count.
@ -127,6 +159,7 @@ private:
size_t m_peak{}; size_t m_peak{};
size_t m_count{}; size_t m_count{};
VAddr m_address{}; VAddr m_address{};
VAddr m_aligned_address{};
size_t m_size{}; size_t m_size{};
// TODO(bunnei): Back by host memory until we emulate kernel virtual address space. // TODO(bunnei): Back by host memory until we emulate kernel virtual address space.