hle: kernel: Migrate to KMemoryBlock, KMemoryBlockManager, and others.
This commit is contained in:
parent
9e520e8f12
commit
65e0178cc0
@ -166,6 +166,9 @@ add_library(core STATIC
|
|||||||
hle/kernel/k_light_condition_variable.h
|
hle/kernel/k_light_condition_variable.h
|
||||||
hle/kernel/k_light_lock.cpp
|
hle/kernel/k_light_lock.cpp
|
||||||
hle/kernel/k_light_lock.h
|
hle/kernel/k_light_lock.h
|
||||||
|
hle/kernel/k_memory_block.h
|
||||||
|
hle/kernel/k_memory_block_manager.cpp
|
||||||
|
hle/kernel/k_memory_block_manager.h
|
||||||
hle/kernel/k_memory_layout.h
|
hle/kernel/k_memory_layout.h
|
||||||
hle/kernel/k_page_bitmap.h
|
hle/kernel/k_page_bitmap.h
|
||||||
hle/kernel/k_priority_queue.h
|
hle/kernel/k_priority_queue.h
|
||||||
@ -195,12 +198,9 @@ add_library(core STATIC
|
|||||||
hle/kernel/k_writable_event.h
|
hle/kernel/k_writable_event.h
|
||||||
hle/kernel/kernel.cpp
|
hle/kernel/kernel.cpp
|
||||||
hle/kernel/kernel.h
|
hle/kernel/kernel.h
|
||||||
hle/kernel/memory/memory_block.h
|
hle/kernel/memory_types.h
|
||||||
hle/kernel/memory/memory_block_manager.cpp
|
|
||||||
hle/kernel/memory/memory_block_manager.h
|
|
||||||
hle/kernel/memory/memory_manager.cpp
|
hle/kernel/memory/memory_manager.cpp
|
||||||
hle/kernel/memory/memory_manager.h
|
hle/kernel/memory/memory_manager.h
|
||||||
hle/kernel/memory/memory_types.h
|
|
||||||
hle/kernel/memory/page_linked_list.h
|
hle/kernel/memory/page_linked_list.h
|
||||||
hle/kernel/memory/page_heap.cpp
|
hle/kernel/memory/page_heap.cpp
|
||||||
hle/kernel/memory/page_heap.h
|
hle/kernel/memory/page_heap.h
|
||||||
|
@ -2,20 +2,17 @@
|
|||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
// This file references various implementation details from Atmosphere, an open-source firmware for
|
|
||||||
// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/kernel/memory/memory_types.h"
|
#include "core/hle/kernel/memory_types.h"
|
||||||
#include "core/hle/kernel/svc_types.h"
|
#include "core/hle/kernel/svc_types.h"
|
||||||
|
|
||||||
namespace Kernel::Memory {
|
namespace Kernel {
|
||||||
|
|
||||||
enum class MemoryState : u32 {
|
enum class KMemoryState : u32 {
|
||||||
None = 0,
|
None = 0,
|
||||||
Mask = 0xFF,
|
Mask = 0xFF,
|
||||||
All = ~None,
|
All = ~None,
|
||||||
@ -97,31 +94,31 @@ enum class MemoryState : u32 {
|
|||||||
FlagReferenceCounted | FlagCanDebug,
|
FlagReferenceCounted | FlagCanDebug,
|
||||||
CodeOut = static_cast<u32>(Svc::MemoryState::CodeOut) | FlagMapped | FlagReferenceCounted,
|
CodeOut = static_cast<u32>(Svc::MemoryState::CodeOut) | FlagMapped | FlagReferenceCounted,
|
||||||
};
|
};
|
||||||
DECLARE_ENUM_FLAG_OPERATORS(MemoryState);
|
DECLARE_ENUM_FLAG_OPERATORS(KMemoryState);
|
||||||
|
|
||||||
static_assert(static_cast<u32>(MemoryState::Free) == 0x00000000);
|
static_assert(static_cast<u32>(KMemoryState::Free) == 0x00000000);
|
||||||
static_assert(static_cast<u32>(MemoryState::Io) == 0x00002001);
|
static_assert(static_cast<u32>(KMemoryState::Io) == 0x00002001);
|
||||||
static_assert(static_cast<u32>(MemoryState::Static) == 0x00042002);
|
static_assert(static_cast<u32>(KMemoryState::Static) == 0x00042002);
|
||||||
static_assert(static_cast<u32>(MemoryState::Code) == 0x00DC7E03);
|
static_assert(static_cast<u32>(KMemoryState::Code) == 0x00DC7E03);
|
||||||
static_assert(static_cast<u32>(MemoryState::CodeData) == 0x03FEBD04);
|
static_assert(static_cast<u32>(KMemoryState::CodeData) == 0x03FEBD04);
|
||||||
static_assert(static_cast<u32>(MemoryState::Normal) == 0x037EBD05);
|
static_assert(static_cast<u32>(KMemoryState::Normal) == 0x037EBD05);
|
||||||
static_assert(static_cast<u32>(MemoryState::Shared) == 0x00402006);
|
static_assert(static_cast<u32>(KMemoryState::Shared) == 0x00402006);
|
||||||
static_assert(static_cast<u32>(MemoryState::AliasCode) == 0x00DD7E08);
|
static_assert(static_cast<u32>(KMemoryState::AliasCode) == 0x00DD7E08);
|
||||||
static_assert(static_cast<u32>(MemoryState::AliasCodeData) == 0x03FFBD09);
|
static_assert(static_cast<u32>(KMemoryState::AliasCodeData) == 0x03FFBD09);
|
||||||
static_assert(static_cast<u32>(MemoryState::Ipc) == 0x005C3C0A);
|
static_assert(static_cast<u32>(KMemoryState::Ipc) == 0x005C3C0A);
|
||||||
static_assert(static_cast<u32>(MemoryState::Stack) == 0x005C3C0B);
|
static_assert(static_cast<u32>(KMemoryState::Stack) == 0x005C3C0B);
|
||||||
static_assert(static_cast<u32>(MemoryState::ThreadLocal) == 0x0040200C);
|
static_assert(static_cast<u32>(KMemoryState::ThreadLocal) == 0x0040200C);
|
||||||
static_assert(static_cast<u32>(MemoryState::Transferred) == 0x015C3C0D);
|
static_assert(static_cast<u32>(KMemoryState::Transferred) == 0x015C3C0D);
|
||||||
static_assert(static_cast<u32>(MemoryState::SharedTransferred) == 0x005C380E);
|
static_assert(static_cast<u32>(KMemoryState::SharedTransferred) == 0x005C380E);
|
||||||
static_assert(static_cast<u32>(MemoryState::SharedCode) == 0x0040380F);
|
static_assert(static_cast<u32>(KMemoryState::SharedCode) == 0x0040380F);
|
||||||
static_assert(static_cast<u32>(MemoryState::Inaccessible) == 0x00000010);
|
static_assert(static_cast<u32>(KMemoryState::Inaccessible) == 0x00000010);
|
||||||
static_assert(static_cast<u32>(MemoryState::NonSecureIpc) == 0x005C3811);
|
static_assert(static_cast<u32>(KMemoryState::NonSecureIpc) == 0x005C3811);
|
||||||
static_assert(static_cast<u32>(MemoryState::NonDeviceIpc) == 0x004C2812);
|
static_assert(static_cast<u32>(KMemoryState::NonDeviceIpc) == 0x004C2812);
|
||||||
static_assert(static_cast<u32>(MemoryState::Kernel) == 0x00002013);
|
static_assert(static_cast<u32>(KMemoryState::Kernel) == 0x00002013);
|
||||||
static_assert(static_cast<u32>(MemoryState::GeneratedCode) == 0x00402214);
|
static_assert(static_cast<u32>(KMemoryState::GeneratedCode) == 0x00402214);
|
||||||
static_assert(static_cast<u32>(MemoryState::CodeOut) == 0x00402015);
|
static_assert(static_cast<u32>(KMemoryState::CodeOut) == 0x00402015);
|
||||||
|
|
||||||
enum class MemoryPermission : u8 {
|
enum class KMemoryPermission : u8 {
|
||||||
None = 0,
|
None = 0,
|
||||||
Mask = static_cast<u8>(~None),
|
Mask = static_cast<u8>(~None),
|
||||||
|
|
||||||
@ -135,9 +132,9 @@ enum class MemoryPermission : u8 {
|
|||||||
UserMask = static_cast<u8>(Svc::MemoryPermission::Read | Svc::MemoryPermission::Write |
|
UserMask = static_cast<u8>(Svc::MemoryPermission::Read | Svc::MemoryPermission::Write |
|
||||||
Svc::MemoryPermission::Execute),
|
Svc::MemoryPermission::Execute),
|
||||||
};
|
};
|
||||||
DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission);
|
DECLARE_ENUM_FLAG_OPERATORS(KMemoryPermission);
|
||||||
|
|
||||||
enum class MemoryAttribute : u8 {
|
enum class KMemoryAttribute : u8 {
|
||||||
None = 0x00,
|
None = 0x00,
|
||||||
Mask = 0x7F,
|
Mask = 0x7F,
|
||||||
All = Mask,
|
All = Mask,
|
||||||
@ -152,18 +149,18 @@ enum class MemoryAttribute : u8 {
|
|||||||
LockedAndIpcLocked = Locked | IpcLocked,
|
LockedAndIpcLocked = Locked | IpcLocked,
|
||||||
DeviceSharedAndUncached = DeviceShared | Uncached
|
DeviceSharedAndUncached = DeviceShared | Uncached
|
||||||
};
|
};
|
||||||
DECLARE_ENUM_FLAG_OPERATORS(MemoryAttribute);
|
DECLARE_ENUM_FLAG_OPERATORS(KMemoryAttribute);
|
||||||
|
|
||||||
static_assert((static_cast<u8>(MemoryAttribute::Mask) &
|
static_assert((static_cast<u8>(KMemoryAttribute::Mask) &
|
||||||
static_cast<u8>(MemoryAttribute::DontCareMask)) == 0);
|
static_cast<u8>(KMemoryAttribute::DontCareMask)) == 0);
|
||||||
|
|
||||||
struct MemoryInfo {
|
struct KMemoryInfo {
|
||||||
VAddr addr{};
|
VAddr addr{};
|
||||||
std::size_t size{};
|
std::size_t size{};
|
||||||
MemoryState state{};
|
KMemoryState state{};
|
||||||
MemoryPermission perm{};
|
KMemoryPermission perm{};
|
||||||
MemoryAttribute attribute{};
|
KMemoryAttribute attribute{};
|
||||||
MemoryPermission original_perm{};
|
KMemoryPermission original_perm{};
|
||||||
u16 ipc_lock_count{};
|
u16 ipc_lock_count{};
|
||||||
u16 device_use_count{};
|
u16 device_use_count{};
|
||||||
|
|
||||||
@ -171,9 +168,9 @@ struct MemoryInfo {
|
|||||||
return {
|
return {
|
||||||
addr,
|
addr,
|
||||||
size,
|
size,
|
||||||
static_cast<Svc::MemoryState>(state & MemoryState::Mask),
|
static_cast<Svc::MemoryState>(state & KMemoryState::Mask),
|
||||||
static_cast<Svc::MemoryAttribute>(attribute & MemoryAttribute::Mask),
|
static_cast<Svc::MemoryAttribute>(attribute & KMemoryAttribute::Mask),
|
||||||
static_cast<Svc::MemoryPermission>(perm & MemoryPermission::UserMask),
|
static_cast<Svc::MemoryPermission>(perm & KMemoryPermission::UserMask),
|
||||||
ipc_lock_count,
|
ipc_lock_count,
|
||||||
device_use_count,
|
device_use_count,
|
||||||
};
|
};
|
||||||
@ -196,21 +193,21 @@ struct MemoryInfo {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MemoryBlock final {
|
class KMemoryBlock final {
|
||||||
friend class MemoryBlockManager;
|
friend class KMemoryBlockManager;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VAddr addr{};
|
VAddr addr{};
|
||||||
std::size_t num_pages{};
|
std::size_t num_pages{};
|
||||||
MemoryState state{MemoryState::None};
|
KMemoryState state{KMemoryState::None};
|
||||||
u16 ipc_lock_count{};
|
u16 ipc_lock_count{};
|
||||||
u16 device_use_count{};
|
u16 device_use_count{};
|
||||||
MemoryPermission perm{MemoryPermission::None};
|
KMemoryPermission perm{KMemoryPermission::None};
|
||||||
MemoryPermission original_perm{MemoryPermission::None};
|
KMemoryPermission original_perm{KMemoryPermission::None};
|
||||||
MemoryAttribute attribute{MemoryAttribute::None};
|
KMemoryAttribute attribute{KMemoryAttribute::None};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr int Compare(const MemoryBlock& lhs, const MemoryBlock& rhs) {
|
static constexpr int Compare(const KMemoryBlock& lhs, const KMemoryBlock& rhs) {
|
||||||
if (lhs.GetAddress() < rhs.GetAddress()) {
|
if (lhs.GetAddress() < rhs.GetAddress()) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (lhs.GetAddress() <= rhs.GetLastAddress()) {
|
} else if (lhs.GetAddress() <= rhs.GetLastAddress()) {
|
||||||
@ -221,9 +218,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr MemoryBlock() = default;
|
constexpr KMemoryBlock() = default;
|
||||||
constexpr MemoryBlock(VAddr addr_, std::size_t num_pages_, MemoryState state_,
|
constexpr KMemoryBlock(VAddr addr_, std::size_t num_pages_, KMemoryState state_,
|
||||||
MemoryPermission perm_, MemoryAttribute attribute_)
|
KMemoryPermission perm_, KMemoryAttribute attribute_)
|
||||||
: addr{addr_}, num_pages(num_pages_), state{state_}, perm{perm_}, attribute{attribute_} {}
|
: addr{addr_}, num_pages(num_pages_), state{state_}, perm{perm_}, attribute{attribute_} {}
|
||||||
|
|
||||||
constexpr VAddr GetAddress() const {
|
constexpr VAddr GetAddress() const {
|
||||||
@ -246,40 +243,40 @@ public:
|
|||||||
return GetEndAddress() - 1;
|
return GetEndAddress() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr MemoryInfo GetMemoryInfo() const {
|
constexpr KMemoryInfo GetMemoryInfo() const {
|
||||||
return {
|
return {
|
||||||
GetAddress(), GetSize(), state, perm,
|
GetAddress(), GetSize(), state, perm,
|
||||||
attribute, original_perm, ipc_lock_count, device_use_count,
|
attribute, original_perm, ipc_lock_count, device_use_count,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareToDevice(MemoryPermission /*new_perm*/) {
|
void ShareToDevice(KMemoryPermission /*new_perm*/) {
|
||||||
ASSERT((attribute & MemoryAttribute::DeviceShared) == MemoryAttribute::DeviceShared ||
|
ASSERT((attribute & KMemoryAttribute::DeviceShared) == KMemoryAttribute::DeviceShared ||
|
||||||
device_use_count == 0);
|
device_use_count == 0);
|
||||||
attribute |= MemoryAttribute::DeviceShared;
|
attribute |= KMemoryAttribute::DeviceShared;
|
||||||
const u16 new_use_count{++device_use_count};
|
const u16 new_use_count{++device_use_count};
|
||||||
ASSERT(new_use_count > 0);
|
ASSERT(new_use_count > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnshareToDevice(MemoryPermission /*new_perm*/) {
|
void UnshareToDevice(KMemoryPermission /*new_perm*/) {
|
||||||
ASSERT((attribute & MemoryAttribute::DeviceShared) == MemoryAttribute::DeviceShared);
|
ASSERT((attribute & KMemoryAttribute::DeviceShared) == KMemoryAttribute::DeviceShared);
|
||||||
const u16 prev_use_count{device_use_count--};
|
const u16 prev_use_count{device_use_count--};
|
||||||
ASSERT(prev_use_count > 0);
|
ASSERT(prev_use_count > 0);
|
||||||
if (prev_use_count == 1) {
|
if (prev_use_count == 1) {
|
||||||
attribute &= ~MemoryAttribute::DeviceShared;
|
attribute &= ~KMemoryAttribute::DeviceShared;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
constexpr bool HasProperties(MemoryState s, MemoryPermission p, MemoryAttribute a) const {
|
constexpr bool HasProperties(KMemoryState s, KMemoryPermission p, KMemoryAttribute a) const {
|
||||||
constexpr MemoryAttribute AttributeIgnoreMask{MemoryAttribute::DontCareMask |
|
constexpr KMemoryAttribute AttributeIgnoreMask{KMemoryAttribute::DontCareMask |
|
||||||
MemoryAttribute::IpcLocked |
|
KMemoryAttribute::IpcLocked |
|
||||||
MemoryAttribute::DeviceShared};
|
KMemoryAttribute::DeviceShared};
|
||||||
return state == s && perm == p &&
|
return state == s && perm == p &&
|
||||||
(attribute | AttributeIgnoreMask) == (a | AttributeIgnoreMask);
|
(attribute | AttributeIgnoreMask) == (a | AttributeIgnoreMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool HasSameProperties(const MemoryBlock& rhs) const {
|
constexpr bool HasSameProperties(const KMemoryBlock& rhs) const {
|
||||||
return state == rhs.state && perm == rhs.perm && original_perm == rhs.original_perm &&
|
return state == rhs.state && perm == rhs.perm && original_perm == rhs.original_perm &&
|
||||||
attribute == rhs.attribute && ipc_lock_count == rhs.ipc_lock_count &&
|
attribute == rhs.attribute && ipc_lock_count == rhs.ipc_lock_count &&
|
||||||
device_use_count == rhs.device_use_count;
|
device_use_count == rhs.device_use_count;
|
||||||
@ -296,25 +293,25 @@ private:
|
|||||||
num_pages += count;
|
num_pages += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void Update(MemoryState new_state, MemoryPermission new_perm,
|
constexpr void Update(KMemoryState new_state, KMemoryPermission new_perm,
|
||||||
MemoryAttribute new_attribute) {
|
KMemoryAttribute new_attribute) {
|
||||||
ASSERT(original_perm == MemoryPermission::None);
|
ASSERT(original_perm == KMemoryPermission::None);
|
||||||
ASSERT((attribute & MemoryAttribute::IpcLocked) == MemoryAttribute::None);
|
ASSERT((attribute & KMemoryAttribute::IpcLocked) == KMemoryAttribute::None);
|
||||||
|
|
||||||
state = new_state;
|
state = new_state;
|
||||||
perm = new_perm;
|
perm = new_perm;
|
||||||
|
|
||||||
attribute = static_cast<MemoryAttribute>(
|
attribute = static_cast<KMemoryAttribute>(
|
||||||
new_attribute |
|
new_attribute |
|
||||||
(attribute & (MemoryAttribute::IpcLocked | MemoryAttribute::DeviceShared)));
|
(attribute & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared)));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr MemoryBlock Split(VAddr split_addr) {
|
constexpr KMemoryBlock Split(VAddr split_addr) {
|
||||||
ASSERT(GetAddress() < split_addr);
|
ASSERT(GetAddress() < split_addr);
|
||||||
ASSERT(Contains(split_addr));
|
ASSERT(Contains(split_addr));
|
||||||
ASSERT(Common::IsAligned(split_addr, PageSize));
|
ASSERT(Common::IsAligned(split_addr, PageSize));
|
||||||
|
|
||||||
MemoryBlock block;
|
KMemoryBlock block;
|
||||||
block.addr = addr;
|
block.addr = addr;
|
||||||
block.num_pages = (split_addr - GetAddress()) / PageSize;
|
block.num_pages = (split_addr - GetAddress()) / PageSize;
|
||||||
block.state = state;
|
block.state = state;
|
||||||
@ -330,6 +327,6 @@ private:
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static_assert(std::is_trivially_destructible<MemoryBlock>::value);
|
static_assert(std::is_trivially_destructible<KMemoryBlock>::value);
|
||||||
|
|
||||||
} // namespace Kernel::Memory
|
} // namespace Kernel
|
@ -2,19 +2,19 @@
|
|||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "core/hle/kernel/memory/memory_block_manager.h"
|
#include "core/hle/kernel/k_memory_block_manager.h"
|
||||||
#include "core/hle/kernel/memory/memory_types.h"
|
#include "core/hle/kernel/memory_types.h"
|
||||||
|
|
||||||
namespace Kernel::Memory {
|
namespace Kernel {
|
||||||
|
|
||||||
MemoryBlockManager::MemoryBlockManager(VAddr start_addr, VAddr end_addr)
|
KMemoryBlockManager::KMemoryBlockManager(VAddr start_addr, VAddr end_addr)
|
||||||
: start_addr{start_addr}, end_addr{end_addr} {
|
: start_addr{start_addr}, end_addr{end_addr} {
|
||||||
const u64 num_pages{(end_addr - start_addr) / PageSize};
|
const u64 num_pages{(end_addr - start_addr) / PageSize};
|
||||||
memory_block_tree.emplace_back(start_addr, num_pages, MemoryState::Free, MemoryPermission::None,
|
memory_block_tree.emplace_back(start_addr, num_pages, KMemoryState::Free,
|
||||||
MemoryAttribute::None);
|
KMemoryPermission::None, KMemoryAttribute::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBlockManager::iterator MemoryBlockManager::FindIterator(VAddr addr) {
|
KMemoryBlockManager::iterator KMemoryBlockManager::FindIterator(VAddr addr) {
|
||||||
auto node{memory_block_tree.begin()};
|
auto node{memory_block_tree.begin()};
|
||||||
while (node != end()) {
|
while (node != end()) {
|
||||||
const VAddr end_addr{node->GetNumPages() * PageSize + node->GetAddress()};
|
const VAddr end_addr{node->GetNumPages() * PageSize + node->GetAddress()};
|
||||||
@ -26,9 +26,9 @@ MemoryBlockManager::iterator MemoryBlockManager::FindIterator(VAddr addr) {
|
|||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
|
|
||||||
VAddr MemoryBlockManager::FindFreeArea(VAddr region_start, std::size_t region_num_pages,
|
VAddr KMemoryBlockManager::FindFreeArea(VAddr region_start, std::size_t region_num_pages,
|
||||||
std::size_t num_pages, std::size_t align, std::size_t offset,
|
std::size_t num_pages, std::size_t align,
|
||||||
std::size_t guard_pages) {
|
std::size_t offset, std::size_t guard_pages) {
|
||||||
if (num_pages == 0) {
|
if (num_pages == 0) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ VAddr MemoryBlockManager::FindFreeArea(VAddr region_start, std::size_t region_nu
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.state != MemoryState::Free) {
|
if (info.state != KMemoryState::Free) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,17 +63,17 @@ VAddr MemoryBlockManager::FindFreeArea(VAddr region_start, std::size_t region_nu
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState prev_state,
|
void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState prev_state,
|
||||||
MemoryPermission prev_perm, MemoryAttribute prev_attribute,
|
KMemoryPermission prev_perm, KMemoryAttribute prev_attribute,
|
||||||
MemoryState state, MemoryPermission perm,
|
KMemoryState state, KMemoryPermission perm,
|
||||||
MemoryAttribute attribute) {
|
KMemoryAttribute attribute) {
|
||||||
const VAddr end_addr{addr + num_pages * PageSize};
|
const VAddr end_addr{addr + num_pages * PageSize};
|
||||||
iterator node{memory_block_tree.begin()};
|
iterator node{memory_block_tree.begin()};
|
||||||
|
|
||||||
prev_attribute |= MemoryAttribute::IpcAndDeviceMapped;
|
prev_attribute |= KMemoryAttribute::IpcAndDeviceMapped;
|
||||||
|
|
||||||
while (node != memory_block_tree.end()) {
|
while (node != memory_block_tree.end()) {
|
||||||
MemoryBlock* block{&(*node)};
|
KMemoryBlock* block{&(*node)};
|
||||||
iterator next_node{std::next(node)};
|
iterator next_node{std::next(node)};
|
||||||
const VAddr cur_addr{block->GetAddress()};
|
const VAddr cur_addr{block->GetAddress()};
|
||||||
const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr};
|
const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr};
|
||||||
@ -106,13 +106,13 @@ void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState state,
|
void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState state,
|
||||||
MemoryPermission perm, MemoryAttribute attribute) {
|
KMemoryPermission perm, KMemoryAttribute attribute) {
|
||||||
const VAddr end_addr{addr + num_pages * PageSize};
|
const VAddr end_addr{addr + num_pages * PageSize};
|
||||||
iterator node{memory_block_tree.begin()};
|
iterator node{memory_block_tree.begin()};
|
||||||
|
|
||||||
while (node != memory_block_tree.end()) {
|
while (node != memory_block_tree.end()) {
|
||||||
MemoryBlock* block{&(*node)};
|
KMemoryBlock* block{&(*node)};
|
||||||
iterator next_node{std::next(node)};
|
iterator next_node{std::next(node)};
|
||||||
const VAddr cur_addr{block->GetAddress()};
|
const VAddr cur_addr{block->GetAddress()};
|
||||||
const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr};
|
const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr};
|
||||||
@ -141,13 +141,13 @@ void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func,
|
void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func,
|
||||||
MemoryPermission perm) {
|
KMemoryPermission perm) {
|
||||||
const VAddr end_addr{addr + num_pages * PageSize};
|
const VAddr end_addr{addr + num_pages * PageSize};
|
||||||
iterator node{memory_block_tree.begin()};
|
iterator node{memory_block_tree.begin()};
|
||||||
|
|
||||||
while (node != memory_block_tree.end()) {
|
while (node != memory_block_tree.end()) {
|
||||||
MemoryBlock* block{&(*node)};
|
KMemoryBlock* block{&(*node)};
|
||||||
iterator next_node{std::next(node)};
|
iterator next_node{std::next(node)};
|
||||||
const VAddr cur_addr{block->GetAddress()};
|
const VAddr cur_addr{block->GetAddress()};
|
||||||
const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr};
|
const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr};
|
||||||
@ -176,9 +176,9 @@ void MemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryBlockManager::IterateForRange(VAddr start, VAddr end, IterateFunc&& func) {
|
void KMemoryBlockManager::IterateForRange(VAddr start, VAddr end, IterateFunc&& func) {
|
||||||
const_iterator it{FindIterator(start)};
|
const_iterator it{FindIterator(start)};
|
||||||
MemoryInfo info{};
|
KMemoryInfo info{};
|
||||||
do {
|
do {
|
||||||
info = it->GetMemoryInfo();
|
info = it->GetMemoryInfo();
|
||||||
func(info);
|
func(info);
|
||||||
@ -186,8 +186,8 @@ void MemoryBlockManager::IterateForRange(VAddr start, VAddr end, IterateFunc&& f
|
|||||||
} while (info.addr + info.size - 1 < end - 1 && it != cend());
|
} while (info.addr + info.size - 1 < end - 1 && it != cend());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryBlockManager::MergeAdjacent(iterator it, iterator& next_it) {
|
void KMemoryBlockManager::MergeAdjacent(iterator it, iterator& next_it) {
|
||||||
MemoryBlock* block{&(*it)};
|
KMemoryBlock* block{&(*it)};
|
||||||
|
|
||||||
auto EraseIt = [&](const iterator it_to_erase) {
|
auto EraseIt = [&](const iterator it_to_erase) {
|
||||||
if (next_it == it_to_erase) {
|
if (next_it == it_to_erase) {
|
||||||
@ -197,7 +197,7 @@ void MemoryBlockManager::MergeAdjacent(iterator it, iterator& next_it) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (it != memory_block_tree.begin()) {
|
if (it != memory_block_tree.begin()) {
|
||||||
MemoryBlock* prev{&(*std::prev(it))};
|
KMemoryBlock* prev{&(*std::prev(it))};
|
||||||
|
|
||||||
if (block->HasSameProperties(*prev)) {
|
if (block->HasSameProperties(*prev)) {
|
||||||
const iterator prev_it{std::prev(it)};
|
const iterator prev_it{std::prev(it)};
|
||||||
@ -211,7 +211,7 @@ void MemoryBlockManager::MergeAdjacent(iterator it, iterator& next_it) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (it != cend()) {
|
if (it != cend()) {
|
||||||
const MemoryBlock* const next{&(*std::next(it))};
|
const KMemoryBlock* const next{&(*std::next(it))};
|
||||||
|
|
||||||
if (block->HasSameProperties(*next)) {
|
if (block->HasSameProperties(*next)) {
|
||||||
block->Add(next->GetNumPages());
|
block->Add(next->GetNumPages());
|
||||||
@ -220,4 +220,4 @@ void MemoryBlockManager::MergeAdjacent(iterator it, iterator& next_it) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Kernel::Memory
|
} // namespace Kernel
|
@ -8,18 +8,18 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/kernel/memory/memory_block.h"
|
#include "core/hle/kernel/k_memory_block.h"
|
||||||
|
|
||||||
namespace Kernel::Memory {
|
namespace Kernel {
|
||||||
|
|
||||||
class MemoryBlockManager final {
|
class KMemoryBlockManager final {
|
||||||
public:
|
public:
|
||||||
using MemoryBlockTree = std::list<MemoryBlock>;
|
using MemoryBlockTree = std::list<KMemoryBlock>;
|
||||||
using iterator = MemoryBlockTree::iterator;
|
using iterator = MemoryBlockTree::iterator;
|
||||||
using const_iterator = MemoryBlockTree::const_iterator;
|
using const_iterator = MemoryBlockTree::const_iterator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemoryBlockManager(VAddr start_addr, VAddr end_addr);
|
KMemoryBlockManager(VAddr start_addr, VAddr end_addr);
|
||||||
|
|
||||||
iterator end() {
|
iterator end() {
|
||||||
return memory_block_tree.end();
|
return memory_block_tree.end();
|
||||||
@ -36,21 +36,22 @@ public:
|
|||||||
VAddr FindFreeArea(VAddr region_start, std::size_t region_num_pages, std::size_t num_pages,
|
VAddr FindFreeArea(VAddr region_start, std::size_t region_num_pages, std::size_t num_pages,
|
||||||
std::size_t align, std::size_t offset, std::size_t guard_pages);
|
std::size_t align, std::size_t offset, std::size_t guard_pages);
|
||||||
|
|
||||||
void Update(VAddr addr, std::size_t num_pages, MemoryState prev_state,
|
void Update(VAddr addr, std::size_t num_pages, KMemoryState prev_state,
|
||||||
MemoryPermission prev_perm, MemoryAttribute prev_attribute, MemoryState state,
|
KMemoryPermission prev_perm, KMemoryAttribute prev_attribute, KMemoryState state,
|
||||||
MemoryPermission perm, MemoryAttribute attribute);
|
KMemoryPermission perm, KMemoryAttribute attribute);
|
||||||
|
|
||||||
void Update(VAddr addr, std::size_t num_pages, MemoryState state,
|
void Update(VAddr addr, std::size_t num_pages, KMemoryState state,
|
||||||
MemoryPermission perm = MemoryPermission::None,
|
KMemoryPermission perm = KMemoryPermission::None,
|
||||||
MemoryAttribute attribute = MemoryAttribute::None);
|
KMemoryAttribute attribute = KMemoryAttribute::None);
|
||||||
|
|
||||||
using LockFunc = std::function<void(iterator, MemoryPermission)>;
|
using LockFunc = std::function<void(iterator, KMemoryPermission)>;
|
||||||
void UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, MemoryPermission perm);
|
void UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func,
|
||||||
|
KMemoryPermission perm);
|
||||||
|
|
||||||
using IterateFunc = std::function<void(const MemoryInfo&)>;
|
using IterateFunc = std::function<void(const KMemoryInfo&)>;
|
||||||
void IterateForRange(VAddr start, VAddr end, IterateFunc&& func);
|
void IterateForRange(VAddr start, VAddr end, IterateFunc&& func);
|
||||||
|
|
||||||
MemoryBlock& FindBlock(VAddr addr) {
|
KMemoryBlock& FindBlock(VAddr addr) {
|
||||||
return *FindIterator(addr);
|
return *FindIterator(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,4 +64,4 @@ private:
|
|||||||
MemoryBlockTree memory_block_tree;
|
MemoryBlockTree memory_block_tree;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Kernel::Memory
|
} // namespace Kernel
|
@ -20,8 +20,8 @@ KSharedMemory::~KSharedMemory() {
|
|||||||
|
|
||||||
std::shared_ptr<KSharedMemory> KSharedMemory::Create(
|
std::shared_ptr<KSharedMemory> KSharedMemory::Create(
|
||||||
KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process,
|
KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process,
|
||||||
Memory::PageLinkedList&& page_list, Memory::MemoryPermission owner_permission,
|
Memory::PageLinkedList&& page_list, KMemoryPermission owner_permission,
|
||||||
Memory::MemoryPermission user_permission, PAddr physical_address, std::size_t size,
|
KMemoryPermission user_permission, PAddr physical_address, std::size_t size,
|
||||||
std::string name) {
|
std::string name) {
|
||||||
|
|
||||||
const auto resource_limit = kernel.GetSystemResourceLimit();
|
const auto resource_limit = kernel.GetSystemResourceLimit();
|
||||||
@ -45,21 +45,21 @@ std::shared_ptr<KSharedMemory> KSharedMemory::Create(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode KSharedMemory::Map(Process& target_process, VAddr address, std::size_t size,
|
ResultCode KSharedMemory::Map(Process& target_process, VAddr address, std::size_t size,
|
||||||
Memory::MemoryPermission permissions) {
|
KMemoryPermission permissions) {
|
||||||
const u64 page_count{(size + Memory::PageSize - 1) / Memory::PageSize};
|
const u64 page_count{(size + PageSize - 1) / PageSize};
|
||||||
|
|
||||||
if (page_list.GetNumPages() != page_count) {
|
if (page_list.GetNumPages() != page_count) {
|
||||||
UNIMPLEMENTED_MSG("Page count does not match");
|
UNIMPLEMENTED_MSG("Page count does not match");
|
||||||
}
|
}
|
||||||
|
|
||||||
const Memory::MemoryPermission expected =
|
const KMemoryPermission expected =
|
||||||
&target_process == owner_process ? owner_permission : user_permission;
|
&target_process == owner_process ? owner_permission : user_permission;
|
||||||
|
|
||||||
if (permissions != expected) {
|
if (permissions != expected) {
|
||||||
UNIMPLEMENTED_MSG("Permission does not match");
|
UNIMPLEMENTED_MSG("Permission does not match");
|
||||||
}
|
}
|
||||||
|
|
||||||
return target_process.PageTable().MapPages(address, page_list, Memory::MemoryState::Shared,
|
return target_process.PageTable().MapPages(address, page_list, KMemoryState::Shared,
|
||||||
permissions);
|
permissions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/device_memory.h"
|
#include "core/device_memory.h"
|
||||||
#include "core/hle/kernel/memory/memory_block.h"
|
#include "core/hle/kernel/k_memory_block.h"
|
||||||
#include "core/hle/kernel/memory/page_linked_list.h"
|
#include "core/hle/kernel/memory/page_linked_list.h"
|
||||||
#include "core/hle/kernel/object.h"
|
#include "core/hle/kernel/object.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
@ -26,8 +26,8 @@ public:
|
|||||||
|
|
||||||
static std::shared_ptr<KSharedMemory> Create(
|
static std::shared_ptr<KSharedMemory> Create(
|
||||||
KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process,
|
KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process,
|
||||||
Memory::PageLinkedList&& page_list, Memory::MemoryPermission owner_permission,
|
Memory::PageLinkedList&& page_list, KMemoryPermission owner_permission,
|
||||||
Memory::MemoryPermission user_permission, PAddr physical_address, std::size_t size,
|
KMemoryPermission user_permission, PAddr physical_address, std::size_t size,
|
||||||
std::string name);
|
std::string name);
|
||||||
|
|
||||||
std::string GetTypeName() const override {
|
std::string GetTypeName() const override {
|
||||||
@ -51,7 +51,7 @@ public:
|
|||||||
* @param permissions Memory block map permissions (specified by SVC field)
|
* @param permissions Memory block map permissions (specified by SVC field)
|
||||||
*/
|
*/
|
||||||
ResultCode Map(Process& target_process, VAddr address, std::size_t size,
|
ResultCode Map(Process& target_process, VAddr address, std::size_t size,
|
||||||
Memory::MemoryPermission permissions);
|
KMemoryPermission permissions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a pointer to the shared memory block
|
* Gets a pointer to the shared memory block
|
||||||
@ -77,8 +77,8 @@ private:
|
|||||||
Core::DeviceMemory& device_memory;
|
Core::DeviceMemory& device_memory;
|
||||||
Process* owner_process{};
|
Process* owner_process{};
|
||||||
Memory::PageLinkedList page_list;
|
Memory::PageLinkedList page_list;
|
||||||
Memory::MemoryPermission owner_permission{};
|
KMemoryPermission owner_permission{};
|
||||||
Memory::MemoryPermission user_permission{};
|
KMemoryPermission user_permission{};
|
||||||
PAddr physical_address{};
|
PAddr physical_address{};
|
||||||
std::size_t size{};
|
std::size_t size{};
|
||||||
std::string name;
|
std::string name;
|
||||||
|
@ -289,24 +289,24 @@ struct KernelCore::Impl {
|
|||||||
layout.System().EndAddress());
|
layout.System().EndAddress());
|
||||||
|
|
||||||
hid_shared_mem = Kernel::KSharedMemory::Create(
|
hid_shared_mem = Kernel::KSharedMemory::Create(
|
||||||
system.Kernel(), system.DeviceMemory(), nullptr,
|
system.Kernel(), system.DeviceMemory(), nullptr, {hid_addr, hid_size / PageSize},
|
||||||
{hid_addr, hid_size / Memory::PageSize}, Memory::MemoryPermission::None,
|
KMemoryPermission::None, KMemoryPermission::Read, hid_addr, hid_size,
|
||||||
Memory::MemoryPermission::Read, hid_addr, hid_size, "HID:SharedMemory");
|
"HID:SharedMemory");
|
||||||
font_shared_mem = Kernel::KSharedMemory::Create(
|
font_shared_mem = Kernel::KSharedMemory::Create(
|
||||||
system.Kernel(), system.DeviceMemory(), nullptr,
|
system.Kernel(), system.DeviceMemory(), nullptr, {font_pa, font_size / PageSize},
|
||||||
{font_pa, font_size / Memory::PageSize}, Memory::MemoryPermission::None,
|
KMemoryPermission::None, KMemoryPermission::Read, font_pa, font_size,
|
||||||
Memory::MemoryPermission::Read, font_pa, font_size, "Font:SharedMemory");
|
"Font:SharedMemory");
|
||||||
irs_shared_mem = Kernel::KSharedMemory::Create(
|
irs_shared_mem = Kernel::KSharedMemory::Create(
|
||||||
system.Kernel(), system.DeviceMemory(), nullptr,
|
system.Kernel(), system.DeviceMemory(), nullptr, {irs_addr, irs_size / PageSize},
|
||||||
{irs_addr, irs_size / Memory::PageSize}, Memory::MemoryPermission::None,
|
KMemoryPermission::None, KMemoryPermission::Read, irs_addr, irs_size,
|
||||||
Memory::MemoryPermission::Read, irs_addr, irs_size, "IRS:SharedMemory");
|
"IRS:SharedMemory");
|
||||||
time_shared_mem = Kernel::KSharedMemory::Create(
|
time_shared_mem = Kernel::KSharedMemory::Create(
|
||||||
system.Kernel(), system.DeviceMemory(), nullptr,
|
system.Kernel(), system.DeviceMemory(), nullptr, {time_addr, time_size / PageSize},
|
||||||
{time_addr, time_size / Memory::PageSize}, Memory::MemoryPermission::None,
|
KMemoryPermission::None, KMemoryPermission::Read, time_addr, time_size,
|
||||||
Memory::MemoryPermission::Read, time_addr, time_size, "Time:SharedMemory");
|
"Time:SharedMemory");
|
||||||
|
|
||||||
// Allocate slab heaps
|
// Allocate slab heaps
|
||||||
user_slab_heap_pages = std::make_unique<KSlabHeap<Memory::Page>>();
|
user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>();
|
||||||
|
|
||||||
constexpr u64 user_slab_heap_size{0x1ef000};
|
constexpr u64 user_slab_heap_size{0x1ef000};
|
||||||
// Reserve slab heaps
|
// Reserve slab heaps
|
||||||
@ -349,7 +349,7 @@ struct KernelCore::Impl {
|
|||||||
|
|
||||||
// Kernel memory management
|
// Kernel memory management
|
||||||
std::unique_ptr<Memory::MemoryManager> memory_manager;
|
std::unique_ptr<Memory::MemoryManager> memory_manager;
|
||||||
std::unique_ptr<KSlabHeap<Memory::Page>> user_slab_heap_pages;
|
std::unique_ptr<KSlabHeap<Page>> user_slab_heap_pages;
|
||||||
|
|
||||||
// Shared memory for services
|
// Shared memory for services
|
||||||
std::shared_ptr<Kernel::KSharedMemory> hid_shared_mem;
|
std::shared_ptr<Kernel::KSharedMemory> hid_shared_mem;
|
||||||
@ -581,11 +581,11 @@ const Memory::MemoryManager& KernelCore::MemoryManager() const {
|
|||||||
return *impl->memory_manager;
|
return *impl->memory_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
KSlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() {
|
KSlabHeap<Page>& KernelCore::GetUserSlabHeapPages() {
|
||||||
return *impl->user_slab_heap_pages;
|
return *impl->user_slab_heap_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
const KSlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() const {
|
const KSlabHeap<Page>& KernelCore::GetUserSlabHeapPages() const {
|
||||||
return *impl->user_slab_heap_pages;
|
return *impl->user_slab_heap_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "core/arm/cpu_interrupt_handler.h"
|
#include "core/arm/cpu_interrupt_handler.h"
|
||||||
#include "core/hardware_properties.h"
|
#include "core/hardware_properties.h"
|
||||||
#include "core/hle/kernel/memory/memory_types.h"
|
#include "core/hle/kernel/memory_types.h"
|
||||||
#include "core/hle/kernel/object.h"
|
#include "core/hle/kernel/object.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
@ -186,10 +186,10 @@ public:
|
|||||||
const Memory::MemoryManager& MemoryManager() const;
|
const Memory::MemoryManager& MemoryManager() const;
|
||||||
|
|
||||||
/// Gets the slab heap allocated for user space pages.
|
/// Gets the slab heap allocated for user space pages.
|
||||||
KSlabHeap<Memory::Page>& GetUserSlabHeapPages();
|
KSlabHeap<Page>& GetUserSlabHeapPages();
|
||||||
|
|
||||||
/// Gets the slab heap allocated for user space pages.
|
/// Gets the slab heap allocated for user space pages.
|
||||||
const KSlabHeap<Memory::Page>& GetUserSlabHeapPages() const;
|
const KSlabHeap<Page>& GetUserSlabHeapPages() const;
|
||||||
|
|
||||||
/// Gets the shared memory object for HID services.
|
/// Gets the shared memory object for HID services.
|
||||||
Kernel::KSharedMemory& GetHidSharedMem();
|
Kernel::KSharedMemory& GetHidSharedMem();
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/kernel/k_page_bitmap.h"
|
#include "core/hle/kernel/k_page_bitmap.h"
|
||||||
#include "core/hle/kernel/memory/memory_types.h"
|
#include "core/hle/kernel/memory_types.h"
|
||||||
|
|
||||||
namespace Kernel::Memory {
|
namespace Kernel::Memory {
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/kernel/memory/memory_types.h"
|
#include "core/hle/kernel/memory_types.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
namespace Kernel::Memory {
|
namespace Kernel::Memory {
|
||||||
|
@ -7,12 +7,12 @@
|
|||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/kernel/k_address_space_info.h"
|
#include "core/hle/kernel/k_address_space_info.h"
|
||||||
|
#include "core/hle/kernel/k_memory_block.h"
|
||||||
|
#include "core/hle/kernel/k_memory_block_manager.h"
|
||||||
#include "core/hle/kernel/k_resource_limit.h"
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
||||||
#include "core/hle/kernel/k_system_control.h"
|
#include "core/hle/kernel/k_system_control.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/memory/memory_block.h"
|
|
||||||
#include "core/hle/kernel/memory/memory_block_manager.h"
|
|
||||||
#include "core/hle/kernel/memory/page_linked_list.h"
|
#include "core/hle/kernel/memory/page_linked_list.h"
|
||||||
#include "core/hle/kernel/memory/page_table.h"
|
#include "core/hle/kernel/memory/page_table.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
@ -38,14 +38,14 @@ constexpr std::size_t GetAddressSpaceWidthFromType(FileSys::ProgramAddressSpaceT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr u64 GetAddressInRange(const MemoryInfo& info, VAddr addr) {
|
constexpr u64 GetAddressInRange(const KMemoryInfo& info, VAddr addr) {
|
||||||
if (info.GetAddress() < addr) {
|
if (info.GetAddress() < addr) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
return info.GetAddress();
|
return info.GetAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr std::size_t GetSizeInRange(const MemoryInfo& info, VAddr start, VAddr end) {
|
constexpr std::size_t GetSizeInRange(const KMemoryInfo& info, VAddr start, VAddr end) {
|
||||||
std::size_t size{info.GetSize()};
|
std::size_t size{info.GetSize()};
|
||||||
if (info.GetAddress() < start) {
|
if (info.GetAddress() < start) {
|
||||||
size -= start - info.GetAddress();
|
size -= start - info.GetAddress();
|
||||||
@ -271,8 +271,8 @@ ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_t
|
|||||||
return InitializeMemoryLayout(start, end);
|
return InitializeMemoryLayout(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::MapProcessCode(VAddr addr, std::size_t num_pages, MemoryState state,
|
ResultCode PageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemoryState state,
|
||||||
MemoryPermission perm) {
|
KMemoryPermission perm) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
const u64 size{num_pages * PageSize};
|
const u64 size{num_pages * PageSize};
|
||||||
@ -300,12 +300,12 @@ ResultCode PageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::
|
|||||||
|
|
||||||
const std::size_t num_pages{size / PageSize};
|
const std::size_t num_pages{size / PageSize};
|
||||||
|
|
||||||
MemoryState state{};
|
KMemoryState state{};
|
||||||
MemoryPermission perm{};
|
KMemoryPermission perm{};
|
||||||
CASCADE_CODE(CheckMemoryState(&state, &perm, nullptr, src_addr, size, MemoryState::All,
|
CASCADE_CODE(CheckMemoryState(&state, &perm, nullptr, src_addr, size, KMemoryState::All,
|
||||||
MemoryState::Normal, MemoryPermission::Mask,
|
KMemoryState::Normal, KMemoryPermission::Mask,
|
||||||
MemoryPermission::ReadAndWrite, MemoryAttribute::Mask,
|
KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask,
|
||||||
MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
if (IsRegionMapped(dst_addr, size)) {
|
if (IsRegionMapped(dst_addr, size)) {
|
||||||
return ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
@ -318,16 +318,16 @@ ResultCode PageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::
|
|||||||
auto block_guard = detail::ScopeExit(
|
auto block_guard = detail::ScopeExit(
|
||||||
[&] { Operate(src_addr, num_pages, perm, OperationType::ChangePermissions); });
|
[&] { Operate(src_addr, num_pages, perm, OperationType::ChangePermissions); });
|
||||||
|
|
||||||
CASCADE_CODE(
|
CASCADE_CODE(Operate(src_addr, num_pages, KMemoryPermission::None,
|
||||||
Operate(src_addr, num_pages, MemoryPermission::None, OperationType::ChangePermissions));
|
OperationType::ChangePermissions));
|
||||||
CASCADE_CODE(MapPages(dst_addr, page_linked_list, MemoryPermission::None));
|
CASCADE_CODE(MapPages(dst_addr, page_linked_list, KMemoryPermission::None));
|
||||||
|
|
||||||
block_guard.Cancel();
|
block_guard.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
block_manager->Update(src_addr, num_pages, state, MemoryPermission::None,
|
block_manager->Update(src_addr, num_pages, state, KMemoryPermission::None,
|
||||||
MemoryAttribute::Locked);
|
KMemoryAttribute::Locked);
|
||||||
block_manager->Update(dst_addr, num_pages, MemoryState::AliasCode);
|
block_manager->Update(dst_addr, num_pages, KMemoryState::AliasCode);
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -341,23 +341,24 @@ ResultCode PageTable::UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std
|
|||||||
|
|
||||||
const std::size_t num_pages{size / PageSize};
|
const std::size_t num_pages{size / PageSize};
|
||||||
|
|
||||||
CASCADE_CODE(CheckMemoryState(nullptr, nullptr, nullptr, src_addr, size, MemoryState::All,
|
CASCADE_CODE(CheckMemoryState(nullptr, nullptr, nullptr, src_addr, size, KMemoryState::All,
|
||||||
MemoryState::Normal, MemoryPermission::None,
|
KMemoryState::Normal, KMemoryPermission::None,
|
||||||
MemoryPermission::None, MemoryAttribute::Mask,
|
KMemoryPermission::None, KMemoryAttribute::Mask,
|
||||||
MemoryAttribute::Locked, MemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
MemoryState state{};
|
KMemoryState state{};
|
||||||
CASCADE_CODE(CheckMemoryState(
|
CASCADE_CODE(CheckMemoryState(
|
||||||
&state, nullptr, nullptr, dst_addr, PageSize, MemoryState::FlagCanCodeAlias,
|
&state, nullptr, nullptr, dst_addr, PageSize, KMemoryState::FlagCanCodeAlias,
|
||||||
MemoryState::FlagCanCodeAlias, MemoryPermission::None, MemoryPermission::None,
|
KMemoryState::FlagCanCodeAlias, KMemoryPermission::None, KMemoryPermission::None,
|
||||||
MemoryAttribute::Mask, MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
CASCADE_CODE(CheckMemoryState(dst_addr, size, MemoryState::All, state, MemoryPermission::None,
|
CASCADE_CODE(CheckMemoryState(dst_addr, size, KMemoryState::All, state, KMemoryPermission::None,
|
||||||
MemoryPermission::None, MemoryAttribute::Mask,
|
KMemoryPermission::None, KMemoryAttribute::Mask,
|
||||||
MemoryAttribute::None));
|
KMemoryAttribute::None));
|
||||||
CASCADE_CODE(Operate(dst_addr, num_pages, MemoryPermission::None, OperationType::Unmap));
|
CASCADE_CODE(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap));
|
||||||
|
|
||||||
block_manager->Update(dst_addr, num_pages, MemoryState::Free);
|
block_manager->Update(dst_addr, num_pages, KMemoryState::Free);
|
||||||
block_manager->Update(src_addr, num_pages, MemoryState::Normal, MemoryPermission::ReadAndWrite);
|
block_manager->Update(src_addr, num_pages, KMemoryState::Normal,
|
||||||
|
KMemoryPermission::ReadAndWrite);
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -367,8 +368,8 @@ void PageTable::MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start,
|
|||||||
PAddr map_addr{node->GetAddress()};
|
PAddr map_addr{node->GetAddress()};
|
||||||
std::size_t src_num_pages{node->GetNumPages()};
|
std::size_t src_num_pages{node->GetNumPages()};
|
||||||
|
|
||||||
block_manager->IterateForRange(start, end, [&](const MemoryInfo& info) {
|
block_manager->IterateForRange(start, end, [&](const KMemoryInfo& info) {
|
||||||
if (info.state != MemoryState::Free) {
|
if (info.state != KMemoryState::Free) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,7 +384,7 @@ void PageTable::MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const std::size_t num_pages{std::min(src_num_pages, dst_num_pages)};
|
const std::size_t num_pages{std::min(src_num_pages, dst_num_pages)};
|
||||||
Operate(dst_addr, num_pages, MemoryPermission::ReadAndWrite, OperationType::Map,
|
Operate(dst_addr, num_pages, KMemoryPermission::ReadAndWrite, OperationType::Map,
|
||||||
map_addr);
|
map_addr);
|
||||||
|
|
||||||
dst_addr += num_pages * PageSize;
|
dst_addr += num_pages * PageSize;
|
||||||
@ -400,8 +401,8 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
|
|||||||
std::size_t mapped_size{};
|
std::size_t mapped_size{};
|
||||||
const VAddr end_addr{addr + size};
|
const VAddr end_addr{addr + size};
|
||||||
|
|
||||||
block_manager->IterateForRange(addr, end_addr, [&](const MemoryInfo& info) {
|
block_manager->IterateForRange(addr, end_addr, [&](const KMemoryInfo& info) {
|
||||||
if (info.state != MemoryState::Free) {
|
if (info.state != KMemoryState::Free) {
|
||||||
mapped_size += GetSizeInRange(info, addr, end_addr);
|
mapped_size += GetSizeInRange(info, addr, end_addr);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -435,9 +436,9 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
|
|||||||
physical_memory_usage += remaining_size;
|
physical_memory_usage += remaining_size;
|
||||||
|
|
||||||
const std::size_t num_pages{size / PageSize};
|
const std::size_t num_pages{size / PageSize};
|
||||||
block_manager->Update(addr, num_pages, MemoryState::Free, MemoryPermission::None,
|
block_manager->Update(addr, num_pages, KMemoryState::Free, KMemoryPermission::None,
|
||||||
MemoryAttribute::None, MemoryState::Normal,
|
KMemoryAttribute::None, KMemoryState::Normal,
|
||||||
MemoryPermission::ReadAndWrite, MemoryAttribute::None);
|
KMemoryPermission::ReadAndWrite, KMemoryAttribute::None);
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -450,14 +451,14 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
|
|||||||
std::size_t mapped_size{};
|
std::size_t mapped_size{};
|
||||||
|
|
||||||
// Verify that the region can be unmapped
|
// Verify that the region can be unmapped
|
||||||
block_manager->IterateForRange(addr, end_addr, [&](const MemoryInfo& info) {
|
block_manager->IterateForRange(addr, end_addr, [&](const KMemoryInfo& info) {
|
||||||
if (info.state == MemoryState::Normal) {
|
if (info.state == KMemoryState::Normal) {
|
||||||
if (info.attribute != MemoryAttribute::None) {
|
if (info.attribute != KMemoryAttribute::None) {
|
||||||
result = ResultInvalidCurrentMemory;
|
result = ResultInvalidCurrentMemory;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mapped_size += GetSizeInRange(info, addr, end_addr);
|
mapped_size += GetSizeInRange(info, addr, end_addr);
|
||||||
} else if (info.state != MemoryState::Free) {
|
} else if (info.state != KMemoryState::Free) {
|
||||||
result = ResultInvalidCurrentMemory;
|
result = ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -487,15 +488,15 @@ ResultCode PageTable::UnmapMemory(VAddr addr, std::size_t size) {
|
|||||||
PageLinkedList page_linked_list;
|
PageLinkedList page_linked_list;
|
||||||
|
|
||||||
// Unmap each region within the range
|
// Unmap each region within the range
|
||||||
block_manager->IterateForRange(addr, end_addr, [&](const MemoryInfo& info) {
|
block_manager->IterateForRange(addr, end_addr, [&](const KMemoryInfo& info) {
|
||||||
if (info.state == MemoryState::Normal) {
|
if (info.state == KMemoryState::Normal) {
|
||||||
const std::size_t block_size{GetSizeInRange(info, addr, end_addr)};
|
const std::size_t block_size{GetSizeInRange(info, addr, end_addr)};
|
||||||
const std::size_t block_num_pages{block_size / PageSize};
|
const std::size_t block_num_pages{block_size / PageSize};
|
||||||
const VAddr block_addr{GetAddressInRange(info, addr)};
|
const VAddr block_addr{GetAddressInRange(info, addr)};
|
||||||
|
|
||||||
AddRegionToPages(block_addr, block_size / PageSize, page_linked_list);
|
AddRegionToPages(block_addr, block_size / PageSize, page_linked_list);
|
||||||
|
|
||||||
if (result = Operate(block_addr, block_num_pages, MemoryPermission::None,
|
if (result = Operate(block_addr, block_num_pages, KMemoryPermission::None,
|
||||||
OperationType::Unmap);
|
OperationType::Unmap);
|
||||||
result.IsError()) {
|
result.IsError()) {
|
||||||
return;
|
return;
|
||||||
@ -510,7 +511,7 @@ ResultCode PageTable::UnmapMemory(VAddr addr, std::size_t size) {
|
|||||||
const std::size_t num_pages{size / PageSize};
|
const std::size_t num_pages{size / PageSize};
|
||||||
system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool);
|
system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool);
|
||||||
|
|
||||||
block_manager->Update(addr, num_pages, MemoryState::Free);
|
block_manager->Update(addr, num_pages, KMemoryState::Free);
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -518,11 +519,11 @@ ResultCode PageTable::UnmapMemory(VAddr addr, std::size_t size) {
|
|||||||
ResultCode PageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
ResultCode PageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryState src_state{};
|
KMemoryState src_state{};
|
||||||
CASCADE_CODE(CheckMemoryState(
|
CASCADE_CODE(CheckMemoryState(
|
||||||
&src_state, nullptr, nullptr, src_addr, size, MemoryState::FlagCanAlias,
|
&src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias,
|
||||||
MemoryState::FlagCanAlias, MemoryPermission::Mask, MemoryPermission::ReadAndWrite,
|
KMemoryState::FlagCanAlias, KMemoryPermission::Mask, KMemoryPermission::ReadAndWrite,
|
||||||
MemoryAttribute::Mask, MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
if (IsRegionMapped(dst_addr, size)) {
|
if (IsRegionMapped(dst_addr, size)) {
|
||||||
return ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
@ -535,20 +536,21 @@ ResultCode PageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
auto block_guard = detail::ScopeExit([&] {
|
auto block_guard = detail::ScopeExit([&] {
|
||||||
Operate(src_addr, num_pages, MemoryPermission::ReadAndWrite,
|
Operate(src_addr, num_pages, KMemoryPermission::ReadAndWrite,
|
||||||
OperationType::ChangePermissions);
|
OperationType::ChangePermissions);
|
||||||
});
|
});
|
||||||
|
|
||||||
CASCADE_CODE(
|
CASCADE_CODE(Operate(src_addr, num_pages, KMemoryPermission::None,
|
||||||
Operate(src_addr, num_pages, MemoryPermission::None, OperationType::ChangePermissions));
|
OperationType::ChangePermissions));
|
||||||
CASCADE_CODE(MapPages(dst_addr, page_linked_list, MemoryPermission::ReadAndWrite));
|
CASCADE_CODE(MapPages(dst_addr, page_linked_list, KMemoryPermission::ReadAndWrite));
|
||||||
|
|
||||||
block_guard.Cancel();
|
block_guard.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
block_manager->Update(src_addr, num_pages, src_state, MemoryPermission::None,
|
block_manager->Update(src_addr, num_pages, src_state, KMemoryPermission::None,
|
||||||
MemoryAttribute::Locked);
|
KMemoryAttribute::Locked);
|
||||||
block_manager->Update(dst_addr, num_pages, MemoryState::Stack, MemoryPermission::ReadAndWrite);
|
block_manager->Update(dst_addr, num_pages, KMemoryState::Stack,
|
||||||
|
KMemoryPermission::ReadAndWrite);
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -556,17 +558,17 @@ ResultCode PageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
|||||||
ResultCode PageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
ResultCode PageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryState src_state{};
|
KMemoryState src_state{};
|
||||||
CASCADE_CODE(CheckMemoryState(
|
CASCADE_CODE(CheckMemoryState(
|
||||||
&src_state, nullptr, nullptr, src_addr, size, MemoryState::FlagCanAlias,
|
&src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias,
|
||||||
MemoryState::FlagCanAlias, MemoryPermission::Mask, MemoryPermission::None,
|
KMemoryState::FlagCanAlias, KMemoryPermission::Mask, KMemoryPermission::None,
|
||||||
MemoryAttribute::Mask, MemoryAttribute::Locked, MemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::Mask, KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
MemoryPermission dst_perm{};
|
KMemoryPermission dst_perm{};
|
||||||
CASCADE_CODE(CheckMemoryState(nullptr, &dst_perm, nullptr, dst_addr, size, MemoryState::All,
|
CASCADE_CODE(CheckMemoryState(nullptr, &dst_perm, nullptr, dst_addr, size, KMemoryState::All,
|
||||||
MemoryState::Stack, MemoryPermission::None,
|
KMemoryState::Stack, KMemoryPermission::None,
|
||||||
MemoryPermission::None, MemoryAttribute::Mask,
|
KMemoryPermission::None, KMemoryAttribute::Mask,
|
||||||
MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
PageLinkedList src_pages;
|
PageLinkedList src_pages;
|
||||||
PageLinkedList dst_pages;
|
PageLinkedList dst_pages;
|
||||||
@ -582,21 +584,21 @@ ResultCode PageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
|||||||
{
|
{
|
||||||
auto block_guard = detail::ScopeExit([&] { MapPages(dst_addr, dst_pages, dst_perm); });
|
auto block_guard = detail::ScopeExit([&] { MapPages(dst_addr, dst_pages, dst_perm); });
|
||||||
|
|
||||||
CASCADE_CODE(Operate(dst_addr, num_pages, MemoryPermission::None, OperationType::Unmap));
|
CASCADE_CODE(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap));
|
||||||
CASCADE_CODE(Operate(src_addr, num_pages, MemoryPermission::ReadAndWrite,
|
CASCADE_CODE(Operate(src_addr, num_pages, KMemoryPermission::ReadAndWrite,
|
||||||
OperationType::ChangePermissions));
|
OperationType::ChangePermissions));
|
||||||
|
|
||||||
block_guard.Cancel();
|
block_guard.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
block_manager->Update(src_addr, num_pages, src_state, MemoryPermission::ReadAndWrite);
|
block_manager->Update(src_addr, num_pages, src_state, KMemoryPermission::ReadAndWrite);
|
||||||
block_manager->Update(dst_addr, num_pages, MemoryState::Free);
|
block_manager->Update(dst_addr, num_pages, KMemoryState::Free);
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_list,
|
ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_list,
|
||||||
MemoryPermission perm) {
|
KMemoryPermission perm) {
|
||||||
VAddr cur_addr{addr};
|
VAddr cur_addr{addr};
|
||||||
|
|
||||||
for (const auto& node : page_linked_list.Nodes()) {
|
for (const auto& node : page_linked_list.Nodes()) {
|
||||||
@ -605,8 +607,8 @@ ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_lis
|
|||||||
result.IsError()) {
|
result.IsError()) {
|
||||||
const std::size_t num_pages{(addr - cur_addr) / PageSize};
|
const std::size_t num_pages{(addr - cur_addr) / PageSize};
|
||||||
|
|
||||||
ASSERT(
|
ASSERT(Operate(addr, num_pages, KMemoryPermission::None, OperationType::Unmap)
|
||||||
Operate(addr, num_pages, MemoryPermission::None, OperationType::Unmap).IsSuccess());
|
.IsSuccess());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -617,8 +619,8 @@ ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_lis
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::MapPages(VAddr addr, PageLinkedList& page_linked_list, MemoryState state,
|
ResultCode PageTable::MapPages(VAddr addr, PageLinkedList& page_linked_list, KMemoryState state,
|
||||||
MemoryPermission perm) {
|
KMemoryPermission perm) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
const std::size_t num_pages{page_linked_list.GetNumPages()};
|
const std::size_t num_pages{page_linked_list.GetNumPages()};
|
||||||
@ -639,26 +641,27 @@ ResultCode PageTable::MapPages(VAddr addr, PageLinkedList& page_linked_list, Mem
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, MemoryPermission perm) {
|
ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size,
|
||||||
|
KMemoryPermission perm) {
|
||||||
|
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryState prev_state{};
|
KMemoryState prev_state{};
|
||||||
MemoryPermission prev_perm{};
|
KMemoryPermission prev_perm{};
|
||||||
|
|
||||||
CASCADE_CODE(CheckMemoryState(
|
CASCADE_CODE(CheckMemoryState(
|
||||||
&prev_state, &prev_perm, nullptr, addr, size, MemoryState::FlagCode, MemoryState::FlagCode,
|
&prev_state, &prev_perm, nullptr, addr, size, KMemoryState::FlagCode,
|
||||||
MemoryPermission::None, MemoryPermission::None, MemoryAttribute::Mask,
|
KMemoryState::FlagCode, KMemoryPermission::None, KMemoryPermission::None,
|
||||||
MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
MemoryState state{prev_state};
|
KMemoryState state{prev_state};
|
||||||
|
|
||||||
// Ensure state is mutable if permission allows write
|
// Ensure state is mutable if permission allows write
|
||||||
if ((perm & MemoryPermission::Write) != MemoryPermission::None) {
|
if ((perm & KMemoryPermission::Write) != KMemoryPermission::None) {
|
||||||
if (prev_state == MemoryState::Code) {
|
if (prev_state == KMemoryState::Code) {
|
||||||
state = MemoryState::CodeData;
|
state = KMemoryState::CodeData;
|
||||||
} else if (prev_state == MemoryState::AliasCode) {
|
} else if (prev_state == KMemoryState::AliasCode) {
|
||||||
state = MemoryState::AliasCodeData;
|
state = KMemoryState::AliasCodeData;
|
||||||
} else {
|
} else {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
@ -669,13 +672,13 @@ ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, Memo
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((prev_perm & MemoryPermission::Execute) != (perm & MemoryPermission::Execute)) {
|
if ((prev_perm & KMemoryPermission::Execute) != (perm & KMemoryPermission::Execute)) {
|
||||||
// Memory execution state is changing, invalidate CPU cache range
|
// Memory execution state is changing, invalidate CPU cache range
|
||||||
system.InvalidateCpuInstructionCacheRange(addr, size);
|
system.InvalidateCpuInstructionCacheRange(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::size_t num_pages{size / PageSize};
|
const std::size_t num_pages{size / PageSize};
|
||||||
const OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None
|
const OperationType operation{(perm & KMemoryPermission::Execute) != KMemoryPermission::None
|
||||||
? OperationType::ChangePermissionsAndRefresh
|
? OperationType::ChangePermissionsAndRefresh
|
||||||
: OperationType::ChangePermissions};
|
: OperationType::ChangePermissions};
|
||||||
|
|
||||||
@ -686,35 +689,35 @@ ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, Memo
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryInfo PageTable::QueryInfoImpl(VAddr addr) {
|
KMemoryInfo PageTable::QueryInfoImpl(VAddr addr) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
return block_manager->FindBlock(addr).GetMemoryInfo();
|
return block_manager->FindBlock(addr).GetMemoryInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryInfo PageTable::QueryInfo(VAddr addr) {
|
KMemoryInfo PageTable::QueryInfo(VAddr addr) {
|
||||||
if (!Contains(addr, 1)) {
|
if (!Contains(addr, 1)) {
|
||||||
return {address_space_end, 0 - address_space_end, MemoryState::Inaccessible,
|
return {address_space_end, 0 - address_space_end, KMemoryState::Inaccessible,
|
||||||
MemoryPermission::None, MemoryAttribute::None, MemoryPermission::None};
|
KMemoryPermission::None, KMemoryAttribute::None, KMemoryPermission::None};
|
||||||
}
|
}
|
||||||
|
|
||||||
return QueryInfoImpl(addr);
|
return QueryInfoImpl(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::ReserveTransferMemory(VAddr addr, std::size_t size, MemoryPermission perm) {
|
ResultCode PageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryState state{};
|
KMemoryState state{};
|
||||||
MemoryAttribute attribute{};
|
KMemoryAttribute attribute{};
|
||||||
|
|
||||||
CASCADE_CODE(CheckMemoryState(&state, nullptr, &attribute, addr, size,
|
CASCADE_CODE(CheckMemoryState(
|
||||||
MemoryState::FlagCanTransfer | MemoryState::FlagReferenceCounted,
|
&state, nullptr, &attribute, addr, size,
|
||||||
MemoryState::FlagCanTransfer | MemoryState::FlagReferenceCounted,
|
KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted,
|
||||||
MemoryPermission::Mask, MemoryPermission::ReadAndWrite,
|
KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, KMemoryPermission::Mask,
|
||||||
MemoryAttribute::Mask, MemoryAttribute::None,
|
KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, KMemoryAttribute::None,
|
||||||
MemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
block_manager->Update(addr, size / PageSize, state, perm, attribute | MemoryAttribute::Locked);
|
block_manager->Update(addr, size / PageSize, state, perm, attribute | KMemoryAttribute::Locked);
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -722,33 +725,33 @@ ResultCode PageTable::ReserveTransferMemory(VAddr addr, std::size_t size, Memory
|
|||||||
ResultCode PageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
|
ResultCode PageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryState state{};
|
KMemoryState state{};
|
||||||
|
|
||||||
CASCADE_CODE(CheckMemoryState(&state, nullptr, nullptr, addr, size,
|
CASCADE_CODE(
|
||||||
MemoryState::FlagCanTransfer | MemoryState::FlagReferenceCounted,
|
CheckMemoryState(&state, nullptr, nullptr, addr, size,
|
||||||
MemoryState::FlagCanTransfer | MemoryState::FlagReferenceCounted,
|
KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted,
|
||||||
MemoryPermission::None, MemoryPermission::None,
|
KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted,
|
||||||
MemoryAttribute::Mask, MemoryAttribute::Locked,
|
KMemoryPermission::None, KMemoryPermission::None, KMemoryAttribute::Mask,
|
||||||
MemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
block_manager->Update(addr, size / PageSize, state, MemoryPermission::ReadAndWrite);
|
block_manager->Update(addr, size / PageSize, state, KMemoryPermission::ReadAndWrite);
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::SetMemoryAttribute(VAddr addr, std::size_t size, MemoryAttribute mask,
|
ResultCode PageTable::SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask,
|
||||||
MemoryAttribute value) {
|
KMemoryAttribute value) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryState state{};
|
KMemoryState state{};
|
||||||
MemoryPermission perm{};
|
KMemoryPermission perm{};
|
||||||
MemoryAttribute attribute{};
|
KMemoryAttribute attribute{};
|
||||||
|
|
||||||
CASCADE_CODE(CheckMemoryState(&state, &perm, &attribute, addr, size,
|
CASCADE_CODE(CheckMemoryState(
|
||||||
MemoryState::FlagCanChangeAttribute,
|
&state, &perm, &attribute, addr, size, KMemoryState::FlagCanChangeAttribute,
|
||||||
MemoryState::FlagCanChangeAttribute, MemoryPermission::None,
|
KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None,
|
||||||
MemoryPermission::None, MemoryAttribute::LockedAndIpcLocked,
|
KMemoryAttribute::LockedAndIpcLocked, KMemoryAttribute::None,
|
||||||
MemoryAttribute::None, MemoryAttribute::DeviceSharedAndUncached));
|
KMemoryAttribute::DeviceSharedAndUncached));
|
||||||
|
|
||||||
attribute = attribute & ~mask;
|
attribute = attribute & ~mask;
|
||||||
attribute = attribute | (mask & value);
|
attribute = attribute | (mask & value);
|
||||||
@ -806,8 +809,8 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
|
|||||||
// Succeeded in allocation, commit the resource reservation
|
// Succeeded in allocation, commit the resource reservation
|
||||||
memory_reservation.Commit();
|
memory_reservation.Commit();
|
||||||
|
|
||||||
block_manager->Update(current_heap_addr, num_pages, MemoryState::Normal,
|
block_manager->Update(current_heap_addr, num_pages, KMemoryState::Normal,
|
||||||
MemoryPermission::ReadAndWrite);
|
KMemoryPermission::ReadAndWrite);
|
||||||
|
|
||||||
current_heap_addr = heap_region_start + size;
|
current_heap_addr = heap_region_start + size;
|
||||||
}
|
}
|
||||||
@ -817,8 +820,8 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
|
|||||||
|
|
||||||
ResultVal<VAddr> PageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
|
ResultVal<VAddr> PageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
|
||||||
bool is_map_only, VAddr region_start,
|
bool is_map_only, VAddr region_start,
|
||||||
std::size_t region_num_pages, MemoryState state,
|
std::size_t region_num_pages, KMemoryState state,
|
||||||
MemoryPermission perm, PAddr map_addr) {
|
KMemoryPermission perm, PAddr map_addr) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
if (!CanContain(region_start, region_num_pages * PageSize, state)) {
|
if (!CanContain(region_start, region_num_pages * PageSize, state)) {
|
||||||
@ -852,19 +855,19 @@ ResultVal<VAddr> PageTable::AllocateAndMapMemory(std::size_t needed_num_pages, s
|
|||||||
ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
|
ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryPermission perm{};
|
KMemoryPermission perm{};
|
||||||
if (const ResultCode result{CheckMemoryState(
|
if (const ResultCode result{CheckMemoryState(
|
||||||
nullptr, &perm, nullptr, addr, size, MemoryState::FlagCanChangeAttribute,
|
nullptr, &perm, nullptr, addr, size, KMemoryState::FlagCanChangeAttribute,
|
||||||
MemoryState::FlagCanChangeAttribute, MemoryPermission::None, MemoryPermission::None,
|
KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None,
|
||||||
MemoryAttribute::LockedAndIpcLocked, MemoryAttribute::None,
|
KMemoryAttribute::LockedAndIpcLocked, KMemoryAttribute::None,
|
||||||
MemoryAttribute::DeviceSharedAndUncached)};
|
KMemoryAttribute::DeviceSharedAndUncached)};
|
||||||
result.IsError()) {
|
result.IsError()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
block_manager->UpdateLock(
|
block_manager->UpdateLock(
|
||||||
addr, size / PageSize,
|
addr, size / PageSize,
|
||||||
[](MemoryBlockManager::iterator block, MemoryPermission perm) {
|
[](KMemoryBlockManager::iterator block, KMemoryPermission perm) {
|
||||||
block->ShareToDevice(perm);
|
block->ShareToDevice(perm);
|
||||||
},
|
},
|
||||||
perm);
|
perm);
|
||||||
@ -875,19 +878,19 @@ ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
|
|||||||
ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) {
|
ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
MemoryPermission perm{};
|
KMemoryPermission perm{};
|
||||||
if (const ResultCode result{CheckMemoryState(
|
if (const ResultCode result{CheckMemoryState(
|
||||||
nullptr, &perm, nullptr, addr, size, MemoryState::FlagCanChangeAttribute,
|
nullptr, &perm, nullptr, addr, size, KMemoryState::FlagCanChangeAttribute,
|
||||||
MemoryState::FlagCanChangeAttribute, MemoryPermission::None, MemoryPermission::None,
|
KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None,
|
||||||
MemoryAttribute::LockedAndIpcLocked, MemoryAttribute::None,
|
KMemoryAttribute::LockedAndIpcLocked, KMemoryAttribute::None,
|
||||||
MemoryAttribute::DeviceSharedAndUncached)};
|
KMemoryAttribute::DeviceSharedAndUncached)};
|
||||||
result.IsError()) {
|
result.IsError()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
block_manager->UpdateLock(
|
block_manager->UpdateLock(
|
||||||
addr, size / PageSize,
|
addr, size / PageSize,
|
||||||
[](MemoryBlockManager::iterator block, MemoryPermission perm) {
|
[](KMemoryBlockManager::iterator block, KMemoryPermission perm) {
|
||||||
block->UnshareToDevice(perm);
|
block->UnshareToDevice(perm);
|
||||||
},
|
},
|
||||||
perm);
|
perm);
|
||||||
@ -896,15 +899,16 @@ ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::InitializeMemoryLayout(VAddr start, VAddr end) {
|
ResultCode PageTable::InitializeMemoryLayout(VAddr start, VAddr end) {
|
||||||
block_manager = std::make_unique<MemoryBlockManager>(start, end);
|
block_manager = std::make_unique<KMemoryBlockManager>(start, end);
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PageTable::IsRegionMapped(VAddr address, u64 size) {
|
bool PageTable::IsRegionMapped(VAddr address, u64 size) {
|
||||||
return CheckMemoryState(address, size, MemoryState::All, MemoryState::Free,
|
return CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free,
|
||||||
MemoryPermission::Mask, MemoryPermission::None, MemoryAttribute::Mask,
|
KMemoryPermission::Mask, KMemoryPermission::None,
|
||||||
MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped)
|
KMemoryAttribute::Mask, KMemoryAttribute::None,
|
||||||
|
KMemoryAttribute::IpcAndDeviceMapped)
|
||||||
.IsError();
|
.IsError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -966,7 +970,7 @@ ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, const PageLinke
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, MemoryPermission perm,
|
ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, KMemoryPermission perm,
|
||||||
OperationType operation, PAddr map_addr) {
|
OperationType operation, PAddr map_addr) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
@ -993,34 +997,34 @@ ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, MemoryPermissio
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr VAddr PageTable::GetRegionAddress(MemoryState state) const {
|
constexpr VAddr PageTable::GetRegionAddress(KMemoryState state) const {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case MemoryState::Free:
|
case KMemoryState::Free:
|
||||||
case MemoryState::Kernel:
|
case KMemoryState::Kernel:
|
||||||
return address_space_start;
|
return address_space_start;
|
||||||
case MemoryState::Normal:
|
case KMemoryState::Normal:
|
||||||
return heap_region_start;
|
return heap_region_start;
|
||||||
case MemoryState::Ipc:
|
case KMemoryState::Ipc:
|
||||||
case MemoryState::NonSecureIpc:
|
case KMemoryState::NonSecureIpc:
|
||||||
case MemoryState::NonDeviceIpc:
|
case KMemoryState::NonDeviceIpc:
|
||||||
return alias_region_start;
|
return alias_region_start;
|
||||||
case MemoryState::Stack:
|
case KMemoryState::Stack:
|
||||||
return stack_region_start;
|
return stack_region_start;
|
||||||
case MemoryState::Io:
|
case KMemoryState::Io:
|
||||||
case MemoryState::Static:
|
case KMemoryState::Static:
|
||||||
case MemoryState::ThreadLocal:
|
case KMemoryState::ThreadLocal:
|
||||||
return kernel_map_region_start;
|
return kernel_map_region_start;
|
||||||
case MemoryState::Shared:
|
case KMemoryState::Shared:
|
||||||
case MemoryState::AliasCode:
|
case KMemoryState::AliasCode:
|
||||||
case MemoryState::AliasCodeData:
|
case KMemoryState::AliasCodeData:
|
||||||
case MemoryState::Transferred:
|
case KMemoryState::Transferred:
|
||||||
case MemoryState::SharedTransferred:
|
case KMemoryState::SharedTransferred:
|
||||||
case MemoryState::SharedCode:
|
case KMemoryState::SharedCode:
|
||||||
case MemoryState::GeneratedCode:
|
case KMemoryState::GeneratedCode:
|
||||||
case MemoryState::CodeOut:
|
case KMemoryState::CodeOut:
|
||||||
return alias_code_region_start;
|
return alias_code_region_start;
|
||||||
case MemoryState::Code:
|
case KMemoryState::Code:
|
||||||
case MemoryState::CodeData:
|
case KMemoryState::CodeData:
|
||||||
return code_region_start;
|
return code_region_start;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -1028,34 +1032,34 @@ constexpr VAddr PageTable::GetRegionAddress(MemoryState state) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr std::size_t PageTable::GetRegionSize(MemoryState state) const {
|
constexpr std::size_t PageTable::GetRegionSize(KMemoryState state) const {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case MemoryState::Free:
|
case KMemoryState::Free:
|
||||||
case MemoryState::Kernel:
|
case KMemoryState::Kernel:
|
||||||
return address_space_end - address_space_start;
|
return address_space_end - address_space_start;
|
||||||
case MemoryState::Normal:
|
case KMemoryState::Normal:
|
||||||
return heap_region_end - heap_region_start;
|
return heap_region_end - heap_region_start;
|
||||||
case MemoryState::Ipc:
|
case KMemoryState::Ipc:
|
||||||
case MemoryState::NonSecureIpc:
|
case KMemoryState::NonSecureIpc:
|
||||||
case MemoryState::NonDeviceIpc:
|
case KMemoryState::NonDeviceIpc:
|
||||||
return alias_region_end - alias_region_start;
|
return alias_region_end - alias_region_start;
|
||||||
case MemoryState::Stack:
|
case KMemoryState::Stack:
|
||||||
return stack_region_end - stack_region_start;
|
return stack_region_end - stack_region_start;
|
||||||
case MemoryState::Io:
|
case KMemoryState::Io:
|
||||||
case MemoryState::Static:
|
case KMemoryState::Static:
|
||||||
case MemoryState::ThreadLocal:
|
case KMemoryState::ThreadLocal:
|
||||||
return kernel_map_region_end - kernel_map_region_start;
|
return kernel_map_region_end - kernel_map_region_start;
|
||||||
case MemoryState::Shared:
|
case KMemoryState::Shared:
|
||||||
case MemoryState::AliasCode:
|
case KMemoryState::AliasCode:
|
||||||
case MemoryState::AliasCodeData:
|
case KMemoryState::AliasCodeData:
|
||||||
case MemoryState::Transferred:
|
case KMemoryState::Transferred:
|
||||||
case MemoryState::SharedTransferred:
|
case KMemoryState::SharedTransferred:
|
||||||
case MemoryState::SharedCode:
|
case KMemoryState::SharedCode:
|
||||||
case MemoryState::GeneratedCode:
|
case KMemoryState::GeneratedCode:
|
||||||
case MemoryState::CodeOut:
|
case KMemoryState::CodeOut:
|
||||||
return alias_code_region_end - alias_code_region_start;
|
return alias_code_region_end - alias_code_region_start;
|
||||||
case MemoryState::Code:
|
case KMemoryState::Code:
|
||||||
case MemoryState::CodeData:
|
case KMemoryState::CodeData:
|
||||||
return code_region_end - code_region_start;
|
return code_region_end - code_region_start;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -1063,7 +1067,7 @@ constexpr std::size_t PageTable::GetRegionSize(MemoryState state) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool PageTable::CanContain(VAddr addr, std::size_t size, MemoryState state) const {
|
constexpr bool PageTable::CanContain(VAddr addr, std::size_t size, KMemoryState state) const {
|
||||||
const VAddr end{addr + size};
|
const VAddr end{addr + size};
|
||||||
const VAddr last{end - 1};
|
const VAddr last{end - 1};
|
||||||
const VAddr region_start{GetRegionAddress(state)};
|
const VAddr region_start{GetRegionAddress(state)};
|
||||||
@ -1074,30 +1078,30 @@ constexpr bool PageTable::CanContain(VAddr addr, std::size_t size, MemoryState s
|
|||||||
const bool is_in_alias{!(end <= alias_region_start || alias_region_end <= addr)};
|
const bool is_in_alias{!(end <= alias_region_start || alias_region_end <= addr)};
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case MemoryState::Free:
|
case KMemoryState::Free:
|
||||||
case MemoryState::Kernel:
|
case KMemoryState::Kernel:
|
||||||
return is_in_region;
|
return is_in_region;
|
||||||
case MemoryState::Io:
|
case KMemoryState::Io:
|
||||||
case MemoryState::Static:
|
case KMemoryState::Static:
|
||||||
case MemoryState::Code:
|
case KMemoryState::Code:
|
||||||
case MemoryState::CodeData:
|
case KMemoryState::CodeData:
|
||||||
case MemoryState::Shared:
|
case KMemoryState::Shared:
|
||||||
case MemoryState::AliasCode:
|
case KMemoryState::AliasCode:
|
||||||
case MemoryState::AliasCodeData:
|
case KMemoryState::AliasCodeData:
|
||||||
case MemoryState::Stack:
|
case KMemoryState::Stack:
|
||||||
case MemoryState::ThreadLocal:
|
case KMemoryState::ThreadLocal:
|
||||||
case MemoryState::Transferred:
|
case KMemoryState::Transferred:
|
||||||
case MemoryState::SharedTransferred:
|
case KMemoryState::SharedTransferred:
|
||||||
case MemoryState::SharedCode:
|
case KMemoryState::SharedCode:
|
||||||
case MemoryState::GeneratedCode:
|
case KMemoryState::GeneratedCode:
|
||||||
case MemoryState::CodeOut:
|
case KMemoryState::CodeOut:
|
||||||
return is_in_region && !is_in_heap && !is_in_alias;
|
return is_in_region && !is_in_heap && !is_in_alias;
|
||||||
case MemoryState::Normal:
|
case KMemoryState::Normal:
|
||||||
ASSERT(is_in_heap);
|
ASSERT(is_in_heap);
|
||||||
return is_in_region && !is_in_alias;
|
return is_in_region && !is_in_alias;
|
||||||
case MemoryState::Ipc:
|
case KMemoryState::Ipc:
|
||||||
case MemoryState::NonSecureIpc:
|
case KMemoryState::NonSecureIpc:
|
||||||
case MemoryState::NonDeviceIpc:
|
case KMemoryState::NonDeviceIpc:
|
||||||
ASSERT(is_in_alias);
|
ASSERT(is_in_alias);
|
||||||
return is_in_region && !is_in_heap;
|
return is_in_region && !is_in_heap;
|
||||||
default:
|
default:
|
||||||
@ -1105,10 +1109,10 @@ constexpr bool PageTable::CanContain(VAddr addr, std::size_t size, MemoryState s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ResultCode PageTable::CheckMemoryState(const MemoryInfo& info, MemoryState state_mask,
|
constexpr ResultCode PageTable::CheckMemoryState(const KMemoryInfo& info, KMemoryState state_mask,
|
||||||
MemoryState state, MemoryPermission perm_mask,
|
KMemoryState state, KMemoryPermission perm_mask,
|
||||||
MemoryPermission perm, MemoryAttribute attr_mask,
|
KMemoryPermission perm, KMemoryAttribute attr_mask,
|
||||||
MemoryAttribute attr) const {
|
KMemoryAttribute attr) const {
|
||||||
// Validate the states match expectation
|
// Validate the states match expectation
|
||||||
if ((info.state & state_mask) != state) {
|
if ((info.state & state_mask) != state) {
|
||||||
return ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
@ -1123,23 +1127,23 @@ constexpr ResultCode PageTable::CheckMemoryState(const MemoryInfo& info, MemoryS
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode PageTable::CheckMemoryState(MemoryState* out_state, MemoryPermission* out_perm,
|
ResultCode PageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm,
|
||||||
MemoryAttribute* out_attr, VAddr addr, std::size_t size,
|
KMemoryAttribute* out_attr, VAddr addr, std::size_t size,
|
||||||
MemoryState state_mask, MemoryState state,
|
KMemoryState state_mask, KMemoryState state,
|
||||||
MemoryPermission perm_mask, MemoryPermission perm,
|
KMemoryPermission perm_mask, KMemoryPermission perm,
|
||||||
MemoryAttribute attr_mask, MemoryAttribute attr,
|
KMemoryAttribute attr_mask, KMemoryAttribute attr,
|
||||||
MemoryAttribute ignore_attr) {
|
KMemoryAttribute ignore_attr) {
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
// Get information about the first block
|
// Get information about the first block
|
||||||
const VAddr last_addr{addr + size - 1};
|
const VAddr last_addr{addr + size - 1};
|
||||||
MemoryBlockManager::const_iterator it{block_manager->FindIterator(addr)};
|
KMemoryBlockManager::const_iterator it{block_manager->FindIterator(addr)};
|
||||||
MemoryInfo info{it->GetMemoryInfo()};
|
KMemoryInfo info{it->GetMemoryInfo()};
|
||||||
|
|
||||||
// Validate all blocks in the range have correct state
|
// Validate all blocks in the range have correct state
|
||||||
const MemoryState first_state{info.state};
|
const KMemoryState first_state{info.state};
|
||||||
const MemoryPermission first_perm{info.perm};
|
const KMemoryPermission first_perm{info.perm};
|
||||||
const MemoryAttribute first_attr{info.attribute};
|
const KMemoryAttribute first_attr{info.attribute};
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// Validate the current block
|
// Validate the current block
|
||||||
@ -1149,8 +1153,8 @@ ResultCode PageTable::CheckMemoryState(MemoryState* out_state, MemoryPermission*
|
|||||||
if (!(info.perm == first_perm)) {
|
if (!(info.perm == first_perm)) {
|
||||||
return ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
if (!((info.attribute | static_cast<MemoryAttribute>(ignore_attr)) ==
|
if (!((info.attribute | static_cast<KMemoryAttribute>(ignore_attr)) ==
|
||||||
(first_attr | static_cast<MemoryAttribute>(ignore_attr)))) {
|
(first_attr | static_cast<KMemoryAttribute>(ignore_attr)))) {
|
||||||
return ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1176,7 +1180,7 @@ ResultCode PageTable::CheckMemoryState(MemoryState* out_state, MemoryPermission*
|
|||||||
*out_perm = first_perm;
|
*out_perm = first_perm;
|
||||||
}
|
}
|
||||||
if (out_attr) {
|
if (out_attr) {
|
||||||
*out_attr = first_attr & static_cast<MemoryAttribute>(~ignore_attr);
|
*out_attr = first_attr & static_cast<KMemoryAttribute>(~ignore_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/page_table.h"
|
#include "common/page_table.h"
|
||||||
#include "core/file_sys/program_metadata.h"
|
#include "core/file_sys/program_metadata.h"
|
||||||
#include "core/hle/kernel/memory/memory_block.h"
|
#include "core/hle/kernel/k_memory_block.h"
|
||||||
#include "core/hle/kernel/memory/memory_manager.h"
|
#include "core/hle/kernel/memory/memory_manager.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
@ -18,9 +18,11 @@ namespace Core {
|
|||||||
class System;
|
class System;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Kernel::Memory {
|
namespace Kernel {
|
||||||
|
class KMemoryBlockManager;
|
||||||
|
}
|
||||||
|
|
||||||
class MemoryBlockManager;
|
namespace Kernel::Memory {
|
||||||
|
|
||||||
class PageTable final : NonCopyable {
|
class PageTable final : NonCopyable {
|
||||||
public:
|
public:
|
||||||
@ -29,8 +31,8 @@ public:
|
|||||||
ResultCode InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr,
|
ResultCode InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr,
|
||||||
VAddr code_addr, std::size_t code_size,
|
VAddr code_addr, std::size_t code_size,
|
||||||
Memory::MemoryManager::Pool pool);
|
Memory::MemoryManager::Pool pool);
|
||||||
ResultCode MapProcessCode(VAddr addr, std::size_t pages_count, MemoryState state,
|
ResultCode MapProcessCode(VAddr addr, std::size_t pages_count, KMemoryState state,
|
||||||
MemoryPermission perm);
|
KMemoryPermission perm);
|
||||||
ResultCode MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size);
|
ResultCode MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size);
|
||||||
ResultCode UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size);
|
ResultCode UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size);
|
||||||
ResultCode MapPhysicalMemory(VAddr addr, std::size_t size);
|
ResultCode MapPhysicalMemory(VAddr addr, std::size_t size);
|
||||||
@ -38,20 +40,20 @@ public:
|
|||||||
ResultCode UnmapMemory(VAddr addr, std::size_t size);
|
ResultCode UnmapMemory(VAddr addr, std::size_t size);
|
||||||
ResultCode Map(VAddr dst_addr, VAddr src_addr, std::size_t size);
|
ResultCode Map(VAddr dst_addr, VAddr src_addr, std::size_t size);
|
||||||
ResultCode Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size);
|
ResultCode Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size);
|
||||||
ResultCode MapPages(VAddr addr, PageLinkedList& page_linked_list, MemoryState state,
|
ResultCode MapPages(VAddr addr, PageLinkedList& page_linked_list, KMemoryState state,
|
||||||
MemoryPermission perm);
|
KMemoryPermission perm);
|
||||||
ResultCode SetCodeMemoryPermission(VAddr addr, std::size_t size, MemoryPermission perm);
|
ResultCode SetCodeMemoryPermission(VAddr addr, std::size_t size, KMemoryPermission perm);
|
||||||
MemoryInfo QueryInfo(VAddr addr);
|
KMemoryInfo QueryInfo(VAddr addr);
|
||||||
ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, MemoryPermission perm);
|
ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm);
|
||||||
ResultCode ResetTransferMemory(VAddr addr, std::size_t size);
|
ResultCode ResetTransferMemory(VAddr addr, std::size_t size);
|
||||||
ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, MemoryAttribute mask,
|
ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask,
|
||||||
MemoryAttribute value);
|
KMemoryAttribute value);
|
||||||
ResultCode SetHeapCapacity(std::size_t new_heap_capacity);
|
ResultCode SetHeapCapacity(std::size_t new_heap_capacity);
|
||||||
ResultVal<VAddr> SetHeapSize(std::size_t size);
|
ResultVal<VAddr> SetHeapSize(std::size_t size);
|
||||||
ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
|
ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
|
||||||
bool is_map_only, VAddr region_start,
|
bool is_map_only, VAddr region_start,
|
||||||
std::size_t region_num_pages, MemoryState state,
|
std::size_t region_num_pages, KMemoryState state,
|
||||||
MemoryPermission perm, PAddr map_addr = 0);
|
KMemoryPermission perm, PAddr map_addr = 0);
|
||||||
ResultCode LockForDeviceAddressSpace(VAddr addr, std::size_t size);
|
ResultCode LockForDeviceAddressSpace(VAddr addr, std::size_t size);
|
||||||
ResultCode UnlockForDeviceAddressSpace(VAddr addr, std::size_t size);
|
ResultCode UnlockForDeviceAddressSpace(VAddr addr, std::size_t size);
|
||||||
|
|
||||||
@ -72,47 +74,48 @@ private:
|
|||||||
ChangePermissionsAndRefresh,
|
ChangePermissionsAndRefresh,
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr MemoryAttribute DefaultMemoryIgnoreAttr =
|
static constexpr KMemoryAttribute DefaultMemoryIgnoreAttr = KMemoryAttribute::DontCareMask |
|
||||||
MemoryAttribute::DontCareMask | MemoryAttribute::IpcLocked | MemoryAttribute::DeviceShared;
|
KMemoryAttribute::IpcLocked |
|
||||||
|
KMemoryAttribute::DeviceShared;
|
||||||
|
|
||||||
ResultCode InitializeMemoryLayout(VAddr start, VAddr end);
|
ResultCode InitializeMemoryLayout(VAddr start, VAddr end);
|
||||||
ResultCode MapPages(VAddr addr, const PageLinkedList& page_linked_list, MemoryPermission perm);
|
ResultCode MapPages(VAddr addr, const PageLinkedList& page_linked_list, KMemoryPermission perm);
|
||||||
void MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start, VAddr end);
|
void MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start, VAddr end);
|
||||||
bool IsRegionMapped(VAddr address, u64 size);
|
bool IsRegionMapped(VAddr address, u64 size);
|
||||||
bool IsRegionContiguous(VAddr addr, u64 size) const;
|
bool IsRegionContiguous(VAddr addr, u64 size) const;
|
||||||
void AddRegionToPages(VAddr start, std::size_t num_pages, PageLinkedList& page_linked_list);
|
void AddRegionToPages(VAddr start, std::size_t num_pages, PageLinkedList& page_linked_list);
|
||||||
MemoryInfo QueryInfoImpl(VAddr addr);
|
KMemoryInfo QueryInfoImpl(VAddr addr);
|
||||||
VAddr AllocateVirtualMemory(VAddr start, std::size_t region_num_pages, u64 needed_num_pages,
|
VAddr AllocateVirtualMemory(VAddr start, std::size_t region_num_pages, u64 needed_num_pages,
|
||||||
std::size_t align);
|
std::size_t align);
|
||||||
ResultCode Operate(VAddr addr, std::size_t num_pages, const PageLinkedList& page_group,
|
ResultCode Operate(VAddr addr, std::size_t num_pages, const PageLinkedList& page_group,
|
||||||
OperationType operation);
|
OperationType operation);
|
||||||
ResultCode Operate(VAddr addr, std::size_t num_pages, MemoryPermission perm,
|
ResultCode Operate(VAddr addr, std::size_t num_pages, KMemoryPermission perm,
|
||||||
OperationType operation, PAddr map_addr = 0);
|
OperationType operation, PAddr map_addr = 0);
|
||||||
constexpr VAddr GetRegionAddress(MemoryState state) const;
|
constexpr VAddr GetRegionAddress(KMemoryState state) const;
|
||||||
constexpr std::size_t GetRegionSize(MemoryState state) const;
|
constexpr std::size_t GetRegionSize(KMemoryState state) const;
|
||||||
constexpr bool CanContain(VAddr addr, std::size_t size, MemoryState state) const;
|
constexpr bool CanContain(VAddr addr, std::size_t size, KMemoryState state) const;
|
||||||
|
|
||||||
constexpr ResultCode CheckMemoryState(const MemoryInfo& info, MemoryState state_mask,
|
constexpr ResultCode CheckMemoryState(const KMemoryInfo& info, KMemoryState state_mask,
|
||||||
MemoryState state, MemoryPermission perm_mask,
|
KMemoryState state, KMemoryPermission perm_mask,
|
||||||
MemoryPermission perm, MemoryAttribute attr_mask,
|
KMemoryPermission perm, KMemoryAttribute attr_mask,
|
||||||
MemoryAttribute attr) const;
|
KMemoryAttribute attr) const;
|
||||||
ResultCode CheckMemoryState(MemoryState* out_state, MemoryPermission* out_perm,
|
ResultCode CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm,
|
||||||
MemoryAttribute* out_attr, VAddr addr, std::size_t size,
|
KMemoryAttribute* out_attr, VAddr addr, std::size_t size,
|
||||||
MemoryState state_mask, MemoryState state,
|
KMemoryState state_mask, KMemoryState state,
|
||||||
MemoryPermission perm_mask, MemoryPermission perm,
|
KMemoryPermission perm_mask, KMemoryPermission perm,
|
||||||
MemoryAttribute attr_mask, MemoryAttribute attr,
|
KMemoryAttribute attr_mask, KMemoryAttribute attr,
|
||||||
MemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr);
|
KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr);
|
||||||
ResultCode CheckMemoryState(VAddr addr, std::size_t size, MemoryState state_mask,
|
ResultCode CheckMemoryState(VAddr addr, std::size_t size, KMemoryState state_mask,
|
||||||
MemoryState state, MemoryPermission perm_mask,
|
KMemoryState state, KMemoryPermission perm_mask,
|
||||||
MemoryPermission perm, MemoryAttribute attr_mask,
|
KMemoryPermission perm, KMemoryAttribute attr_mask,
|
||||||
MemoryAttribute attr,
|
KMemoryAttribute attr,
|
||||||
MemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) {
|
KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) {
|
||||||
return CheckMemoryState(nullptr, nullptr, nullptr, addr, size, state_mask, state, perm_mask,
|
return CheckMemoryState(nullptr, nullptr, nullptr, addr, size, state_mask, state, perm_mask,
|
||||||
perm, attr_mask, attr, ignore_attr);
|
perm, attr_mask, attr, ignore_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::recursive_mutex page_table_lock;
|
std::recursive_mutex page_table_lock;
|
||||||
std::unique_ptr<MemoryBlockManager> block_manager;
|
std::unique_ptr<KMemoryBlockManager> block_manager;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr VAddr GetAddressSpaceStart() const {
|
constexpr VAddr GetAddressSpaceStart() const {
|
||||||
@ -212,7 +215,7 @@ public:
|
|||||||
return !IsOutsideASLRRegion(address, size);
|
return !IsOutsideASLRRegion(address, size);
|
||||||
}
|
}
|
||||||
constexpr PAddr GetPhysicalAddr(VAddr addr) {
|
constexpr PAddr GetPhysicalAddr(VAddr addr) {
|
||||||
return page_table_impl.backing_addr[addr >> Memory::PageBits] + addr;
|
return page_table_impl.backing_addr[addr >> PageBits] + addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -8,11 +8,11 @@
|
|||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace Kernel::Memory {
|
namespace Kernel {
|
||||||
|
|
||||||
constexpr std::size_t PageBits{12};
|
constexpr std::size_t PageBits{12};
|
||||||
constexpr std::size_t PageSize{1 << PageBits};
|
constexpr std::size_t PageSize{1 << PageBits};
|
||||||
|
|
||||||
using Page = std::array<u8, PageSize>;
|
using Page = std::array<u8, PageSize>;
|
||||||
|
|
||||||
} // namespace Kernel::Memory
|
} // namespace Kernel
|
@ -14,14 +14,14 @@
|
|||||||
#include "core/device_memory.h"
|
#include "core/device_memory.h"
|
||||||
#include "core/file_sys/program_metadata.h"
|
#include "core/file_sys/program_metadata.h"
|
||||||
#include "core/hle/kernel/code_set.h"
|
#include "core/hle/kernel/code_set.h"
|
||||||
|
#include "core/hle/kernel/k_memory_block_manager.h"
|
||||||
#include "core/hle/kernel/k_resource_limit.h"
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
#include "core/hle/kernel/k_scheduler.h"
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
||||||
|
#include "core/hle/kernel/k_slab_heap.h"
|
||||||
#include "core/hle/kernel/k_thread.h"
|
#include "core/hle/kernel/k_thread.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/memory/memory_block_manager.h"
|
|
||||||
#include "core/hle/kernel/memory/page_table.h"
|
#include "core/hle/kernel/memory/page_table.h"
|
||||||
#include "core/hle/kernel/memory/slab_heap.h"
|
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/svc_results.h"
|
#include "core/hle/kernel/svc_results.h"
|
||||||
#include "core/hle/lock.h"
|
#include "core/hle/lock.h"
|
||||||
@ -291,9 +291,9 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Map process code region
|
// Map process code region
|
||||||
if (const ResultCode result{page_table->MapProcessCode(
|
if (const ResultCode result{page_table->MapProcessCode(page_table->GetCodeRegionStart(),
|
||||||
page_table->GetCodeRegionStart(), code_size / Memory::PageSize,
|
code_size / PageSize, KMemoryState::Code,
|
||||||
Memory::MemoryState::Code, Memory::MemoryPermission::None)};
|
KMemoryPermission::None)};
|
||||||
result.IsError()) {
|
result.IsError()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -400,22 +400,22 @@ VAddr Process::CreateTLSRegion() {
|
|||||||
return *tls_page_iter->ReserveSlot();
|
return *tls_page_iter->ReserveSlot();
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Page* const tls_page_ptr{kernel.GetUserSlabHeapPages().Allocate()};
|
Page* const tls_page_ptr{kernel.GetUserSlabHeapPages().Allocate()};
|
||||||
ASSERT(tls_page_ptr);
|
ASSERT(tls_page_ptr);
|
||||||
|
|
||||||
const VAddr start{page_table->GetKernelMapRegionStart()};
|
const VAddr start{page_table->GetKernelMapRegionStart()};
|
||||||
const VAddr size{page_table->GetKernelMapRegionEnd() - start};
|
const VAddr size{page_table->GetKernelMapRegionEnd() - start};
|
||||||
const PAddr tls_map_addr{system.DeviceMemory().GetPhysicalAddr(tls_page_ptr)};
|
const PAddr tls_map_addr{system.DeviceMemory().GetPhysicalAddr(tls_page_ptr)};
|
||||||
const VAddr tls_page_addr{
|
const VAddr tls_page_addr{page_table
|
||||||
page_table
|
->AllocateAndMapMemory(1, PageSize, true, start, size / PageSize,
|
||||||
->AllocateAndMapMemory(1, Memory::PageSize, true, start, size / Memory::PageSize,
|
KMemoryState::ThreadLocal,
|
||||||
Memory::MemoryState::ThreadLocal,
|
KMemoryPermission::ReadAndWrite,
|
||||||
Memory::MemoryPermission::ReadAndWrite, tls_map_addr)
|
tls_map_addr)
|
||||||
.ValueOr(0)};
|
.ValueOr(0)};
|
||||||
|
|
||||||
ASSERT(tls_page_addr);
|
ASSERT(tls_page_addr);
|
||||||
|
|
||||||
std::memset(tls_page_ptr, 0, Memory::PageSize);
|
std::memset(tls_page_ptr, 0, PageSize);
|
||||||
tls_pages.emplace_back(tls_page_addr);
|
tls_pages.emplace_back(tls_page_addr);
|
||||||
|
|
||||||
const auto reserve_result{tls_pages.back().ReserveSlot()};
|
const auto reserve_result{tls_pages.back().ReserveSlot()};
|
||||||
@ -442,15 +442,15 @@ void Process::FreeTLSRegion(VAddr tls_address) {
|
|||||||
void Process::LoadModule(CodeSet code_set, VAddr base_addr) {
|
void Process::LoadModule(CodeSet code_set, VAddr base_addr) {
|
||||||
std::lock_guard lock{HLE::g_hle_lock};
|
std::lock_guard lock{HLE::g_hle_lock};
|
||||||
const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
|
const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
|
||||||
Memory::MemoryPermission permission) {
|
KMemoryPermission permission) {
|
||||||
page_table->SetCodeMemoryPermission(segment.addr + base_addr, segment.size, permission);
|
page_table->SetCodeMemoryPermission(segment.addr + base_addr, segment.size, permission);
|
||||||
};
|
};
|
||||||
|
|
||||||
system.Memory().WriteBlock(*this, base_addr, code_set.memory.data(), code_set.memory.size());
|
system.Memory().WriteBlock(*this, base_addr, code_set.memory.data(), code_set.memory.size());
|
||||||
|
|
||||||
ReprotectSegment(code_set.CodeSegment(), Memory::MemoryPermission::ReadAndExecute);
|
ReprotectSegment(code_set.CodeSegment(), KMemoryPermission::ReadAndExecute);
|
||||||
ReprotectSegment(code_set.RODataSegment(), Memory::MemoryPermission::Read);
|
ReprotectSegment(code_set.RODataSegment(), KMemoryPermission::Read);
|
||||||
ReprotectSegment(code_set.DataSegment(), Memory::MemoryPermission::ReadAndWrite);
|
ReprotectSegment(code_set.DataSegment(), KMemoryPermission::ReadAndWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Process::IsSignaled() const {
|
bool Process::IsSignaled() const {
|
||||||
@ -479,16 +479,15 @@ ResultCode Process::AllocateMainThreadStack(std::size_t stack_size) {
|
|||||||
ASSERT(stack_size);
|
ASSERT(stack_size);
|
||||||
|
|
||||||
// The kernel always ensures that the given stack size is page aligned.
|
// The kernel always ensures that the given stack size is page aligned.
|
||||||
main_thread_stack_size = Common::AlignUp(stack_size, Memory::PageSize);
|
main_thread_stack_size = Common::AlignUp(stack_size, PageSize);
|
||||||
|
|
||||||
const VAddr start{page_table->GetStackRegionStart()};
|
const VAddr start{page_table->GetStackRegionStart()};
|
||||||
const std::size_t size{page_table->GetStackRegionEnd() - start};
|
const std::size_t size{page_table->GetStackRegionEnd() - start};
|
||||||
|
|
||||||
CASCADE_RESULT(main_thread_stack_top,
|
CASCADE_RESULT(main_thread_stack_top,
|
||||||
page_table->AllocateAndMapMemory(
|
page_table->AllocateAndMapMemory(
|
||||||
main_thread_stack_size / Memory::PageSize, Memory::PageSize, false, start,
|
main_thread_stack_size / PageSize, PageSize, false, start, size / PageSize,
|
||||||
size / Memory::PageSize, Memory::MemoryState::Stack,
|
KMemoryState::Stack, KMemoryPermission::ReadAndWrite));
|
||||||
Memory::MemoryPermission::ReadAndWrite));
|
|
||||||
|
|
||||||
main_thread_stack_top += main_thread_stack_size;
|
main_thread_stack_top += main_thread_stack_size;
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "core/hle/kernel/k_address_arbiter.h"
|
#include "core/hle/kernel/k_address_arbiter.h"
|
||||||
#include "core/hle/kernel/k_condition_variable.h"
|
#include "core/hle/kernel/k_condition_variable.h"
|
||||||
#include "core/hle/kernel/k_event.h"
|
#include "core/hle/kernel/k_event.h"
|
||||||
|
#include "core/hle/kernel/k_memory_block.h"
|
||||||
#include "core/hle/kernel/k_memory_layout.h"
|
#include "core/hle/kernel/k_memory_layout.h"
|
||||||
#include "core/hle/kernel/k_readable_event.h"
|
#include "core/hle/kernel/k_readable_event.h"
|
||||||
#include "core/hle/kernel/k_resource_limit.h"
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
@ -38,7 +39,6 @@
|
|||||||
#include "core/hle/kernel/k_thread.h"
|
#include "core/hle/kernel/k_thread.h"
|
||||||
#include "core/hle/kernel/k_writable_event.h"
|
#include "core/hle/kernel/k_writable_event.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/memory/memory_block.h"
|
|
||||||
#include "core/hle/kernel/memory/page_table.h"
|
#include "core/hle/kernel/memory/page_table.h"
|
||||||
#include "core/hle/kernel/physical_core.h"
|
#include "core/hle/kernel/physical_core.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
@ -230,9 +230,9 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si
|
|||||||
return ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto attributes{static_cast<Memory::MemoryAttribute>(mask | attribute)};
|
const auto attributes{static_cast<MemoryAttribute>(mask | attribute)};
|
||||||
if (attributes != static_cast<Memory::MemoryAttribute>(mask) ||
|
if (attributes != static_cast<MemoryAttribute>(mask) ||
|
||||||
(attributes | Memory::MemoryAttribute::Uncached) != Memory::MemoryAttribute::Uncached) {
|
(attributes | MemoryAttribute::Uncached) != MemoryAttribute::Uncached) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}",
|
"Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}",
|
||||||
attribute, mask);
|
attribute, mask);
|
||||||
@ -241,8 +241,8 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si
|
|||||||
|
|
||||||
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
|
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
|
||||||
|
|
||||||
return page_table.SetMemoryAttribute(address, size, static_cast<Memory::MemoryAttribute>(mask),
|
return page_table.SetMemoryAttribute(address, size, static_cast<KMemoryAttribute>(mask),
|
||||||
static_cast<Memory::MemoryAttribute>(attribute));
|
static_cast<KMemoryAttribute>(attribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask,
|
static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask,
|
||||||
@ -1231,9 +1231,8 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han
|
|||||||
return ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto permission_type = static_cast<Memory::MemoryPermission>(permissions);
|
const auto permission_type = static_cast<MemoryPermission>(permissions);
|
||||||
if ((permission_type | Memory::MemoryPermission::Write) !=
|
if ((permission_type | MemoryPermission::Write) != MemoryPermission::ReadWrite) {
|
||||||
Memory::MemoryPermission::ReadAndWrite) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}",
|
LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}",
|
||||||
permissions);
|
permissions);
|
||||||
return ResultInvalidMemoryPermissions;
|
return ResultInvalidMemoryPermissions;
|
||||||
@ -1273,7 +1272,8 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han
|
|||||||
return ResultInvalidHandle;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
return shared_memory->Map(*current_process, addr, size, permission_type);
|
return shared_memory->Map(*current_process, addr, size,
|
||||||
|
static_cast<KMemoryPermission>(permission_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr,
|
static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr,
|
||||||
@ -1886,9 +1886,8 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
|
|||||||
return ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto perms{static_cast<Memory::MemoryPermission>(permissions)};
|
const auto perms{static_cast<MemoryPermission>(permissions)};
|
||||||
if (perms > Memory::MemoryPermission::ReadAndWrite ||
|
if (perms > MemoryPermission::ReadWrite || perms == MemoryPermission::Write) {
|
||||||
perms == Memory::MemoryPermission::Write) {
|
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})",
|
LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})",
|
||||||
permissions);
|
permissions);
|
||||||
return ResultInvalidMemoryPermissions;
|
return ResultInvalidMemoryPermissions;
|
||||||
@ -1902,7 +1901,8 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
|
|||||||
LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory");
|
LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory");
|
||||||
return ResultResourceLimitedExceeded;
|
return ResultResourceLimitedExceeded;
|
||||||
}
|
}
|
||||||
auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms);
|
auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size,
|
||||||
|
static_cast<KMemoryPermission>(perms));
|
||||||
|
|
||||||
if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) {
|
if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) {
|
||||||
return reserve_result;
|
return reserve_result;
|
||||||
|
@ -24,7 +24,7 @@ TransferMemory::~TransferMemory() {
|
|||||||
std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel,
|
std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel,
|
||||||
Core::Memory::Memory& memory,
|
Core::Memory::Memory& memory,
|
||||||
VAddr base_address, std::size_t size,
|
VAddr base_address, std::size_t size,
|
||||||
Memory::MemoryPermission permissions) {
|
KMemoryPermission permissions) {
|
||||||
std::shared_ptr<TransferMemory> transfer_memory{
|
std::shared_ptr<TransferMemory> transfer_memory{
|
||||||
std::make_shared<TransferMemory>(kernel, memory)};
|
std::make_shared<TransferMemory>(kernel, memory)};
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "core/hle/kernel/memory/memory_block.h"
|
#include "core/hle/kernel/k_memory_block.h"
|
||||||
#include "core/hle/kernel/object.h"
|
#include "core/hle/kernel/object.h"
|
||||||
#include "core/hle/kernel/physical_memory.h"
|
#include "core/hle/kernel/physical_memory.h"
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ public:
|
|||||||
|
|
||||||
static std::shared_ptr<TransferMemory> Create(KernelCore& kernel, Core::Memory::Memory& memory,
|
static std::shared_ptr<TransferMemory> Create(KernelCore& kernel, Core::Memory::Memory& memory,
|
||||||
VAddr base_address, std::size_t size,
|
VAddr base_address, std::size_t size,
|
||||||
Memory::MemoryPermission permissions);
|
KMemoryPermission permissions);
|
||||||
|
|
||||||
TransferMemory(const TransferMemory&) = delete;
|
TransferMemory(const TransferMemory&) = delete;
|
||||||
TransferMemory& operator=(const TransferMemory&) = delete;
|
TransferMemory& operator=(const TransferMemory&) = delete;
|
||||||
@ -82,7 +82,7 @@ private:
|
|||||||
std::size_t size{};
|
std::size_t size{};
|
||||||
|
|
||||||
/// The memory permissions that are applied to this instance.
|
/// The memory permissions that are applied to this instance.
|
||||||
Memory::MemoryPermission owner_permissions{};
|
KMemoryPermission owner_permissions{};
|
||||||
|
|
||||||
/// The process that this transfer memory instance was created under.
|
/// The process that this transfer memory instance was created under.
|
||||||
Process* owner_process{};
|
Process* owner_process{};
|
||||||
|
@ -289,10 +289,10 @@ public:
|
|||||||
|
|
||||||
bool ValidateRegionForMap(Kernel::Memory::PageTable& page_table, VAddr start,
|
bool ValidateRegionForMap(Kernel::Memory::PageTable& page_table, VAddr start,
|
||||||
std::size_t size) const {
|
std::size_t size) const {
|
||||||
constexpr std::size_t padding_size{4 * Kernel::Memory::PageSize};
|
constexpr std::size_t padding_size{4 * Kernel::PageSize};
|
||||||
const auto start_info{page_table.QueryInfo(start - 1)};
|
const auto start_info{page_table.QueryInfo(start - 1)};
|
||||||
|
|
||||||
if (start_info.state != Kernel::Memory::MemoryState::Free) {
|
if (start_info.state != Kernel::KMemoryState::Free) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +302,7 @@ public:
|
|||||||
|
|
||||||
const auto end_info{page_table.QueryInfo(start + size)};
|
const auto end_info{page_table.QueryInfo(start + size)};
|
||||||
|
|
||||||
if (end_info.state != Kernel::Memory::MemoryState::Free) {
|
if (end_info.state != Kernel::KMemoryState::Free) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,11 +312,10 @@ public:
|
|||||||
VAddr GetRandomMapRegion(const Kernel::Memory::PageTable& page_table, std::size_t size) const {
|
VAddr GetRandomMapRegion(const Kernel::Memory::PageTable& page_table, std::size_t size) const {
|
||||||
VAddr addr{};
|
VAddr addr{};
|
||||||
const std::size_t end_pages{(page_table.GetAliasCodeRegionSize() - size) >>
|
const std::size_t end_pages{(page_table.GetAliasCodeRegionSize() - size) >>
|
||||||
Kernel::Memory::PageBits};
|
Kernel::PageBits};
|
||||||
do {
|
do {
|
||||||
addr = page_table.GetAliasCodeRegionStart() +
|
addr = page_table.GetAliasCodeRegionStart() +
|
||||||
(Kernel::KSystemControl::GenerateRandomRange(0, end_pages)
|
(Kernel::KSystemControl::GenerateRandomRange(0, end_pages) << Kernel::PageBits);
|
||||||
<< Kernel::Memory::PageBits);
|
|
||||||
} while (!page_table.IsInsideAddressSpace(addr, size) ||
|
} while (!page_table.IsInsideAddressSpace(addr, size) ||
|
||||||
page_table.IsInsideHeapRegion(addr, size) ||
|
page_table.IsInsideHeapRegion(addr, size) ||
|
||||||
page_table.IsInsideAliasRegion(addr, size));
|
page_table.IsInsideAliasRegion(addr, size));
|
||||||
@ -387,7 +386,7 @@ public:
|
|||||||
const VAddr data_start{start + nro_header.segment_headers[DATA_INDEX].memory_offset};
|
const VAddr data_start{start + nro_header.segment_headers[DATA_INDEX].memory_offset};
|
||||||
const VAddr bss_start{data_start + nro_header.segment_headers[DATA_INDEX].memory_size};
|
const VAddr bss_start{data_start + nro_header.segment_headers[DATA_INDEX].memory_size};
|
||||||
const VAddr bss_end_addr{
|
const VAddr bss_end_addr{
|
||||||
Common::AlignUp(bss_start + nro_header.bss_size, Kernel::Memory::PageSize)};
|
Common::AlignUp(bss_start + nro_header.bss_size, Kernel::PageSize)};
|
||||||
|
|
||||||
auto CopyCode{[&](VAddr src_addr, VAddr dst_addr, u64 size) {
|
auto CopyCode{[&](VAddr src_addr, VAddr dst_addr, u64 size) {
|
||||||
std::vector<u8> source_data(size);
|
std::vector<u8> source_data(size);
|
||||||
@ -402,12 +401,12 @@ public:
|
|||||||
nro_header.segment_headers[DATA_INDEX].memory_size);
|
nro_header.segment_headers[DATA_INDEX].memory_size);
|
||||||
|
|
||||||
CASCADE_CODE(process->PageTable().SetCodeMemoryPermission(
|
CASCADE_CODE(process->PageTable().SetCodeMemoryPermission(
|
||||||
text_start, ro_start - text_start, Kernel::Memory::MemoryPermission::ReadAndExecute));
|
text_start, ro_start - text_start, Kernel::KMemoryPermission::ReadAndExecute));
|
||||||
CASCADE_CODE(process->PageTable().SetCodeMemoryPermission(
|
CASCADE_CODE(process->PageTable().SetCodeMemoryPermission(ro_start, data_start - ro_start,
|
||||||
ro_start, data_start - ro_start, Kernel::Memory::MemoryPermission::Read));
|
Kernel::KMemoryPermission::Read));
|
||||||
|
|
||||||
return process->PageTable().SetCodeMemoryPermission(
|
return process->PageTable().SetCodeMemoryPermission(
|
||||||
data_start, bss_end_addr - data_start, Kernel::Memory::MemoryPermission::ReadAndWrite);
|
data_start, bss_end_addr - data_start, Kernel::KMemoryPermission::ReadAndWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadNro(Kernel::HLERequestContext& ctx) {
|
void LoadNro(Kernel::HLERequestContext& ctx) {
|
||||||
|
Loading…
Reference in New Issue
Block a user