mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
kern: implement K(Secure)SystemResource
This commit is contained in:
parent
752704a798
commit
2e73f33eb0
20 changed files with 413 additions and 200 deletions
|
@ -178,7 +178,7 @@ namespace ams::kern::arch::arm64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
NOINLINE Result InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end);
|
NOINLINE Result InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end);
|
||||||
NOINLINE Result InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager, KResourceLimit *resource_limit);
|
NOINLINE Result InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit);
|
||||||
Result Finalize();
|
Result Finalize();
|
||||||
private:
|
private:
|
||||||
Result MapL1Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
|
Result MapL1Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
|
||||||
|
|
|
@ -28,8 +28,8 @@ namespace ams::kern::arch::arm64 {
|
||||||
m_page_table.Activate(id);
|
m_page_table.Activate(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Initialize(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager, KResourceLimit *resource_limit) {
|
Result Initialize(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) {
|
||||||
R_RETURN(m_page_table.InitializeForProcess(id, as_type, enable_aslr, enable_das_merge, from_back, pool, code_address, code_size, mem_block_slab_manager, block_info_manager, pt_manager, resource_limit));
|
R_RETURN(m_page_table.InitializeForProcess(id, as_type, enable_aslr, enable_das_merge, from_back, pool, code_address, code_size, system_resource, resource_limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Finalize() { m_page_table.Finalize(); }
|
void Finalize() { m_page_table.Finalize(); }
|
||||||
|
|
|
@ -21,6 +21,8 @@ namespace ams::kern {
|
||||||
|
|
||||||
class KAutoObject;
|
class KAutoObject;
|
||||||
|
|
||||||
|
class KSystemResource;
|
||||||
|
|
||||||
#define FOR_EACH_K_CLASS_TOKEN_OBJECT_TYPE(HANDLER) \
|
#define FOR_EACH_K_CLASS_TOKEN_OBJECT_TYPE(HANDLER) \
|
||||||
HANDLER(KAutoObject) \
|
HANDLER(KAutoObject) \
|
||||||
\
|
\
|
||||||
|
@ -48,7 +50,8 @@ namespace ams::kern {
|
||||||
HANDLER(KSessionRequest) \
|
HANDLER(KSessionRequest) \
|
||||||
HANDLER(KCodeMemory) \
|
HANDLER(KCodeMemory) \
|
||||||
HANDLER(KIoPool) \
|
HANDLER(KIoPool) \
|
||||||
HANDLER(KIoRegion)
|
HANDLER(KIoRegion) \
|
||||||
|
HANDLER(KSystemResource)
|
||||||
|
|
||||||
class KClassTokenGenerator {
|
class KClassTokenGenerator {
|
||||||
public:
|
public:
|
||||||
|
@ -95,7 +98,7 @@ namespace ams::kern {
|
||||||
if constexpr (std::is_same<T, KAutoObject>::value) {
|
if constexpr (std::is_same<T, KAutoObject>::value) {
|
||||||
static_assert(T::ObjectType == ObjectType::KAutoObject);
|
static_assert(T::ObjectType == ObjectType::KAutoObject);
|
||||||
return 0;
|
return 0;
|
||||||
} else if constexpr (!std::is_final<T>::value) {
|
} else if constexpr (!std::is_final<T>::value && !std::same_as<T, KSystemResource>) {
|
||||||
static_assert(ObjectType::BaseClassesStart <= T::ObjectType && T::ObjectType < ObjectType::BaseClassesEnd);
|
static_assert(ObjectType::BaseClassesStart <= T::ObjectType && T::ObjectType < ObjectType::BaseClassesEnd);
|
||||||
constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) - static_cast<TokenBaseType>(ObjectType::BaseClassesStart);
|
constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) - static_cast<TokenBaseType>(ObjectType::BaseClassesStart);
|
||||||
return BaseClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>();
|
return BaseClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>();
|
||||||
|
@ -142,6 +145,12 @@ namespace ams::kern {
|
||||||
KIoPool,
|
KIoPool,
|
||||||
KIoRegion,
|
KIoRegion,
|
||||||
|
|
||||||
|
/* NOTE: What occupies these gaps? They can be inferred, but they don't make sense. */
|
||||||
|
KAlpha,
|
||||||
|
KBeta,
|
||||||
|
|
||||||
|
KSystemResource,
|
||||||
|
|
||||||
FinalClassesLast,
|
FinalClassesLast,
|
||||||
|
|
||||||
FinalClassesEnd = FinalClassesStart + NumFinalClasses,
|
FinalClassesEnd = FinalClassesStart + NumFinalClasses,
|
||||||
|
@ -178,8 +187,10 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto fin = util::ToUnderlying(KClassTokenGenerator::ObjectType::FinalClassesStart); fin < util::ToUnderlying(KClassTokenGenerator::ObjectType::FinalClassesLast); ++fin) {
|
for (auto fin = util::ToUnderlying(KClassTokenGenerator::ObjectType::FinalClassesStart); fin < util::ToUnderlying(KClassTokenGenerator::ObjectType::FinalClassesLast); ++fin) {
|
||||||
if (!IsObjectTypeIncludedByMacro(static_cast<KClassTokenGenerator::ObjectType>(fin))) {
|
if (const auto o = static_cast<KClassTokenGenerator::ObjectType>(fin); !IsObjectTypeIncludedByMacro(o)) {
|
||||||
return false;
|
if (o != KClassTokenGenerator::ObjectType::KAlpha && o != KClassTokenGenerator::ObjectType::KBeta) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ namespace ams::kern {
|
||||||
static_assert(sizeof(KPageProperties) == sizeof(u32));
|
static_assert(sizeof(KPageProperties) == sizeof(u32));
|
||||||
|
|
||||||
class KResourceLimit;
|
class KResourceLimit;
|
||||||
|
class KSystemResource;
|
||||||
|
|
||||||
class KPageTableBase {
|
class KPageTableBase {
|
||||||
NON_COPYABLE(KPageTableBase);
|
NON_COPYABLE(KPageTableBase);
|
||||||
|
@ -200,7 +201,7 @@ namespace ams::kern {
|
||||||
explicit KPageTableBase() { /* ... */ }
|
explicit KPageTableBase() { /* ... */ }
|
||||||
|
|
||||||
NOINLINE Result InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end);
|
NOINLINE Result InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end);
|
||||||
NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_device_address_space_merge, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KResourceLimit *resource_limit);
|
NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_device_address_space_merge, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit);
|
||||||
|
|
||||||
void Finalize();
|
void Finalize();
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <mesosphere/kern_k_wait_object.hpp>
|
#include <mesosphere/kern_k_wait_object.hpp>
|
||||||
#include <mesosphere/kern_k_dynamic_resource_manager.hpp>
|
#include <mesosphere/kern_k_dynamic_resource_manager.hpp>
|
||||||
#include <mesosphere/kern_k_page_table_manager.hpp>
|
#include <mesosphere/kern_k_page_table_manager.hpp>
|
||||||
|
#include <mesosphere/kern_k_system_resource.hpp>
|
||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
|
@ -64,8 +65,7 @@ namespace ams::kern {
|
||||||
s32 m_ideal_core_id;
|
s32 m_ideal_core_id;
|
||||||
void *m_attached_object;
|
void *m_attached_object;
|
||||||
KResourceLimit *m_resource_limit;
|
KResourceLimit *m_resource_limit;
|
||||||
KVirtualAddress m_system_resource_address;
|
KSystemResource *m_system_resource;
|
||||||
size_t m_system_resource_num_pages;
|
|
||||||
size_t m_memory_release_hint;
|
size_t m_memory_release_hint;
|
||||||
State m_state;
|
State m_state;
|
||||||
KLightLock m_state_lock;
|
KLightLock m_state_lock;
|
||||||
|
@ -117,13 +117,6 @@ namespace ams::kern {
|
||||||
util::Atomic<s64> m_num_ipc_messages;
|
util::Atomic<s64> m_num_ipc_messages;
|
||||||
util::Atomic<s64> m_num_ipc_replies;
|
util::Atomic<s64> m_num_ipc_replies;
|
||||||
util::Atomic<s64> m_num_ipc_receives;
|
util::Atomic<s64> m_num_ipc_receives;
|
||||||
KDynamicPageManager m_dynamic_page_manager;
|
|
||||||
KMemoryBlockSlabManager m_memory_block_slab_manager;
|
|
||||||
KBlockInfoManager m_block_info_manager;
|
|
||||||
KPageTableManager m_page_table_manager;
|
|
||||||
KMemoryBlockSlabHeap m_memory_block_heap;
|
|
||||||
KBlockInfoSlabHeap m_block_info_heap;
|
|
||||||
KPageTableSlabHeap m_page_table_heap;
|
|
||||||
private:
|
private:
|
||||||
Result Initialize(const ams::svc::CreateProcessParameter ¶ms);
|
Result Initialize(const ams::svc::CreateProcessParameter ¶ms);
|
||||||
|
|
||||||
|
@ -284,12 +277,12 @@ namespace ams::kern {
|
||||||
void IncrementRunningThreadCount();
|
void IncrementRunningThreadCount();
|
||||||
void DecrementRunningThreadCount();
|
void DecrementRunningThreadCount();
|
||||||
|
|
||||||
size_t GetTotalSystemResourceSize() const { return m_system_resource_num_pages * PageSize; }
|
size_t GetTotalSystemResourceSize() const {
|
||||||
|
return m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->GetSize() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t GetUsedSystemResourceSize() const {
|
size_t GetUsedSystemResourceSize() const {
|
||||||
if (m_system_resource_num_pages == 0) {
|
return m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->GetUsedSize() : 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return m_dynamic_page_manager.GetUsed() * PageSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRunningThread(s32 core, KThread *thread, u64 idle_count) {
|
void SetRunningThread(s32 core, KThread *thread, u64 idle_count) {
|
||||||
|
@ -305,10 +298,11 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const KDynamicPageManager &GetDynamicPageManager() const { return m_dynamic_page_manager; }
|
const KSystemResource &GetSystemResource() const { return *m_system_resource; }
|
||||||
const KMemoryBlockSlabManager &GetMemoryBlockSlabManager() const { return m_memory_block_slab_manager; }
|
|
||||||
const KBlockInfoManager &GetBlockInfoManager() const { return m_block_info_manager; }
|
const KMemoryBlockSlabManager &GetMemoryBlockSlabManager() const { return m_system_resource->GetMemoryBlockSlabManager(); }
|
||||||
const KPageTableManager &GetPageTableManager() const { return m_page_table_manager; }
|
const KBlockInfoManager &GetBlockInfoManager() const { return m_system_resource->GetBlockInfoManager(); }
|
||||||
|
const KPageTableManager &GetPageTableManager() const { return m_system_resource->GetPageTableManager(); }
|
||||||
|
|
||||||
constexpr KThread *GetRunningThread(s32 core) const { return m_running_threads[core]; }
|
constexpr KThread *GetRunningThread(s32 core) const { return m_running_threads[core]; }
|
||||||
constexpr u64 GetRunningThreadIdleCount(s32 core) const { return m_running_thread_idle_counts[core]; }
|
constexpr u64 GetRunningThreadIdleCount(s32 core) const { return m_running_thread_idle_counts[core]; }
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace ams::kern {
|
||||||
bool m_is_initialized;
|
bool m_is_initialized;
|
||||||
public:
|
public:
|
||||||
explicit KSharedMemory()
|
explicit KSharedMemory()
|
||||||
: m_page_group(std::addressof(Kernel::GetSystemBlockInfoManager())), m_resource_limit(nullptr), m_owner_process_id(std::numeric_limits<u64>::max()),
|
: m_page_group(Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer()), m_resource_limit(nullptr), m_owner_process_id(std::numeric_limits<u64>::max()),
|
||||||
m_owner_perm(ams::svc::MemoryPermission_None), m_remote_perm(ams::svc::MemoryPermission_None), m_is_initialized(false)
|
m_owner_perm(ams::svc::MemoryPermission_None), m_remote_perm(ams::svc::MemoryPermission_None), m_is_initialized(false)
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <mesosphere/kern_common.hpp>
|
||||||
|
#include <mesosphere/kern_k_auto_object.hpp>
|
||||||
|
#include <mesosphere/kern_slab_helpers.hpp>
|
||||||
|
#include <mesosphere/kern_k_memory_manager.hpp>
|
||||||
|
#include <mesosphere/kern_k_dynamic_resource_manager.hpp>
|
||||||
|
#include <mesosphere/kern_k_page_table_manager.hpp>
|
||||||
|
#include <mesosphere/kern_k_resource_limit.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
/* NOTE: Nintendo's implementation does not have the "is_secure_resource" field, and instead uses virtual IsSecureResource(). */
|
||||||
|
|
||||||
|
class KSystemResource : public KAutoObject {
|
||||||
|
MESOSPHERE_AUTOOBJECT_TRAITS(KSystemResource, KAutoObject);
|
||||||
|
private:
|
||||||
|
KMemoryBlockSlabManager *m_p_memory_block_slab_manager{};
|
||||||
|
KBlockInfoManager *m_p_block_info_manager{};
|
||||||
|
KPageTableManager *m_p_page_table_manager{};
|
||||||
|
bool m_is_secure_resource{false};
|
||||||
|
public:
|
||||||
|
explicit KSystemResource() : KAutoObject() { /* ... */ }
|
||||||
|
|
||||||
|
constexpr explicit KSystemResource(util::ConstantInitializeTag) : KAutoObject(util::ConstantInitialize) { /* ... */ }
|
||||||
|
protected:
|
||||||
|
ALWAYS_INLINE void SetSecureResource() { m_is_secure_resource = true; }
|
||||||
|
public:
|
||||||
|
virtual void Destroy() override { MESOSPHERE_PANIC("KSystemResource::Destroy() was called"); }
|
||||||
|
|
||||||
|
ALWAYS_INLINE bool IsSecureResource() const { return m_is_secure_resource; }
|
||||||
|
|
||||||
|
void SetManagers(KMemoryBlockSlabManager &mb, KBlockInfoManager &bi, KPageTableManager &pt) {
|
||||||
|
MESOSPHERE_ASSERT(m_p_memory_block_slab_manager == nullptr);
|
||||||
|
MESOSPHERE_ASSERT(m_p_block_info_manager == nullptr);
|
||||||
|
MESOSPHERE_ASSERT(m_p_page_table_manager == nullptr);
|
||||||
|
|
||||||
|
m_p_memory_block_slab_manager = std::addressof(mb);
|
||||||
|
m_p_block_info_manager = std::addressof(bi);
|
||||||
|
m_p_page_table_manager = std::addressof(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
const KMemoryBlockSlabManager &GetMemoryBlockSlabManager() const { return *m_p_memory_block_slab_manager; }
|
||||||
|
const KBlockInfoManager &GetBlockInfoManager() const { return *m_p_block_info_manager; }
|
||||||
|
const KPageTableManager &GetPageTableManager() const { return *m_p_page_table_manager; }
|
||||||
|
|
||||||
|
KMemoryBlockSlabManager &GetMemoryBlockSlabManager() { return *m_p_memory_block_slab_manager; }
|
||||||
|
KBlockInfoManager &GetBlockInfoManager() { return *m_p_block_info_manager; }
|
||||||
|
KPageTableManager &GetPageTableManager() { return *m_p_page_table_manager; }
|
||||||
|
|
||||||
|
KMemoryBlockSlabManager *GetMemoryBlockSlabManagerPointer() { return m_p_memory_block_slab_manager; }
|
||||||
|
KBlockInfoManager *GetBlockInfoManagerPointer() { return m_p_block_info_manager; }
|
||||||
|
KPageTableManager *GetPageTableManagerPointer() { return m_p_page_table_manager; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class KSecureSystemResource final : public KAutoObjectWithSlabHeap<KSecureSystemResource, KSystemResource> {
|
||||||
|
private:
|
||||||
|
bool m_is_initialized;
|
||||||
|
KMemoryManager::Pool m_resource_pool;
|
||||||
|
KDynamicPageManager m_dynamic_page_manager;
|
||||||
|
KMemoryBlockSlabManager m_memory_block_slab_manager;
|
||||||
|
KBlockInfoManager m_block_info_manager;
|
||||||
|
KPageTableManager m_page_table_manager;
|
||||||
|
KMemoryBlockSlabHeap m_memory_block_heap;
|
||||||
|
KBlockInfoSlabHeap m_block_info_heap;
|
||||||
|
KPageTableSlabHeap m_page_table_heap;
|
||||||
|
KResourceLimit *m_resource_limit;
|
||||||
|
KVirtualAddress m_resource_address;
|
||||||
|
size_t m_resource_size;
|
||||||
|
public:
|
||||||
|
explicit KSecureSystemResource() : m_is_initialized(false), m_resource_limit(nullptr) {
|
||||||
|
/* Mark ourselves as being a secure resource. */
|
||||||
|
this->SetSecureResource();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Initialize(size_t size, KResourceLimit *resource_limit, KMemoryManager::Pool pool);
|
||||||
|
void Finalize();
|
||||||
|
|
||||||
|
bool IsInitialized() const { return m_is_initialized; }
|
||||||
|
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
|
||||||
|
|
||||||
|
ALWAYS_INLINE size_t CalculateRequiredSecureMemorySize() const {
|
||||||
|
return CalculateRequiredSecureMemorySize(m_resource_size, m_resource_pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE size_t GetSize() const { return m_resource_size; }
|
||||||
|
ALWAYS_INLINE size_t GetUsedSize() const { return m_dynamic_page_manager.GetUsed() * PageSize; }
|
||||||
|
|
||||||
|
const KDynamicPageManager &GetDynamicPageManager() const { return m_dynamic_page_manager; }
|
||||||
|
public:
|
||||||
|
static size_t CalculateRequiredSecureMemorySize(size_t size, KMemoryManager::Pool pool);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -78,6 +78,8 @@ namespace ams::kern {
|
||||||
static KMemoryBlockSlabManager s_sys_memory_block_manager;
|
static KMemoryBlockSlabManager s_sys_memory_block_manager;
|
||||||
static KBlockInfoManager s_app_block_info_manager;
|
static KBlockInfoManager s_app_block_info_manager;
|
||||||
static KBlockInfoManager s_sys_block_info_manager;
|
static KBlockInfoManager s_sys_block_info_manager;
|
||||||
|
static KSystemResource s_app_system_resource;
|
||||||
|
static KSystemResource s_sys_system_resource;
|
||||||
static KSupervisorPageTable s_supervisor_page_table;
|
static KSupervisorPageTable s_supervisor_page_table;
|
||||||
static KUnsafeMemory s_unsafe_memory;
|
static KUnsafeMemory s_unsafe_memory;
|
||||||
static KWorkerTaskManager s_worker_task_managers[KWorkerTaskManager::WorkerType_Count];
|
static KWorkerTaskManager s_worker_task_managers[KWorkerTaskManager::WorkerType_Count];
|
||||||
|
@ -129,28 +131,12 @@ namespace ams::kern {
|
||||||
return s_memory_manager;
|
return s_memory_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE KMemoryBlockSlabManager &GetApplicationMemoryBlockManager() {
|
static ALWAYS_INLINE KSystemResource &GetApplicationSystemResource() {
|
||||||
return s_app_memory_block_manager;
|
return s_app_system_resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE KMemoryBlockSlabManager &GetSystemMemoryBlockManager() {
|
static ALWAYS_INLINE KSystemResource &GetSystemSystemResource() {
|
||||||
return s_sys_memory_block_manager;
|
return s_sys_system_resource;
|
||||||
}
|
|
||||||
|
|
||||||
static ALWAYS_INLINE KBlockInfoManager &GetApplicationBlockInfoManager() {
|
|
||||||
return s_app_block_info_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ALWAYS_INLINE KBlockInfoManager &GetSystemBlockInfoManager() {
|
|
||||||
return s_sys_block_info_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ALWAYS_INLINE KPageTableManager &GetApplicationPageTableManager() {
|
|
||||||
return s_app_page_table_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ALWAYS_INLINE KPageTableManager &GetSystemPageTableManager() {
|
|
||||||
return s_sys_page_table_manager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE KSupervisorPageTable &GetKernelPageTable() {
|
static ALWAYS_INLINE KSupervisorPageTable &GetKernelPageTable() {
|
||||||
|
|
|
@ -64,11 +64,13 @@ namespace ams::kern {
|
||||||
static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); }
|
static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Derived, typename Base, bool SupportDynamicExpansion = false> requires std::derived_from<Base, KAutoObjectWithList>
|
template<typename Derived, typename Base, bool SupportDynamicExpansion> requires std::derived_from<Base, KAutoObject>
|
||||||
class KAutoObjectWithSlabHeapAndContainer : public Base {
|
class KAutoObjectWithSlabHeapBase : public Base {
|
||||||
|
private:
|
||||||
|
template<typename, typename, bool> friend class KAutoObjectWithSlabHeap;
|
||||||
|
template<typename, typename, bool> friend class KAutoObjectWithSlabHeapAndContainer;
|
||||||
private:
|
private:
|
||||||
static constinit inline KSlabHeap<Derived, SupportDynamicExpansion> s_slab_heap;
|
static constinit inline KSlabHeap<Derived, SupportDynamicExpansion> s_slab_heap;
|
||||||
static constinit inline KAutoObjectWithListContainer<Derived> s_container;
|
|
||||||
private:
|
private:
|
||||||
static ALWAYS_INLINE Derived *Allocate() {
|
static ALWAYS_INLINE Derived *Allocate() {
|
||||||
return s_slab_heap.Allocate();
|
return s_slab_heap.Allocate();
|
||||||
|
@ -77,12 +79,6 @@ namespace ams::kern {
|
||||||
static ALWAYS_INLINE void Free(Derived *obj) {
|
static ALWAYS_INLINE void Free(Derived *obj) {
|
||||||
s_slab_heap.Free(obj);
|
s_slab_heap.Free(obj);
|
||||||
}
|
}
|
||||||
public:
|
|
||||||
class ListAccessor : public KAutoObjectWithListContainer<Derived>::ListAccessor {
|
|
||||||
public:
|
|
||||||
ALWAYS_INLINE ListAccessor() : KAutoObjectWithListContainer<Derived>::ListAccessor(s_container) { /* ... */ }
|
|
||||||
ALWAYS_INLINE ~ListAccessor() { /* ... */ }
|
|
||||||
};
|
|
||||||
private:
|
private:
|
||||||
static ALWAYS_INLINE bool IsInitialized(const Derived *obj) {
|
static ALWAYS_INLINE bool IsInitialized(const Derived *obj) {
|
||||||
if constexpr (requires { { obj->IsInitialized() } -> std::same_as<bool>; }) {
|
if constexpr (requires { { obj->IsInitialized() } -> std::same_as<bool>; }) {
|
||||||
|
@ -100,9 +96,9 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
constexpr explicit KAutoObjectWithSlabHeapAndContainer(util::ConstantInitializeTag) : Base(util::ConstantInitialize) { /* ... */ }
|
constexpr explicit KAutoObjectWithSlabHeapBase(util::ConstantInitializeTag) : Base(util::ConstantInitialize) { /* ... */ }
|
||||||
|
|
||||||
explicit KAutoObjectWithSlabHeapAndContainer() { /* ... */ }
|
explicit KAutoObjectWithSlabHeapBase() { /* ... */ }
|
||||||
|
|
||||||
/* NOTE: IsInitialized() and GetPostDestroyArgument() are virtual functions declared in this class, */
|
/* NOTE: IsInitialized() and GetPostDestroyArgument() are virtual functions declared in this class, */
|
||||||
/* in Nintendo's kernel. We fully devirtualize them, as Destroy() is the only user of them. */
|
/* in Nintendo's kernel. We fully devirtualize them, as Destroy() is the only user of them. */
|
||||||
|
@ -110,14 +106,14 @@ namespace ams::kern {
|
||||||
virtual void Destroy() override final {
|
virtual void Destroy() override final {
|
||||||
Derived * const derived = static_cast<Derived *>(this);
|
Derived * const derived = static_cast<Derived *>(this);
|
||||||
|
|
||||||
if (IsInitialized(derived)) {
|
if (KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::IsInitialized(derived)) {
|
||||||
s_container.Unregister(derived);
|
Derived::PreFinalize(derived);
|
||||||
const uintptr_t arg = GetPostDestroyArgument(derived);
|
const uintptr_t arg = KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::GetPostDestroyArgument(derived);
|
||||||
derived->Finalize();
|
derived->Finalize();
|
||||||
Free(derived);
|
KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::Free(derived);
|
||||||
Derived::PostDestroy(arg);
|
Derived::PostDestroy(arg);
|
||||||
} else {
|
} else {
|
||||||
Free(derived);
|
KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::Free(derived);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +123,6 @@ namespace ams::kern {
|
||||||
public:
|
public:
|
||||||
static void InitializeSlabHeap(void *memory, size_t memory_size) {
|
static void InitializeSlabHeap(void *memory, size_t memory_size) {
|
||||||
s_slab_heap.Initialize(memory, memory_size);
|
s_slab_heap.Initialize(memory, memory_size);
|
||||||
s_container.Initialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Derived *Create() {
|
static Derived *Create() {
|
||||||
|
@ -150,10 +145,6 @@ namespace ams::kern {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Register(Derived *obj) {
|
|
||||||
return s_container.Register(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t GetObjectSize() { return s_slab_heap.GetObjectSize(); }
|
static size_t GetObjectSize() { return s_slab_heap.GetObjectSize(); }
|
||||||
static size_t GetSlabHeapSize() { return s_slab_heap.GetSlabHeapSize(); }
|
static size_t GetSlabHeapSize() { return s_slab_heap.GetSlabHeapSize(); }
|
||||||
static size_t GetPeakIndex() { return s_slab_heap.GetPeakIndex(); }
|
static size_t GetPeakIndex() { return s_slab_heap.GetPeakIndex(); }
|
||||||
|
@ -162,4 +153,42 @@ namespace ams::kern {
|
||||||
static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); }
|
static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Derived, typename Base, bool SupportDynamicExpansion = false>
|
||||||
|
class KAutoObjectWithSlabHeap : public KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion> {
|
||||||
|
public:
|
||||||
|
constexpr explicit KAutoObjectWithSlabHeap(util::ConstantInitializeTag) : KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>(util::ConstantInitialize) { /* ... */ }
|
||||||
|
|
||||||
|
explicit KAutoObjectWithSlabHeap() { /* ... */ }
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void PreFinalize(Derived *) { /* ... */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Derived, typename Base, bool SupportDynamicExpansion = false> requires std::derived_from<Base, KAutoObjectWithList>
|
||||||
|
class KAutoObjectWithSlabHeapAndContainer : public KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion> {
|
||||||
|
private:
|
||||||
|
static constinit inline KAutoObjectWithListContainer<Derived> s_container;
|
||||||
|
public:
|
||||||
|
class ListAccessor : public KAutoObjectWithListContainer<Derived>::ListAccessor {
|
||||||
|
public:
|
||||||
|
ALWAYS_INLINE ListAccessor() : KAutoObjectWithListContainer<Derived>::ListAccessor(s_container) { /* ... */ }
|
||||||
|
ALWAYS_INLINE ~ListAccessor() { /* ... */ }
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
constexpr explicit KAutoObjectWithSlabHeapAndContainer(util::ConstantInitializeTag) : KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>(util::ConstantInitialize) { /* ... */ }
|
||||||
|
|
||||||
|
explicit KAutoObjectWithSlabHeapAndContainer() { /* ... */ }
|
||||||
|
public:
|
||||||
|
static void InitializeSlabHeap(void *memory, size_t memory_size) {
|
||||||
|
KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::InitializeSlabHeap(memory, memory_size);
|
||||||
|
s_container.Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Register(Derived *obj) {
|
||||||
|
return s_container.Register(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void PreFinalize(Derived *obj) { s_container.Unregister(obj); }
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,7 +192,7 @@ namespace ams::kern::arch::arm64 {
|
||||||
Result KPageTable::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) {
|
Result KPageTable::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) {
|
||||||
/* Initialize basic fields. */
|
/* Initialize basic fields. */
|
||||||
m_asid = 0;
|
m_asid = 0;
|
||||||
m_manager = std::addressof(Kernel::GetSystemPageTableManager());
|
m_manager = Kernel::GetSystemSystemResource().GetPageTableManagerPointer();
|
||||||
|
|
||||||
/* Allocate a page for ttbr. */
|
/* Allocate a page for ttbr. */
|
||||||
/* NOTE: It is a postcondition of page table manager allocation that the page is all-zero. */
|
/* NOTE: It is a postcondition of page table manager allocation that the page is all-zero. */
|
||||||
|
@ -207,7 +207,7 @@ namespace ams::kern::arch::arm64 {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KPageTable::InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager, KResourceLimit *resource_limit) {
|
Result KPageTable::InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) {
|
||||||
/* The input ID isn't actually used. */
|
/* The input ID isn't actually used. */
|
||||||
MESOSPHERE_UNUSED(id);
|
MESOSPHERE_UNUSED(id);
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ namespace ams::kern::arch::arm64 {
|
||||||
ON_RESULT_FAILURE { g_asid_manager.Release(m_asid); };
|
ON_RESULT_FAILURE { g_asid_manager.Release(m_asid); };
|
||||||
|
|
||||||
/* Set our manager. */
|
/* Set our manager. */
|
||||||
m_manager = pt_manager;
|
m_manager = system_resource->GetPageTableManagerPointer();
|
||||||
|
|
||||||
/* Allocate a new table, and set our ttbr value. */
|
/* Allocate a new table, and set our ttbr value. */
|
||||||
const KVirtualAddress new_table = m_manager->Allocate();
|
const KVirtualAddress new_table = m_manager->Allocate();
|
||||||
|
@ -228,7 +228,7 @@ namespace ams::kern::arch::arm64 {
|
||||||
const size_t as_width = GetAddressSpaceWidth(as_type);
|
const size_t as_width = GetAddressSpaceWidth(as_type);
|
||||||
const KProcessAddress as_start = 0;
|
const KProcessAddress as_start = 0;
|
||||||
const KProcessAddress as_end = (1ul << as_width);
|
const KProcessAddress as_end = (1ul << as_width);
|
||||||
R_TRY(KPageTableBase::InitializeForProcess(as_type, enable_aslr, enable_das_merge, from_back, pool, GetVoidPointer(new_table), as_start, as_end, code_address, code_size, mem_block_slab_manager, block_info_manager, resource_limit));
|
R_TRY(KPageTableBase::InitializeForProcess(as_type, enable_aslr, enable_das_merge, from_back, pool, GetVoidPointer(new_table), as_start, as_end, code_address, code_size, system_resource, resource_limit));
|
||||||
|
|
||||||
/* Note that we've updated the table (since we created it). */
|
/* Note that we've updated the table (since we created it). */
|
||||||
this->NoteUpdated();
|
this->NoteUpdated();
|
||||||
|
|
|
@ -651,11 +651,13 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
g_memory_controller_address = KMemoryLayout::GetDevicePhysicalAddress(KMemoryRegionType_MemoryController);
|
g_memory_controller_address = KMemoryLayout::GetDevicePhysicalAddress(KMemoryRegionType_MemoryController);
|
||||||
|
|
||||||
/* Allocate a page to use as a reserved/no device table. */
|
/* Allocate a page to use as a reserved/no device table. */
|
||||||
const KVirtualAddress table_virt_addr = Kernel::GetSystemPageTableManager().Allocate();
|
auto &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
|
||||||
|
|
||||||
|
const KVirtualAddress table_virt_addr = ptm.Allocate();
|
||||||
MESOSPHERE_ABORT_UNLESS(table_virt_addr != Null<KVirtualAddress>);
|
MESOSPHERE_ABORT_UNLESS(table_virt_addr != Null<KVirtualAddress>);
|
||||||
const KPhysicalAddress table_phys_addr = GetPageTablePhysicalAddress(table_virt_addr);
|
const KPhysicalAddress table_phys_addr = GetPageTablePhysicalAddress(table_virt_addr);
|
||||||
MESOSPHERE_ASSERT(IsValidPhysicalAddress(table_phys_addr));
|
MESOSPHERE_ASSERT(IsValidPhysicalAddress(table_phys_addr));
|
||||||
Kernel::GetSystemPageTableManager().Open(table_virt_addr, 1);
|
ptm.Open(table_virt_addr, 1);
|
||||||
|
|
||||||
/* Save the page. Note that it is a pre-condition that the page is cleared, when allocated from the system page table manager. */
|
/* Save the page. Note that it is a pre-condition that the page is cleared, when allocated from the system page table manager. */
|
||||||
/* NOTE: Nintendo does not check the result of StoreDataCache. */
|
/* NOTE: Nintendo does not check the result of StoreDataCache. */
|
||||||
|
@ -779,7 +781,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
const size_t end_index = (space_address + space_size - 1) / DeviceRegionSize;
|
const size_t end_index = (space_address + space_size - 1) / DeviceRegionSize;
|
||||||
|
|
||||||
/* Get the page table manager. */
|
/* Get the page table manager. */
|
||||||
auto &ptm = Kernel::GetSystemPageTableManager();
|
auto &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
|
||||||
|
|
||||||
/* Clear the tables. */
|
/* Clear the tables. */
|
||||||
static_assert(TableCount == (1ul << DeviceVirtualAddressBits) / DeviceRegionSize);
|
static_assert(TableCount == (1ul << DeviceVirtualAddressBits) / DeviceRegionSize);
|
||||||
|
@ -839,7 +841,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
|
|
||||||
void KDevicePageTable::Finalize() {
|
void KDevicePageTable::Finalize() {
|
||||||
/* Get the page table manager. */
|
/* Get the page table manager. */
|
||||||
auto &ptm = Kernel::GetSystemPageTableManager();
|
auto &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
|
||||||
|
|
||||||
/* Detach from all devices. */
|
/* Detach from all devices. */
|
||||||
{
|
{
|
||||||
|
@ -1014,7 +1016,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
|
|
||||||
/* Get the memory manager and page table manager. */
|
/* Get the memory manager and page table manager. */
|
||||||
KMemoryManager &mm = Kernel::GetMemoryManager();
|
KMemoryManager &mm = Kernel::GetMemoryManager();
|
||||||
KPageTableManager &ptm = Kernel::GetSystemPageTableManager();
|
KPageTableManager &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
|
||||||
|
|
||||||
/* Cache permissions. */
|
/* Cache permissions. */
|
||||||
const bool read = (device_perm & ams::svc::MemoryPermission_Read) != 0;
|
const bool read = (device_perm & ams::svc::MemoryPermission_Read) != 0;
|
||||||
|
@ -1158,10 +1160,10 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
|
|
||||||
/* Get the memory manager and page table manager. */
|
/* Get the memory manager and page table manager. */
|
||||||
KMemoryManager &mm = Kernel::GetMemoryManager();
|
KMemoryManager &mm = Kernel::GetMemoryManager();
|
||||||
KPageTableManager &ptm = Kernel::GetSystemPageTableManager();
|
KPageTableManager &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
|
||||||
|
|
||||||
/* Make a page group for the pages we're closing. */
|
/* Make a page group for the pages we're closing. */
|
||||||
KPageGroup pg(std::addressof(Kernel::GetSystemBlockInfoManager()));
|
KPageGroup pg(Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer());
|
||||||
|
|
||||||
/* Walk the directory. */
|
/* Walk the directory. */
|
||||||
u64 remaining = size;
|
u64 remaining = size;
|
||||||
|
|
|
@ -20,27 +20,28 @@ namespace ams::kern::init {
|
||||||
#define SLAB_COUNT(CLASS) g_slab_resource_counts.num_##CLASS
|
#define SLAB_COUNT(CLASS) g_slab_resource_counts.num_##CLASS
|
||||||
|
|
||||||
#define FOREACH_SLAB_TYPE(HANDLER, ...) \
|
#define FOREACH_SLAB_TYPE(HANDLER, ...) \
|
||||||
HANDLER(KProcess, (SLAB_COUNT(KProcess)), ## __VA_ARGS__) \
|
HANDLER(KProcess, (SLAB_COUNT(KProcess)), ## __VA_ARGS__) \
|
||||||
HANDLER(KThread, (SLAB_COUNT(KThread)), ## __VA_ARGS__) \
|
HANDLER(KThread, (SLAB_COUNT(KThread)), ## __VA_ARGS__) \
|
||||||
HANDLER(KEvent, (SLAB_COUNT(KEvent)), ## __VA_ARGS__) \
|
HANDLER(KEvent, (SLAB_COUNT(KEvent)), ## __VA_ARGS__) \
|
||||||
HANDLER(KInterruptEvent, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
|
HANDLER(KInterruptEvent, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
|
||||||
HANDLER(KInterruptEventTask, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
|
HANDLER(KInterruptEventTask, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
|
||||||
HANDLER(KPort, (SLAB_COUNT(KPort)), ## __VA_ARGS__) \
|
HANDLER(KPort, (SLAB_COUNT(KPort)), ## __VA_ARGS__) \
|
||||||
HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ## __VA_ARGS__) \
|
HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ## __VA_ARGS__) \
|
||||||
HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ## __VA_ARGS__) \
|
HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ## __VA_ARGS__) \
|
||||||
HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ## __VA_ARGS__) \
|
HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ## __VA_ARGS__) \
|
||||||
HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ## __VA_ARGS__) \
|
HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ## __VA_ARGS__) \
|
||||||
HANDLER(KDeviceAddressSpace, (SLAB_COUNT(KDeviceAddressSpace)), ## __VA_ARGS__) \
|
HANDLER(KDeviceAddressSpace, (SLAB_COUNT(KDeviceAddressSpace)), ## __VA_ARGS__) \
|
||||||
HANDLER(KSession, (SLAB_COUNT(KSession)), ## __VA_ARGS__) \
|
HANDLER(KSession, (SLAB_COUNT(KSession)), ## __VA_ARGS__) \
|
||||||
HANDLER(KSessionRequest, (SLAB_COUNT(KSession) * 2), ## __VA_ARGS__) \
|
HANDLER(KSessionRequest, (SLAB_COUNT(KSession) * 2), ## __VA_ARGS__) \
|
||||||
HANDLER(KLightSession, (SLAB_COUNT(KLightSession)), ## __VA_ARGS__) \
|
HANDLER(KLightSession, (SLAB_COUNT(KLightSession)), ## __VA_ARGS__) \
|
||||||
HANDLER(KThreadLocalPage, (SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), ## __VA_ARGS__) \
|
HANDLER(KThreadLocalPage, (SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), ## __VA_ARGS__) \
|
||||||
HANDLER(KObjectName, (SLAB_COUNT(KObjectName)), ## __VA_ARGS__) \
|
HANDLER(KObjectName, (SLAB_COUNT(KObjectName)), ## __VA_ARGS__) \
|
||||||
HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ## __VA_ARGS__) \
|
HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ## __VA_ARGS__) \
|
||||||
HANDLER(KEventInfo, (SLAB_COUNT(KThread) + SLAB_COUNT(KDebug)), ## __VA_ARGS__) \
|
HANDLER(KEventInfo, (SLAB_COUNT(KThread) + SLAB_COUNT(KDebug)), ## __VA_ARGS__) \
|
||||||
HANDLER(KDebug, (SLAB_COUNT(KDebug)), ## __VA_ARGS__) \
|
HANDLER(KDebug, (SLAB_COUNT(KDebug)), ## __VA_ARGS__) \
|
||||||
HANDLER(KIoPool, (SLAB_COUNT(KIoPool)), ## __VA_ARGS__) \
|
HANDLER(KIoPool, (SLAB_COUNT(KIoPool)), ## __VA_ARGS__) \
|
||||||
HANDLER(KIoRegion, (SLAB_COUNT(KIoRegion)), ## __VA_ARGS__)
|
HANDLER(KIoRegion, (SLAB_COUNT(KIoRegion)), ## __VA_ARGS__) \
|
||||||
|
HANDLER(KSecureSystemResource, (SLAB_COUNT(KProcess)), ## __VA_ARGS__)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|
|
@ -128,13 +128,13 @@ namespace ams::kern {
|
||||||
KProcess *new_process = nullptr;
|
KProcess *new_process = nullptr;
|
||||||
{
|
{
|
||||||
/* Make page groups to represent the data. */
|
/* Make page groups to represent the data. */
|
||||||
KPageGroup pg(std::addressof(Kernel::GetSystemBlockInfoManager()));
|
KPageGroup pg(Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer());
|
||||||
KPageGroup workaround_pg(std::addressof(Kernel::GetSystemBlockInfoManager()));
|
KPageGroup workaround_pg(Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer());
|
||||||
|
|
||||||
/* Populate the page group to represent the data. */
|
/* Populate the page group to represent the data. */
|
||||||
{
|
{
|
||||||
/* Allocate the previously unreserved pages. */
|
/* Allocate the previously unreserved pages. */
|
||||||
KPageGroup unreserve_pg(std::addressof(Kernel::GetSystemBlockInfoManager()));
|
KPageGroup unreserve_pg(Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer());
|
||||||
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetMemoryManager().AllocateAndOpen(std::addressof(unreserve_pg), unreserved_size / PageSize, KMemoryManager::EncodeOption(dst_pool, KMemoryManager::Direction_FromFront)));
|
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetMemoryManager().AllocateAndOpen(std::addressof(unreserve_pg), unreserved_size / PageSize, KMemoryManager::EncodeOption(dst_pool, KMemoryManager::Direction_FromFront)));
|
||||||
|
|
||||||
/* Add the previously reserved pages. */
|
/* Add the previously reserved pages. */
|
||||||
|
|
|
@ -43,6 +43,12 @@ namespace ams::kern {
|
||||||
static_assert(ClassToken<KDeviceAddressSpace> == 0b10010001'00000000);
|
static_assert(ClassToken<KDeviceAddressSpace> == 0b10010001'00000000);
|
||||||
static_assert(ClassToken<KSessionRequest> == 0b01100001'00000000);
|
static_assert(ClassToken<KSessionRequest> == 0b01100001'00000000);
|
||||||
static_assert(ClassToken<KCodeMemory> == 0b10100001'00000000);
|
static_assert(ClassToken<KCodeMemory> == 0b10100001'00000000);
|
||||||
|
static_assert(ClassToken<KIoPool> == 0b11000001'00000000);
|
||||||
|
static_assert(ClassToken<KIoRegion> == 0b00001110'00000000);
|
||||||
|
/* 0b00010110'00000000 */
|
||||||
|
/* 0b00100110'00000000 */
|
||||||
|
static_assert(ClassToken<KSystemResource> == 0b01000110'00000000);
|
||||||
|
|
||||||
|
|
||||||
/* Ensure that the token hierarchy is correct. */
|
/* Ensure that the token hierarchy is correct. */
|
||||||
|
|
||||||
|
@ -72,6 +78,10 @@ namespace ams::kern {
|
||||||
static_assert(ClassToken<KDeviceAddressSpace> == ((0b10010001 << 8) | ClassToken<KAutoObject>));
|
static_assert(ClassToken<KDeviceAddressSpace> == ((0b10010001 << 8) | ClassToken<KAutoObject>));
|
||||||
static_assert(ClassToken<KSessionRequest> == ((0b01100001 << 8) | ClassToken<KAutoObject>));
|
static_assert(ClassToken<KSessionRequest> == ((0b01100001 << 8) | ClassToken<KAutoObject>));
|
||||||
static_assert(ClassToken<KCodeMemory> == ((0b10100001 << 8) | ClassToken<KAutoObject>));
|
static_assert(ClassToken<KCodeMemory> == ((0b10100001 << 8) | ClassToken<KAutoObject>));
|
||||||
|
static_assert(ClassToken<KIoPool> == ((0b11000001 << 8) | ClassToken<KAutoObject>));
|
||||||
|
static_assert(ClassToken<KIoRegion> == ((0b00001110 << 8) | ClassToken<KAutoObject>));
|
||||||
|
|
||||||
|
static_assert(ClassToken<KSystemResource> == ((0b01000110 << 8) | ClassToken<KAutoObject>));
|
||||||
|
|
||||||
/* Ensure that the token hierarchy reflects the class hierarchy. */
|
/* Ensure that the token hierarchy reflects the class hierarchy. */
|
||||||
|
|
||||||
|
@ -100,6 +110,10 @@ namespace ams::kern {
|
||||||
static_assert(std::is_final<KDeviceAddressSpace>::value && std::is_base_of<KAutoObject, KDeviceAddressSpace>::value);
|
static_assert(std::is_final<KDeviceAddressSpace>::value && std::is_base_of<KAutoObject, KDeviceAddressSpace>::value);
|
||||||
static_assert(std::is_final<KSessionRequest>::value && std::is_base_of<KAutoObject, KSessionRequest>::value);
|
static_assert(std::is_final<KSessionRequest>::value && std::is_base_of<KAutoObject, KSessionRequest>::value);
|
||||||
static_assert(std::is_final<KCodeMemory>::value && std::is_base_of<KAutoObject, KCodeMemory>::value);
|
static_assert(std::is_final<KCodeMemory>::value && std::is_base_of<KAutoObject, KCodeMemory>::value);
|
||||||
|
static_assert(std::is_final<KIoPool>::value && std::is_base_of<KAutoObject, KIoPool>::value);
|
||||||
|
static_assert(std::is_final<KIoRegion>::value && std::is_base_of<KAutoObject, KIoRegion>::value);
|
||||||
|
|
||||||
|
static_assert(std::is_base_of<KAutoObject, KSystemResource>::value);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,24 +362,24 @@ namespace ams::kern::KDumpObject {
|
||||||
/* Memory block slabs. */
|
/* Memory block slabs. */
|
||||||
{
|
{
|
||||||
MESOSPHERE_RELEASE_LOG("App Memory Block\n");
|
MESOSPHERE_RELEASE_LOG("App Memory Block\n");
|
||||||
auto &app = Kernel::GetApplicationMemoryBlockManager();
|
auto &app = Kernel::GetApplicationSystemResource().GetMemoryBlockSlabManager();
|
||||||
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", app.GetUsed(), app.GetPeak(), app.GetCount());
|
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", app.GetUsed(), app.GetPeak(), app.GetCount());
|
||||||
MESOSPHERE_RELEASE_LOG("Sys Memory Block\n");
|
MESOSPHERE_RELEASE_LOG("Sys Memory Block\n");
|
||||||
auto &sys = Kernel::GetSystemMemoryBlockManager();
|
auto &sys = Kernel::GetSystemSystemResource().GetMemoryBlockSlabManager();
|
||||||
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", sys.GetUsed(), sys.GetPeak(), sys.GetCount());
|
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", sys.GetUsed(), sys.GetPeak(), sys.GetCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* KBlockInfo slab. */
|
/* KBlockInfo slab. */
|
||||||
{
|
{
|
||||||
MESOSPHERE_RELEASE_LOG("KBlockInfo\n");
|
MESOSPHERE_RELEASE_LOG("KBlockInfo\n");
|
||||||
auto &manager = Kernel::GetSystemBlockInfoManager();
|
auto &manager = Kernel::GetSystemSystemResource().GetBlockInfoManager();
|
||||||
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", manager.GetUsed(), manager.GetPeak(), manager.GetCount());
|
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", manager.GetUsed(), manager.GetPeak(), manager.GetCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Page Table slab. */
|
/* Page Table slab. */
|
||||||
{
|
{
|
||||||
MESOSPHERE_RELEASE_LOG("Page Table\n");
|
MESOSPHERE_RELEASE_LOG("Page Table\n");
|
||||||
auto &manager = Kernel::GetSystemPageTableManager();
|
auto &manager = Kernel::GetSystemSystemResource().GetPageTableManager();
|
||||||
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", manager.GetUsed(), manager.GetPeak(), manager.GetCount());
|
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", manager.GetUsed(), manager.GetPeak(), manager.GetCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,15 +425,17 @@ namespace ams::kern::KDumpObject {
|
||||||
process_pts += pts;
|
process_pts += pts;
|
||||||
|
|
||||||
MESOSPHERE_RELEASE_LOG("%-12s: PID=%3lu Thread %4d / Event %4d / PageTable %5zu\n", process->GetName(), process->GetId(), threads, events, pts);
|
MESOSPHERE_RELEASE_LOG("%-12s: PID=%3lu Thread %4d / Event %4d / PageTable %5zu\n", process->GetName(), process->GetId(), threads, events, pts);
|
||||||
if (process->GetTotalSystemResourceSize() != 0) {
|
if (const auto &system_resource = process->GetSystemResource(); system_resource.IsSecureResource()) {
|
||||||
|
const auto &secure_resource = static_cast<const KSecureSystemResource &>(system_resource);
|
||||||
|
|
||||||
MESOSPHERE_RELEASE_LOG(" System Resource\n");
|
MESOSPHERE_RELEASE_LOG(" System Resource\n");
|
||||||
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", process->GetDynamicPageManager().GetUsed(), process->GetDynamicPageManager().GetPeak(), process->GetDynamicPageManager().GetCount());
|
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", secure_resource.GetDynamicPageManager().GetUsed(), secure_resource.GetDynamicPageManager().GetPeak(), secure_resource.GetDynamicPageManager().GetCount());
|
||||||
MESOSPHERE_RELEASE_LOG(" Memory Block\n");
|
MESOSPHERE_RELEASE_LOG(" Memory Block\n");
|
||||||
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", process->GetMemoryBlockSlabManager().GetUsed(), process->GetMemoryBlockSlabManager().GetPeak(), process->GetMemoryBlockSlabManager().GetCount());
|
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", secure_resource.GetMemoryBlockSlabManager().GetUsed(), secure_resource.GetMemoryBlockSlabManager().GetPeak(), secure_resource.GetMemoryBlockSlabManager().GetCount());
|
||||||
MESOSPHERE_RELEASE_LOG(" Page Table\n");
|
MESOSPHERE_RELEASE_LOG(" Page Table\n");
|
||||||
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", process->GetPageTableManager().GetUsed(), process->GetPageTableManager().GetPeak(), process->GetPageTableManager().GetCount());
|
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", secure_resource.GetPageTableManager().GetUsed(), secure_resource.GetPageTableManager().GetPeak(), secure_resource.GetPageTableManager().GetCount());
|
||||||
MESOSPHERE_RELEASE_LOG(" Block Info\n");
|
MESOSPHERE_RELEASE_LOG(" Block Info\n");
|
||||||
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", process->GetBlockInfoManager().GetUsed(), process->GetBlockInfoManager().GetPeak(), process->GetBlockInfoManager().GetCount());
|
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", secure_resource.GetBlockInfoManager().GetUsed(), secure_resource.GetBlockInfoManager().GetPeak(), secure_resource.GetBlockInfoManager().GetCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,8 +105,8 @@ namespace ams::kern {
|
||||||
m_mapped_unsafe_physical_memory = 0;
|
m_mapped_unsafe_physical_memory = 0;
|
||||||
m_mapped_ipc_server_memory = 0;
|
m_mapped_ipc_server_memory = 0;
|
||||||
|
|
||||||
m_memory_block_slab_manager = std::addressof(Kernel::GetSystemMemoryBlockManager());
|
m_memory_block_slab_manager = Kernel::GetSystemSystemResource().GetMemoryBlockSlabManagerPointer();
|
||||||
m_block_info_manager = std::addressof(Kernel::GetSystemBlockInfoManager());
|
m_block_info_manager = Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer();
|
||||||
m_resource_limit = std::addressof(Kernel::GetSystemResourceLimit());
|
m_resource_limit = std::addressof(Kernel::GetSystemResourceLimit());
|
||||||
|
|
||||||
m_allocate_option = KMemoryManager::EncodeOption(KMemoryManager::Pool_System, KMemoryManager::Direction_FromFront);
|
m_allocate_option = KMemoryManager::EncodeOption(KMemoryManager::Pool_System, KMemoryManager::Direction_FromFront);
|
||||||
|
@ -124,7 +124,7 @@ namespace ams::kern {
|
||||||
R_RETURN(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager));
|
R_RETURN(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KResourceLimit *resource_limit) {
|
Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) {
|
||||||
/* Validate the region. */
|
/* Validate the region. */
|
||||||
MESOSPHERE_ABORT_UNLESS(start <= code_address);
|
MESOSPHERE_ABORT_UNLESS(start <= code_address);
|
||||||
MESOSPHERE_ABORT_UNLESS(code_address < code_address + code_size);
|
MESOSPHERE_ABORT_UNLESS(code_address < code_address + code_size);
|
||||||
|
@ -186,8 +186,8 @@ namespace ams::kern {
|
||||||
m_address_space_start = start;
|
m_address_space_start = start;
|
||||||
m_address_space_end = end;
|
m_address_space_end = end;
|
||||||
m_is_kernel = false;
|
m_is_kernel = false;
|
||||||
m_memory_block_slab_manager = mem_block_slab_manager;
|
m_memory_block_slab_manager = system_resource->GetMemoryBlockSlabManagerPointer();
|
||||||
m_block_info_manager = block_info_manager;
|
m_block_info_manager = system_resource->GetBlockInfoManagerPointer();
|
||||||
m_resource_limit = resource_limit;
|
m_resource_limit = resource_limit;
|
||||||
|
|
||||||
/* Determine the region we can place our undetermineds in. */
|
/* Determine the region we can place our undetermineds in. */
|
||||||
|
|
|
@ -117,34 +117,19 @@ namespace ams::kern {
|
||||||
this->DeleteThreadLocalRegion(m_plr_address);
|
this->DeleteThreadLocalRegion(m_plr_address);
|
||||||
|
|
||||||
/* Get the used memory size. */
|
/* Get the used memory size. */
|
||||||
const size_t used_memory_size = this->GetUsedUserPhysicalMemorySize();
|
const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize();
|
||||||
|
|
||||||
/* Finalize the page table. */
|
/* Finalize the page table. */
|
||||||
m_page_table.Finalize();
|
m_page_table.Finalize();
|
||||||
|
|
||||||
/* Free the system resource. */
|
/* Finish using our system resource. */
|
||||||
if (m_system_resource_address != Null<KVirtualAddress>) {
|
{
|
||||||
/* Check that we have no outstanding allocations. */
|
if (m_system_resource->IsSecureResource()) {
|
||||||
MESOSPHERE_ABORT_UNLESS(m_memory_block_slab_manager.GetUsed() == 0);
|
/* Finalize optimized memory. If memory wasn't optimized, this is a no-op. */
|
||||||
MESOSPHERE_ABORT_UNLESS(m_block_info_manager.GetUsed() == 0);
|
Kernel::GetMemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool);
|
||||||
MESOSPHERE_ABORT_UNLESS(m_page_table_manager.GetUsed() == 0);
|
}
|
||||||
|
|
||||||
/* Free the memory. */
|
m_system_resource->Close();
|
||||||
KSystemControl::FreeSecureMemory(m_system_resource_address, m_system_resource_num_pages * PageSize, m_memory_pool);
|
|
||||||
|
|
||||||
/* Clear our tracking variables. */
|
|
||||||
m_system_resource_address = Null<KVirtualAddress>;
|
|
||||||
m_system_resource_num_pages = 0;
|
|
||||||
|
|
||||||
/* Finalize optimized memory. If memory wasn't optimized, this is a no-op. */
|
|
||||||
Kernel::GetMemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release memory to the resource limit. */
|
|
||||||
if (m_resource_limit != nullptr) {
|
|
||||||
MESOSPHERE_ABORT_UNLESS(used_memory_size >= m_memory_release_hint);
|
|
||||||
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, used_memory_size, used_memory_size - m_memory_release_hint);
|
|
||||||
m_resource_limit->Close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free all shared memory infos. */
|
/* Free all shared memory infos. */
|
||||||
|
@ -179,6 +164,13 @@ namespace ams::kern {
|
||||||
MESOSPHERE_ABORT_UNLESS(m_partially_used_tlp_tree.empty());
|
MESOSPHERE_ABORT_UNLESS(m_partially_used_tlp_tree.empty());
|
||||||
MESOSPHERE_ABORT_UNLESS(m_fully_used_tlp_tree.empty());
|
MESOSPHERE_ABORT_UNLESS(m_fully_used_tlp_tree.empty());
|
||||||
|
|
||||||
|
/* Release memory to the resource limit. */
|
||||||
|
if (m_resource_limit != nullptr) {
|
||||||
|
MESOSPHERE_ABORT_UNLESS(used_memory_size >= m_memory_release_hint);
|
||||||
|
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, used_memory_size, used_memory_size - m_memory_release_hint);
|
||||||
|
m_resource_limit->Close();
|
||||||
|
}
|
||||||
|
|
||||||
/* Log that we finalized for debug. */
|
/* Log that we finalized for debug. */
|
||||||
MESOSPHERE_LOG("KProcess::Finalize() pid=%ld name=%-12s\n", m_process_id, m_name);
|
MESOSPHERE_LOG("KProcess::Finalize() pid=%ld name=%-12s\n", m_process_id, m_name);
|
||||||
|
|
||||||
|
@ -267,13 +259,18 @@ namespace ams::kern {
|
||||||
MESOSPHERE_ASSERT(res_limit != nullptr);
|
MESOSPHERE_ASSERT(res_limit != nullptr);
|
||||||
MESOSPHERE_ABORT_UNLESS((params.code_num_pages * PageSize) / PageSize == static_cast<size_t>(params.code_num_pages));
|
MESOSPHERE_ABORT_UNLESS((params.code_num_pages * PageSize) / PageSize == static_cast<size_t>(params.code_num_pages));
|
||||||
|
|
||||||
|
/* Determine is application. */
|
||||||
|
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication) != 0;
|
||||||
|
|
||||||
/* Set members. */
|
/* Set members. */
|
||||||
m_memory_pool = pool;
|
m_memory_pool = pool;
|
||||||
m_resource_limit = res_limit;
|
m_resource_limit = res_limit;
|
||||||
m_system_resource_address = Null<KVirtualAddress>;
|
m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource());
|
||||||
m_system_resource_num_pages = 0;
|
|
||||||
m_is_immortal = immortal;
|
m_is_immortal = immortal;
|
||||||
|
|
||||||
|
/* Open reference to our system resource. */
|
||||||
|
m_system_resource->Open();
|
||||||
|
|
||||||
/* Setup page table. */
|
/* Setup page table. */
|
||||||
/* NOTE: Nintendo passes process ID despite not having set it yet. */
|
/* NOTE: Nintendo passes process ID despite not having set it yet. */
|
||||||
/* This goes completely unused, but even so... */
|
/* This goes completely unused, but even so... */
|
||||||
|
@ -281,11 +278,7 @@ namespace ams::kern {
|
||||||
const auto as_type = static_cast<ams::svc::CreateProcessFlag>(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask);
|
const auto as_type = static_cast<ams::svc::CreateProcessFlag>(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask);
|
||||||
const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0;
|
const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0;
|
||||||
const bool enable_das_merge = (params.flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0;
|
const bool enable_das_merge = (params.flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0;
|
||||||
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication) != 0;
|
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, params.code_num_pages * PageSize, m_system_resource, res_limit));
|
||||||
auto *mem_block_manager = std::addressof(is_app ? Kernel::GetApplicationMemoryBlockManager() : Kernel::GetSystemMemoryBlockManager());
|
|
||||||
auto *block_info_manager = std::addressof(is_app ? Kernel::GetApplicationBlockInfoManager() : Kernel::GetSystemBlockInfoManager());
|
|
||||||
auto *pt_manager = std::addressof(is_app ? Kernel::GetApplicationPageTableManager() : Kernel::GetSystemPageTableManager());
|
|
||||||
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, params.code_num_pages * PageSize, mem_block_manager, block_info_manager, pt_manager, res_limit));
|
|
||||||
}
|
}
|
||||||
ON_RESULT_FAILURE { m_page_table.Finalize(); };
|
ON_RESULT_FAILURE { m_page_table.Finalize(); };
|
||||||
|
|
||||||
|
@ -328,64 +321,35 @@ namespace ams::kern {
|
||||||
const size_t code_size = code_num_pages * PageSize;
|
const size_t code_size = code_num_pages * PageSize;
|
||||||
const size_t system_resource_size = system_resource_num_pages * PageSize;
|
const size_t system_resource_size = system_resource_num_pages * PageSize;
|
||||||
|
|
||||||
/* Reserve memory for the system resource. */
|
/* Reserve memory for our code resource. */
|
||||||
KScopedResourceReservation memory_reservation(this, ams::svc::LimitableResource_PhysicalMemoryMax, code_size + KSystemControl::CalculateRequiredSecureMemorySize(system_resource_size, pool));
|
KScopedResourceReservation memory_reservation(this, ams::svc::LimitableResource_PhysicalMemoryMax, code_size);
|
||||||
R_UNLESS(memory_reservation.Succeeded(), svc::ResultLimitReached());
|
R_UNLESS(memory_reservation.Succeeded(), svc::ResultLimitReached());
|
||||||
|
|
||||||
/* Setup page table resource objects. */
|
/* Setup our system resource. */
|
||||||
KMemoryBlockSlabManager *mem_block_manager;
|
|
||||||
KBlockInfoManager *block_info_manager;
|
|
||||||
KPageTableManager *pt_manager;
|
|
||||||
|
|
||||||
m_system_resource_address = Null<KVirtualAddress>;
|
|
||||||
m_system_resource_num_pages = 0;
|
|
||||||
|
|
||||||
if (system_resource_num_pages != 0) {
|
if (system_resource_num_pages != 0) {
|
||||||
/* Allocate secure memory. */
|
/* Create a secure system resource. */
|
||||||
R_TRY(KSystemControl::AllocateSecureMemory(std::addressof(m_system_resource_address), system_resource_size, pool));
|
KSecureSystemResource *secure_resource = KSecureSystemResource::Create();
|
||||||
|
R_UNLESS(secure_resource != nullptr, svc::ResultOutOfResource());
|
||||||
|
|
||||||
/* Set the number of system resource pages. */
|
ON_RESULT_FAILURE { secure_resource->Close(); };
|
||||||
MESOSPHERE_ASSERT(m_system_resource_address != Null<KVirtualAddress>);
|
|
||||||
m_system_resource_num_pages = system_resource_num_pages;
|
|
||||||
|
|
||||||
/* Initialize slab heaps. */
|
/* Initialize the secure resource. */
|
||||||
const size_t rc_size = util::AlignUp(KPageTableSlabHeap::CalculateReferenceCountSize(system_resource_size), PageSize);
|
R_TRY(secure_resource->Initialize(system_resource_size, m_resource_limit, m_memory_pool));
|
||||||
m_dynamic_page_manager.Initialize(m_system_resource_address + rc_size, system_resource_size - rc_size);
|
|
||||||
m_page_table_heap.Initialize(std::addressof(m_dynamic_page_manager), 0, GetPointer<KPageTableManager::RefCount>(m_system_resource_address));
|
|
||||||
m_memory_block_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
|
|
||||||
m_block_info_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
|
|
||||||
|
|
||||||
/* Initialize managers. */
|
/* Set our system resource. */
|
||||||
m_page_table_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_page_table_heap));
|
m_system_resource = secure_resource;
|
||||||
m_memory_block_slab_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_memory_block_heap));
|
|
||||||
m_block_info_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_block_info_heap));
|
|
||||||
|
|
||||||
mem_block_manager = std::addressof(m_memory_block_slab_manager);
|
|
||||||
block_info_manager = std::addressof(m_block_info_manager);
|
|
||||||
pt_manager = std::addressof(m_page_table_manager);
|
|
||||||
} else {
|
} else {
|
||||||
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication);
|
/* Use the system-wide system resource. */
|
||||||
mem_block_manager = std::addressof(is_app ? Kernel::GetApplicationMemoryBlockManager() : Kernel::GetSystemMemoryBlockManager());
|
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication);
|
||||||
block_info_manager = std::addressof(is_app ? Kernel::GetApplicationBlockInfoManager() : Kernel::GetSystemBlockInfoManager());
|
m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource());
|
||||||
pt_manager = std::addressof(is_app ? Kernel::GetApplicationPageTableManager() : Kernel::GetSystemPageTableManager());
|
|
||||||
|
/* Open reference to the system resource. */
|
||||||
|
m_system_resource->Open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure we don't leak any secure memory we allocated. */
|
/* Ensure we clean up our secure resource, if we fail. */
|
||||||
ON_RESULT_FAILURE {
|
ON_RESULT_FAILURE { m_system_resource->Close(); };
|
||||||
if (m_system_resource_address != Null<KVirtualAddress>) {
|
|
||||||
/* Check that we have no outstanding allocations. */
|
|
||||||
MESOSPHERE_ABORT_UNLESS(m_memory_block_slab_manager.GetUsed() == 0);
|
|
||||||
MESOSPHERE_ABORT_UNLESS(m_block_info_manager.GetUsed() == 0);
|
|
||||||
MESOSPHERE_ABORT_UNLESS(m_page_table_manager.GetUsed() == 0);
|
|
||||||
|
|
||||||
/* Free the memory. */
|
|
||||||
KSystemControl::FreeSecureMemory(m_system_resource_address, system_resource_size, pool);
|
|
||||||
|
|
||||||
/* Clear our tracking variables. */
|
|
||||||
m_system_resource_address = Null<KVirtualAddress>;
|
|
||||||
m_system_resource_num_pages = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Setup page table. */
|
/* Setup page table. */
|
||||||
/* NOTE: Nintendo passes process ID despite not having set it yet. */
|
/* NOTE: Nintendo passes process ID despite not having set it yet. */
|
||||||
|
@ -394,7 +358,7 @@ namespace ams::kern {
|
||||||
const auto as_type = static_cast<ams::svc::CreateProcessFlag>(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask);
|
const auto as_type = static_cast<ams::svc::CreateProcessFlag>(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask);
|
||||||
const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0;
|
const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0;
|
||||||
const bool enable_das_merge = (params.flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0;
|
const bool enable_das_merge = (params.flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0;
|
||||||
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, code_size, mem_block_manager, block_info_manager, pt_manager, res_limit));
|
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, code_size, m_system_resource, res_limit));
|
||||||
}
|
}
|
||||||
ON_RESULT_FAILURE_2 { m_page_table.Finalize(); };
|
ON_RESULT_FAILURE_2 { m_page_table.Finalize(); };
|
||||||
|
|
||||||
|
@ -413,7 +377,7 @@ namespace ams::kern {
|
||||||
MESOSPHERE_ABORT_UNLESS(m_process_id <= ProcessIdMax);
|
MESOSPHERE_ABORT_UNLESS(m_process_id <= ProcessIdMax);
|
||||||
|
|
||||||
/* If we should optimize memory allocations, do so. */
|
/* If we should optimize memory allocations, do so. */
|
||||||
if (m_system_resource_address != Null<KVirtualAddress> && (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0) {
|
if (m_system_resource->IsSecureResource() && (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0) {
|
||||||
R_TRY(Kernel::GetMemoryManager().InitializeOptimizedMemory(m_process_id, pool));
|
R_TRY(Kernel::GetMemoryManager().InitializeOptimizedMemory(m_process_id, pool));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,7 +425,7 @@ namespace ams::kern {
|
||||||
if (!m_is_immortal) {
|
if (!m_is_immortal) {
|
||||||
/* Release resource limit hint. */
|
/* Release resource limit hint. */
|
||||||
if (m_resource_limit != nullptr) {
|
if (m_resource_limit != nullptr) {
|
||||||
m_memory_release_hint = this->GetUsedUserPhysicalMemorySize();
|
m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize();
|
||||||
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, 0, m_memory_release_hint);
|
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, 0, m_memory_release_hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,7 +844,7 @@ namespace ams::kern {
|
||||||
size_t KProcess::GetUsedUserPhysicalMemorySize() const {
|
size_t KProcess::GetUsedUserPhysicalMemorySize() const {
|
||||||
const size_t norm_size = m_page_table.GetNormalMemorySize();
|
const size_t norm_size = m_page_table.GetNormalMemorySize();
|
||||||
const size_t other_size = m_code_size + m_main_thread_stack_size;
|
const size_t other_size = m_code_size + m_main_thread_stack_size;
|
||||||
const size_t sec_size = KSystemControl::CalculateRequiredSecureMemorySize(m_system_resource_num_pages * PageSize, m_memory_pool);
|
const size_t sec_size = m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->CalculateRequiredSecureMemorySize() : 0;
|
||||||
|
|
||||||
return norm_size + other_size + sec_size;
|
return norm_size + other_size + sec_size;
|
||||||
}
|
}
|
||||||
|
@ -909,7 +873,7 @@ namespace ams::kern {
|
||||||
/* Get the amount of free and used size. */
|
/* Get the amount of free and used size. */
|
||||||
const size_t free_size = m_resource_limit->GetFreeValue(ams::svc::LimitableResource_PhysicalMemoryMax);
|
const size_t free_size = m_resource_limit->GetFreeValue(ams::svc::LimitableResource_PhysicalMemoryMax);
|
||||||
const size_t used_size = this->GetUsedUserPhysicalMemorySize();
|
const size_t used_size = this->GetUsedUserPhysicalMemorySize();
|
||||||
const size_t sec_size = KSystemControl::CalculateRequiredSecureMemorySize(m_system_resource_num_pages * PageSize, m_memory_pool);
|
const size_t sec_size = m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->CalculateRequiredSecureMemorySize() : 0;
|
||||||
const size_t max_size = m_max_process_memory;
|
const size_t max_size = m_max_process_memory;
|
||||||
|
|
||||||
if (used_size + free_size > max_size) {
|
if (used_size + free_size > max_size) {
|
||||||
|
|
90
libraries/libmesosphere/source/kern_k_system_resource.cpp
Normal file
90
libraries/libmesosphere/source/kern_k_system_resource.cpp
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <mesosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
Result KSecureSystemResource::Initialize(size_t size, KResourceLimit *resource_limit, KMemoryManager::Pool pool) {
|
||||||
|
/* Set members. */
|
||||||
|
m_resource_limit = resource_limit;
|
||||||
|
m_resource_size = size;
|
||||||
|
m_resource_pool = pool;
|
||||||
|
|
||||||
|
/* Determine required size for our secure resource. */
|
||||||
|
const size_t secure_size = this->CalculateRequiredSecureMemorySize();
|
||||||
|
|
||||||
|
/* Reserve memory for our secure resource. */
|
||||||
|
KScopedResourceReservation memory_reservation(m_resource_limit, ams::svc::LimitableResource_PhysicalMemoryMax, secure_size);
|
||||||
|
R_UNLESS(memory_reservation.Succeeded(), svc::ResultLimitReached());
|
||||||
|
|
||||||
|
/* Allocate secure memory. */
|
||||||
|
R_TRY(KSystemControl::AllocateSecureMemory(std::addressof(m_resource_address), m_resource_size, m_resource_pool));
|
||||||
|
MESOSPHERE_ASSERT(m_resource_address != Null<KVirtualAddress>);
|
||||||
|
|
||||||
|
/* Ensure we clean up the secure memory, if we fail past this point. */
|
||||||
|
ON_RESULT_FAILURE { KSystemControl::FreeSecureMemory(m_resource_address, m_resource_size, m_resource_pool); };
|
||||||
|
|
||||||
|
/* Check that our allocation is bigger than the reference counts needed for it. */
|
||||||
|
const size_t rc_size = util::AlignUp(KPageTableSlabHeap::CalculateReferenceCountSize(m_resource_size), PageSize);
|
||||||
|
R_UNLESS(m_resource_size > rc_size, svc::ResultOutOfMemory());
|
||||||
|
|
||||||
|
/* Initialize slab heaps. */
|
||||||
|
m_dynamic_page_manager.Initialize(m_resource_address + rc_size, m_resource_size - rc_size);
|
||||||
|
m_page_table_heap.Initialize(std::addressof(m_dynamic_page_manager), 0, GetPointer<KPageTableManager::RefCount>(m_resource_address));
|
||||||
|
m_memory_block_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
|
||||||
|
m_block_info_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
|
||||||
|
|
||||||
|
/* Initialize managers. */
|
||||||
|
m_page_table_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_page_table_heap));
|
||||||
|
m_memory_block_slab_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_memory_block_heap));
|
||||||
|
m_block_info_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_block_info_heap));
|
||||||
|
|
||||||
|
/* Set our managers. */
|
||||||
|
this->SetManagers(m_memory_block_slab_manager, m_block_info_manager, m_page_table_manager);
|
||||||
|
|
||||||
|
/* Commit the memory reservation. */
|
||||||
|
memory_reservation.Commit();
|
||||||
|
|
||||||
|
/* Open reference to our resource limit. */
|
||||||
|
m_resource_limit->Open();
|
||||||
|
|
||||||
|
/* Set ourselves as initialized. */
|
||||||
|
m_is_initialized = true;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KSecureSystemResource::Finalize() {
|
||||||
|
/* Check that we have no outstanding allocations. */
|
||||||
|
MESOSPHERE_ABORT_UNLESS(m_memory_block_slab_manager.GetUsed() == 0);
|
||||||
|
MESOSPHERE_ABORT_UNLESS(m_block_info_manager.GetUsed() == 0);
|
||||||
|
MESOSPHERE_ABORT_UNLESS(m_page_table_manager.GetUsed() == 0);
|
||||||
|
|
||||||
|
/* Free our secure memory. */
|
||||||
|
KSystemControl::FreeSecureMemory(m_resource_address, m_resource_size, m_resource_pool);
|
||||||
|
|
||||||
|
/* Release the memory reservation. */
|
||||||
|
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, this->CalculateRequiredSecureMemorySize());
|
||||||
|
|
||||||
|
/* Close reference to our resource limit. */
|
||||||
|
m_resource_limit->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size, KMemoryManager::Pool pool) {
|
||||||
|
return KSystemControl::CalculateRequiredSecureMemorySize(size, pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -100,6 +100,14 @@ namespace ams::kern {
|
||||||
|
|
||||||
/* Check that we have the correct number of dynamic pages available. */
|
/* Check that we have the correct number of dynamic pages available. */
|
||||||
MESOSPHERE_ABORT_UNLESS(g_resource_manager_page_manager.GetCount() - g_resource_manager_page_manager.GetUsed() == ReservedDynamicPageCount);
|
MESOSPHERE_ABORT_UNLESS(g_resource_manager_page_manager.GetCount() - g_resource_manager_page_manager.GetUsed() == ReservedDynamicPageCount);
|
||||||
|
|
||||||
|
/* Create the system page table managers. */
|
||||||
|
KAutoObject::Create<KSystemResource>(std::addressof(s_app_system_resource));
|
||||||
|
KAutoObject::Create<KSystemResource>(std::addressof(s_sys_system_resource));
|
||||||
|
|
||||||
|
/* Set the managers for the system resources. */
|
||||||
|
s_app_system_resource.SetManagers(s_app_memory_block_manager, s_app_block_info_manager, s_app_page_table_manager);
|
||||||
|
s_sys_system_resource.SetManagers(s_sys_memory_block_manager, s_sys_block_info_manager, s_sys_page_table_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kernel::PrintLayout() {
|
void Kernel::PrintLayout() {
|
||||||
|
|
|
@ -40,6 +40,9 @@ namespace ams::kern {
|
||||||
constinit KBlockInfoManager Kernel::s_app_block_info_manager;
|
constinit KBlockInfoManager Kernel::s_app_block_info_manager;
|
||||||
constinit KBlockInfoManager Kernel::s_sys_block_info_manager;
|
constinit KBlockInfoManager Kernel::s_sys_block_info_manager;
|
||||||
|
|
||||||
|
constinit KSystemResource Kernel::s_app_system_resource{util::ConstantInitialize};
|
||||||
|
constinit KSystemResource Kernel::s_sys_system_resource{util::ConstantInitialize};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template<size_t N> requires (N > 0)
|
template<size_t N> requires (N > 0)
|
||||||
|
|
Loading…
Reference in a new issue