Browse Source
Merge pull request #7519 from itsmeft24/master
Merge pull request #7519 from itsmeft24/master
kernel: svc: Implement ProcessMemory and CodeMemory SVCsnce_cpp
committed by
GitHub
12 changed files with 611 additions and 6 deletions
-
2src/core/CMakeLists.txt
-
2src/core/hle/kernel/init/init_slab_setup.cpp
-
5src/core/hle/kernel/k_class_token.cpp
-
146src/core/hle/kernel/k_code_memory.cpp
-
66src/core/hle/kernel/k_code_memory.h
-
20src/core/hle/kernel/k_memory_block.h
-
4src/core/hle/kernel/k_page_linked_list.h
-
119src/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,146 @@ |
|||
// Copyright 2021 yuzu Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include "common/common_types.h"
|
|||
#include "core/device_memory.h"
|
|||
#include "core/hle/kernel/k_auto_object.h"
|
|||
#include "core/hle/kernel/k_code_memory.h"
|
|||
#include "core/hle/kernel/k_light_lock.h"
|
|||
#include "core/hle/kernel/k_memory_block.h"
|
|||
#include "core/hle/kernel/k_page_linked_list.h"
|
|||
#include "core/hle/kernel/k_page_table.h"
|
|||
#include "core/hle/kernel/k_process.h"
|
|||
#include "core/hle/kernel/slab_helpers.h"
|
|||
#include "core/hle/kernel/svc_types.h"
|
|||
#include "core/hle/result.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,66 @@ |
|||
// Copyright 2021 yuzu Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include "common/common_types.h" |
|||
#include "core/device_memory.h" |
|||
#include "core/hle/kernel/k_auto_object.h" |
|||
#include "core/hle/kernel/k_light_lock.h" |
|||
#include "core/hle/kernel/k_page_linked_list.h" |
|||
#include "core/hle/kernel/k_process.h" |
|||
#include "core/hle/kernel/slab_helpers.h" |
|||
#include "core/hle/kernel/svc_types.h" |
|||
#include "core/hle/result.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); |
|||
|
|||
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() const { |
|||
return m_address; |
|||
} |
|||
size_t GetSize() const { |
|||
return m_is_initialized ? m_page_group.GetNumPages() * PageSize : 0; |
|||
} |
|||
|
|||
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{}; |
|||
}; |
|||
|
|||
} // namespace Kernel |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue