forked from suyu/suyu
hle: kernel: k_memory_manager: Clear pages on allocation & free.
- Heap pages should be zero'd. - Also explicitly passed along heap allocation option.
This commit is contained in:
parent
4064e03568
commit
b54cbc985e
5 changed files with 34 additions and 16 deletions
|
@ -8,12 +8,16 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/device_memory.h"
|
||||||
#include "core/hle/kernel/k_memory_manager.h"
|
#include "core/hle/kernel/k_memory_manager.h"
|
||||||
#include "core/hle/kernel/k_page_linked_list.h"
|
#include "core/hle/kernel/k_page_linked_list.h"
|
||||||
#include "core/hle/kernel/svc_results.h"
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
KMemoryManager::KMemoryManager(Core::System& system_) : system{system_} {}
|
||||||
|
|
||||||
std::size_t KMemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u64 end_address) {
|
std::size_t KMemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u64 end_address) {
|
||||||
const auto size{end_address - start_address};
|
const auto size{end_address - start_address};
|
||||||
|
|
||||||
|
@ -81,7 +85,7 @@ VAddr KMemoryManager::AllocateAndOpenContinuous(std::size_t num_pages, std::size
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool,
|
ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool,
|
||||||
Direction dir) {
|
Direction dir, u32 heap_fill_value) {
|
||||||
ASSERT(page_list.GetNumPages() == 0);
|
ASSERT(page_list.GetNumPages() == 0);
|
||||||
|
|
||||||
// Early return if we're allocating no pages
|
// Early return if we're allocating no pages
|
||||||
|
@ -139,6 +143,12 @@ ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear allocated memory.
|
||||||
|
for (const auto& it : page_list.Nodes()) {
|
||||||
|
std::memset(system.DeviceMemory().GetPointer(it.GetAddress()), heap_fill_value,
|
||||||
|
it.GetSize());
|
||||||
|
}
|
||||||
|
|
||||||
// Only succeed if we allocated as many pages as we wanted
|
// Only succeed if we allocated as many pages as we wanted
|
||||||
if (num_pages) {
|
if (num_pages) {
|
||||||
return ResultOutOfMemory;
|
return ResultOutOfMemory;
|
||||||
|
@ -146,11 +156,12 @@ ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_
|
||||||
|
|
||||||
// We succeeded!
|
// We succeeded!
|
||||||
group_guard.Cancel();
|
group_guard.Cancel();
|
||||||
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode KMemoryManager::Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool,
|
ResultCode KMemoryManager::Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool,
|
||||||
Direction dir) {
|
Direction dir, u32 heap_fill_value) {
|
||||||
// Early return if we're freeing no pages
|
// Early return if we're freeing no pages
|
||||||
if (!num_pages) {
|
if (!num_pages) {
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
#include "core/hle/kernel/k_page_heap.h"
|
#include "core/hle/kernel/k_page_heap.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
class KPageLinkedList;
|
class KPageLinkedList;
|
||||||
|
@ -42,7 +46,7 @@ public:
|
||||||
Mask = (0xF << Shift),
|
Mask = (0xF << Shift),
|
||||||
};
|
};
|
||||||
|
|
||||||
KMemoryManager() = default;
|
explicit KMemoryManager(Core::System& system_);
|
||||||
|
|
||||||
constexpr std::size_t GetSize(Pool pool) const {
|
constexpr std::size_t GetSize(Pool pool) const {
|
||||||
return managers[static_cast<std::size_t>(pool)].GetSize();
|
return managers[static_cast<std::size_t>(pool)].GetSize();
|
||||||
|
@ -51,10 +55,10 @@ public:
|
||||||
void InitializeManager(Pool pool, u64 start_address, u64 end_address);
|
void InitializeManager(Pool pool, u64 start_address, u64 end_address);
|
||||||
|
|
||||||
VAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option);
|
VAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option);
|
||||||
ResultCode Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool,
|
ResultCode Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, Direction dir,
|
||||||
Direction dir = Direction::FromFront);
|
u32 heap_fill_value = 0);
|
||||||
ResultCode Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool,
|
ResultCode Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, Direction dir,
|
||||||
Direction dir = Direction::FromFront);
|
u32 heap_fill_value = 0);
|
||||||
|
|
||||||
static constexpr std::size_t MaxManagerCount = 10;
|
static constexpr std::size_t MaxManagerCount = 10;
|
||||||
|
|
||||||
|
@ -129,6 +133,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Core::System& system;
|
||||||
std::array<std::mutex, static_cast<std::size_t>(Pool::Count)> pool_locks;
|
std::array<std::mutex, static_cast<std::size_t>(Pool::Count)> pool_locks;
|
||||||
std::array<Impl, MaxManagerCount> managers;
|
std::array<Impl, MaxManagerCount> managers;
|
||||||
};
|
};
|
||||||
|
|
|
@ -289,8 +289,8 @@ ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemory
|
||||||
}
|
}
|
||||||
|
|
||||||
KPageLinkedList page_linked_list;
|
KPageLinkedList page_linked_list;
|
||||||
CASCADE_CODE(
|
CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool,
|
||||||
system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool));
|
allocation_option));
|
||||||
CASCADE_CODE(Operate(addr, num_pages, page_linked_list, OperationType::MapGroup));
|
CASCADE_CODE(Operate(addr, num_pages, page_linked_list, OperationType::MapGroup));
|
||||||
|
|
||||||
block_manager->Update(addr, num_pages, state, perm);
|
block_manager->Update(addr, num_pages, state, perm);
|
||||||
|
@ -457,8 +457,8 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
|
||||||
|
|
||||||
KPageLinkedList page_linked_list;
|
KPageLinkedList page_linked_list;
|
||||||
|
|
||||||
CASCADE_CODE(
|
CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages,
|
||||||
system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, memory_pool));
|
memory_pool, allocation_option));
|
||||||
|
|
||||||
// We succeeded, so commit the memory reservation.
|
// We succeeded, so commit the memory reservation.
|
||||||
memory_reservation.Commit();
|
memory_reservation.Commit();
|
||||||
|
@ -541,7 +541,8 @@ ResultCode KPageTable::UnmapMemory(VAddr addr, std::size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::size_t num_pages{size / PageSize};
|
const std::size_t num_pages{size / PageSize};
|
||||||
system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool);
|
system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool,
|
||||||
|
allocation_option);
|
||||||
|
|
||||||
block_manager->Update(addr, num_pages, KMemoryState::Free);
|
block_manager->Update(addr, num_pages, KMemoryState::Free);
|
||||||
|
|
||||||
|
@ -960,7 +961,7 @@ ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) {
|
||||||
// Allocate pages for the heap extension.
|
// Allocate pages for the heap extension.
|
||||||
KPageLinkedList page_linked_list;
|
KPageLinkedList page_linked_list;
|
||||||
R_TRY(system.Kernel().MemoryManager().Allocate(page_linked_list, allocation_size / PageSize,
|
R_TRY(system.Kernel().MemoryManager().Allocate(page_linked_list, allocation_size / PageSize,
|
||||||
memory_pool));
|
memory_pool, allocation_option));
|
||||||
|
|
||||||
// Map the pages.
|
// Map the pages.
|
||||||
{
|
{
|
||||||
|
@ -1027,8 +1028,8 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages,
|
||||||
CASCADE_CODE(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr));
|
CASCADE_CODE(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr));
|
||||||
} else {
|
} else {
|
||||||
KPageLinkedList page_group;
|
KPageLinkedList page_group;
|
||||||
CASCADE_CODE(
|
CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages,
|
||||||
system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages, memory_pool));
|
memory_pool, allocation_option));
|
||||||
CASCADE_CODE(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup));
|
CASCADE_CODE(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -303,6 +303,7 @@ private:
|
||||||
bool is_aslr_enabled{};
|
bool is_aslr_enabled{};
|
||||||
|
|
||||||
KMemoryManager::Pool memory_pool{KMemoryManager::Pool::Application};
|
KMemoryManager::Pool memory_pool{KMemoryManager::Pool::Application};
|
||||||
|
KMemoryManager::Direction allocation_option{KMemoryManager::Direction::FromFront};
|
||||||
|
|
||||||
Common::PageTable page_table_impl;
|
Common::PageTable page_table_impl;
|
||||||
|
|
||||||
|
|
|
@ -629,7 +629,7 @@ struct KernelCore::Impl {
|
||||||
const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents();
|
const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents();
|
||||||
|
|
||||||
// Initialize memory managers
|
// Initialize memory managers
|
||||||
memory_manager = std::make_unique<KMemoryManager>();
|
memory_manager = std::make_unique<KMemoryManager>(system);
|
||||||
memory_manager->InitializeManager(KMemoryManager::Pool::Application,
|
memory_manager->InitializeManager(KMemoryManager::Pool::Application,
|
||||||
application_pool.GetAddress(),
|
application_pool.GetAddress(),
|
||||||
application_pool.GetEndAddress());
|
application_pool.GetEndAddress());
|
||||||
|
|
Loading…
Reference in a new issue