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