Browse Source
kernel: svc: Implement Map/UnmapProcessMemory and Create/ControlCodeMemory
kernel: svc: Implement Map/UnmapProcessMemory and Create/ControlCodeMemory
Used by Skyline modding frameworknce_cpp
11 changed files with 636 additions and 7 deletions
-
2src/core/hle/kernel/init/init_slab_setup.cpp
-
5src/core/hle/kernel/k_class_token.cpp
-
159src/core/hle/kernel/k_code_memory.cpp
-
76src/core/hle/kernel/k_code_memory.h
-
20src/core/hle/kernel/k_memory_block.h
-
4src/core/hle/kernel/k_page_linked_list.h
-
124src/core/hle/kernel/k_page_table.cpp
-
8src/core/hle/kernel/k_page_table.h
-
4src/core/hle/kernel/kernel.h
-
214src/core/hle/kernel/svc.cpp
-
27src/core/hle/kernel/svc_wrap.h
@ -0,0 +1,159 @@ |
|||
#include "core/core.h"
|
|||
#include "core/core_timing.h"
|
|||
#include "core/hle/kernel/k_client_port.h"
|
|||
#include "core/hle/kernel/k_client_session.h"
|
|||
#include "core/hle/kernel/k_code_memory.h"
|
|||
#include "core/hle/kernel/k_event.h"
|
|||
#include "core/hle/kernel/k_handle_table.h"
|
|||
#include "core/hle/kernel/k_memory_block.h"
|
|||
#include "core/hle/kernel/k_memory_layout.h"
|
|||
#include "core/hle/kernel/k_page_table.h"
|
|||
#include "core/hle/kernel/k_process.h"
|
|||
#include "core/hle/kernel/k_readable_event.h"
|
|||
#include "core/hle/kernel/k_resource_limit.h"
|
|||
#include "core/hle/kernel/k_scheduler.h"
|
|||
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
|||
#include "core/hle/kernel/k_shared_memory.h"
|
|||
#include "core/hle/kernel/k_synchronization_object.h"
|
|||
#include "core/hle/kernel/k_thread.h"
|
|||
#include "core/hle/kernel/k_transfer_memory.h"
|
|||
#include "core/hle/kernel/k_writable_event.h"
|
|||
#include "core/hle/kernel/kernel.h"
|
|||
#include "core/hle/kernel/physical_core.h"
|
|||
#include "core/hle/kernel/svc.h"
|
|||
#include "core/hle/kernel/svc_results.h"
|
|||
#include "core/hle/kernel/svc_types.h"
|
|||
#include "core/hle/kernel/svc_wrap.h"
|
|||
#include "core/hle/lock.h"
|
|||
#include "core/hle/result.h"
|
|||
#include "core/memory.h"
|
|||
#include "core/reporter.h"
|
|||
namespace Kernel { |
|||
|
|||
KCodeMemory::KCodeMemory(KernelCore& kernel_) |
|||
: KAutoObjectWithSlabHeapAndContainer{kernel_}, m_lock(kernel_) {} |
|||
|
|||
ResultCode KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr, size_t size) { |
|||
// Set members.
|
|||
m_owner = kernel.CurrentProcess(); |
|||
|
|||
// Get the owner page table.
|
|||
auto& page_table = m_owner->PageTable(); |
|||
|
|||
// Construct the page group.
|
|||
KMemoryInfo kBlockInfo = page_table.QueryInfo(addr); |
|||
m_page_group = KPageLinkedList(kBlockInfo.GetAddress(), kBlockInfo.GetNumPages()); |
|||
|
|||
// Lock the memory.
|
|||
R_TRY(page_table.LockForCodeMemory(addr, size)) |
|||
|
|||
// Clear the memory.
|
|||
for (const auto& block : m_page_group.Nodes()) { |
|||
std::memset(device_memory.GetPointer(block.GetAddress()), 0xFF, block.GetSize()); |
|||
} |
|||
|
|||
// Set remaining tracking members.
|
|||
m_address = addr; |
|||
m_is_initialized = true; |
|||
m_is_owner_mapped = false; |
|||
m_is_mapped = false; |
|||
|
|||
// We succeeded.
|
|||
return ResultSuccess; |
|||
} |
|||
|
|||
void KCodeMemory::Finalize() { |
|||
// Unlock.
|
|||
if (!m_is_mapped && !m_is_owner_mapped) { |
|||
const size_t size = m_page_group.GetNumPages() * PageSize; |
|||
m_owner->PageTable().UnlockForCodeMemory(m_address, size); |
|||
} |
|||
} |
|||
|
|||
ResultCode KCodeMemory::Map(VAddr address, size_t size) { |
|||
// Validate the size.
|
|||
R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); |
|||
|
|||
// Lock ourselves.
|
|||
KScopedLightLock lk(m_lock); |
|||
|
|||
// Ensure we're not already mapped.
|
|||
R_UNLESS(!m_is_mapped, ResultInvalidState); |
|||
|
|||
// Map the memory.
|
|||
R_TRY(kernel.CurrentProcess()->PageTable().MapPages( |
|||
address, m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite)); |
|||
|
|||
// Mark ourselves as mapped.
|
|||
m_is_mapped = true; |
|||
|
|||
return ResultSuccess; |
|||
} |
|||
|
|||
ResultCode KCodeMemory::Unmap(VAddr address, size_t size) { |
|||
// Validate the size.
|
|||
R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); |
|||
|
|||
// Lock ourselves.
|
|||
KScopedLightLock lk(m_lock); |
|||
|
|||
// Unmap the memory.
|
|||
R_TRY(kernel.CurrentProcess()->PageTable().UnmapPages(address, m_page_group, |
|||
KMemoryState::CodeOut)); |
|||
|
|||
// Mark ourselves as unmapped.
|
|||
m_is_mapped = false; |
|||
|
|||
return ResultSuccess; |
|||
} |
|||
|
|||
ResultCode KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm) { |
|||
// Validate the size.
|
|||
R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); |
|||
|
|||
// Lock ourselves.
|
|||
KScopedLightLock lk(m_lock); |
|||
|
|||
// Ensure we're not already mapped.
|
|||
R_UNLESS(!m_is_owner_mapped, ResultInvalidState); |
|||
|
|||
// Convert the memory permission.
|
|||
KMemoryPermission k_perm{}; |
|||
switch (perm) { |
|||
case Svc::MemoryPermission::Read: |
|||
k_perm = KMemoryPermission::UserRead; |
|||
break; |
|||
case Svc::MemoryPermission::ReadExecute: |
|||
k_perm = KMemoryPermission::UserReadExecute; |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
|
|||
// Map the memory.
|
|||
R_TRY( |
|||
m_owner->PageTable().MapPages(address, m_page_group, KMemoryState::GeneratedCode, k_perm)); |
|||
|
|||
// Mark ourselves as mapped.
|
|||
m_is_owner_mapped = true; |
|||
|
|||
return ResultSuccess; |
|||
} |
|||
|
|||
ResultCode KCodeMemory::UnmapFromOwner(VAddr address, size_t size) { |
|||
// Validate the size.
|
|||
R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); |
|||
|
|||
// Lock ourselves.
|
|||
KScopedLightLock lk(m_lock); |
|||
|
|||
// Unmap the memory.
|
|||
R_TRY(m_owner->PageTable().UnmapPages(address, m_page_group, KMemoryState::GeneratedCode)); |
|||
|
|||
// Mark ourselves as unmapped.
|
|||
m_is_owner_mapped = false; |
|||
|
|||
return ResultSuccess; |
|||
} |
|||
|
|||
} // namespace Kernel
|
|||
@ -0,0 +1,76 @@ |
|||
#pragma once |
|||
|
|||
#include "core/core.h" |
|||
#include "core/core_timing.h" |
|||
#include "core/hle/kernel/k_client_port.h" |
|||
#include "core/hle/kernel/k_client_session.h" |
|||
#include "core/hle/kernel/k_event.h" |
|||
#include "core/hle/kernel/k_handle_table.h" |
|||
#include "core/hle/kernel/k_memory_block.h" |
|||
#include "core/hle/kernel/k_memory_layout.h" |
|||
#include "core/hle/kernel/k_page_table.h" |
|||
#include "core/hle/kernel/k_process.h" |
|||
#include "core/hle/kernel/k_readable_event.h" |
|||
#include "core/hle/kernel/k_resource_limit.h" |
|||
#include "core/hle/kernel/k_scheduler.h" |
|||
#include "core/hle/kernel/k_scoped_resource_reservation.h" |
|||
#include "core/hle/kernel/k_shared_memory.h" |
|||
#include "core/hle/kernel/k_synchronization_object.h" |
|||
#include "core/hle/kernel/k_thread.h" |
|||
#include "core/hle/kernel/k_transfer_memory.h" |
|||
#include "core/hle/kernel/k_writable_event.h" |
|||
#include "core/hle/kernel/kernel.h" |
|||
#include "core/hle/kernel/physical_core.h" |
|||
#include "core/hle/kernel/svc.h" |
|||
#include "core/hle/kernel/svc_results.h" |
|||
#include "core/hle/kernel/svc_types.h" |
|||
#include "core/hle/kernel/svc_wrap.h" |
|||
#include "core/hle/lock.h" |
|||
#include "core/hle/result.h" |
|||
#include "core/memory.h" |
|||
#include "core/reporter.h" |
|||
|
|||
namespace Kernel { |
|||
|
|||
enum class CodeMemoryOperation : u32 { Map = 0, MapToOwner = 1, Unmap = 2, UnmapFromOwner = 3 }; |
|||
|
|||
class KCodeMemory final |
|||
: public KAutoObjectWithSlabHeapAndContainer<KCodeMemory, KAutoObjectWithList> { |
|||
KERNEL_AUTOOBJECT_TRAITS(KCodeMemory, KAutoObject); |
|||
|
|||
private: |
|||
KPageLinkedList m_page_group; |
|||
KProcess* m_owner; |
|||
VAddr m_address; |
|||
KLightLock m_lock; |
|||
bool m_is_initialized; |
|||
bool m_is_owner_mapped; |
|||
bool m_is_mapped; |
|||
|
|||
public: |
|||
explicit KCodeMemory(KernelCore& kernel_); |
|||
|
|||
ResultCode Initialize(Core::DeviceMemory& device_memory, VAddr address, size_t size); |
|||
void Finalize(); |
|||
|
|||
ResultCode Map(VAddr address, size_t size); |
|||
ResultCode Unmap(VAddr address, size_t size); |
|||
ResultCode MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm); |
|||
ResultCode UnmapFromOwner(VAddr address, size_t size); |
|||
|
|||
bool IsInitialized() const { |
|||
return m_is_initialized; |
|||
} |
|||
static void PostDestroy([[maybe_unused]] uintptr_t arg) {} |
|||
|
|||
KProcess* GetOwner() const { |
|||
return m_owner; |
|||
} |
|||
VAddr GetSourceAddress() { |
|||
return m_address; |
|||
} |
|||
size_t GetSize() const { |
|||
return m_is_initialized ? m_page_group.GetNumPages() * PageSize : 0; |
|||
} |
|||
}; |
|||
} // namespace Kernel |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue