Merge pull request #9964 from liamwhite/typed-address

kernel: use KTypedAddress for addresses
merge-requests/60/head
liamwhite 2023-03-23 10:00:19 +07:00 committed by GitHub
commit c41a4baf06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
101 changed files with 1574 additions and 1102 deletions

@ -132,6 +132,7 @@ add_library(common STATIC
time_zone.h time_zone.h
tiny_mt.h tiny_mt.h
tree.h tree.h
typed_address.h
uint128.h uint128.h
unique_function.h unique_function.h
uuid.cpp uuid.cpp

@ -0,0 +1,320 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <compare>
#include <type_traits>
#include <fmt/format.h>
#include "common/common_types.h"
namespace Common {
template <bool Virtual, typename T>
class TypedAddress {
public:
// Constructors.
constexpr inline TypedAddress() : m_address(0) {}
constexpr inline TypedAddress(uint64_t a) : m_address(a) {}
template <typename U>
constexpr inline explicit TypedAddress(const U* ptr)
: m_address(reinterpret_cast<uint64_t>(ptr)) {}
// Copy constructor.
constexpr inline TypedAddress(const TypedAddress& rhs) = default;
// Assignment operator.
constexpr inline TypedAddress& operator=(const TypedAddress& rhs) = default;
// Arithmetic operators.
template <typename I>
constexpr inline TypedAddress operator+(I rhs) const {
static_assert(std::is_integral_v<I>);
return m_address + rhs;
}
constexpr inline TypedAddress operator+(TypedAddress rhs) const {
return m_address + rhs.m_address;
}
constexpr inline TypedAddress operator++() {
return ++m_address;
}
constexpr inline TypedAddress operator++(int) {
return m_address++;
}
template <typename I>
constexpr inline TypedAddress operator-(I rhs) const {
static_assert(std::is_integral_v<I>);
return m_address - rhs;
}
constexpr inline ptrdiff_t operator-(TypedAddress rhs) const {
return m_address - rhs.m_address;
}
constexpr inline TypedAddress operator--() {
return --m_address;
}
constexpr inline TypedAddress operator--(int) {
return m_address--;
}
template <typename I>
constexpr inline TypedAddress operator+=(I rhs) {
static_assert(std::is_integral_v<I>);
m_address += rhs;
return *this;
}
template <typename I>
constexpr inline TypedAddress operator-=(I rhs) {
static_assert(std::is_integral_v<I>);
m_address -= rhs;
return *this;
}
// Logical operators.
constexpr inline uint64_t operator&(uint64_t mask) const {
return m_address & mask;
}
constexpr inline uint64_t operator|(uint64_t mask) const {
return m_address | mask;
}
template <typename I>
constexpr inline TypedAddress operator|=(I rhs) {
static_assert(std::is_integral_v<I>);
m_address |= rhs;
return *this;
}
constexpr inline uint64_t operator<<(int shift) const {
return m_address << shift;
}
constexpr inline uint64_t operator>>(int shift) const {
return m_address >> shift;
}
template <typename U>
constexpr inline size_t operator/(U size) const {
return m_address / size;
}
constexpr explicit operator bool() const {
return m_address != 0;
}
// constexpr inline uint64_t operator%(U align) const { return m_address % align; }
// Comparison operators.
constexpr bool operator==(const TypedAddress&) const = default;
constexpr bool operator!=(const TypedAddress&) const = default;
constexpr auto operator<=>(const TypedAddress&) const = default;
// For convenience, also define comparison operators versus uint64_t.
constexpr inline bool operator==(uint64_t rhs) const {
return m_address == rhs;
}
constexpr inline bool operator!=(uint64_t rhs) const {
return m_address != rhs;
}
// Allow getting the address explicitly, for use in accessors.
constexpr inline uint64_t GetValue() const {
return m_address;
}
private:
uint64_t m_address{};
};
struct PhysicalAddressTag {};
struct VirtualAddressTag {};
struct ProcessAddressTag {};
using PhysicalAddress = TypedAddress<false, PhysicalAddressTag>;
using VirtualAddress = TypedAddress<true, VirtualAddressTag>;
using ProcessAddress = TypedAddress<true, ProcessAddressTag>;
// Define accessors.
template <typename T>
concept IsTypedAddress = std::same_as<T, PhysicalAddress> || std::same_as<T, VirtualAddress> ||
std::same_as<T, ProcessAddress>;
template <typename T>
constexpr inline T Null = [] {
if constexpr (std::is_same<T, uint64_t>::value) {
return 0;
} else {
static_assert(std::is_same<T, PhysicalAddress>::value ||
std::is_same<T, VirtualAddress>::value ||
std::is_same<T, ProcessAddress>::value);
return T(0);
}
}();
// Basic type validations.
static_assert(sizeof(PhysicalAddress) == sizeof(uint64_t));
static_assert(sizeof(VirtualAddress) == sizeof(uint64_t));
static_assert(sizeof(ProcessAddress) == sizeof(uint64_t));
static_assert(std::is_trivially_copyable_v<PhysicalAddress>);
static_assert(std::is_trivially_copyable_v<VirtualAddress>);
static_assert(std::is_trivially_copyable_v<ProcessAddress>);
static_assert(std::is_trivially_copy_constructible_v<PhysicalAddress>);
static_assert(std::is_trivially_copy_constructible_v<VirtualAddress>);
static_assert(std::is_trivially_copy_constructible_v<ProcessAddress>);
static_assert(std::is_trivially_move_constructible_v<PhysicalAddress>);
static_assert(std::is_trivially_move_constructible_v<VirtualAddress>);
static_assert(std::is_trivially_move_constructible_v<ProcessAddress>);
static_assert(std::is_trivially_copy_assignable_v<PhysicalAddress>);
static_assert(std::is_trivially_copy_assignable_v<VirtualAddress>);
static_assert(std::is_trivially_copy_assignable_v<ProcessAddress>);
static_assert(std::is_trivially_move_assignable_v<PhysicalAddress>);
static_assert(std::is_trivially_move_assignable_v<VirtualAddress>);
static_assert(std::is_trivially_move_assignable_v<ProcessAddress>);
static_assert(std::is_trivially_destructible_v<PhysicalAddress>);
static_assert(std::is_trivially_destructible_v<VirtualAddress>);
static_assert(std::is_trivially_destructible_v<ProcessAddress>);
static_assert(Null<uint64_t> == 0);
static_assert(Null<PhysicalAddress> == Null<uint64_t>);
static_assert(Null<VirtualAddress> == Null<uint64_t>);
static_assert(Null<ProcessAddress> == Null<uint64_t>);
// Constructor/assignment validations.
static_assert([] {
const PhysicalAddress a(5);
PhysicalAddress b(a);
return b;
}() == PhysicalAddress(5));
static_assert([] {
const PhysicalAddress a(5);
PhysicalAddress b(10);
b = a;
return b;
}() == PhysicalAddress(5));
// Arithmetic validations.
static_assert(PhysicalAddress(10) + 5 == PhysicalAddress(15));
static_assert(PhysicalAddress(10) - 5 == PhysicalAddress(5));
static_assert([] {
PhysicalAddress v(10);
v += 5;
return v;
}() == PhysicalAddress(15));
static_assert([] {
PhysicalAddress v(10);
v -= 5;
return v;
}() == PhysicalAddress(5));
static_assert(PhysicalAddress(10)++ == PhysicalAddress(10));
static_assert(++PhysicalAddress(10) == PhysicalAddress(11));
static_assert(PhysicalAddress(10)-- == PhysicalAddress(10));
static_assert(--PhysicalAddress(10) == PhysicalAddress(9));
// Logical validations.
static_assert((PhysicalAddress(0b11111111) >> 1) == 0b01111111);
static_assert((PhysicalAddress(0b10101010) >> 1) == 0b01010101);
static_assert((PhysicalAddress(0b11111111) << 1) == 0b111111110);
static_assert((PhysicalAddress(0b01010101) << 1) == 0b10101010);
static_assert((PhysicalAddress(0b11111111) & 0b01010101) == 0b01010101);
static_assert((PhysicalAddress(0b11111111) & 0b10101010) == 0b10101010);
static_assert((PhysicalAddress(0b01010101) & 0b10101010) == 0b00000000);
static_assert((PhysicalAddress(0b00000000) | 0b01010101) == 0b01010101);
static_assert((PhysicalAddress(0b11111111) | 0b01010101) == 0b11111111);
static_assert((PhysicalAddress(0b10101010) | 0b01010101) == 0b11111111);
// Comparisons.
static_assert(PhysicalAddress(0) == PhysicalAddress(0));
static_assert(PhysicalAddress(0) != PhysicalAddress(1));
static_assert(PhysicalAddress(0) < PhysicalAddress(1));
static_assert(PhysicalAddress(0) <= PhysicalAddress(1));
static_assert(PhysicalAddress(1) > PhysicalAddress(0));
static_assert(PhysicalAddress(1) >= PhysicalAddress(0));
static_assert(!(PhysicalAddress(0) == PhysicalAddress(1)));
static_assert(!(PhysicalAddress(0) != PhysicalAddress(0)));
static_assert(!(PhysicalAddress(1) < PhysicalAddress(0)));
static_assert(!(PhysicalAddress(1) <= PhysicalAddress(0)));
static_assert(!(PhysicalAddress(0) > PhysicalAddress(1)));
static_assert(!(PhysicalAddress(0) >= PhysicalAddress(1)));
} // namespace Common
template <bool Virtual, typename T>
constexpr inline uint64_t GetInteger(Common::TypedAddress<Virtual, T> address) {
return address.GetValue();
}
template <>
struct fmt::formatter<Common::PhysicalAddress> {
constexpr auto parse(fmt::format_parse_context& ctx) {
return ctx.begin();
}
template <typename FormatContext>
auto format(const Common::PhysicalAddress& addr, FormatContext& ctx) {
return fmt::format_to(ctx.out(), "{:#x}", static_cast<u64>(addr.GetValue()));
}
};
template <>
struct fmt::formatter<Common::ProcessAddress> {
constexpr auto parse(fmt::format_parse_context& ctx) {
return ctx.begin();
}
template <typename FormatContext>
auto format(const Common::ProcessAddress& addr, FormatContext& ctx) {
return fmt::format_to(ctx.out(), "{:#x}", static_cast<u64>(addr.GetValue()));
}
};
template <>
struct fmt::formatter<Common::VirtualAddress> {
constexpr auto parse(fmt::format_parse_context& ctx) {
return ctx.begin();
}
template <typename FormatContext>
auto format(const Common::VirtualAddress& addr, FormatContext& ctx) {
return fmt::format_to(ctx.out(), "{:#x}", static_cast<u64>(addr.GetValue()));
}
};
namespace std {
template <>
struct hash<Common::PhysicalAddress> {
size_t operator()(const Common::PhysicalAddress& k) const noexcept {
return k.GetValue();
}
};
template <>
struct hash<Common::ProcessAddress> {
size_t operator()(const Common::ProcessAddress& k) const noexcept {
return k.GetValue();
}
};
template <>
struct hash<Common::VirtualAddress> {
size_t operator()(const Common::VirtualAddress& k) const noexcept {
return k.GetValue();
}
};
} // namespace std

@ -278,6 +278,7 @@ add_library(core STATIC
hle/kernel/k_trace.h hle/kernel/k_trace.h
hle/kernel/k_transfer_memory.cpp hle/kernel/k_transfer_memory.cpp
hle/kernel/k_transfer_memory.h hle/kernel/k_transfer_memory.h
hle/kernel/k_typed_address.h
hle/kernel/k_worker_task.h hle/kernel/k_worker_task.h
hle/kernel/k_worker_task_manager.cpp hle/kernel/k_worker_task_manager.cpp
hle/kernel/k_worker_task_manager.h hle/kernel/k_worker_task_manager.h

@ -168,21 +168,21 @@ void ARM_Interface::LoadWatchpointArray(const WatchpointArray& wp) {
} }
const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint( const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint(
VAddr addr, u64 size, Kernel::DebugWatchpointType access_type) const { u64 addr, u64 size, Kernel::DebugWatchpointType access_type) const {
if (!watchpoints) { if (!watchpoints) {
return nullptr; return nullptr;
} }
const VAddr start_address{addr}; const u64 start_address{addr};
const VAddr end_address{addr + size}; const u64 end_address{addr + size};
for (size_t i = 0; i < Core::Hardware::NUM_WATCHPOINTS; i++) { for (size_t i = 0; i < Core::Hardware::NUM_WATCHPOINTS; i++) {
const auto& watch{(*watchpoints)[i]}; const auto& watch{(*watchpoints)[i]};
if (end_address <= watch.start_address) { if (end_address <= GetInteger(watch.start_address)) {
continue; continue;
} }
if (start_address >= watch.end_address) { if (start_address >= GetInteger(watch.end_address)) {
continue; continue;
} }
if ((access_type & watch.type) == Kernel::DebugWatchpointType::None) { if ((access_type & watch.type) == Kernel::DebugWatchpointType::None) {

@ -78,7 +78,7 @@ public:
* @param addr Start address of the cache range to clear * @param addr Start address of the cache range to clear
* @param size Size of the cache range to clear, starting at addr * @param size Size of the cache range to clear, starting at addr
*/ */
virtual void InvalidateCacheRange(VAddr addr, std::size_t size) = 0; virtual void InvalidateCacheRange(u64 addr, std::size_t size) = 0;
/** /**
* Notifies CPU emulation that the current page table has changed. * Notifies CPU emulation that the current page table has changed.
@ -149,9 +149,9 @@ public:
*/ */
virtual void SetPSTATE(u32 pstate) = 0; virtual void SetPSTATE(u32 pstate) = 0;
virtual VAddr GetTlsAddress() const = 0; virtual u64 GetTlsAddress() const = 0;
virtual void SetTlsAddress(VAddr address) = 0; virtual void SetTlsAddress(u64 address) = 0;
/** /**
* Gets the value within the TPIDR_EL0 (read/write software thread ID) register. * Gets the value within the TPIDR_EL0 (read/write software thread ID) register.
@ -214,7 +214,7 @@ protected:
static void SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out); static void SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out);
const Kernel::DebugWatchpoint* MatchingWatchpoint( const Kernel::DebugWatchpoint* MatchingWatchpoint(
VAddr addr, u64 size, Kernel::DebugWatchpointType access_type) const; u64 addr, u64 size, Kernel::DebugWatchpointType access_type) const;
virtual Dynarmic::HaltReason RunJit() = 0; virtual Dynarmic::HaltReason RunJit() = 0;
virtual Dynarmic::HaltReason StepJit() = 0; virtual Dynarmic::HaltReason StepJit() = 0;

@ -155,7 +155,7 @@ public:
return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0);
} }
bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { bool CheckMemoryAccess(u64 addr, u64 size, Kernel::DebugWatchpointType type) {
if (!check_memory_access) { if (!check_memory_access) {
return true; return true;
} }
@ -397,7 +397,7 @@ u64 ARM_Dynarmic_32::GetTlsAddress() const {
return cp15->uro; return cp15->uro;
} }
void ARM_Dynarmic_32::SetTlsAddress(VAddr address) { void ARM_Dynarmic_32::SetTlsAddress(u64 address) {
cp15->uro = static_cast<u32>(address); cp15->uro = static_cast<u32>(address);
} }
@ -439,7 +439,7 @@ void ARM_Dynarmic_32::ClearInstructionCache() {
jit.load()->ClearCache(); jit.load()->ClearCache();
} }
void ARM_Dynarmic_32::InvalidateCacheRange(VAddr addr, std::size_t size) { void ARM_Dynarmic_32::InvalidateCacheRange(u64 addr, std::size_t size) {
jit.load()->InvalidateCacheRange(static_cast<u32>(addr), size); jit.load()->InvalidateCacheRange(static_cast<u32>(addr), size);
} }

@ -41,8 +41,8 @@ public:
void SetVectorReg(int index, u128 value) override; void SetVectorReg(int index, u128 value) override;
u32 GetPSTATE() const override; u32 GetPSTATE() const override;
void SetPSTATE(u32 pstate) override; void SetPSTATE(u32 pstate) override;
VAddr GetTlsAddress() const override; u64 GetTlsAddress() const override;
void SetTlsAddress(VAddr address) override; void SetTlsAddress(u64 address) override;
void SetTPIDR_EL0(u64 value) override; void SetTPIDR_EL0(u64 value) override;
u64 GetTPIDR_EL0() const override; u64 GetTPIDR_EL0() const override;
@ -60,7 +60,7 @@ public:
void ClearExclusiveState() override; void ClearExclusiveState() override;
void ClearInstructionCache() override; void ClearInstructionCache() override;
void InvalidateCacheRange(VAddr addr, std::size_t size) override; void InvalidateCacheRange(u64 addr, std::size_t size) override;
void PageTableChanged(Common::PageTable& new_page_table, void PageTableChanged(Common::PageTable& new_page_table,
std::size_t new_address_space_size_in_bits) override; std::size_t new_address_space_size_in_bits) override;

@ -117,7 +117,7 @@ public:
} }
void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op, void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op,
VAddr value) override { u64 value) override {
switch (op) { switch (op) {
case Dynarmic::A64::InstructionCacheOperation::InvalidateByVAToPoU: { case Dynarmic::A64::InstructionCacheOperation::InvalidateByVAToPoU: {
static constexpr u64 ICACHE_LINE_SIZE = 64; static constexpr u64 ICACHE_LINE_SIZE = 64;
@ -199,7 +199,7 @@ public:
return parent.system.CoreTiming().GetClockTicks(); return parent.system.CoreTiming().GetClockTicks();
} }
bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { bool CheckMemoryAccess(u64 addr, u64 size, Kernel::DebugWatchpointType type) {
if (!check_memory_access) { if (!check_memory_access) {
return true; return true;
} }
@ -452,7 +452,7 @@ u64 ARM_Dynarmic_64::GetTlsAddress() const {
return cb->tpidrro_el0; return cb->tpidrro_el0;
} }
void ARM_Dynarmic_64::SetTlsAddress(VAddr address) { void ARM_Dynarmic_64::SetTlsAddress(u64 address) {
cb->tpidrro_el0 = address; cb->tpidrro_el0 = address;
} }
@ -500,7 +500,7 @@ void ARM_Dynarmic_64::ClearInstructionCache() {
jit.load()->ClearCache(); jit.load()->ClearCache();
} }
void ARM_Dynarmic_64::InvalidateCacheRange(VAddr addr, std::size_t size) { void ARM_Dynarmic_64::InvalidateCacheRange(u64 addr, std::size_t size) {
jit.load()->InvalidateCacheRange(addr, size); jit.load()->InvalidateCacheRange(addr, size);
} }

@ -38,8 +38,8 @@ public:
void SetVectorReg(int index, u128 value) override; void SetVectorReg(int index, u128 value) override;
u32 GetPSTATE() const override; u32 GetPSTATE() const override;
void SetPSTATE(u32 pstate) override; void SetPSTATE(u32 pstate) override;
VAddr GetTlsAddress() const override; u64 GetTlsAddress() const override;
void SetTlsAddress(VAddr address) override; void SetTlsAddress(u64 address) override;
void SetTPIDR_EL0(u64 value) override; void SetTPIDR_EL0(u64 value) override;
u64 GetTPIDR_EL0() const override; u64 GetTPIDR_EL0() const override;
@ -53,7 +53,7 @@ public:
void ClearExclusiveState() override; void ClearExclusiveState() override;
void ClearInstructionCache() override; void ClearInstructionCache() override;
void InvalidateCacheRange(VAddr addr, std::size_t size) override; void InvalidateCacheRange(u64 addr, std::size_t size) override;
void PageTableChanged(Common::PageTable& new_page_table, void PageTableChanged(Common::PageTable& new_page_table,
std::size_t new_address_space_size_in_bits) override; std::size_t new_address_space_size_in_bits) override;

@ -564,7 +564,7 @@ void System::InvalidateCpuInstructionCaches() {
impl->kernel.InvalidateAllInstructionCaches(); impl->kernel.InvalidateAllInstructionCaches();
} }
void System::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) { void System::InvalidateCpuInstructionCacheRange(u64 addr, std::size_t size) {
impl->kernel.InvalidateCpuInstructionCacheRange(addr, size); impl->kernel.InvalidateCpuInstructionCacheRange(addr, size);
} }
@ -794,7 +794,7 @@ FileSys::VirtualFilesystem System::GetFilesystem() const {
} }
void System::RegisterCheatList(const std::vector<Memory::CheatEntry>& list, void System::RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
const std::array<u8, 32>& build_id, VAddr main_region_begin, const std::array<u8, 32>& build_id, u64 main_region_begin,
u64 main_region_size) { u64 main_region_size) {
impl->cheat_engine = std::make_unique<Memory::CheatEngine>(*this, list, build_id); impl->cheat_engine = std::make_unique<Memory::CheatEngine>(*this, list, build_id);
impl->cheat_engine->SetMainMemoryParameters(main_region_begin, main_region_size); impl->cheat_engine->SetMainMemoryParameters(main_region_begin, main_region_size);

@ -172,7 +172,7 @@ public:
*/ */
void InvalidateCpuInstructionCaches(); void InvalidateCpuInstructionCaches();
void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); void InvalidateCpuInstructionCacheRange(u64 addr, std::size_t size);
/// Shutdown the main emulated process. /// Shutdown the main emulated process.
void ShutdownMainProcess(); void ShutdownMainProcess();
@ -353,7 +353,7 @@ public:
[[nodiscard]] FileSys::VirtualFilesystem GetFilesystem() const; [[nodiscard]] FileSys::VirtualFilesystem GetFilesystem() const;
void RegisterCheatList(const std::vector<Memory::CheatEntry>& list, void RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
const std::array<u8, 0x20>& build_id, VAddr main_region_begin, const std::array<u8, 0x20>& build_id, u64 main_region_begin,
u64 main_region_size); u64 main_region_size);
void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set); void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set);

@ -118,14 +118,14 @@ void GDBStub::Watchpoint(Kernel::KThread* thread, const Kernel::DebugWatchpoint&
switch (watch.type) { switch (watch.type) {
case Kernel::DebugWatchpointType::Read: case Kernel::DebugWatchpointType::Read:
SendReply(fmt::format("{}rwatch:{:x};", status, watch.start_address)); SendReply(fmt::format("{}rwatch:{:x};", status, GetInteger(watch.start_address)));
break; break;
case Kernel::DebugWatchpointType::Write: case Kernel::DebugWatchpointType::Write:
SendReply(fmt::format("{}watch:{:x};", status, watch.start_address)); SendReply(fmt::format("{}watch:{:x};", status, GetInteger(watch.start_address)));
break; break;
case Kernel::DebugWatchpointType::ReadOrWrite: case Kernel::DebugWatchpointType::ReadOrWrite:
default: default:
SendReply(fmt::format("{}awatch:{:x};", status, watch.start_address)); SendReply(fmt::format("{}awatch:{:x};", status, GetInteger(watch.start_address)));
break; break;
} }
} }
@ -554,8 +554,9 @@ void GDBStub::HandleQuery(std::string_view command) {
if (main != modules.end()) { if (main != modules.end()) {
SendReply(fmt::format("TextSeg={:x}", main->first)); SendReply(fmt::format("TextSeg={:x}", main->first));
} else { } else {
SendReply(fmt::format("TextSeg={:x}", SendReply(fmt::format(
system.ApplicationProcess()->PageTable().GetCodeRegionStart())); "TextSeg={:x}",
GetInteger(system.ApplicationProcess()->PageTable().GetCodeRegionStart())));
} }
} else if (command.starts_with("Xfer:libraries:read::")) { } else if (command.starts_with("Xfer:libraries:read::")) {
Loader::AppLoader::Modules modules; Loader::AppLoader::Modules modules;
@ -757,17 +758,20 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
reply = fmt::format("Process: {:#x} ({})\n" reply = fmt::format("Process: {:#x} ({})\n"
"Program Id: {:#018x}\n", "Program Id: {:#018x}\n",
process->GetProcessId(), process->GetName(), process->GetProgramId()); process->GetProcessId(), process->GetName(), process->GetProgramId());
reply += reply += fmt::format("Layout:\n"
fmt::format("Layout:\n"
" Alias: {:#012x} - {:#012x}\n" " Alias: {:#012x} - {:#012x}\n"
" Heap: {:#012x} - {:#012x}\n" " Heap: {:#012x} - {:#012x}\n"
" Aslr: {:#012x} - {:#012x}\n" " Aslr: {:#012x} - {:#012x}\n"
" Stack: {:#012x} - {:#012x}\n" " Stack: {:#012x} - {:#012x}\n"
"Modules:\n", "Modules:\n",
page_table.GetAliasRegionStart(), page_table.GetAliasRegionEnd(), GetInteger(page_table.GetAliasRegionStart()),
page_table.GetHeapRegionStart(), page_table.GetHeapRegionEnd(), GetInteger(page_table.GetAliasRegionEnd()),
page_table.GetAliasCodeRegionStart(), page_table.GetAliasCodeRegionEnd(), GetInteger(page_table.GetHeapRegionStart()),
page_table.GetStackRegionStart(), page_table.GetStackRegionEnd()); GetInteger(page_table.GetHeapRegionEnd()),
GetInteger(page_table.GetAliasCodeRegionStart()),
GetInteger(page_table.GetAliasCodeRegionEnd()),
GetInteger(page_table.GetStackRegionStart()),
GetInteger(page_table.GetStackRegionEnd()));
for (const auto& [vaddr, name] : modules) { for (const auto& [vaddr, name] : modules) {
reply += fmt::format(" {:#012x} - {:#012x} {}\n", vaddr, reply += fmt::format(" {:#012x} - {:#012x} {}\n", vaddr,

@ -3,8 +3,8 @@
#pragma once #pragma once
#include "common/common_types.h"
#include "common/host_memory.h" #include "common/host_memory.h"
#include "common/typed_address.h"
namespace Core { namespace Core {
@ -25,20 +25,22 @@ public:
DeviceMemory(const DeviceMemory&) = delete; DeviceMemory(const DeviceMemory&) = delete;
template <typename T> template <typename T>
PAddr GetPhysicalAddr(const T* ptr) const { Common::PhysicalAddress GetPhysicalAddr(const T* ptr) const {
return (reinterpret_cast<uintptr_t>(ptr) - return (reinterpret_cast<uintptr_t>(ptr) -
reinterpret_cast<uintptr_t>(buffer.BackingBasePointer())) + reinterpret_cast<uintptr_t>(buffer.BackingBasePointer())) +
DramMemoryMap::Base; DramMemoryMap::Base;
} }
template <typename T> template <typename T>
T* GetPointer(PAddr addr) { T* GetPointer(Common::PhysicalAddress addr) {
return reinterpret_cast<T*>(buffer.BackingBasePointer() + (addr - DramMemoryMap::Base)); return reinterpret_cast<T*>(buffer.BackingBasePointer() +
(GetInteger(addr) - DramMemoryMap::Base));
} }
template <typename T> template <typename T>
const T* GetPointer(PAddr addr) const { const T* GetPointer(Common::PhysicalAddress addr) const {
return reinterpret_cast<T*>(buffer.BackingBasePointer() + (addr - DramMemoryMap::Base)); return reinterpret_cast<T*>(buffer.BackingBasePointer() +
(GetInteger(addr) - DramMemoryMap::Base));
} }
Common::HostMemory buffer; Common::HostMemory buffer;

@ -76,22 +76,24 @@ void SetupDevicePhysicalMemoryRegions(KMemoryLayout& memory_layout) {
void SetupDramPhysicalMemoryRegions(KMemoryLayout& memory_layout) { void SetupDramPhysicalMemoryRegions(KMemoryLayout& memory_layout) {
const size_t intended_memory_size = KSystemControl::Init::GetIntendedMemorySize(); const size_t intended_memory_size = KSystemControl::Init::GetIntendedMemorySize();
const PAddr physical_memory_base_address = const KPhysicalAddress physical_memory_base_address =
KSystemControl::Init::GetKernelPhysicalBaseAddress(DramPhysicalAddress); KSystemControl::Init::GetKernelPhysicalBaseAddress(DramPhysicalAddress);
// Insert blocks into the tree. // Insert blocks into the tree.
ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
physical_memory_base_address, intended_memory_size, KMemoryRegionType_Dram)); GetInteger(physical_memory_base_address), intended_memory_size, KMemoryRegionType_Dram));
ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
physical_memory_base_address, ReservedEarlyDramSize, KMemoryRegionType_DramReservedEarly)); GetInteger(physical_memory_base_address), ReservedEarlyDramSize,
KMemoryRegionType_DramReservedEarly));
// Insert the KTrace block at the end of Dram, if KTrace is enabled. // Insert the KTrace block at the end of Dram, if KTrace is enabled.
static_assert(!IsKTraceEnabled || KTraceBufferSize > 0); static_assert(!IsKTraceEnabled || KTraceBufferSize > 0);
if constexpr (IsKTraceEnabled) { if constexpr (IsKTraceEnabled) {
const PAddr ktrace_buffer_phys_addr = const KPhysicalAddress ktrace_buffer_phys_addr =
physical_memory_base_address + intended_memory_size - KTraceBufferSize; physical_memory_base_address + intended_memory_size - KTraceBufferSize;
ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
ktrace_buffer_phys_addr, KTraceBufferSize, KMemoryRegionType_KernelTraceBuffer)); GetInteger(ktrace_buffer_phys_addr), KTraceBufferSize,
KMemoryRegionType_KernelTraceBuffer));
} }
} }

@ -3,10 +3,10 @@
#pragma once #pragma once
#include "common/common_types.h" #include "core/hle/kernel/k_typed_address.h"
namespace Kernel { namespace Kernel {
constexpr inline PAddr MainMemoryAddress = 0x80000000; constexpr inline KPhysicalAddress MainMemoryAddress = 0x80000000;
} // namespace Kernel } // namespace Kernel

@ -61,7 +61,7 @@ size_t KSystemControl::Init::GetIntendedMemorySize() {
} }
} }
PAddr KSystemControl::Init::GetKernelPhysicalBaseAddress(u64 base_address) { KPhysicalAddress KSystemControl::Init::GetKernelPhysicalBaseAddress(KPhysicalAddress base_address) {
const size_t real_dram_size = KSystemControl::Init::GetRealMemorySize(); const size_t real_dram_size = KSystemControl::Init::GetRealMemorySize();
const size_t intended_dram_size = KSystemControl::Init::GetIntendedMemorySize(); const size_t intended_dram_size = KSystemControl::Init::GetIntendedMemorySize();
if (intended_dram_size * 2 < real_dram_size) { if (intended_dram_size * 2 < real_dram_size) {

@ -3,7 +3,7 @@
#pragma once #pragma once
#include "common/common_types.h" #include "core/hle/kernel/k_typed_address.h"
namespace Kernel::Board::Nintendo::Nx { namespace Kernel::Board::Nintendo::Nx {
@ -18,7 +18,7 @@ public:
// Initialization. // Initialization.
static std::size_t GetRealMemorySize(); static std::size_t GetRealMemorySize();
static std::size_t GetIntendedMemorySize(); static std::size_t GetIntendedMemorySize();
static PAddr GetKernelPhysicalBaseAddress(u64 base_address); static KPhysicalAddress GetKernelPhysicalBaseAddress(KPhysicalAddress base_address);
static bool ShouldIncreaseThreadResourceLimit(); static bool ShouldIncreaseThreadResourceLimit();
static std::size_t GetApplicationPoolSize(); static std::size_t GetApplicationPoolSize();
static std::size_t GetAppletPoolSize(); static std::size_t GetAppletPoolSize();

@ -5,7 +5,7 @@
#include <cstddef> #include <cstddef>
#include "common/common_types.h" #include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/physical_memory.h" #include "core/hle/kernel/physical_memory.h"
namespace Kernel { namespace Kernel {
@ -36,7 +36,7 @@ struct CodeSet final {
std::size_t offset = 0; std::size_t offset = 0;
/// The address to map this segment to. /// The address to map this segment to.
VAddr addr = 0; KProcessAddress addr = 0;
/// The size of this segment in bytes. /// The size of this segment in bytes.
u32 size = 0; u32 size = 0;
@ -82,7 +82,7 @@ struct CodeSet final {
std::array<Segment, 3> segments; std::array<Segment, 3> segments;
/// The entry point address for this code set. /// The entry point address for this code set.
VAddr entrypoint = 0; KProcessAddress entrypoint = 0;
}; };
} // namespace Kernel } // namespace Kernel

@ -4,7 +4,6 @@
#include "common/alignment.h" #include "common/alignment.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h"
#include "core/core.h" #include "core/core.h"
#include "core/device_memory.h" #include "core/device_memory.h"
#include "core/hardware_properties.h" #include "core/hardware_properties.h"
@ -30,6 +29,7 @@
#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_thread_local_page.h" #include "core/hle/kernel/k_thread_local_page.h"
#include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/kernel/k_typed_address.h"
namespace Kernel::Init { namespace Kernel::Init {
@ -104,17 +104,18 @@ static_assert(KernelPageBufferAdditionalSize ==
/// Helper function to translate from the slab virtual address to the reserved location in physical /// Helper function to translate from the slab virtual address to the reserved location in physical
/// memory. /// memory.
static PAddr TranslateSlabAddrToPhysical(KMemoryLayout& memory_layout, VAddr slab_addr) { static KPhysicalAddress TranslateSlabAddrToPhysical(KMemoryLayout& memory_layout,
slab_addr -= memory_layout.GetSlabRegionAddress(); KVirtualAddress slab_addr) {
return slab_addr + Core::DramMemoryMap::SlabHeapBase; slab_addr -= GetInteger(memory_layout.GetSlabRegionAddress());
return GetInteger(slab_addr) + Core::DramMemoryMap::SlabHeapBase;
} }
template <typename T> template <typename T>
VAddr InitializeSlabHeap(Core::System& system, KMemoryLayout& memory_layout, VAddr address, KVirtualAddress InitializeSlabHeap(Core::System& system, KMemoryLayout& memory_layout,
size_t num_objects) { KVirtualAddress address, size_t num_objects) {
const size_t size = Common::AlignUp(sizeof(T) * num_objects, alignof(void*)); const size_t size = Common::AlignUp(sizeof(T) * num_objects, alignof(void*));
VAddr start = Common::AlignUp(address, alignof(T)); KVirtualAddress start = Common::AlignUp(GetInteger(address), alignof(T));
// This should use the virtual memory address passed in, but currently, we do not setup the // This should use the virtual memory address passed in, but currently, we do not setup the
// kernel virtual memory layout. Instead, we simply map these at a region of physical memory // kernel virtual memory layout. Instead, we simply map these at a region of physical memory
@ -195,7 +196,7 @@ void InitializeSlabHeaps(Core::System& system, KMemoryLayout& memory_layout) {
auto& kernel = system.Kernel(); auto& kernel = system.Kernel();
// Get the start of the slab region, since that's where we'll be working. // Get the start of the slab region, since that's where we'll be working.
VAddr address = memory_layout.GetSlabRegionAddress(); KVirtualAddress address = memory_layout.GetSlabRegionAddress();
// Initialize slab type array to be in sorted order. // Initialize slab type array to be in sorted order.
std::array<KSlabType, KSlabType_Count> slab_types; std::array<KSlabType, KSlabType_Count> slab_types;
@ -228,7 +229,7 @@ void InitializeSlabHeaps(Core::System& system, KMemoryLayout& memory_layout) {
} }
// Track the gaps, so that we can free them to the unused slab tree. // Track the gaps, so that we can free them to the unused slab tree.
VAddr gap_start = address; KVirtualAddress gap_start = address;
size_t gap_size = 0; size_t gap_size = 0;
for (size_t i = 0; i < slab_gaps.size(); i++) { for (size_t i = 0; i < slab_gaps.size(); i++) {
@ -280,7 +281,7 @@ void KPageBufferSlabHeap::Initialize(Core::System& system) {
// Allocate memory for the slab. // Allocate memory for the slab.
constexpr auto AllocateOption = KMemoryManager::EncodeOption( constexpr auto AllocateOption = KMemoryManager::EncodeOption(
KMemoryManager::Pool::System, KMemoryManager::Direction::FromFront); KMemoryManager::Pool::System, KMemoryManager::Direction::FromFront);
const PAddr slab_address = const KPhysicalAddress slab_address =
kernel.MemoryManager().AllocateAndOpenContinuous(num_pages, 1, AllocateOption); kernel.MemoryManager().AllocateAndOpenContinuous(num_pages, 1, AllocateOption);
ASSERT(slab_address != 0); ASSERT(slab_address != 0);

@ -14,7 +14,7 @@ using namespace Common::Literals;
constexpr std::size_t InitialProcessBinarySizeMax = 12_MiB; constexpr std::size_t InitialProcessBinarySizeMax = 12_MiB;
static inline PAddr GetInitialProcessBinaryPhysicalAddress() { static inline KPhysicalAddress GetInitialProcessBinaryPhysicalAddress() {
return Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetKernelPhysicalBaseAddress( return Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetKernelPhysicalBaseAddress(
MainMemoryAddress); MainMemoryAddress);
} }

@ -8,6 +8,7 @@
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_thread_queue.h" #include "core/hle/kernel/k_thread_queue.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/svc_results.h"
#include "core/memory.h" #include "core/memory.h"
@ -20,12 +21,12 @@ KAddressArbiter::~KAddressArbiter() = default;
namespace { namespace {
bool ReadFromUser(Core::System& system, s32* out, VAddr address) { bool ReadFromUser(Core::System& system, s32* out, KProcessAddress address) {
*out = system.Memory().Read32(address); *out = system.Memory().Read32(GetInteger(address));
return true; return true;
} }
bool DecrementIfLessThan(Core::System& system, s32* out, VAddr address, s32 value) { bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address, s32 value) {
auto& monitor = system.Monitor(); auto& monitor = system.Monitor();
const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
@ -35,7 +36,8 @@ bool DecrementIfLessThan(Core::System& system, s32* out, VAddr address, s32 valu
// TODO(bunnei): We should call CanAccessAtomic(..) here. // TODO(bunnei): We should call CanAccessAtomic(..) here.
// Load the value from the address. // Load the value from the address.
const s32 current_value = static_cast<s32>(monitor.ExclusiveRead32(current_core, address)); const s32 current_value =
static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address)));
// Compare it to the desired one. // Compare it to the desired one.
if (current_value < value) { if (current_value < value) {
@ -43,7 +45,8 @@ bool DecrementIfLessThan(Core::System& system, s32* out, VAddr address, s32 valu
const s32 decrement_value = current_value - 1; const s32 decrement_value = current_value - 1;
// Decrement and try to store. // Decrement and try to store.
if (!monitor.ExclusiveWrite32(current_core, address, static_cast<u32>(decrement_value))) { if (!monitor.ExclusiveWrite32(current_core, GetInteger(address),
static_cast<u32>(decrement_value))) {
// If we failed to store, try again. // If we failed to store, try again.
DecrementIfLessThan(system, out, address, value); DecrementIfLessThan(system, out, address, value);
} }
@ -57,7 +60,8 @@ bool DecrementIfLessThan(Core::System& system, s32* out, VAddr address, s32 valu
return true; return true;
} }
bool UpdateIfEqual(Core::System& system, s32* out, VAddr address, s32 value, s32 new_value) { bool UpdateIfEqual(Core::System& system, s32* out, KProcessAddress address, s32 value,
s32 new_value) {
auto& monitor = system.Monitor(); auto& monitor = system.Monitor();
const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
@ -67,14 +71,16 @@ bool UpdateIfEqual(Core::System& system, s32* out, VAddr address, s32 value, s32
// TODO(bunnei): We should call CanAccessAtomic(..) here. // TODO(bunnei): We should call CanAccessAtomic(..) here.
// Load the value from the address. // Load the value from the address.
const s32 current_value = static_cast<s32>(monitor.ExclusiveRead32(current_core, address)); const s32 current_value =
static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address)));
// Compare it to the desired one. // Compare it to the desired one.
if (current_value == value) { if (current_value == value) {
// If equal, we want to try to write the new value. // If equal, we want to try to write the new value.
// Try to store. // Try to store.
if (!monitor.ExclusiveWrite32(current_core, address, static_cast<u32>(new_value))) { if (!monitor.ExclusiveWrite32(current_core, GetInteger(address),
static_cast<u32>(new_value))) {
// If we failed to store, try again. // If we failed to store, try again.
UpdateIfEqual(system, out, address, value, new_value); UpdateIfEqual(system, out, address, value, new_value);
} }
@ -110,7 +116,7 @@ private:
} // namespace } // namespace
Result KAddressArbiter::Signal(VAddr addr, s32 count) { Result KAddressArbiter::Signal(uint64_t addr, s32 count) {
// Perform signaling. // Perform signaling.
s32 num_waiters{}; s32 num_waiters{};
{ {
@ -133,7 +139,7 @@ Result KAddressArbiter::Signal(VAddr addr, s32 count) {
R_SUCCEED(); R_SUCCEED();
} }
Result KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 count) { Result KAddressArbiter::SignalAndIncrementIfEqual(uint64_t addr, s32 value, s32 count) {
// Perform signaling. // Perform signaling.
s32 num_waiters{}; s32 num_waiters{};
{ {
@ -162,7 +168,7 @@ Result KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 cou
R_SUCCEED(); R_SUCCEED();
} }
Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 value, s32 count) { Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 value, s32 count) {
// Perform signaling. // Perform signaling.
s32 num_waiters{}; s32 num_waiters{};
{ {
@ -225,7 +231,7 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 val
R_SUCCEED(); R_SUCCEED();
} }
Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) { Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, s64 timeout) {
// Prepare to wait. // Prepare to wait.
KThread* cur_thread = GetCurrentThreadPointer(m_kernel); KThread* cur_thread = GetCurrentThreadPointer(m_kernel);
KHardwareTimer* timer{}; KHardwareTimer* timer{};
@ -280,7 +286,7 @@ Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s6
return cur_thread->GetWaitResult(); return cur_thread->GetWaitResult();
} }
Result KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { Result KAddressArbiter::WaitIfEqual(uint64_t addr, s32 value, s64 timeout) {
// Prepare to wait. // Prepare to wait.
KThread* cur_thread = GetCurrentThreadPointer(m_kernel); KThread* cur_thread = GetCurrentThreadPointer(m_kernel);
KHardwareTimer* timer{}; KHardwareTimer* timer{};

@ -25,7 +25,7 @@ public:
explicit KAddressArbiter(Core::System& system); explicit KAddressArbiter(Core::System& system);
~KAddressArbiter(); ~KAddressArbiter();
Result SignalToAddress(VAddr addr, Svc::SignalType type, s32 value, s32 count) { Result SignalToAddress(uint64_t addr, Svc::SignalType type, s32 value, s32 count) {
switch (type) { switch (type) {
case Svc::SignalType::Signal: case Svc::SignalType::Signal:
R_RETURN(this->Signal(addr, count)); R_RETURN(this->Signal(addr, count));
@ -38,7 +38,7 @@ public:
} }
} }
Result WaitForAddress(VAddr addr, Svc::ArbitrationType type, s32 value, s64 timeout) { Result WaitForAddress(uint64_t addr, Svc::ArbitrationType type, s32 value, s64 timeout) {
switch (type) { switch (type) {
case Svc::ArbitrationType::WaitIfLessThan: case Svc::ArbitrationType::WaitIfLessThan:
R_RETURN(WaitIfLessThan(addr, value, false, timeout)); R_RETURN(WaitIfLessThan(addr, value, false, timeout));
@ -52,11 +52,11 @@ public:
} }
private: private:
Result Signal(VAddr addr, s32 count); Result Signal(uint64_t addr, s32 count);
Result SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 count); Result SignalAndIncrementIfEqual(uint64_t addr, s32 value, s32 count);
Result SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 value, s32 count); Result SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 value, s32 count);
Result WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout); Result WaitIfLessThan(uint64_t addr, s32 value, bool decrement, s64 timeout);
Result WaitIfEqual(VAddr addr, s32 value, s64 timeout); Result WaitIfEqual(uint64_t addr, s32 value, s64 timeout);
private: private:
ThreadTree m_tree; ThreadTree m_tree;

@ -29,7 +29,8 @@ Result KClientSession::SendSyncRequest() {
SCOPE_EXIT({ request->Close(); }); SCOPE_EXIT({ request->Close(); });
// Initialize the request. // Initialize the request.
request->Initialize(nullptr, GetCurrentThread(m_kernel).GetTlsAddress(), MessageBufferSize); request->Initialize(nullptr, GetInteger(GetCurrentThread(m_kernel).GetTlsAddress()),
MessageBufferSize);
// Send the request. // Send the request.
R_RETURN(m_parent->GetServerSession().OnRequest(request)); R_RETURN(m_parent->GetServerSession().OnRequest(request));

@ -19,7 +19,8 @@ namespace Kernel {
KCodeMemory::KCodeMemory(KernelCore& kernel) KCodeMemory::KCodeMemory(KernelCore& kernel)
: KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock(kernel) {} : KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock(kernel) {}
Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr, size_t size) { Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, KProcessAddress addr,
size_t size) {
// Set members. // Set members.
m_owner = GetCurrentProcessPointer(m_kernel); m_owner = GetCurrentProcessPointer(m_kernel);
@ -63,7 +64,7 @@ void KCodeMemory::Finalize() {
m_owner->Close(); m_owner->Close();
} }
Result KCodeMemory::Map(VAddr address, size_t size) { Result KCodeMemory::Map(KProcessAddress address, size_t size) {
// Validate the size. // Validate the size.
R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
@ -83,7 +84,7 @@ Result KCodeMemory::Map(VAddr address, size_t size) {
R_SUCCEED(); R_SUCCEED();
} }
Result KCodeMemory::Unmap(VAddr address, size_t size) { Result KCodeMemory::Unmap(KProcessAddress address, size_t size) {
// Validate the size. // Validate the size.
R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
@ -100,7 +101,7 @@ Result KCodeMemory::Unmap(VAddr address, size_t size) {
R_SUCCEED(); R_SUCCEED();
} }
Result KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm) { Result KCodeMemory::MapToOwner(KProcessAddress address, size_t size, Svc::MemoryPermission perm) {
// Validate the size. // Validate the size.
R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
@ -134,7 +135,7 @@ Result KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission
R_SUCCEED(); R_SUCCEED();
} }
Result KCodeMemory::UnmapFromOwner(VAddr address, size_t size) { Result KCodeMemory::UnmapFromOwner(KProcessAddress address, size_t size) {
// Validate the size. // Validate the size.
R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);

@ -5,12 +5,12 @@
#include <optional> #include <optional>
#include "common/common_types.h"
#include "core/device_memory.h" #include "core/device_memory.h"
#include "core/hle/kernel/k_auto_object.h" #include "core/hle/kernel/k_auto_object.h"
#include "core/hle/kernel/k_light_lock.h" #include "core/hle/kernel/k_light_lock.h"
#include "core/hle/kernel/k_page_group.h" #include "core/hle/kernel/k_page_group.h"
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/slab_helpers.h" #include "core/hle/kernel/slab_helpers.h"
#include "core/hle/kernel/svc_types.h" #include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h" #include "core/hle/result.h"
@ -31,13 +31,13 @@ class KCodeMemory final
public: public:
explicit KCodeMemory(KernelCore& kernel); explicit KCodeMemory(KernelCore& kernel);
Result Initialize(Core::DeviceMemory& device_memory, VAddr address, size_t size); Result Initialize(Core::DeviceMemory& device_memory, KProcessAddress address, size_t size);
void Finalize() override; void Finalize() override;
Result Map(VAddr address, size_t size); Result Map(KProcessAddress address, size_t size);
Result Unmap(VAddr address, size_t size); Result Unmap(KProcessAddress address, size_t size);
Result MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm); Result MapToOwner(KProcessAddress address, size_t size, Svc::MemoryPermission perm);
Result UnmapFromOwner(VAddr address, size_t size); Result UnmapFromOwner(KProcessAddress address, size_t size);
bool IsInitialized() const override { bool IsInitialized() const override {
return m_is_initialized; return m_is_initialized;
@ -47,7 +47,7 @@ public:
KProcess* GetOwner() const override { KProcess* GetOwner() const override {
return m_owner; return m_owner;
} }
VAddr GetSourceAddress() const { KProcessAddress GetSourceAddress() const {
return m_address; return m_address;
} }
size_t GetSize() const { size_t GetSize() const {
@ -57,7 +57,7 @@ public:
private: private:
std::optional<KPageGroup> m_page_group{}; std::optional<KPageGroup> m_page_group{};
KProcess* m_owner{}; KProcess* m_owner{};
VAddr m_address{}; KProcessAddress m_address{};
KLightLock m_lock; KLightLock m_lock;
bool m_is_initialized{}; bool m_is_initialized{};
bool m_is_owner_mapped{}; bool m_is_owner_mapped{};

@ -18,23 +18,23 @@ namespace Kernel {
namespace { namespace {
bool ReadFromUser(Core::System& system, u32* out, VAddr address) { bool ReadFromUser(Core::System& system, u32* out, KProcessAddress address) {
*out = system.Memory().Read32(address); *out = system.Memory().Read32(GetInteger(address));
return true; return true;
} }
bool WriteToUser(Core::System& system, VAddr address, const u32* p) { bool WriteToUser(Core::System& system, KProcessAddress address, const u32* p) {
system.Memory().Write32(address, *p); system.Memory().Write32(GetInteger(address), *p);
return true; return true;
} }
bool UpdateLockAtomic(Core::System& system, u32* out, VAddr address, u32 if_zero, bool UpdateLockAtomic(Core::System& system, u32* out, KProcessAddress address, u32 if_zero,
u32 new_orr_mask) { u32 new_orr_mask) {
auto& monitor = system.Monitor(); auto& monitor = system.Monitor();
const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
// Load the value from the address. // Load the value from the address.
const auto expected = monitor.ExclusiveRead32(current_core, address); const auto expected = monitor.ExclusiveRead32(current_core, GetInteger(address));
// Orr in the new mask. // Orr in the new mask.
u32 value = expected | new_orr_mask; u32 value = expected | new_orr_mask;
@ -45,7 +45,7 @@ bool UpdateLockAtomic(Core::System& system, u32* out, VAddr address, u32 if_zero
} }
// Try to store. // Try to store.
if (!monitor.ExclusiveWrite32(current_core, address, value)) { if (!monitor.ExclusiveWrite32(current_core, GetInteger(address), value)) {
// If we failed to store, try again. // If we failed to store, try again.
return UpdateLockAtomic(system, out, address, if_zero, new_orr_mask); return UpdateLockAtomic(system, out, address, if_zero, new_orr_mask);
} }
@ -102,7 +102,7 @@ KConditionVariable::KConditionVariable(Core::System& system)
KConditionVariable::~KConditionVariable() = default; KConditionVariable::~KConditionVariable() = default;
Result KConditionVariable::SignalToAddress(VAddr addr) { Result KConditionVariable::SignalToAddress(KProcessAddress addr) {
KThread* owner_thread = GetCurrentThreadPointer(m_kernel); KThread* owner_thread = GetCurrentThreadPointer(m_kernel);
// Signal the address. // Signal the address.
@ -143,7 +143,7 @@ Result KConditionVariable::SignalToAddress(VAddr addr) {
} }
} }
Result KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 value) { Result KConditionVariable::WaitForAddress(Handle handle, KProcessAddress addr, u32 value) {
KThread* cur_thread = GetCurrentThreadPointer(m_kernel); KThread* cur_thread = GetCurrentThreadPointer(m_kernel);
ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(m_kernel); ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(m_kernel);
@ -191,7 +191,7 @@ void KConditionVariable::SignalImpl(KThread* thread) {
ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
// Update the tag. // Update the tag.
VAddr address = thread->GetAddressKey(); KProcessAddress address = thread->GetAddressKey();
u32 own_tag = thread->GetAddressKeyValue(); u32 own_tag = thread->GetAddressKeyValue();
u32 prev_tag{}; u32 prev_tag{};
@ -262,7 +262,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
} }
} }
Result KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) { Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout) {
// Prepare to wait. // Prepare to wait.
KThread* cur_thread = GetCurrentThreadPointer(m_kernel); KThread* cur_thread = GetCurrentThreadPointer(m_kernel);
KHardwareTimer* timer{}; KHardwareTimer* timer{};

@ -4,10 +4,10 @@
#pragma once #pragma once
#include "common/assert.h" #include "common/assert.h"
#include "common/common_types.h"
#include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/result.h" #include "core/hle/result.h"
@ -25,12 +25,12 @@ public:
~KConditionVariable(); ~KConditionVariable();
// Arbitration // Arbitration
Result SignalToAddress(VAddr addr); Result SignalToAddress(KProcessAddress addr);
Result WaitForAddress(Handle handle, VAddr addr, u32 value); Result WaitForAddress(Handle handle, KProcessAddress addr, u32 value);
// Condition variable // Condition variable
void Signal(u64 cv_key, s32 count); void Signal(u64 cv_key, s32 count);
Result Wait(VAddr addr, u64 key, u32 value, s64 timeout); Result Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout);
private: private:
void SignalImpl(KThread* thread); void SignalImpl(KThread* thread);

@ -54,8 +54,8 @@ Result KDeviceAddressSpace::Detach(Svc::DeviceName device_name) {
R_SUCCEED(); R_SUCCEED();
} }
Result KDeviceAddressSpace::Map(KPageTable* page_table, VAddr process_address, size_t size, Result KDeviceAddressSpace::Map(KPageTable* page_table, KProcessAddress process_address,
u64 device_address, u32 option, bool is_aligned) { size_t size, u64 device_address, u32 option, bool is_aligned) {
// Check that the address falls within the space. // Check that the address falls within the space.
R_UNLESS((m_space_address <= device_address && R_UNLESS((m_space_address <= device_address &&
device_address + size - 1 <= m_space_address + m_space_size - 1), device_address + size - 1 <= m_space_address + m_space_size - 1),
@ -113,8 +113,8 @@ Result KDeviceAddressSpace::Map(KPageTable* page_table, VAddr process_address, s
R_SUCCEED(); R_SUCCEED();
} }
Result KDeviceAddressSpace::Unmap(KPageTable* page_table, VAddr process_address, size_t size, Result KDeviceAddressSpace::Unmap(KPageTable* page_table, KProcessAddress process_address,
u64 device_address) { size_t size, u64 device_address) {
// Check that the address falls within the space. // Check that the address falls within the space.
R_UNLESS((m_space_address <= device_address && R_UNLESS((m_space_address <= device_address &&
device_address + size - 1 <= m_space_address + m_space_size - 1), device_address + size - 1 <= m_space_address + m_space_size - 1),

@ -5,8 +5,8 @@
#include <string> #include <string>
#include "common/common_types.h"
#include "core/hle/kernel/k_page_table.h" #include "core/hle/kernel/k_page_table.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/slab_helpers.h" #include "core/hle/kernel/slab_helpers.h"
#include "core/hle/result.h" #include "core/hle/result.h"
@ -31,23 +31,24 @@ public:
Result Attach(Svc::DeviceName device_name); Result Attach(Svc::DeviceName device_name);
Result Detach(Svc::DeviceName device_name); Result Detach(Svc::DeviceName device_name);
Result MapByForce(KPageTable* page_table, VAddr process_address, size_t size, Result MapByForce(KPageTable* page_table, KProcessAddress process_address, size_t size,
u64 device_address, u32 option) { u64 device_address, u32 option) {
R_RETURN(this->Map(page_table, process_address, size, device_address, option, false)); R_RETURN(this->Map(page_table, process_address, size, device_address, option, false));
} }
Result MapAligned(KPageTable* page_table, VAddr process_address, size_t size, Result MapAligned(KPageTable* page_table, KProcessAddress process_address, size_t size,
u64 device_address, u32 option) { u64 device_address, u32 option) {
R_RETURN(this->Map(page_table, process_address, size, device_address, option, true)); R_RETURN(this->Map(page_table, process_address, size, device_address, option, true));
} }
Result Unmap(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address); Result Unmap(KPageTable* page_table, KProcessAddress process_address, size_t size,
u64 device_address);
static void Initialize(); static void Initialize();
private: private:
Result Map(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address, Result Map(KPageTable* page_table, KProcessAddress process_address, size_t size,
u32 option, bool is_aligned); u64 device_address, u32 option, bool is_aligned);
private: private:
KLightLock m_lock; KLightLock m_lock;

@ -6,9 +6,9 @@
#include <vector> #include <vector>
#include "common/alignment.h" #include "common/alignment.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/k_spin_lock.h" #include "core/hle/kernel/k_spin_lock.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/memory_types.h" #include "core/hle/kernel/memory_types.h"
#include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/svc_results.h"
@ -26,23 +26,23 @@ public:
KDynamicPageManager() = default; KDynamicPageManager() = default;
template <typename T> template <typename T>
T* GetPointer(VAddr addr) { T* GetPointer(KVirtualAddress addr) {
return reinterpret_cast<T*>(m_backing_memory.data() + (addr - m_address)); return reinterpret_cast<T*>(m_backing_memory.data() + (addr - m_address));
} }
template <typename T> template <typename T>
const T* GetPointer(VAddr addr) const { const T* GetPointer(KVirtualAddress addr) const {
return reinterpret_cast<T*>(m_backing_memory.data() + (addr - m_address)); return reinterpret_cast<T*>(m_backing_memory.data() + (addr - m_address));
} }
Result Initialize(VAddr memory, size_t size, size_t align) { Result Initialize(KVirtualAddress memory, size_t size, size_t align) {
// We need to have positive size. // We need to have positive size.
R_UNLESS(size > 0, ResultOutOfMemory); R_UNLESS(size > 0, ResultOutOfMemory);
m_backing_memory.resize(size); m_backing_memory.resize(size);
// Set addresses. // Set addresses.
m_address = memory; m_address = memory;
m_aligned_address = Common::AlignDown(memory, align); m_aligned_address = Common::AlignDown(GetInteger(memory), align);
// Calculate extents. // Calculate extents.
const size_t managed_size = m_address + size - m_aligned_address; const size_t managed_size = m_address + size - m_aligned_address;
@ -79,7 +79,7 @@ public:
R_SUCCEED(); R_SUCCEED();
} }
VAddr GetAddress() const { KVirtualAddress GetAddress() const {
return m_address; return m_address;
} }
size_t GetSize() const { size_t GetSize() const {
@ -145,7 +145,8 @@ public:
KScopedSpinLock lk(m_lock); KScopedSpinLock lk(m_lock);
// Set the bit for the free page. // Set the bit for the free page.
size_t offset = (reinterpret_cast<uintptr_t>(pb) - m_aligned_address) / sizeof(PageBuffer); size_t offset =
(reinterpret_cast<uint64_t>(pb) - GetInteger(m_aligned_address)) / sizeof(PageBuffer);
m_page_bitmap.SetBit(offset); m_page_bitmap.SetBit(offset);
// Decrement our used count. // Decrement our used count.
@ -158,8 +159,8 @@ private:
size_t m_used{}; size_t m_used{};
size_t m_peak{}; size_t m_peak{};
size_t m_count{}; size_t m_count{};
VAddr m_address{}; KVirtualAddress m_address{};
VAddr m_aligned_address{}; KVirtualAddress m_aligned_address{};
size_t m_size{}; size_t m_size{};
// TODO(bunnei): Back by host memory until we emulate kernel virtual address space. // TODO(bunnei): Back by host memory until we emulate kernel virtual address space.

@ -19,7 +19,7 @@ class KDynamicSlabHeap : protected impl::KSlabHeapImpl {
public: public:
constexpr KDynamicSlabHeap() = default; constexpr KDynamicSlabHeap() = default;
constexpr VAddr GetAddress() const { constexpr KVirtualAddress GetAddress() const {
return m_address; return m_address;
} }
constexpr size_t GetSize() const { constexpr size_t GetSize() const {
@ -35,7 +35,7 @@ public:
return m_count.load(); return m_count.load();
} }
constexpr bool IsInRange(VAddr addr) const { constexpr bool IsInRange(KVirtualAddress addr) const {
return this->GetAddress() <= addr && addr <= this->GetAddress() + this->GetSize() - 1; return this->GetAddress() <= addr && addr <= this->GetAddress() + this->GetSize() - 1;
} }
@ -115,7 +115,7 @@ private:
std::atomic<size_t> m_used{}; std::atomic<size_t> m_used{};
std::atomic<size_t> m_peak{}; std::atomic<size_t> m_peak{};
std::atomic<size_t> m_count{}; std::atomic<size_t> m_count{};
VAddr m_address{}; KVirtualAddress m_address{};
size_t m_size{}; size_t m_size{};
}; };

@ -5,8 +5,8 @@
#include "common/alignment.h" #include "common/alignment.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/common_types.h"
#include "common/intrusive_red_black_tree.h" #include "common/intrusive_red_black_tree.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/memory_types.h" #include "core/hle/kernel/memory_types.h"
#include "core/hle/kernel/svc_types.h" #include "core/hle/kernel/svc_types.h"
@ -282,7 +282,7 @@ class KMemoryBlock : public Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock>
private: private:
u16 m_device_disable_merge_left_count{}; u16 m_device_disable_merge_left_count{};
u16 m_device_disable_merge_right_count{}; u16 m_device_disable_merge_right_count{};
VAddr m_address{}; KProcessAddress m_address{};
size_t m_num_pages{}; size_t m_num_pages{};
KMemoryState m_memory_state{KMemoryState::None}; KMemoryState m_memory_state{KMemoryState::None};
u16 m_ipc_lock_count{}; u16 m_ipc_lock_count{};
@ -306,7 +306,7 @@ public:
} }
public: public:
constexpr VAddr GetAddress() const { constexpr KProcessAddress GetAddress() const {
return m_address; return m_address;
} }
@ -318,11 +318,11 @@ public:
return this->GetNumPages() * PageSize; return this->GetNumPages() * PageSize;
} }
constexpr VAddr GetEndAddress() const { constexpr KProcessAddress GetEndAddress() const {
return this->GetAddress() + this->GetSize(); return this->GetAddress() + this->GetSize();
} }
constexpr VAddr GetLastAddress() const { constexpr KProcessAddress GetLastAddress() const {
return this->GetEndAddress() - 1; return this->GetEndAddress() - 1;
} }
@ -348,7 +348,7 @@ public:
constexpr KMemoryInfo GetMemoryInfo() const { constexpr KMemoryInfo GetMemoryInfo() const {
return { return {
.m_address = this->GetAddress(), .m_address = GetInteger(this->GetAddress()),
.m_size = this->GetSize(), .m_size = this->GetSize(),
.m_state = m_memory_state, .m_state = m_memory_state,
.m_device_disable_merge_left_count = m_device_disable_merge_left_count, .m_device_disable_merge_left_count = m_device_disable_merge_left_count,
@ -366,12 +366,12 @@ public:
public: public:
explicit KMemoryBlock() = default; explicit KMemoryBlock() = default;
constexpr KMemoryBlock(VAddr addr, size_t np, KMemoryState ms, KMemoryPermission p, constexpr KMemoryBlock(KProcessAddress addr, size_t np, KMemoryState ms, KMemoryPermission p,
KMemoryAttribute attr) KMemoryAttribute attr)
: Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock>(), m_address(addr), m_num_pages(np), : Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock>(), m_address(addr), m_num_pages(np),
m_memory_state(ms), m_permission(p), m_attribute(attr) {} m_memory_state(ms), m_permission(p), m_attribute(attr) {}
constexpr void Initialize(VAddr addr, size_t np, KMemoryState ms, KMemoryPermission p, constexpr void Initialize(KProcessAddress addr, size_t np, KMemoryState ms, KMemoryPermission p,
KMemoryAttribute attr) { KMemoryAttribute attr) {
m_device_disable_merge_left_count = 0; m_device_disable_merge_left_count = 0;
m_device_disable_merge_right_count = 0; m_device_disable_merge_right_count = 0;
@ -408,7 +408,7 @@ public:
KMemoryBlockDisableMergeAttribute::None; KMemoryBlockDisableMergeAttribute::None;
} }
constexpr bool Contains(VAddr addr) const { constexpr bool Contains(KProcessAddress addr) const {
return this->GetAddress() <= addr && addr <= this->GetEndAddress(); return this->GetAddress() <= addr && addr <= this->GetEndAddress();
} }
@ -443,10 +443,10 @@ public:
} }
} }
constexpr void Split(KMemoryBlock* block, VAddr addr) { constexpr void Split(KMemoryBlock* block, KProcessAddress addr) {
ASSERT(this->GetAddress() < addr); ASSERT(this->GetAddress() < addr);
ASSERT(this->Contains(addr)); ASSERT(this->Contains(addr));
ASSERT(Common::IsAligned(addr, PageSize)); ASSERT(Common::IsAligned(GetInteger(addr), PageSize));
block->m_address = m_address; block->m_address = m_address;
block->m_num_pages = (addr - this->GetAddress()) / PageSize; block->m_num_pages = (addr - this->GetAddress()) / PageSize;

@ -7,7 +7,8 @@ namespace Kernel {
KMemoryBlockManager::KMemoryBlockManager() = default; KMemoryBlockManager::KMemoryBlockManager() = default;
Result KMemoryBlockManager::Initialize(VAddr st, VAddr nd, KMemoryBlockSlabManager* slab_manager) { Result KMemoryBlockManager::Initialize(KProcessAddress st, KProcessAddress nd,
KMemoryBlockSlabManager* slab_manager) {
// Allocate a block to encapsulate the address space, insert it into the tree. // Allocate a block to encapsulate the address space, insert it into the tree.
KMemoryBlock* start_block = slab_manager->Allocate(); KMemoryBlock* start_block = slab_manager->Allocate();
R_UNLESS(start_block != nullptr, ResultOutOfResource); R_UNLESS(start_block != nullptr, ResultOutOfResource);
@ -15,8 +16,8 @@ Result KMemoryBlockManager::Initialize(VAddr st, VAddr nd, KMemoryBlockSlabManag
// Set our start and end. // Set our start and end.
m_start_address = st; m_start_address = st;
m_end_address = nd; m_end_address = nd;
ASSERT(Common::IsAligned(m_start_address, PageSize)); ASSERT(Common::IsAligned(GetInteger(m_start_address), PageSize));
ASSERT(Common::IsAligned(m_end_address, PageSize)); ASSERT(Common::IsAligned(GetInteger(m_end_address), PageSize));
// Initialize and insert the block. // Initialize and insert the block.
start_block->Initialize(m_start_address, (m_end_address - m_start_address) / PageSize, start_block->Initialize(m_start_address, (m_end_address - m_start_address) / PageSize,
@ -40,12 +41,13 @@ void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager,
ASSERT(m_memory_block_tree.empty()); ASSERT(m_memory_block_tree.empty());
} }
VAddr KMemoryBlockManager::FindFreeArea(VAddr region_start, size_t region_num_pages, KProcessAddress KMemoryBlockManager::FindFreeArea(KProcessAddress region_start,
size_t num_pages, size_t alignment, size_t offset, size_t region_num_pages, size_t num_pages,
size_t alignment, size_t offset,
size_t guard_pages) const { size_t guard_pages) const {
if (num_pages > 0) { if (num_pages > 0) {
const VAddr region_end = region_start + region_num_pages * PageSize; const KProcessAddress region_end = region_start + region_num_pages * PageSize;
const VAddr region_last = region_end - 1; const KProcessAddress region_last = region_end - 1;
for (const_iterator it = this->FindIterator(region_start); it != m_memory_block_tree.cend(); for (const_iterator it = this->FindIterator(region_start); it != m_memory_block_tree.cend();
it++) { it++) {
const KMemoryInfo info = it->GetMemoryInfo(); const KMemoryInfo info = it->GetMemoryInfo();
@ -56,17 +58,19 @@ VAddr KMemoryBlockManager::FindFreeArea(VAddr region_start, size_t region_num_pa
continue; continue;
} }
VAddr area = (info.GetAddress() <= region_start) ? region_start : info.GetAddress(); KProcessAddress area =
(info.GetAddress() <= GetInteger(region_start)) ? region_start : info.GetAddress();
area += guard_pages * PageSize; area += guard_pages * PageSize;
const VAddr offset_area = Common::AlignDown(area, alignment) + offset; const KProcessAddress offset_area =
Common::AlignDown(GetInteger(area), alignment) + offset;
area = (area <= offset_area) ? offset_area : offset_area + alignment; area = (area <= offset_area) ? offset_area : offset_area + alignment;
const VAddr area_end = area + num_pages * PageSize + guard_pages * PageSize; const KProcessAddress area_end = area + num_pages * PageSize + guard_pages * PageSize;
const VAddr area_last = area_end - 1; const KProcessAddress area_last = area_end - 1;
if (info.GetAddress() <= area && area < area_last && area_last <= region_last && if (info.GetAddress() <= GetInteger(area) && area < area_last &&
area_last <= info.GetLastAddress()) { area_last <= region_last && area_last <= info.GetLastAddress()) {
return area; return area;
} }
} }
@ -76,7 +80,7 @@ VAddr KMemoryBlockManager::FindFreeArea(VAddr region_start, size_t region_num_pa
} }
void KMemoryBlockManager::CoalesceForUpdate(KMemoryBlockManagerUpdateAllocator* allocator, void KMemoryBlockManager::CoalesceForUpdate(KMemoryBlockManagerUpdateAllocator* allocator,
VAddr address, size_t num_pages) { KProcessAddress address, size_t num_pages) {
// Find the iterator now that we've updated. // Find the iterator now that we've updated.
iterator it = this->FindIterator(address); iterator it = this->FindIterator(address);
if (address != m_start_address) { if (address != m_start_address) {
@ -104,18 +108,18 @@ void KMemoryBlockManager::CoalesceForUpdate(KMemoryBlockManagerUpdateAllocator*
} }
} }
void KMemoryBlockManager::Update(KMemoryBlockManagerUpdateAllocator* allocator, VAddr address, void KMemoryBlockManager::Update(KMemoryBlockManagerUpdateAllocator* allocator,
size_t num_pages, KMemoryState state, KMemoryPermission perm, KProcessAddress address, size_t num_pages, KMemoryState state,
KMemoryAttribute attr, KMemoryPermission perm, KMemoryAttribute attr,
KMemoryBlockDisableMergeAttribute set_disable_attr, KMemoryBlockDisableMergeAttribute set_disable_attr,
KMemoryBlockDisableMergeAttribute clear_disable_attr) { KMemoryBlockDisableMergeAttribute clear_disable_attr) {
// Ensure for auditing that we never end up with an invalid tree. // Ensure for auditing that we never end up with an invalid tree.
KScopedMemoryBlockManagerAuditor auditor(this); KScopedMemoryBlockManagerAuditor auditor(this);
ASSERT(Common::IsAligned(address, PageSize)); ASSERT(Common::IsAligned(GetInteger(address), PageSize));
ASSERT((attr & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared)) == ASSERT((attr & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared)) ==
KMemoryAttribute::None); KMemoryAttribute::None);
VAddr cur_address = address; KProcessAddress cur_address = address;
size_t remaining_pages = num_pages; size_t remaining_pages = num_pages;
iterator it = this->FindIterator(address); iterator it = this->FindIterator(address);
@ -168,17 +172,17 @@ void KMemoryBlockManager::Update(KMemoryBlockManagerUpdateAllocator* allocator,
} }
void KMemoryBlockManager::UpdateIfMatch(KMemoryBlockManagerUpdateAllocator* allocator, void KMemoryBlockManager::UpdateIfMatch(KMemoryBlockManagerUpdateAllocator* allocator,
VAddr address, size_t num_pages, KMemoryState test_state, KProcessAddress address, size_t num_pages,
KMemoryPermission test_perm, KMemoryAttribute test_attr, KMemoryState test_state, KMemoryPermission test_perm,
KMemoryState state, KMemoryPermission perm, KMemoryAttribute test_attr, KMemoryState state,
KMemoryAttribute attr) { KMemoryPermission perm, KMemoryAttribute attr) {
// Ensure for auditing that we never end up with an invalid tree. // Ensure for auditing that we never end up with an invalid tree.
KScopedMemoryBlockManagerAuditor auditor(this); KScopedMemoryBlockManagerAuditor auditor(this);
ASSERT(Common::IsAligned(address, PageSize)); ASSERT(Common::IsAligned(GetInteger(address), PageSize));
ASSERT((attr & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared)) == ASSERT((attr & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared)) ==
KMemoryAttribute::None); KMemoryAttribute::None);
VAddr cur_address = address; KProcessAddress cur_address = address;
size_t remaining_pages = num_pages; size_t remaining_pages = num_pages;
iterator it = this->FindIterator(address); iterator it = this->FindIterator(address);
@ -230,18 +234,18 @@ void KMemoryBlockManager::UpdateIfMatch(KMemoryBlockManagerUpdateAllocator* allo
this->CoalesceForUpdate(allocator, address, num_pages); this->CoalesceForUpdate(allocator, address, num_pages);
} }
void KMemoryBlockManager::UpdateLock(KMemoryBlockManagerUpdateAllocator* allocator, VAddr address, void KMemoryBlockManager::UpdateLock(KMemoryBlockManagerUpdateAllocator* allocator,
size_t num_pages, MemoryBlockLockFunction lock_func, KProcessAddress address, size_t num_pages,
KMemoryPermission perm) { MemoryBlockLockFunction lock_func, KMemoryPermission perm) {
// Ensure for auditing that we never end up with an invalid tree. // Ensure for auditing that we never end up with an invalid tree.
KScopedMemoryBlockManagerAuditor auditor(this); KScopedMemoryBlockManagerAuditor auditor(this);
ASSERT(Common::IsAligned(address, PageSize)); ASSERT(Common::IsAligned(GetInteger(address), PageSize));
VAddr cur_address = address; KProcessAddress cur_address = address;
size_t remaining_pages = num_pages; size_t remaining_pages = num_pages;
iterator it = this->FindIterator(address); iterator it = this->FindIterator(address);
const VAddr end_address = address + (num_pages * PageSize); const KProcessAddress end_address = address + (num_pages * PageSize);
while (remaining_pages > 0) { while (remaining_pages > 0) {
const size_t remaining_size = remaining_pages * PageSize; const size_t remaining_size = remaining_pages * PageSize;

@ -7,9 +7,9 @@
#include <functional> #include <functional>
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h"
#include "core/hle/kernel/k_dynamic_resource_manager.h" #include "core/hle/kernel/k_dynamic_resource_manager.h"
#include "core/hle/kernel/k_memory_block.h" #include "core/hle/kernel/k_memory_block.h"
#include "core/hle/kernel/k_typed_address.h"
namespace Kernel { namespace Kernel {
@ -85,9 +85,10 @@ public:
public: public:
KMemoryBlockManager(); KMemoryBlockManager();
using HostUnmapCallback = std::function<void(VAddr, u64)>; using HostUnmapCallback = std::function<void(Common::ProcessAddress, u64)>;
Result Initialize(VAddr st, VAddr nd, KMemoryBlockSlabManager* slab_manager); Result Initialize(KProcessAddress st, KProcessAddress nd,
KMemoryBlockSlabManager* slab_manager);
void Finalize(KMemoryBlockSlabManager* slab_manager, HostUnmapCallback&& host_unmap_callback); void Finalize(KMemoryBlockSlabManager* slab_manager, HostUnmapCallback&& host_unmap_callback);
iterator end() { iterator end() {
@ -100,27 +101,28 @@ public:
return m_memory_block_tree.cend(); return m_memory_block_tree.cend();
} }
VAddr FindFreeArea(VAddr region_start, size_t region_num_pages, size_t num_pages, KProcessAddress FindFreeArea(KProcessAddress region_start, size_t region_num_pages,
size_t alignment, size_t offset, size_t guard_pages) const; size_t num_pages, size_t alignment, size_t offset,
size_t guard_pages) const;
void Update(KMemoryBlockManagerUpdateAllocator* allocator, VAddr address, size_t num_pages, void Update(KMemoryBlockManagerUpdateAllocator* allocator, KProcessAddress address,
KMemoryState state, KMemoryPermission perm, KMemoryAttribute attr, size_t num_pages, KMemoryState state, KMemoryPermission perm, KMemoryAttribute attr,
KMemoryBlockDisableMergeAttribute set_disable_attr, KMemoryBlockDisableMergeAttribute set_disable_attr,
KMemoryBlockDisableMergeAttribute clear_disable_attr); KMemoryBlockDisableMergeAttribute clear_disable_attr);
void UpdateLock(KMemoryBlockManagerUpdateAllocator* allocator, VAddr address, size_t num_pages, void UpdateLock(KMemoryBlockManagerUpdateAllocator* allocator, KProcessAddress address,
MemoryBlockLockFunction lock_func, KMemoryPermission perm); size_t num_pages, MemoryBlockLockFunction lock_func, KMemoryPermission perm);
void UpdateIfMatch(KMemoryBlockManagerUpdateAllocator* allocator, VAddr address, void UpdateIfMatch(KMemoryBlockManagerUpdateAllocator* allocator, KProcessAddress address,
size_t num_pages, KMemoryState test_state, KMemoryPermission test_perm, size_t num_pages, KMemoryState test_state, KMemoryPermission test_perm,
KMemoryAttribute test_attr, KMemoryState state, KMemoryPermission perm, KMemoryAttribute test_attr, KMemoryState state, KMemoryPermission perm,
KMemoryAttribute attr); KMemoryAttribute attr);
iterator FindIterator(VAddr address) const { iterator FindIterator(KProcessAddress address) const {
return m_memory_block_tree.find(KMemoryBlock( return m_memory_block_tree.find(KMemoryBlock(
address, 1, KMemoryState::Free, KMemoryPermission::None, KMemoryAttribute::None)); address, 1, KMemoryState::Free, KMemoryPermission::None, KMemoryAttribute::None));
} }
const KMemoryBlock* FindBlock(VAddr address) const { const KMemoryBlock* FindBlock(KProcessAddress address) const {
if (const_iterator it = this->FindIterator(address); it != m_memory_block_tree.end()) { if (const_iterator it = this->FindIterator(address); it != m_memory_block_tree.end()) {
return std::addressof(*it); return std::addressof(*it);
} }
@ -132,12 +134,12 @@ public:
bool CheckState() const; bool CheckState() const;
private: private:
void CoalesceForUpdate(KMemoryBlockManagerUpdateAllocator* allocator, VAddr address, void CoalesceForUpdate(KMemoryBlockManagerUpdateAllocator* allocator, KProcessAddress address,
size_t num_pages); size_t num_pages);
MemoryBlockTree m_memory_block_tree; MemoryBlockTree m_memory_block_tree;
VAddr m_start_address{}; KProcessAddress m_start_address{};
VAddr m_end_address{}; KProcessAddress m_end_address{};
}; };
class KScopedMemoryBlockManagerAuditor { class KScopedMemoryBlockManagerAuditor {

@ -85,7 +85,8 @@ bool KMemoryRegionTree::Insert(u64 address, size_t size, u32 type_id, u32 new_at
return true; return true;
} }
VAddr KMemoryRegionTree::GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id) { KVirtualAddress KMemoryRegionTree::GetRandomAlignedRegion(size_t size, size_t alignment,
u32 type_id) {
// We want to find the total extents of the type id. // We want to find the total extents of the type id.
const auto extents = this->GetDerivedRegionExtents(static_cast<KMemoryRegionType>(type_id)); const auto extents = this->GetDerivedRegionExtents(static_cast<KMemoryRegionType>(type_id));
@ -130,11 +131,13 @@ KMemoryLayout::KMemoryLayout()
m_virtual_linear_tree{m_memory_region_allocator}, m_physical_linear_tree{ m_virtual_linear_tree{m_memory_region_allocator}, m_physical_linear_tree{
m_memory_region_allocator} {} m_memory_region_allocator} {}
void KMemoryLayout::InitializeLinearMemoryRegionTrees(PAddr aligned_linear_phys_start, void KMemoryLayout::InitializeLinearMemoryRegionTrees(KPhysicalAddress aligned_linear_phys_start,
VAddr linear_virtual_start) { KVirtualAddress linear_virtual_start) {
// Set static differences. // Set static differences.
m_linear_phys_to_virt_diff = linear_virtual_start - aligned_linear_phys_start; m_linear_phys_to_virt_diff =
m_linear_virt_to_phys_diff = aligned_linear_phys_start - linear_virtual_start; GetInteger(linear_virtual_start) - GetInteger(aligned_linear_phys_start);
m_linear_virt_to_phys_diff =
GetInteger(aligned_linear_phys_start) - GetInteger(linear_virtual_start);
// Initialize linear trees. // Initialize linear trees.
for (auto& region : GetPhysicalMemoryRegionTree()) { for (auto& region : GetPhysicalMemoryRegionTree()) {

@ -10,6 +10,7 @@
#include "core/device_memory.h" #include "core/device_memory.h"
#include "core/hle/kernel/k_memory_region.h" #include "core/hle/kernel/k_memory_region.h"
#include "core/hle/kernel/k_memory_region_type.h" #include "core/hle/kernel/k_memory_region_type.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/memory_types.h" #include "core/hle/kernel/memory_types.h"
namespace Kernel { namespace Kernel {
@ -69,10 +70,11 @@ constexpr std::size_t KernelResourceSize = KernelPageTableHeapSize + KernelIniti
//! NB: Use KThread::GetAddressKeyIsKernel(). //! NB: Use KThread::GetAddressKeyIsKernel().
//! See explanation for deviation of GetAddressKey. //! See explanation for deviation of GetAddressKey.
bool IsKernelAddressKey(VAddr key) = delete; bool IsKernelAddressKey(KProcessAddress key) = delete;
constexpr bool IsKernelAddress(VAddr address) { constexpr bool IsKernelAddress(KProcessAddress address) {
return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd; return KernelVirtualAddressSpaceBase <= GetInteger(address) &&
address < KernelVirtualAddressSpaceEnd;
} }
class KMemoryLayout final { class KMemoryLayout final {
@ -104,38 +106,38 @@ public:
return m_physical_linear_tree; return m_physical_linear_tree;
} }
VAddr GetLinearVirtualAddress(PAddr address) const { KVirtualAddress GetLinearVirtualAddress(KPhysicalAddress address) const {
return address + m_linear_phys_to_virt_diff; return GetInteger(address) + m_linear_phys_to_virt_diff;
} }
PAddr GetLinearPhysicalAddress(VAddr address) const { KPhysicalAddress GetLinearPhysicalAddress(KVirtualAddress address) const {
return address + m_linear_virt_to_phys_diff; return GetInteger(address) + m_linear_virt_to_phys_diff;
} }
const KMemoryRegion* FindVirtual(VAddr address) const { const KMemoryRegion* FindVirtual(KVirtualAddress address) const {
return Find(address, GetVirtualMemoryRegionTree()); return Find(address, GetVirtualMemoryRegionTree());
} }
const KMemoryRegion* FindPhysical(PAddr address) const { const KMemoryRegion* FindPhysical(KPhysicalAddress address) const {
return Find(address, GetPhysicalMemoryRegionTree()); return Find(address, GetPhysicalMemoryRegionTree());
} }
const KMemoryRegion* FindVirtualLinear(VAddr address) const { const KMemoryRegion* FindVirtualLinear(KVirtualAddress address) const {
return Find(address, GetVirtualLinearMemoryRegionTree()); return Find(address, GetVirtualLinearMemoryRegionTree());
} }
const KMemoryRegion* FindPhysicalLinear(PAddr address) const { const KMemoryRegion* FindPhysicalLinear(KPhysicalAddress address) const {
return Find(address, GetPhysicalLinearMemoryRegionTree()); return Find(address, GetPhysicalLinearMemoryRegionTree());
} }
VAddr GetMainStackTopAddress(s32 core_id) const { KVirtualAddress GetMainStackTopAddress(s32 core_id) const {
return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscMainStack); return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscMainStack);
} }
VAddr GetIdleStackTopAddress(s32 core_id) const { KVirtualAddress GetIdleStackTopAddress(s32 core_id) const {
return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscIdleStack); return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscIdleStack);
} }
VAddr GetExceptionStackTopAddress(s32 core_id) const { KVirtualAddress GetExceptionStackTopAddress(s32 core_id) const {
return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscExceptionStack); return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscExceptionStack);
} }
VAddr GetSlabRegionAddress() const { KVirtualAddress GetSlabRegionAddress() const {
return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelSlab)) return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelSlab))
.GetAddress(); .GetAddress();
} }
@ -143,10 +145,10 @@ public:
const KMemoryRegion& GetDeviceRegion(KMemoryRegionType type) const { const KMemoryRegion& GetDeviceRegion(KMemoryRegionType type) const {
return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(type)); return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(type));
} }
PAddr GetDevicePhysicalAddress(KMemoryRegionType type) const { KPhysicalAddress GetDevicePhysicalAddress(KMemoryRegionType type) const {
return GetDeviceRegion(type).GetAddress(); return GetDeviceRegion(type).GetAddress();
} }
VAddr GetDeviceVirtualAddress(KMemoryRegionType type) const { KVirtualAddress GetDeviceVirtualAddress(KMemoryRegionType type) const {
return GetDeviceRegion(type).GetPairAddress(); return GetDeviceRegion(type).GetPairAddress();
} }
@ -175,11 +177,11 @@ public:
KMemoryRegionType_VirtualDramKernelSecureAppletMemory)); KMemoryRegionType_VirtualDramKernelSecureAppletMemory));
} }
const KMemoryRegion& GetVirtualLinearRegion(VAddr address) const { const KMemoryRegion& GetVirtualLinearRegion(KVirtualAddress address) const {
return Dereference(FindVirtualLinear(address)); return Dereference(FindVirtualLinear(address));
} }
const KMemoryRegion& GetPhysicalLinearRegion(PAddr address) const { const KMemoryRegion& GetPhysicalLinearRegion(KPhysicalAddress address) const {
return Dereference(FindPhysicalLinear(address)); return Dereference(FindPhysicalLinear(address));
} }
@ -193,29 +195,32 @@ public:
return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_DTB); return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_DTB);
} }
bool IsHeapPhysicalAddress(const KMemoryRegion*& region, PAddr address) const { bool IsHeapPhysicalAddress(const KMemoryRegion*& region, KPhysicalAddress address) const {
return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(), return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(),
KMemoryRegionType_DramUserPool); KMemoryRegionType_DramUserPool);
} }
bool IsHeapVirtualAddress(const KMemoryRegion*& region, VAddr address) const { bool IsHeapVirtualAddress(const KMemoryRegion*& region, KVirtualAddress address) const {
return IsTypedAddress(region, address, GetVirtualLinearMemoryRegionTree(), return IsTypedAddress(region, address, GetVirtualLinearMemoryRegionTree(),
KMemoryRegionType_VirtualDramUserPool); KMemoryRegionType_VirtualDramUserPool);
} }
bool IsHeapPhysicalAddress(const KMemoryRegion*& region, PAddr address, size_t size) const { bool IsHeapPhysicalAddress(const KMemoryRegion*& region, KPhysicalAddress address,
size_t size) const {
return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(), return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(),
KMemoryRegionType_DramUserPool); KMemoryRegionType_DramUserPool);
} }
bool IsHeapVirtualAddress(const KMemoryRegion*& region, VAddr address, size_t size) const { bool IsHeapVirtualAddress(const KMemoryRegion*& region, KVirtualAddress address,
size_t size) const {
return IsTypedAddress(region, address, size, GetVirtualLinearMemoryRegionTree(), return IsTypedAddress(region, address, size, GetVirtualLinearMemoryRegionTree(),
KMemoryRegionType_VirtualDramUserPool); KMemoryRegionType_VirtualDramUserPool);
} }
bool IsLinearMappedPhysicalAddress(const KMemoryRegion*& region, PAddr address) const { bool IsLinearMappedPhysicalAddress(const KMemoryRegion*& region,
KPhysicalAddress address) const {
return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(), return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(),
static_cast<KMemoryRegionType>(KMemoryRegionAttr_LinearMapped)); static_cast<KMemoryRegionType>(KMemoryRegionAttr_LinearMapped));
} }
bool IsLinearMappedPhysicalAddress(const KMemoryRegion*& region, PAddr address, bool IsLinearMappedPhysicalAddress(const KMemoryRegion*& region, KPhysicalAddress address,
size_t size) const { size_t size) const {
return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(), return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(),
static_cast<KMemoryRegionType>(KMemoryRegionAttr_LinearMapped)); static_cast<KMemoryRegionType>(KMemoryRegionAttr_LinearMapped));
@ -234,8 +239,8 @@ public:
return std::make_pair(total_size, kernel_size); return std::make_pair(total_size, kernel_size);
} }
void InitializeLinearMemoryRegionTrees(PAddr aligned_linear_phys_start, void InitializeLinearMemoryRegionTrees(KPhysicalAddress aligned_linear_phys_start,
VAddr linear_virtual_start); KVirtualAddress linear_virtual_start);
static size_t GetResourceRegionSizeForInit(bool use_extra_resource); static size_t GetResourceRegionSizeForInit(bool use_extra_resource);
auto GetKernelRegionExtents() const { auto GetKernelRegionExtents() const {
@ -261,8 +266,8 @@ public:
auto GetLinearRegionVirtualExtents() const { auto GetLinearRegionVirtualExtents() const {
const auto physical = GetLinearRegionPhysicalExtents(); const auto physical = GetLinearRegionPhysicalExtents();
return KMemoryRegion(GetLinearVirtualAddress(physical.GetAddress()), return KMemoryRegion(GetInteger(GetLinearVirtualAddress(physical.GetAddress())),
GetLinearVirtualAddress(physical.GetLastAddress()), 0, GetInteger(GetLinearVirtualAddress(physical.GetLastAddress())), 0,
KMemoryRegionType_None); KMemoryRegionType_None);
} }
@ -334,12 +339,12 @@ private:
static bool IsTypedAddress(const KMemoryRegion*& region, AddressType address, static bool IsTypedAddress(const KMemoryRegion*& region, AddressType address,
const KMemoryRegionTree& tree, KMemoryRegionType type) { const KMemoryRegionTree& tree, KMemoryRegionType type) {
// Check if the cached region already contains the address. // Check if the cached region already contains the address.
if (region != nullptr && region->Contains(address)) { if (region != nullptr && region->Contains(GetInteger(address))) {
return true; return true;
} }
// Find the containing region, and update the cache. // Find the containing region, and update the cache.
if (const KMemoryRegion* found = tree.Find(address); if (const KMemoryRegion* found = tree.Find(GetInteger(address));
found != nullptr && found->IsDerivedFrom(type)) { found != nullptr && found->IsDerivedFrom(type)) {
region = found; region = found;
return true; return true;
@ -352,11 +357,12 @@ private:
static bool IsTypedAddress(const KMemoryRegion*& region, AddressType address, size_t size, static bool IsTypedAddress(const KMemoryRegion*& region, AddressType address, size_t size,
const KMemoryRegionTree& tree, KMemoryRegionType type) { const KMemoryRegionTree& tree, KMemoryRegionType type) {
// Get the end of the checked region. // Get the end of the checked region.
const u64 last_address = address + size - 1; const u64 last_address = GetInteger(address) + size - 1;
// Walk the tree to verify the region is correct. // Walk the tree to verify the region is correct.
const KMemoryRegion* cur = const KMemoryRegion* cur = (region != nullptr && region->Contains(GetInteger(address)))
(region != nullptr && region->Contains(address)) ? region : tree.Find(address); ? region
: tree.Find(GetInteger(address));
while (cur != nullptr && cur->IsDerivedFrom(type)) { while (cur != nullptr && cur->IsDerivedFrom(type)) {
if (last_address <= cur->GetLastAddress()) { if (last_address <= cur->GetLastAddress()) {
region = cur; region = cur;
@ -370,7 +376,7 @@ private:
template <typename AddressType> template <typename AddressType>
static const KMemoryRegion* Find(AddressType address, const KMemoryRegionTree& tree) { static const KMemoryRegion* Find(AddressType address, const KMemoryRegionTree& tree) {
return tree.Find(address); return tree.Find(GetInteger(address));
} }
static KMemoryRegion& Dereference(KMemoryRegion* region) { static KMemoryRegion& Dereference(KMemoryRegion* region) {
@ -383,7 +389,7 @@ private:
return *region; return *region;
} }
VAddr GetStackTopAddress(s32 core_id, KMemoryRegionType type) const { KVirtualAddress GetStackTopAddress(s32 core_id, KMemoryRegionType type) const {
const auto& region = Dereference( const auto& region = Dereference(
GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast<u32>(core_id))); GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast<u32>(core_id)));
ASSERT(region.GetEndAddress() != 0); ASSERT(region.GetEndAddress() != 0);

@ -5,7 +5,6 @@
#include "common/alignment.h" #include "common/alignment.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/common_types.h"
#include "common/scope_exit.h" #include "common/scope_exit.h"
#include "core/core.h" #include "core/core.h"
#include "core/device_memory.h" #include "core/device_memory.h"
@ -44,10 +43,10 @@ KMemoryManager::KMemoryManager(Core::System& system)
KLightLock{system.Kernel()}, KLightLock{system.Kernel()},
} {} } {}
void KMemoryManager::Initialize(VAddr management_region, size_t management_region_size) { void KMemoryManager::Initialize(KVirtualAddress management_region, size_t management_region_size) {
// Clear the management region to zero. // Clear the management region to zero.
const VAddr management_region_end = management_region + management_region_size; const KVirtualAddress management_region_end = management_region + management_region_size;
// std::memset(GetVoidPointer(management_region), 0, management_region_size); // std::memset(GetVoidPointer(management_region), 0, management_region_size);
// Reset our manager count. // Reset our manager count.
@ -56,7 +55,7 @@ void KMemoryManager::Initialize(VAddr management_region, size_t management_regio
// Traverse the virtual memory layout tree, initializing each manager as appropriate. // Traverse the virtual memory layout tree, initializing each manager as appropriate.
while (m_num_managers != MaxManagerCount) { while (m_num_managers != MaxManagerCount) {
// Locate the region that should initialize the current manager. // Locate the region that should initialize the current manager.
PAddr region_address = 0; KPhysicalAddress region_address = 0;
size_t region_size = 0; size_t region_size = 0;
Pool region_pool = Pool::Count; Pool region_pool = Pool::Count;
for (const auto& it : m_system.Kernel().MemoryLayout().GetPhysicalMemoryRegionTree()) { for (const auto& it : m_system.Kernel().MemoryLayout().GetPhysicalMemoryRegionTree()) {
@ -70,8 +69,8 @@ void KMemoryManager::Initialize(VAddr management_region, size_t management_regio
continue; continue;
} }
const PAddr cur_start = it.GetAddress(); const KPhysicalAddress cur_start = it.GetAddress();
const PAddr cur_end = it.GetEndAddress(); const KPhysicalAddress cur_end = it.GetEndAddress();
// Validate the region. // Validate the region.
ASSERT(cur_end != 0); ASSERT(cur_end != 0);
@ -119,17 +118,17 @@ void KMemoryManager::Initialize(VAddr management_region, size_t management_regio
// Free each region to its corresponding heap. // Free each region to its corresponding heap.
size_t reserved_sizes[MaxManagerCount] = {}; size_t reserved_sizes[MaxManagerCount] = {};
const PAddr ini_start = GetInitialProcessBinaryPhysicalAddress(); const KPhysicalAddress ini_start = GetInitialProcessBinaryPhysicalAddress();
const PAddr ini_end = ini_start + InitialProcessBinarySizeMax; const KPhysicalAddress ini_end = ini_start + InitialProcessBinarySizeMax;
const PAddr ini_last = ini_end - 1; const KPhysicalAddress ini_last = ini_end - 1;
for (const auto& it : m_system.Kernel().MemoryLayout().GetPhysicalMemoryRegionTree()) { for (const auto& it : m_system.Kernel().MemoryLayout().GetPhysicalMemoryRegionTree()) {
if (it.IsDerivedFrom(KMemoryRegionType_DramUserPool)) { if (it.IsDerivedFrom(KMemoryRegionType_DramUserPool)) {
// Get the manager for the region. // Get the manager for the region.
auto& manager = m_managers[it.GetAttributes()]; auto& manager = m_managers[it.GetAttributes()];
const PAddr cur_start = it.GetAddress(); const KPhysicalAddress cur_start = it.GetAddress();
const PAddr cur_last = it.GetLastAddress(); const KPhysicalAddress cur_last = it.GetLastAddress();
const PAddr cur_end = it.GetEndAddress(); const KPhysicalAddress cur_end = it.GetEndAddress();
if (cur_start <= ini_start && ini_last <= cur_last) { if (cur_start <= ini_start && ini_last <= cur_last) {
// Free memory before the ini to the heap. // Free memory before the ini to the heap.
@ -175,7 +174,8 @@ void KMemoryManager::FinalizeOptimizedMemory(u64 process_id, Pool pool) {
UNREACHABLE(); UNREACHABLE();
} }
PAddr KMemoryManager::AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option) { KPhysicalAddress KMemoryManager::AllocateAndOpenContinuous(size_t num_pages, size_t align_pages,
u32 option) {
// Early return if we're allocating no pages. // Early return if we're allocating no pages.
if (num_pages == 0) { if (num_pages == 0) {
return 0; return 0;
@ -190,7 +190,7 @@ PAddr KMemoryManager::AllocateAndOpenContinuous(size_t num_pages, size_t align_p
// Loop, trying to iterate from each block. // Loop, trying to iterate from each block.
Impl* chosen_manager = nullptr; Impl* chosen_manager = nullptr;
PAddr allocated_block = 0; KPhysicalAddress allocated_block = 0;
for (chosen_manager = this->GetFirstManager(pool, dir); chosen_manager != nullptr; for (chosen_manager = this->GetFirstManager(pool, dir); chosen_manager != nullptr;
chosen_manager = this->GetNextManager(chosen_manager, dir)) { chosen_manager = this->GetNextManager(chosen_manager, dir)) {
allocated_block = chosen_manager->AllocateAligned(heap_index, num_pages, align_pages); allocated_block = chosen_manager->AllocateAligned(heap_index, num_pages, align_pages);
@ -239,7 +239,7 @@ Result KMemoryManager::AllocatePageGroupImpl(KPageGroup* out, size_t num_pages,
cur_manager = this->GetNextManager(cur_manager, dir)) { cur_manager = this->GetNextManager(cur_manager, dir)) {
while (num_pages >= pages_per_alloc) { while (num_pages >= pages_per_alloc) {
// Allocate a block. // Allocate a block.
PAddr allocated_block = cur_manager->AllocateBlock(index, random); KPhysicalAddress allocated_block = cur_manager->AllocateBlock(index, random);
if (allocated_block == 0) { if (allocated_block == 0) {
break; break;
} }
@ -286,7 +286,7 @@ Result KMemoryManager::AllocateAndOpen(KPageGroup* out, size_t num_pages, u32 op
// Open the first reference to the pages. // Open the first reference to the pages.
for (const auto& block : *out) { for (const auto& block : *out) {
PAddr cur_address = block.GetAddress(); KPhysicalAddress cur_address = block.GetAddress();
size_t remaining_pages = block.GetNumPages(); size_t remaining_pages = block.GetNumPages();
while (remaining_pages > 0) { while (remaining_pages > 0) {
// Get the manager for the current address. // Get the manager for the current address.
@ -337,7 +337,7 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32
// Iterate over the allocated blocks. // Iterate over the allocated blocks.
for (const auto& block : *out) { for (const auto& block : *out) {
// Get the block extents. // Get the block extents.
const PAddr block_address = block.GetAddress(); const KPhysicalAddress block_address = block.GetAddress();
const size_t block_pages = block.GetNumPages(); const size_t block_pages = block.GetNumPages();
// If it has no pages, we don't need to do anything. // If it has no pages, we don't need to do anything.
@ -348,7 +348,7 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32
// Fill all the pages that we need to fill. // Fill all the pages that we need to fill.
bool any_new = false; bool any_new = false;
{ {
PAddr cur_address = block_address; KPhysicalAddress cur_address = block_address;
size_t remaining_pages = block_pages; size_t remaining_pages = block_pages;
while (remaining_pages > 0) { while (remaining_pages > 0) {
// Get the manager for the current address. // Get the manager for the current address.
@ -369,7 +369,7 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32
// If there are new pages, update tracking for the allocation. // If there are new pages, update tracking for the allocation.
if (any_new) { if (any_new) {
// Update tracking for the allocation. // Update tracking for the allocation.
PAddr cur_address = block_address; KPhysicalAddress cur_address = block_address;
size_t remaining_pages = block_pages; size_t remaining_pages = block_pages;
while (remaining_pages > 0) { while (remaining_pages > 0) {
// Get the manager for the current address. // Get the manager for the current address.
@ -400,8 +400,9 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32
R_SUCCEED(); R_SUCCEED();
} }
size_t KMemoryManager::Impl::Initialize(PAddr address, size_t size, VAddr management, size_t KMemoryManager::Impl::Initialize(KPhysicalAddress address, size_t size,
VAddr management_end, Pool p) { KVirtualAddress management, KVirtualAddress management_end,
Pool p) {
// Calculate management sizes. // Calculate management sizes.
const size_t ref_count_size = (size / PageSize) * sizeof(u16); const size_t ref_count_size = (size / PageSize) * sizeof(u16);
const size_t optimize_map_size = CalculateOptimizedProcessOverheadSize(size); const size_t optimize_map_size = CalculateOptimizedProcessOverheadSize(size);
@ -417,7 +418,7 @@ size_t KMemoryManager::Impl::Initialize(PAddr address, size_t size, VAddr manage
m_management_region = management; m_management_region = management;
m_page_reference_counts.resize( m_page_reference_counts.resize(
Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetIntendedMemorySize() / PageSize); Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetIntendedMemorySize() / PageSize);
ASSERT(Common::IsAligned(m_management_region, PageSize)); ASSERT(Common::IsAligned(GetInteger(m_management_region), PageSize));
// Initialize the manager's KPageHeap. // Initialize the manager's KPageHeap.
m_heap.Initialize(address, size, management + manager_size, page_heap_size); m_heap.Initialize(address, size, management + manager_size, page_heap_size);
@ -425,15 +426,15 @@ size_t KMemoryManager::Impl::Initialize(PAddr address, size_t size, VAddr manage
return total_management_size; return total_management_size;
} }
void KMemoryManager::Impl::TrackUnoptimizedAllocation(PAddr block, size_t num_pages) { void KMemoryManager::Impl::TrackUnoptimizedAllocation(KPhysicalAddress block, size_t num_pages) {
UNREACHABLE(); UNREACHABLE();
} }
void KMemoryManager::Impl::TrackOptimizedAllocation(PAddr block, size_t num_pages) { void KMemoryManager::Impl::TrackOptimizedAllocation(KPhysicalAddress block, size_t num_pages) {
UNREACHABLE(); UNREACHABLE();
} }
bool KMemoryManager::Impl::ProcessOptimizedAllocation(PAddr block, size_t num_pages, bool KMemoryManager::Impl::ProcessOptimizedAllocation(KPhysicalAddress block, size_t num_pages,
u8 fill_pattern) { u8 fill_pattern) {
UNREACHABLE(); UNREACHABLE();
} }

@ -7,10 +7,10 @@
#include <tuple> #include <tuple>
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h"
#include "core/hle/kernel/k_light_lock.h" #include "core/hle/kernel/k_light_lock.h"
#include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_page_heap.h" #include "core/hle/kernel/k_page_heap.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/result.h" #include "core/hle/result.h"
namespace Core { namespace Core {
@ -50,21 +50,21 @@ public:
explicit KMemoryManager(Core::System& system); explicit KMemoryManager(Core::System& system);
void Initialize(VAddr management_region, size_t management_region_size); void Initialize(KVirtualAddress management_region, size_t management_region_size);
Result InitializeOptimizedMemory(u64 process_id, Pool pool); Result InitializeOptimizedMemory(u64 process_id, Pool pool);
void FinalizeOptimizedMemory(u64 process_id, Pool pool); void FinalizeOptimizedMemory(u64 process_id, Pool pool);
PAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option); KPhysicalAddress AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option);
Result AllocateAndOpen(KPageGroup* out, size_t num_pages, u32 option); Result AllocateAndOpen(KPageGroup* out, size_t num_pages, u32 option);
Result AllocateForProcess(KPageGroup* out, size_t num_pages, u32 option, u64 process_id, Result AllocateForProcess(KPageGroup* out, size_t num_pages, u32 option, u64 process_id,
u8 fill_pattern); u8 fill_pattern);
Pool GetPool(PAddr address) const { Pool GetPool(KPhysicalAddress address) const {
return this->GetManager(address).GetPool(); return this->GetManager(address).GetPool();
} }
void Open(PAddr address, size_t num_pages) { void Open(KPhysicalAddress address, size_t num_pages) {
// Repeatedly open references until we've done so for all pages. // Repeatedly open references until we've done so for all pages.
while (num_pages) { while (num_pages) {
auto& manager = this->GetManager(address); auto& manager = this->GetManager(address);
@ -80,7 +80,7 @@ public:
} }
} }
void OpenFirst(PAddr address, size_t num_pages) { void OpenFirst(KPhysicalAddress address, size_t num_pages) {
// Repeatedly open references until we've done so for all pages. // Repeatedly open references until we've done so for all pages.
while (num_pages) { while (num_pages) {
auto& manager = this->GetManager(address); auto& manager = this->GetManager(address);
@ -96,7 +96,7 @@ public:
} }
} }
void Close(PAddr address, size_t num_pages) { void Close(KPhysicalAddress address, size_t num_pages) {
// Repeatedly close references until we've done so for all pages. // Repeatedly close references until we've done so for all pages.
while (num_pages) { while (num_pages) {
auto& manager = this->GetManager(address); auto& manager = this->GetManager(address);
@ -199,16 +199,16 @@ private:
public: public:
Impl() = default; Impl() = default;
size_t Initialize(PAddr address, size_t size, VAddr management, VAddr management_end, size_t Initialize(KPhysicalAddress address, size_t size, KVirtualAddress management,
Pool p); KVirtualAddress management_end, Pool p);
PAddr AllocateBlock(s32 index, bool random) { KPhysicalAddress AllocateBlock(s32 index, bool random) {
return m_heap.AllocateBlock(index, random); return m_heap.AllocateBlock(index, random);
} }
PAddr AllocateAligned(s32 index, size_t num_pages, size_t align_pages) { KPhysicalAddress AllocateAligned(s32 index, size_t num_pages, size_t align_pages) {
return m_heap.AllocateAligned(index, num_pages, align_pages); return m_heap.AllocateAligned(index, num_pages, align_pages);
} }
void Free(PAddr addr, size_t num_pages) { void Free(KPhysicalAddress addr, size_t num_pages) {
m_heap.Free(addr, num_pages); m_heap.Free(addr, num_pages);
} }
@ -220,10 +220,10 @@ private:
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void TrackUnoptimizedAllocation(PAddr block, size_t num_pages); void TrackUnoptimizedAllocation(KPhysicalAddress block, size_t num_pages);
void TrackOptimizedAllocation(PAddr block, size_t num_pages); void TrackOptimizedAllocation(KPhysicalAddress block, size_t num_pages);
bool ProcessOptimizedAllocation(PAddr block, size_t num_pages, u8 fill_pattern); bool ProcessOptimizedAllocation(KPhysicalAddress block, size_t num_pages, u8 fill_pattern);
constexpr Pool GetPool() const { constexpr Pool GetPool() const {
return m_pool; return m_pool;
@ -231,7 +231,7 @@ private:
constexpr size_t GetSize() const { constexpr size_t GetSize() const {
return m_heap.GetSize(); return m_heap.GetSize();
} }
constexpr PAddr GetEndAddress() const { constexpr KPhysicalAddress GetEndAddress() const {
return m_heap.GetEndAddress(); return m_heap.GetEndAddress();
} }
@ -243,10 +243,10 @@ private:
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
constexpr size_t GetPageOffset(PAddr address) const { constexpr size_t GetPageOffset(KPhysicalAddress address) const {
return m_heap.GetPageOffset(address); return m_heap.GetPageOffset(address);
} }
constexpr size_t GetPageOffsetToEnd(PAddr address) const { constexpr size_t GetPageOffsetToEnd(KPhysicalAddress address) const {
return m_heap.GetPageOffsetToEnd(address); return m_heap.GetPageOffsetToEnd(address);
} }
@ -263,7 +263,7 @@ private:
return m_prev; return m_prev;
} }
void OpenFirst(PAddr address, size_t num_pages) { void OpenFirst(KPhysicalAddress address, size_t num_pages) {
size_t index = this->GetPageOffset(address); size_t index = this->GetPageOffset(address);
const size_t end = index + num_pages; const size_t end = index + num_pages;
while (index < end) { while (index < end) {
@ -274,7 +274,7 @@ private:
} }
} }
void Open(PAddr address, size_t num_pages) { void Open(KPhysicalAddress address, size_t num_pages) {
size_t index = this->GetPageOffset(address); size_t index = this->GetPageOffset(address);
const size_t end = index + num_pages; const size_t end = index + num_pages;
while (index < end) { while (index < end) {
@ -285,7 +285,7 @@ private:
} }
} }
void Close(PAddr address, size_t num_pages) { void Close(KPhysicalAddress address, size_t num_pages) {
size_t index = this->GetPageOffset(address); size_t index = this->GetPageOffset(address);
const size_t end = index + num_pages; const size_t end = index + num_pages;
@ -323,18 +323,18 @@ private:
KPageHeap m_heap; KPageHeap m_heap;
std::vector<RefCount> m_page_reference_counts; std::vector<RefCount> m_page_reference_counts;
VAddr m_management_region{}; KVirtualAddress m_management_region{};
Pool m_pool{}; Pool m_pool{};
Impl* m_next{}; Impl* m_next{};
Impl* m_prev{}; Impl* m_prev{};
}; };
private: private:
Impl& GetManager(PAddr address) { Impl& GetManager(KPhysicalAddress address) {
return m_managers[m_memory_layout.GetPhysicalLinearRegion(address).GetAttributes()]; return m_managers[m_memory_layout.GetPhysicalLinearRegion(address).GetAttributes()];
} }
const Impl& GetManager(PAddr address) const { const Impl& GetManager(KPhysicalAddress address) const {
return m_managers[m_memory_layout.GetPhysicalLinearRegion(address).GetAttributes()]; return m_managers[m_memory_layout.GetPhysicalLinearRegion(address).GetAttributes()];
} }

@ -5,9 +5,9 @@
#include "common/assert.h" #include "common/assert.h"
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/intrusive_red_black_tree.h" #include "common/intrusive_red_black_tree.h"
#include "core/hle/kernel/k_memory_region_type.h" #include "core/hle/kernel/k_memory_region_type.h"
#include "core/hle/kernel/k_typed_address.h"
namespace Kernel { namespace Kernel {
@ -243,9 +243,9 @@ public:
void InsertDirectly(u64 address, u64 last_address, u32 attr = 0, u32 type_id = 0); void InsertDirectly(u64 address, u64 last_address, u32 attr = 0, u32 type_id = 0);
bool Insert(u64 address, size_t size, u32 type_id, u32 new_attr = 0, u32 old_attr = 0); bool Insert(u64 address, size_t size, u32 type_id, u32 new_attr = 0, u32 old_attr = 0);
VAddr GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id); KVirtualAddress GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id);
VAddr GetRandomAlignedRegionWithGuard(size_t size, size_t alignment, u32 type_id, KVirtualAddress GetRandomAlignedRegionWithGuard(size_t size, size_t alignment, u32 type_id,
size_t guard_size) { size_t guard_size) {
return this->GetRandomAlignedRegion(size + 2 * guard_size, alignment, type_id) + guard_size; return this->GetRandomAlignedRegion(size + 2 * guard_size, alignment, type_id) + guard_size;
} }

@ -10,8 +10,8 @@
namespace Kernel { namespace Kernel {
KPageBuffer* KPageBuffer::FromPhysicalAddress(Core::System& system, PAddr phys_addr) { KPageBuffer* KPageBuffer::FromPhysicalAddress(Core::System& system, KPhysicalAddress phys_addr) {
ASSERT(Common::IsAligned(phys_addr, PageSize)); ASSERT(Common::IsAligned(GetInteger(phys_addr), PageSize));
return system.DeviceMemory().GetPointer<KPageBuffer>(phys_addr); return system.DeviceMemory().GetPointer<KPageBuffer>(phys_addr);
} }

@ -26,7 +26,7 @@ public:
explicit KPageBuffer(KernelCore&) {} explicit KPageBuffer(KernelCore&) {}
KPageBuffer() = default; KPageBuffer() = default;
static KPageBuffer* FromPhysicalAddress(Core::System& system, PAddr phys_addr); static KPageBuffer* FromPhysicalAddress(Core::System& system, KPhysicalAddress phys_addr);
private: private:
alignas(PageSize) std::array<u8, PageSize> m_buffer{}; alignas(PageSize) std::array<u8, PageSize> m_buffer{};

@ -22,7 +22,7 @@ public:
constexpr explicit KBlockInfo() : m_next(nullptr) {} constexpr explicit KBlockInfo() : m_next(nullptr) {}
constexpr void Initialize(KPhysicalAddress addr, size_t np) { constexpr void Initialize(KPhysicalAddress addr, size_t np) {
ASSERT(Common::IsAligned(addr, PageSize)); ASSERT(Common::IsAligned(GetInteger(addr), PageSize));
ASSERT(static_cast<u32>(np) == np); ASSERT(static_cast<u32>(np) == np);
m_page_index = static_cast<u32>(addr / PageSize); m_page_index = static_cast<u32>(addr / PageSize);

@ -6,14 +6,14 @@
namespace Kernel { namespace Kernel {
void KPageHeap::Initialize(PAddr address, size_t size, VAddr management_address, void KPageHeap::Initialize(KPhysicalAddress address, size_t size,
size_t management_size, const size_t* block_shifts, KVirtualAddress management_address, size_t management_size,
size_t num_block_shifts) { const size_t* block_shifts, size_t num_block_shifts) {
// Check our assumptions. // Check our assumptions.
ASSERT(Common::IsAligned(address, PageSize)); ASSERT(Common::IsAligned(GetInteger(address), PageSize));
ASSERT(Common::IsAligned(size, PageSize)); ASSERT(Common::IsAligned(size, PageSize));
ASSERT(0 < num_block_shifts && num_block_shifts <= NumMemoryBlockPageShifts); ASSERT(0 < num_block_shifts && num_block_shifts <= NumMemoryBlockPageShifts);
const VAddr management_end = management_address + management_size; const KVirtualAddress management_end = management_address + management_size;
// Set our members. // Set our members.
m_heap_address = address; m_heap_address = address;
@ -31,7 +31,7 @@ void KPageHeap::Initialize(PAddr address, size_t size, VAddr management_address,
} }
// Ensure we didn't overextend our bounds. // Ensure we didn't overextend our bounds.
ASSERT(VAddr(cur_bitmap_storage) <= management_end); ASSERT(KVirtualAddress(cur_bitmap_storage) <= management_end);
} }
size_t KPageHeap::GetNumFreePages() const { size_t KPageHeap::GetNumFreePages() const {
@ -44,11 +44,11 @@ size_t KPageHeap::GetNumFreePages() const {
return num_free; return num_free;
} }
PAddr KPageHeap::AllocateByLinearSearch(s32 index) { KPhysicalAddress KPageHeap::AllocateByLinearSearch(s32 index) {
const size_t needed_size = m_blocks[index].GetSize(); const size_t needed_size = m_blocks[index].GetSize();
for (s32 i = index; i < static_cast<s32>(m_num_blocks); i++) { for (s32 i = index; i < static_cast<s32>(m_num_blocks); i++) {
if (const PAddr addr = m_blocks[i].PopBlock(false); addr != 0) { if (const KPhysicalAddress addr = m_blocks[i].PopBlock(false); addr != 0) {
if (const size_t allocated_size = m_blocks[i].GetSize(); allocated_size > needed_size) { if (const size_t allocated_size = m_blocks[i].GetSize(); allocated_size > needed_size) {
this->Free(addr + needed_size, (allocated_size - needed_size) / PageSize); this->Free(addr + needed_size, (allocated_size - needed_size) / PageSize);
} }
@ -59,7 +59,7 @@ PAddr KPageHeap::AllocateByLinearSearch(s32 index) {
return 0; return 0;
} }
PAddr KPageHeap::AllocateByRandom(s32 index, size_t num_pages, size_t align_pages) { KPhysicalAddress KPageHeap::AllocateByRandom(s32 index, size_t num_pages, size_t align_pages) {
// Get the size and required alignment. // Get the size and required alignment.
const size_t needed_size = num_pages * PageSize; const size_t needed_size = num_pages * PageSize;
const size_t align_size = align_pages * PageSize; const size_t align_size = align_pages * PageSize;
@ -110,7 +110,7 @@ PAddr KPageHeap::AllocateByRandom(s32 index, size_t num_pages, size_t align_page
} }
// Pop a block from the index we selected. // Pop a block from the index we selected.
if (PAddr addr = m_blocks[index].PopBlock(true); addr != 0) { if (KPhysicalAddress addr = m_blocks[index].PopBlock(true); addr != 0) {
// Determine how much size we have left over. // Determine how much size we have left over.
if (const size_t leftover_size = m_blocks[index].GetSize() - needed_size; if (const size_t leftover_size = m_blocks[index].GetSize() - needed_size;
leftover_size > 0) { leftover_size > 0) {
@ -141,13 +141,13 @@ PAddr KPageHeap::AllocateByRandom(s32 index, size_t num_pages, size_t align_page
return 0; return 0;
} }
void KPageHeap::FreeBlock(PAddr block, s32 index) { void KPageHeap::FreeBlock(KPhysicalAddress block, s32 index) {
do { do {
block = m_blocks[index++].PushBlock(block); block = m_blocks[index++].PushBlock(block);
} while (block != 0); } while (block != 0);
} }
void KPageHeap::Free(PAddr addr, size_t num_pages) { void KPageHeap::Free(KPhysicalAddress addr, size_t num_pages) {
// Freeing no pages is a no-op. // Freeing no pages is a no-op.
if (num_pages == 0) { if (num_pages == 0) {
return; return;
@ -155,16 +155,16 @@ void KPageHeap::Free(PAddr addr, size_t num_pages) {
// Find the largest block size that we can free, and free as many as possible. // Find the largest block size that we can free, and free as many as possible.
s32 big_index = static_cast<s32>(m_num_blocks) - 1; s32 big_index = static_cast<s32>(m_num_blocks) - 1;
const PAddr start = addr; const KPhysicalAddress start = addr;
const PAddr end = addr + num_pages * PageSize; const KPhysicalAddress end = addr + num_pages * PageSize;
PAddr before_start = start; KPhysicalAddress before_start = start;
PAddr before_end = start; KPhysicalAddress before_end = start;
PAddr after_start = end; KPhysicalAddress after_start = end;
PAddr after_end = end; KPhysicalAddress after_end = end;
while (big_index >= 0) { while (big_index >= 0) {
const size_t block_size = m_blocks[big_index].GetSize(); const size_t block_size = m_blocks[big_index].GetSize();
const PAddr big_start = Common::AlignUp(start, block_size); const KPhysicalAddress big_start = Common::AlignUp(GetInteger(start), block_size);
const PAddr big_end = Common::AlignDown(end, block_size); const KPhysicalAddress big_end = Common::AlignDown(GetInteger(end), block_size);
if (big_start < big_end) { if (big_start < big_end) {
// Free as many big blocks as we can. // Free as many big blocks as we can.
for (auto block = big_start; block < big_end; block += block_size) { for (auto block = big_start; block < big_end; block += block_size) {

@ -8,8 +8,8 @@
#include "common/alignment.h" #include "common/alignment.h"
#include "common/common_funcs.h" #include "common/common_funcs.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/k_typed_address.h"
#include "core/hle/kernel/memory_types.h" #include "core/hle/kernel/memory_types.h"
namespace Kernel { namespace Kernel {
@ -18,24 +18,24 @@ class KPageHeap {
public: public:
KPageHeap() = default; KPageHeap() = default;
constexpr PAddr GetAddress() const { constexpr KPhysicalAddress GetAddress() const {
return m_heap_address; return m_heap_address;
} }
constexpr size_t GetSize() const { constexpr size_t GetSize() const {
return m_heap_size; return m_heap_size;
} }
constexpr PAddr GetEndAddress() const { constexpr KPhysicalAddress GetEndAddress() const {
return this->GetAddress() + this->GetSize(); return this->GetAddress() + this->GetSize();
} }
constexpr size_t GetPageOffset(PAddr block) const { constexpr size_t GetPageOffset(KPhysicalAddress block) const {
return (block - this->GetAddress()) / PageSize; return (block - this->GetAddress()) / PageSize;
} }
constexpr size_t GetPageOffsetToEnd(PAddr block) const { constexpr size_t GetPageOffsetToEnd(KPhysicalAddress block) const {
return (this->GetEndAddress() - block) / PageSize; return (this->GetEndAddress() - block) / PageSize;
} }
void Initialize(PAddr heap_address, size_t heap_size, VAddr management_address, void Initialize(KPhysicalAddress heap_address, size_t heap_size,
size_t management_size) { KVirtualAddress management_address, size_t management_size) {
return this->Initialize(heap_address, heap_size, management_address, management_size, return this->Initialize(heap_address, heap_size, management_address, management_size,
MemoryBlockPageShifts.data(), NumMemoryBlockPageShifts); MemoryBlockPageShifts.data(), NumMemoryBlockPageShifts);
} }
@ -53,7 +53,7 @@ public:
m_initial_used_size = m_heap_size - free_size - reserved_size; m_initial_used_size = m_heap_size - free_size - reserved_size;
} }
PAddr AllocateBlock(s32 index, bool random) { KPhysicalAddress AllocateBlock(s32 index, bool random) {
if (random) { if (random) {
const size_t block_pages = m_blocks[index].GetNumPages(); const size_t block_pages = m_blocks[index].GetNumPages();
return this->AllocateByRandom(index, block_pages, block_pages); return this->AllocateByRandom(index, block_pages, block_pages);
@ -62,12 +62,12 @@ public:
} }
} }
PAddr AllocateAligned(s32 index, size_t num_pages, size_t align_pages) { KPhysicalAddress AllocateAligned(s32 index, size_t num_pages, size_t align_pages) {
// TODO: linear search support? // TODO: linear search support?
return this->AllocateByRandom(index, num_pages, align_pages); return this->AllocateByRandom(index, num_pages, align_pages);
} }
void Free(PAddr addr, size_t num_pages); void Free(KPhysicalAddress addr, size_t num_pages);
static size_t CalculateManagementOverheadSize(size_t region_size) { static size_t CalculateManagementOverheadSize(size_t region_size) {
return CalculateManagementOverheadSize(region_size, MemoryBlockPageShifts.data(), return CalculateManagementOverheadSize(region_size, MemoryBlockPageShifts.data(),
@ -125,24 +125,25 @@ private:
return this->GetNumFreeBlocks() * this->GetNumPages(); return this->GetNumFreeBlocks() * this->GetNumPages();
} }
u64* Initialize(PAddr addr, size_t size, size_t bs, size_t nbs, u64* bit_storage) { u64* Initialize(KPhysicalAddress addr, size_t size, size_t bs, size_t nbs,
u64* bit_storage) {
// Set shifts. // Set shifts.
m_block_shift = bs; m_block_shift = bs;
m_next_block_shift = nbs; m_next_block_shift = nbs;
// Align up the address. // Align up the address.
PAddr end = addr + size; KPhysicalAddress end = addr + size;
const size_t align = (m_next_block_shift != 0) ? (u64(1) << m_next_block_shift) const size_t align = (m_next_block_shift != 0) ? (u64(1) << m_next_block_shift)
: (u64(1) << m_block_shift); : (u64(1) << m_block_shift);
addr = Common::AlignDown(addr, align); addr = Common::AlignDown(GetInteger(addr), align);
end = Common::AlignUp(end, align); end = Common::AlignUp(GetInteger(end), align);
m_heap_address = addr; m_heap_address = addr;
m_end_offset = (end - addr) / (u64(1) << m_block_shift); m_end_offset = (end - addr) / (u64(1) << m_block_shift);
return m_bitmap.Initialize(bit_storage, m_end_offset); return m_bitmap.Initialize(bit_storage, m_end_offset);
} }
PAddr PushBlock(PAddr address) { KPhysicalAddress PushBlock(KPhysicalAddress address) {
// Set the bit for the free block. // Set the bit for the free block.
size_t offset = (address - m_heap_address) >> this->GetShift(); size_t offset = (address - m_heap_address) >> this->GetShift();
m_bitmap.SetBit(offset); m_bitmap.SetBit(offset);
@ -161,7 +162,7 @@ private:
return {}; return {};
} }
PAddr PopBlock(bool random) { KPhysicalAddress PopBlock(bool random) {
// Find a free block. // Find a free block.
s64 soffset = m_bitmap.FindFreeBlock(random); s64 soffset = m_bitmap.FindFreeBlock(random);
if (soffset < 0) { if (soffset < 0) {
@ -187,18 +188,19 @@ private:
private: private:
KPageBitmap m_bitmap; KPageBitmap m_bitmap;
PAddr m_heap_address{}; KPhysicalAddress m_heap_address{};
uintptr_t m_end_offset{}; uintptr_t m_end_offset{};
size_t m_block_shift{}; size_t m_block_shift{};
size_t m_next_block_shift{}; size_t m_next_block_shift{};
}; };
private: private:
void Initialize(PAddr heap_address, size_t heap_size, VAddr management_address, void Initialize(KPhysicalAddress heap_address, size_t heap_size,
size_t management_size, const size_t* block_shifts, size_t num_block_shifts); KVirtualAddress management_address, size_t management_size,
const size_t* block_shifts, size_t num_block_shifts);
size_t GetNumFreePages() const; size_t GetNumFreePages() const;
void FreeBlock(PAddr block, s32 index); void FreeBlock(KPhysicalAddress block, s32 index);
static constexpr size_t NumMemoryBlockPageShifts{7}; static constexpr size_t NumMemoryBlockPageShifts{7};
static constexpr std::array<size_t, NumMemoryBlockPageShifts> MemoryBlockPageShifts{ static constexpr std::array<size_t, NumMemoryBlockPageShifts> MemoryBlockPageShifts{
@ -206,14 +208,14 @@ private:
}; };
private: private:
PAddr AllocateByLinearSearch(s32 index); KPhysicalAddress AllocateByLinearSearch(s32 index);
PAddr AllocateByRandom(s32 index, size_t num_pages, size_t align_pages); KPhysicalAddress AllocateByRandom(s32 index, size_t num_pages, size_t align_pages);
static size_t CalculateManagementOverheadSize(size_t region_size, const size_t* block_shifts, static size_t CalculateManagementOverheadSize(size_t region_size, const size_t* block_shifts,
size_t num_block_shifts); size_t num_block_shifts);
private: private:
PAddr m_heap_address{}; KPhysicalAddress m_heap_address{};
size_t m_heap_size{}; size_t m_heap_size{};
size_t m_initial_used_size{}; size_t m_initial_used_size{};
size_t m_num_blocks{}; size_t m_num_blocks{};

@ -106,7 +106,7 @@ KPageTable::~KPageTable() = default;
Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr,
bool enable_das_merge, bool from_back, bool enable_das_merge, bool from_back,
KMemoryManager::Pool pool, VAddr code_addr, KMemoryManager::Pool pool, KProcessAddress code_addr,
size_t code_size, KSystemResource* system_resource, size_t code_size, KSystemResource* system_resource,
KResourceLimit* resource_limit) { KResourceLimit* resource_limit) {
@ -119,8 +119,8 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
// Set our width and heap/alias sizes // Set our width and heap/alias sizes
m_address_space_width = GetAddressSpaceWidthFromType(as_type); m_address_space_width = GetAddressSpaceWidthFromType(as_type);
const VAddr start = 0; const KProcessAddress start = 0;
const VAddr end{1ULL << m_address_space_width}; const KProcessAddress end{1ULL << m_address_space_width};
size_t alias_region_size{GetSpaceSize(KAddressSpaceInfo::Type::Alias)}; size_t alias_region_size{GetSpaceSize(KAddressSpaceInfo::Type::Alias)};
size_t heap_region_size{GetSpaceSize(KAddressSpaceInfo::Type::Heap)}; size_t heap_region_size{GetSpaceSize(KAddressSpaceInfo::Type::Heap)};
@ -135,8 +135,8 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
// Set code regions and determine remaining // Set code regions and determine remaining
constexpr size_t RegionAlignment{2_MiB}; constexpr size_t RegionAlignment{2_MiB};
VAddr process_code_start{}; KProcessAddress process_code_start{};
VAddr process_code_end{}; KProcessAddress process_code_end{};
size_t stack_region_size{}; size_t stack_region_size{};
size_t kernel_map_region_size{}; size_t kernel_map_region_size{};
@ -149,8 +149,8 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type::Map39Bit); m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type::Map39Bit);
m_alias_code_region_start = m_code_region_start; m_alias_code_region_start = m_code_region_start;
m_alias_code_region_end = m_code_region_end; m_alias_code_region_end = m_code_region_end;
process_code_start = Common::AlignDown(code_addr, RegionAlignment); process_code_start = Common::AlignDown(GetInteger(code_addr), RegionAlignment);
process_code_end = Common::AlignUp(code_addr + code_size, RegionAlignment); process_code_end = Common::AlignUp(GetInteger(code_addr) + code_size, RegionAlignment);
} else { } else {
stack_region_size = 0; stack_region_size = 0;
kernel_map_region_size = 0; kernel_map_region_size = 0;
@ -178,7 +178,7 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
m_resource_limit = resource_limit; m_resource_limit = resource_limit;
// Determine the region we can place our undetermineds in // Determine the region we can place our undetermineds in
VAddr alloc_start{}; KProcessAddress alloc_start{};
size_t alloc_size{}; size_t alloc_size{};
if ((process_code_start - m_code_region_start) >= (end - process_code_end)) { if ((process_code_start - m_code_region_start) >= (end - process_code_end)) {
alloc_start = m_code_region_start; alloc_start = m_code_region_start;
@ -292,7 +292,7 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
: KMemoryManager::Direction::FromFront); : KMemoryManager::Direction::FromFront);
// Ensure that we regions inside our address space // Ensure that we regions inside our address space
auto IsInAddressSpace = [&](VAddr addr) { auto IsInAddressSpace = [&](KProcessAddress addr) {
return m_address_space_start <= addr && addr <= m_address_space_end; return m_address_space_start <= addr && addr <= m_address_space_end;
}; };
ASSERT(IsInAddressSpace(m_alias_region_start)); ASSERT(IsInAddressSpace(m_alias_region_start));
@ -305,14 +305,14 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
ASSERT(IsInAddressSpace(m_kernel_map_region_end)); ASSERT(IsInAddressSpace(m_kernel_map_region_end));
// Ensure that we selected regions that don't overlap // Ensure that we selected regions that don't overlap
const VAddr alias_start{m_alias_region_start}; const KProcessAddress alias_start{m_alias_region_start};
const VAddr alias_last{m_alias_region_end - 1}; const KProcessAddress alias_last{m_alias_region_end - 1};
const VAddr heap_start{m_heap_region_start}; const KProcessAddress heap_start{m_heap_region_start};
const VAddr heap_last{m_heap_region_end - 1}; const KProcessAddress heap_last{m_heap_region_end - 1};
const VAddr stack_start{m_stack_region_start}; const KProcessAddress stack_start{m_stack_region_start};
const VAddr stack_last{m_stack_region_end - 1}; const KProcessAddress stack_last{m_stack_region_end - 1};
const VAddr kmap_start{m_kernel_map_region_start}; const KProcessAddress kmap_start{m_kernel_map_region_start};
const VAddr kmap_last{m_kernel_map_region_end - 1}; const KProcessAddress kmap_last{m_kernel_map_region_end - 1};
ASSERT(alias_last < heap_start || heap_last < alias_start); ASSERT(alias_last < heap_start || heap_last < alias_start);
ASSERT(alias_last < stack_start || stack_last < alias_start); ASSERT(alias_last < stack_start || stack_last < alias_start);
ASSERT(alias_last < kmap_start || kmap_last < alias_start); ASSERT(alias_last < kmap_start || kmap_last < alias_start);
@ -334,7 +334,8 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
void KPageTable::Finalize() { void KPageTable::Finalize() {
// Finalize memory blocks. // Finalize memory blocks.
m_memory_block_manager.Finalize(m_memory_block_slab_manager, [&](VAddr addr, u64 size) { m_memory_block_manager.Finalize(
m_memory_block_slab_manager, [&](KProcessAddress addr, u64 size) {
m_system.Memory().UnmapRegion(*m_page_table_impl, addr, size); m_system.Memory().UnmapRegion(*m_page_table_impl, addr, size);
}); });
@ -352,7 +353,7 @@ void KPageTable::Finalize() {
m_page_table_impl.reset(); m_page_table_impl.reset();
} }
Result KPageTable::MapProcessCode(VAddr addr, size_t num_pages, KMemoryState state, Result KPageTable::MapProcessCode(KProcessAddress addr, size_t num_pages, KMemoryState state,
KMemoryPermission perm) { KMemoryPermission perm) {
const u64 size{num_pages * PageSize}; const u64 size{num_pages * PageSize};
@ -388,7 +389,8 @@ Result KPageTable::MapProcessCode(VAddr addr, size_t num_pages, KMemoryState sta
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::MapCodeMemory(VAddr dst_address, VAddr src_address, size_t size) { Result KPageTable::MapCodeMemory(KProcessAddress dst_address, KProcessAddress src_address,
size_t size) {
// Validate the mapping request. // Validate the mapping request.
R_UNLESS(this->CanContain(dst_address, size, KMemoryState::AliasCode), R_UNLESS(this->CanContain(dst_address, size, KMemoryState::AliasCode),
ResultInvalidMemoryRegion); ResultInvalidMemoryRegion);
@ -473,7 +475,8 @@ Result KPageTable::MapCodeMemory(VAddr dst_address, VAddr src_address, size_t si
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::UnmapCodeMemory(VAddr dst_address, VAddr src_address, size_t size, Result KPageTable::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddress src_address,
size_t size,
ICacheInvalidationStrategy icache_invalidation_strategy) { ICacheInvalidationStrategy icache_invalidation_strategy) {
// Validate the mapping request. // Validate the mapping request.
R_UNLESS(this->CanContain(dst_address, size, KMemoryState::AliasCode), R_UNLESS(this->CanContain(dst_address, size, KMemoryState::AliasCode),
@ -525,7 +528,7 @@ Result KPageTable::UnmapCodeMemory(VAddr dst_address, VAddr src_address, size_t
SCOPE_EXIT({ SCOPE_EXIT({
if (reprotected_pages && any_code_pages) { if (reprotected_pages && any_code_pages) {
if (icache_invalidation_strategy == ICacheInvalidationStrategy::InvalidateRange) { if (icache_invalidation_strategy == ICacheInvalidationStrategy::InvalidateRange) {
m_system.InvalidateCpuInstructionCacheRange(dst_address, size); m_system.InvalidateCpuInstructionCacheRange(GetInteger(dst_address), size);
} else { } else {
m_system.InvalidateCpuInstructionCaches(); m_system.InvalidateCpuInstructionCaches();
} }
@ -575,9 +578,10 @@ Result KPageTable::UnmapCodeMemory(VAddr dst_address, VAddr src_address, size_t
R_SUCCEED(); R_SUCCEED();
} }
VAddr KPageTable::FindFreeArea(VAddr region_start, size_t region_num_pages, size_t num_pages, KProcessAddress KPageTable::FindFreeArea(KProcessAddress region_start, size_t region_num_pages,
size_t alignment, size_t offset, size_t guard_pages) { size_t num_pages, size_t alignment, size_t offset,
VAddr address = 0; size_t guard_pages) {
KProcessAddress address = 0;
if (num_pages <= region_num_pages) { if (num_pages <= region_num_pages) {
if (this->IsAslrEnabled()) { if (this->IsAslrEnabled()) {
@ -593,7 +597,7 @@ VAddr KPageTable::FindFreeArea(VAddr region_start, size_t region_num_pages, size
return address; return address;
} }
Result KPageTable::MakePageGroup(KPageGroup& pg, VAddr addr, size_t num_pages) { Result KPageTable::MakePageGroup(KPageGroup& pg, KProcessAddress addr, size_t num_pages) {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
const size_t size = num_pages * PageSize; const size_t size = num_pages * PageSize;
@ -604,11 +608,11 @@ Result KPageTable::MakePageGroup(KPageGroup& pg, VAddr addr, size_t num_pages) {
// Begin traversal. // Begin traversal.
Common::PageTable::TraversalContext context; Common::PageTable::TraversalContext context;
Common::PageTable::TraversalEntry next_entry; Common::PageTable::TraversalEntry next_entry;
R_UNLESS(m_page_table_impl->BeginTraversal(next_entry, context, addr), R_UNLESS(m_page_table_impl->BeginTraversal(next_entry, context, GetInteger(addr)),
ResultInvalidCurrentMemory); ResultInvalidCurrentMemory);
// Prepare tracking variables. // Prepare tracking variables.
PAddr cur_addr = next_entry.phys_addr; KPhysicalAddress cur_addr = next_entry.phys_addr;
size_t cur_size = next_entry.block_size - (cur_addr & (next_entry.block_size - 1)); size_t cur_size = next_entry.block_size - (cur_addr & (next_entry.block_size - 1));
size_t tot_size = cur_size; size_t tot_size = cur_size;
@ -646,7 +650,7 @@ Result KPageTable::MakePageGroup(KPageGroup& pg, VAddr addr, size_t num_pages) {
R_SUCCEED(); R_SUCCEED();
} }
bool KPageTable::IsValidPageGroup(const KPageGroup& pg, VAddr addr, size_t num_pages) { bool KPageTable::IsValidPageGroup(const KPageGroup& pg, KProcessAddress addr, size_t num_pages) {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
const size_t size = num_pages * PageSize; const size_t size = num_pages * PageSize;
@ -659,7 +663,7 @@ bool KPageTable::IsValidPageGroup(const KPageGroup& pg, VAddr addr, size_t num_p
// We're going to validate that the group we'd expect is the group we see. // We're going to validate that the group we'd expect is the group we see.
auto cur_it = pg.begin(); auto cur_it = pg.begin();
PAddr cur_block_address = cur_it->GetAddress(); KPhysicalAddress cur_block_address = cur_it->GetAddress();
size_t cur_block_pages = cur_it->GetNumPages(); size_t cur_block_pages = cur_it->GetNumPages();
auto UpdateCurrentIterator = [&]() { auto UpdateCurrentIterator = [&]() {
@ -677,12 +681,12 @@ bool KPageTable::IsValidPageGroup(const KPageGroup& pg, VAddr addr, size_t num_p
// Begin traversal. // Begin traversal.
Common::PageTable::TraversalContext context; Common::PageTable::TraversalContext context;
Common::PageTable::TraversalEntry next_entry; Common::PageTable::TraversalEntry next_entry;
if (!m_page_table_impl->BeginTraversal(next_entry, context, addr)) { if (!m_page_table_impl->BeginTraversal(next_entry, context, GetInteger(addr))) {
return false; return false;
} }
// Prepare tracking variables. // Prepare tracking variables.
PAddr cur_addr = next_entry.phys_addr; KPhysicalAddress cur_addr = next_entry.phys_addr;
size_t cur_size = next_entry.block_size - (cur_addr & (next_entry.block_size - 1)); size_t cur_size = next_entry.block_size - (cur_addr & (next_entry.block_size - 1));
size_t tot_size = cur_size; size_t tot_size = cur_size;
@ -734,8 +738,8 @@ bool KPageTable::IsValidPageGroup(const KPageGroup& pg, VAddr addr, size_t num_p
return cur_block_address == cur_addr && cur_block_pages == (cur_size / PageSize); return cur_block_address == cur_addr && cur_block_pages == (cur_size / PageSize);
} }
Result KPageTable::UnmapProcessMemory(VAddr dst_addr, size_t size, KPageTable& src_page_table, Result KPageTable::UnmapProcessMemory(KProcessAddress dst_addr, size_t size,
VAddr src_addr) { KPageTable& src_page_table, KProcessAddress src_addr) {
// Acquire the table locks. // Acquire the table locks.
KScopedLightLockPair lk(src_page_table.m_general_lock, m_general_lock); KScopedLightLockPair lk(src_page_table.m_general_lock, m_general_lock);
@ -774,8 +778,8 @@ Result KPageTable::UnmapProcessMemory(VAddr dst_addr, size_t size, KPageTable& s
} }
Result KPageTable::SetupForIpcClient(PageLinkedList* page_list, size_t* out_blocks_needed, Result KPageTable::SetupForIpcClient(PageLinkedList* page_list, size_t* out_blocks_needed,
VAddr address, size_t size, KMemoryPermission test_perm, KProcessAddress address, size_t size,
KMemoryState dst_state) { KMemoryPermission test_perm, KMemoryState dst_state) {
// Validate pre-conditions. // Validate pre-conditions.
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
ASSERT(test_perm == KMemoryPermission::UserReadWrite || ASSERT(test_perm == KMemoryPermission::UserReadWrite ||
@ -790,10 +794,10 @@ Result KPageTable::SetupForIpcClient(PageLinkedList* page_list, size_t* out_bloc
: KMemoryPermission::UserRead; : KMemoryPermission::UserRead;
// Get aligned extents. // Get aligned extents.
const VAddr aligned_src_start = Common::AlignDown((address), PageSize); const KProcessAddress aligned_src_start = Common::AlignDown(GetInteger(address), PageSize);
const VAddr aligned_src_end = Common::AlignUp((address) + size, PageSize); const KProcessAddress aligned_src_end = Common::AlignUp(GetInteger(address) + size, PageSize);
const VAddr mapping_src_start = Common::AlignUp((address), PageSize); const KProcessAddress mapping_src_start = Common::AlignUp(GetInteger(address), PageSize);
const VAddr mapping_src_end = Common::AlignDown((address) + size, PageSize); const KProcessAddress mapping_src_end = Common::AlignDown(GetInteger(address) + size, PageSize);
const auto aligned_src_last = (aligned_src_end)-1; const auto aligned_src_last = (aligned_src_end)-1;
const auto mapping_src_last = (mapping_src_end)-1; const auto mapping_src_last = (mapping_src_end)-1;
@ -840,14 +844,15 @@ Result KPageTable::SetupForIpcClient(PageLinkedList* page_list, size_t* out_bloc
test_attr_mask, KMemoryAttribute::None)); test_attr_mask, KMemoryAttribute::None));
if (mapping_src_start < mapping_src_end && (mapping_src_start) < info.GetEndAddress() && if (mapping_src_start < mapping_src_end && (mapping_src_start) < info.GetEndAddress() &&
info.GetAddress() < (mapping_src_end)) { info.GetAddress() < GetInteger(mapping_src_end)) {
const auto cur_start = const auto cur_start = info.GetAddress() >= GetInteger(mapping_src_start)
info.GetAddress() >= (mapping_src_start) ? info.GetAddress() : (mapping_src_start); ? info.GetAddress()
: (mapping_src_start);
const auto cur_end = mapping_src_last >= info.GetLastAddress() ? info.GetEndAddress() const auto cur_end = mapping_src_last >= info.GetLastAddress() ? info.GetEndAddress()
: (mapping_src_end); : (mapping_src_end);
const size_t cur_size = cur_end - cur_start; const size_t cur_size = cur_end - cur_start;
if (info.GetAddress() < (mapping_src_start)) { if (info.GetAddress() < GetInteger(mapping_src_start)) {
++blocks_needed; ++blocks_needed;
} }
if (mapping_src_last < info.GetLastAddress()) { if (mapping_src_last < info.GetLastAddress()) {
@ -882,30 +887,32 @@ Result KPageTable::SetupForIpcClient(PageLinkedList* page_list, size_t* out_bloc
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_addr, Result KPageTable::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
KMemoryPermission test_perm, KMemoryState dst_state, KProcessAddress src_addr, KMemoryPermission test_perm,
KPageTable& src_page_table, bool send) { KMemoryState dst_state, KPageTable& src_page_table,
bool send) {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
ASSERT(src_page_table.IsLockedByCurrentThread()); ASSERT(src_page_table.IsLockedByCurrentThread());
// Check that we can theoretically map. // Check that we can theoretically map.
const VAddr region_start = m_alias_region_start; const KProcessAddress region_start = m_alias_region_start;
const size_t region_size = m_alias_region_end - m_alias_region_start; const size_t region_size = m_alias_region_end - m_alias_region_start;
R_UNLESS(size < region_size, ResultOutOfAddressSpace); R_UNLESS(size < region_size, ResultOutOfAddressSpace);
// Get aligned source extents. // Get aligned source extents.
const VAddr src_start = src_addr; const KProcessAddress src_start = src_addr;
const VAddr src_end = src_addr + size; const KProcessAddress src_end = src_addr + size;
const VAddr aligned_src_start = Common::AlignDown((src_start), PageSize); const KProcessAddress aligned_src_start = Common::AlignDown(GetInteger(src_start), PageSize);
const VAddr aligned_src_end = Common::AlignUp((src_start) + size, PageSize); const KProcessAddress aligned_src_end = Common::AlignUp(GetInteger(src_start) + size, PageSize);
const VAddr mapping_src_start = Common::AlignUp((src_start), PageSize); const KProcessAddress mapping_src_start = Common::AlignUp(GetInteger(src_start), PageSize);
const VAddr mapping_src_end = Common::AlignDown((src_start) + size, PageSize); const KProcessAddress mapping_src_end =
Common::AlignDown(GetInteger(src_start) + size, PageSize);
const size_t aligned_src_size = aligned_src_end - aligned_src_start; const size_t aligned_src_size = aligned_src_end - aligned_src_start;
const size_t mapping_src_size = const size_t mapping_src_size =
(mapping_src_start < mapping_src_end) ? (mapping_src_end - mapping_src_start) : 0; (mapping_src_start < mapping_src_end) ? (mapping_src_end - mapping_src_start) : 0;
// Select a random address to map at. // Select a random address to map at.
VAddr dst_addr = KProcessAddress dst_addr =
this->FindFreeArea(region_start, region_size / PageSize, aligned_src_size / PageSize, this->FindFreeArea(region_start, region_size / PageSize, aligned_src_size / PageSize,
PageSize, 0, this->GetNumGuardPages()); PageSize, 0, this->GetNumGuardPages());
@ -930,9 +937,9 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
// Ensure that we manage page references correctly. // Ensure that we manage page references correctly.
PAddr start_partial_page = 0; KPhysicalAddress start_partial_page = 0;
PAddr end_partial_page = 0; KPhysicalAddress end_partial_page = 0;
VAddr cur_mapped_addr = dst_addr; KProcessAddress cur_mapped_addr = dst_addr;
// If the partial pages are mapped, an extra reference will have been opened. Otherwise, they'll // If the partial pages are mapped, an extra reference will have been opened. Otherwise, they'll
// free on scope exit. // free on scope exit.
@ -977,11 +984,12 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
// Begin traversal. // Begin traversal.
Common::PageTable::TraversalContext context; Common::PageTable::TraversalContext context;
Common::PageTable::TraversalEntry next_entry; Common::PageTable::TraversalEntry next_entry;
bool traverse_valid = src_impl.BeginTraversal(next_entry, context, aligned_src_start); bool traverse_valid =
src_impl.BeginTraversal(next_entry, context, GetInteger(aligned_src_start));
ASSERT(traverse_valid); ASSERT(traverse_valid);
// Prepare tracking variables. // Prepare tracking variables.
PAddr cur_block_addr = next_entry.phys_addr; KPhysicalAddress cur_block_addr = next_entry.phys_addr;
size_t cur_block_size = size_t cur_block_size =
next_entry.block_size - ((cur_block_addr) & (next_entry.block_size - 1)); next_entry.block_size - ((cur_block_addr) & (next_entry.block_size - 1));
size_t tot_block_size = cur_block_size; size_t tot_block_size = cur_block_size;
@ -989,7 +997,7 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
// Map the start page, if we have one. // Map the start page, if we have one.
if (start_partial_page != 0) { if (start_partial_page != 0) {
// Ensure the page holds correct data. // Ensure the page holds correct data.
const VAddr start_partial_virt = const KVirtualAddress start_partial_virt =
GetHeapVirtualAddress(m_system.Kernel().MemoryLayout(), start_partial_page); GetHeapVirtualAddress(m_system.Kernel().MemoryLayout(), start_partial_page);
if (send) { if (send) {
const size_t partial_offset = src_start - aligned_src_start; const size_t partial_offset = src_start - aligned_src_start;
@ -1002,21 +1010,23 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
clear_size = 0; clear_size = 0;
} }
std::memset(m_system.Memory().GetPointer<void>(start_partial_virt), fill_val, std::memset(m_system.Memory().GetPointer<void>(GetInteger(start_partial_virt)),
partial_offset); fill_val, partial_offset);
std::memcpy( std::memcpy(
m_system.Memory().GetPointer<void>(start_partial_virt + partial_offset), m_system.Memory().GetPointer<void>(GetInteger(start_partial_virt) + partial_offset),
m_system.Memory().GetPointer<void>( m_system.Memory().GetPointer<void>(
GetHeapVirtualAddress(m_system.Kernel().MemoryLayout(), cur_block_addr) + GetInteger(
GetHeapVirtualAddress(m_system.Kernel().MemoryLayout(), cur_block_addr)) +
partial_offset), partial_offset),
copy_size); copy_size);
if (clear_size > 0) { if (clear_size > 0) {
std::memset(m_system.Memory().GetPointer<void>(start_partial_virt + partial_offset + std::memset(m_system.Memory().GetPointer<void>(GetInteger(start_partial_virt) +
copy_size), partial_offset + copy_size),
fill_val, clear_size); fill_val, clear_size);
} }
} else { } else {
std::memset(m_system.Memory().GetPointer<void>(start_partial_virt), fill_val, PageSize); std::memset(m_system.Memory().GetPointer<void>(GetInteger(start_partial_virt)),
fill_val, PageSize);
} }
// Map the page. // Map the page.
@ -1061,7 +1071,8 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
} }
// Handle the last direct-mapped page. // Handle the last direct-mapped page.
if (const VAddr mapped_block_end = aligned_src_start + tot_block_size - cur_block_size; if (const KProcessAddress mapped_block_end =
aligned_src_start + tot_block_size - cur_block_size;
mapped_block_end < mapping_src_end) { mapped_block_end < mapping_src_end) {
const size_t last_block_size = mapping_src_end - mapped_block_end; const size_t last_block_size = mapping_src_end - mapped_block_end;
@ -1084,18 +1095,20 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
// Map the end page, if we have one. // Map the end page, if we have one.
if (end_partial_page != 0) { if (end_partial_page != 0) {
// Ensure the page holds correct data. // Ensure the page holds correct data.
const VAddr end_partial_virt = const KVirtualAddress end_partial_virt =
GetHeapVirtualAddress(m_system.Kernel().MemoryLayout(), end_partial_page); GetHeapVirtualAddress(m_system.Kernel().MemoryLayout(), end_partial_page);
if (send) { if (send) {
const size_t copy_size = src_end - mapping_src_end; const size_t copy_size = src_end - mapping_src_end;
std::memcpy(m_system.Memory().GetPointer<void>(end_partial_virt), std::memcpy(m_system.Memory().GetPointer<void>(GetInteger(end_partial_virt)),
m_system.Memory().GetPointer<void>(GetHeapVirtualAddress( m_system.Memory().GetPointer<void>(GetInteger(GetHeapVirtualAddress(
m_system.Kernel().MemoryLayout(), cur_block_addr)), m_system.Kernel().MemoryLayout(), cur_block_addr))),
copy_size); copy_size);
std::memset(m_system.Memory().GetPointer<void>(end_partial_virt + copy_size), fill_val, std::memset(
PageSize - copy_size); m_system.Memory().GetPointer<void>(GetInteger(end_partial_virt) + copy_size),
fill_val, PageSize - copy_size);
} else { } else {
std::memset(m_system.Memory().GetPointer<void>(end_partial_virt), fill_val, PageSize); std::memset(m_system.Memory().GetPointer<void>(GetInteger(end_partial_virt)), fill_val,
PageSize);
} }
// Map the page. // Map the page.
@ -1116,7 +1129,7 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::SetupForIpc(VAddr* out_dst_addr, size_t size, VAddr src_addr, Result KPageTable::SetupForIpc(KProcessAddress* out_dst_addr, size_t size, KProcessAddress src_addr,
KPageTable& src_page_table, KMemoryPermission test_perm, KPageTable& src_page_table, KMemoryPermission test_perm,
KMemoryState dst_state, bool send) { KMemoryState dst_state, bool send) {
// For convenience, alias this. // For convenience, alias this.
@ -1142,8 +1155,8 @@ Result KPageTable::SetupForIpc(VAddr* out_dst_addr, size_t size, VAddr src_addr,
R_TRY(allocator_result); R_TRY(allocator_result);
// Get the mapped extents. // Get the mapped extents.
const VAddr src_map_start = Common::AlignUp((src_addr), PageSize); const KProcessAddress src_map_start = Common::AlignUp(GetInteger(src_addr), PageSize);
const VAddr src_map_end = Common::AlignDown((src_addr) + size, PageSize); const KProcessAddress src_map_end = Common::AlignDown(GetInteger(src_addr) + size, PageSize);
const size_t src_map_size = src_map_end - src_map_start; const size_t src_map_size = src_map_end - src_map_start;
// Ensure that we clean up appropriately if we fail after this. // Ensure that we clean up appropriately if we fail after this.
@ -1172,7 +1185,8 @@ Result KPageTable::SetupForIpc(VAddr* out_dst_addr, size_t size, VAddr src_addr,
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::CleanupForIpcServer(VAddr address, size_t size, KMemoryState dst_state) { Result KPageTable::CleanupForIpcServer(KProcessAddress address, size_t size,
KMemoryState dst_state) {
// Validate the address. // Validate the address.
R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory); R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory);
@ -1196,8 +1210,8 @@ Result KPageTable::CleanupForIpcServer(VAddr address, size_t size, KMemoryState
KScopedPageTableUpdater updater(this); KScopedPageTableUpdater updater(this);
// Get aligned extents. // Get aligned extents.
const VAddr aligned_start = Common::AlignDown((address), PageSize); const KProcessAddress aligned_start = Common::AlignDown(GetInteger(address), PageSize);
const VAddr aligned_end = Common::AlignUp((address) + size, PageSize); const KProcessAddress aligned_end = Common::AlignUp(GetInteger(address) + size, PageSize);
const size_t aligned_size = aligned_end - aligned_start; const size_t aligned_size = aligned_end - aligned_start;
const size_t aligned_num_pages = aligned_size / PageSize; const size_t aligned_num_pages = aligned_size / PageSize;
@ -1211,22 +1225,23 @@ Result KPageTable::CleanupForIpcServer(VAddr address, size_t size, KMemoryState
KMemoryBlockDisableMergeAttribute::Normal); KMemoryBlockDisableMergeAttribute::Normal);
// Release from the resource limit as relevant. // Release from the resource limit as relevant.
const VAddr mapping_start = Common::AlignUp((address), PageSize); const KProcessAddress mapping_start = Common::AlignUp(GetInteger(address), PageSize);
const VAddr mapping_end = Common::AlignDown((address) + size, PageSize); const KProcessAddress mapping_end = Common::AlignDown(GetInteger(address) + size, PageSize);
const size_t mapping_size = (mapping_start < mapping_end) ? mapping_end - mapping_start : 0; const size_t mapping_size = (mapping_start < mapping_end) ? mapping_end - mapping_start : 0;
m_resource_limit->Release(LimitableResource::PhysicalMemoryMax, aligned_size - mapping_size); m_resource_limit->Release(LimitableResource::PhysicalMemoryMax, aligned_size - mapping_size);
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::CleanupForIpcClient(VAddr address, size_t size, KMemoryState dst_state) { Result KPageTable::CleanupForIpcClient(KProcessAddress address, size_t size,
KMemoryState dst_state) {
// Validate the address. // Validate the address.
R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory); R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory);
// Get aligned source extents. // Get aligned source extents.
const VAddr mapping_start = Common::AlignUp((address), PageSize); const KProcessAddress mapping_start = Common::AlignUp(GetInteger(address), PageSize);
const VAddr mapping_end = Common::AlignDown((address) + size, PageSize); const KProcessAddress mapping_end = Common::AlignDown(GetInteger(address) + size, PageSize);
const VAddr mapping_last = mapping_end - 1; const KProcessAddress mapping_last = mapping_end - 1;
const size_t mapping_size = (mapping_start < mapping_end) ? (mapping_end - mapping_start) : 0; const size_t mapping_size = (mapping_start < mapping_end) ? (mapping_end - mapping_start) : 0;
// If nothing was mapped, we're actually done immediately. // If nothing was mapped, we're actually done immediately.
@ -1279,7 +1294,7 @@ Result KPageTable::CleanupForIpcClient(VAddr address, size_t size, KMemoryState
KMemoryInfo cur_info = start_it->GetMemoryInfo(); KMemoryInfo cur_info = start_it->GetMemoryInfo();
// Create tracking variables. // Create tracking variables.
VAddr cur_address = cur_info.GetAddress(); KProcessAddress cur_address = cur_info.GetAddress();
size_t cur_size = cur_info.GetSize(); size_t cur_size = cur_info.GetSize();
bool cur_perm_eq = cur_info.GetPermission() == cur_info.GetOriginalPermission(); bool cur_perm_eq = cur_info.GetPermission() == cur_info.GetOriginalPermission();
bool cur_needs_set_perm = !cur_perm_eq && cur_info.GetIpcLockCount() == 1; bool cur_needs_set_perm = !cur_perm_eq && cur_info.GetIpcLockCount() == 1;
@ -1352,7 +1367,7 @@ Result KPageTable::CleanupForIpcClient(VAddr address, size_t size, KMemoryState
.IsSuccess()); .IsSuccess());
// Create tracking variables. // Create tracking variables.
VAddr cur_address = cur_info.GetAddress(); KProcessAddress cur_address = cur_info.GetAddress();
size_t cur_size = cur_info.GetSize(); size_t cur_size = cur_info.GetSize();
bool cur_perm_eq = cur_info.GetPermission() == cur_info.GetOriginalPermission(); bool cur_perm_eq = cur_info.GetPermission() == cur_info.GetOriginalPermission();
bool cur_needs_set_perm = !cur_perm_eq && cur_info.GetIpcLockCount() == 1; bool cur_needs_set_perm = !cur_perm_eq && cur_info.GetIpcLockCount() == 1;
@ -1439,16 +1454,16 @@ Result KPageTable::CleanupForIpcClient(VAddr address, size_t size, KMemoryState
} }
void KPageTable::CleanupForIpcClientOnServerSetupFailure([[maybe_unused]] PageLinkedList* page_list, void KPageTable::CleanupForIpcClientOnServerSetupFailure([[maybe_unused]] PageLinkedList* page_list,
VAddr address, size_t size, KProcessAddress address, size_t size,
KMemoryPermission prot_perm) { KMemoryPermission prot_perm) {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
ASSERT(Common::IsAligned(address, PageSize)); ASSERT(Common::IsAligned(GetInteger(address), PageSize));
ASSERT(Common::IsAligned(size, PageSize)); ASSERT(Common::IsAligned(size, PageSize));
// Get the mapped extents. // Get the mapped extents.
const VAddr src_map_start = address; const KProcessAddress src_map_start = address;
const VAddr src_map_end = address + size; const KProcessAddress src_map_end = address + size;
const VAddr src_map_last = src_map_end - 1; const KProcessAddress src_map_last = src_map_end - 1;
// This function is only invoked when there's something to do. // This function is only invoked when there's something to do.
ASSERT(src_map_end > src_map_start); ASSERT(src_map_end > src_map_start);
@ -1458,8 +1473,9 @@ void KPageTable::CleanupForIpcClientOnServerSetupFailure([[maybe_unused]] PageLi
while (true) { while (true) {
const KMemoryInfo info = it->GetMemoryInfo(); const KMemoryInfo info = it->GetMemoryInfo();
const auto cur_start = const auto cur_start = info.GetAddress() >= GetInteger(src_map_start)
info.GetAddress() >= src_map_start ? info.GetAddress() : src_map_start; ? info.GetAddress()
: GetInteger(src_map_start);
const auto cur_end = const auto cur_end =
src_map_last <= info.GetLastAddress() ? src_map_end : info.GetEndAddress(); src_map_last <= info.GetLastAddress() ? src_map_end : info.GetEndAddress();
@ -1469,7 +1485,7 @@ void KPageTable::CleanupForIpcClientOnServerSetupFailure([[maybe_unused]] PageLi
(info.GetIpcLockCount() != 0 && (info.GetIpcLockCount() != 0 &&
(info.GetOriginalPermission() & KMemoryPermission::IpcLockChangeMask) != prot_perm)) { (info.GetOriginalPermission() & KMemoryPermission::IpcLockChangeMask) != prot_perm)) {
// Check if we actually need to fix the protections on the block. // Check if we actually need to fix the protections on the block.
if (cur_end == src_map_end || info.GetAddress() <= src_map_start || if (cur_end == src_map_end || info.GetAddress() <= GetInteger(src_map_start) ||
(info.GetPermission() & KMemoryPermission::IpcLockChangeMask) != prot_perm) { (info.GetPermission() & KMemoryPermission::IpcLockChangeMask) != prot_perm) {
ASSERT(Operate(cur_start, (cur_end - cur_start) / PageSize, info.GetPermission(), ASSERT(Operate(cur_start, (cur_end - cur_start) / PageSize, info.GetPermission(),
OperationType::ChangePermissions) OperationType::ChangePermissions)
@ -1488,15 +1504,15 @@ void KPageTable::CleanupForIpcClientOnServerSetupFailure([[maybe_unused]] PageLi
} }
} }
Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) { Result KPageTable::MapPhysicalMemory(KProcessAddress address, size_t size) {
// Lock the physical memory lock. // Lock the physical memory lock.
KScopedLightLock phys_lk(m_map_physical_memory_lock); KScopedLightLock phys_lk(m_map_physical_memory_lock);
// Calculate the last address for convenience. // Calculate the last address for convenience.
const VAddr last_address = address + size - 1; const KProcessAddress last_address = address + size - 1;
// Define iteration variables. // Define iteration variables.
VAddr cur_address; KProcessAddress cur_address;
size_t mapped_size; size_t mapped_size;
// The entire mapping process can be retried. // The entire mapping process can be retried.
@ -1528,7 +1544,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
// Track the memory if it's mapped. // Track the memory if it's mapped.
if (info.GetState() != KMemoryState::Free) { if (info.GetState() != KMemoryState::Free) {
mapped_size += VAddr(info.GetEndAddress()) - cur_address; mapped_size += KProcessAddress(info.GetEndAddress()) - cur_address;
} }
// Advance. // Advance.
@ -1581,7 +1597,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
const bool is_free = info.GetState() == KMemoryState::Free; const bool is_free = info.GetState() == KMemoryState::Free;
if (is_free) { if (is_free) {
if (info.GetAddress() < address) { if (info.GetAddress() < GetInteger(address)) {
++num_allocator_blocks; ++num_allocator_blocks;
} }
if (last_address < info.GetLastAddress()) { if (last_address < info.GetLastAddress()) {
@ -1599,7 +1615,8 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
// Track the memory if it's mapped. // Track the memory if it's mapped.
if (!is_free) { if (!is_free) {
checked_mapped_size += VAddr(info.GetEndAddress()) - cur_address; checked_mapped_size +=
KProcessAddress(info.GetEndAddress()) - cur_address;
} }
// Advance. // Advance.
@ -1627,7 +1644,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
// Prepare to iterate over the memory. // Prepare to iterate over the memory.
auto pg_it = pg.begin(); auto pg_it = pg.begin();
PAddr pg_phys_addr = pg_it->GetAddress(); KPhysicalAddress pg_phys_addr = pg_it->GetAddress();
size_t pg_pages = pg_it->GetNumPages(); size_t pg_pages = pg_it->GetNumPages();
// Reset the current tracking address, and make sure we clean up on failure. // Reset the current tracking address, and make sure we clean up on failure.
@ -1635,7 +1652,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
cur_address = address; cur_address = address;
ON_RESULT_FAILURE { ON_RESULT_FAILURE {
if (cur_address > address) { if (cur_address > address) {
const VAddr last_unmap_address = cur_address - 1; const KProcessAddress last_unmap_address = cur_address - 1;
// Iterate, unmapping the pages. // Iterate, unmapping the pages.
cur_address = address; cur_address = address;
@ -1652,7 +1669,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
if (info.GetState() == KMemoryState::Free) { if (info.GetState() == KMemoryState::Free) {
// Determine the range to unmap. // Determine the range to unmap.
const size_t cur_pages = const size_t cur_pages =
std::min(VAddr(info.GetEndAddress()) - cur_address, std::min(KProcessAddress(info.GetEndAddress()) - cur_address,
last_unmap_address + 1 - cur_address) / last_unmap_address + 1 - cur_address) /
PageSize; PageSize;
@ -1695,7 +1712,8 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
// If it's unmapped, we need to map it. // If it's unmapped, we need to map it.
if (info.GetState() == KMemoryState::Free) { if (info.GetState() == KMemoryState::Free) {
// Determine the range to map. // Determine the range to map.
size_t map_pages = std::min(VAddr(info.GetEndAddress()) - cur_address, size_t map_pages =
std::min(KProcessAddress(info.GetEndAddress()) - cur_address,
last_address + 1 - cur_address) / last_address + 1 - cur_address) /
PageSize; PageSize;
@ -1754,7 +1772,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
} }
} }
Result KPageTable::UnmapPhysicalMemory(VAddr address, size_t size) { Result KPageTable::UnmapPhysicalMemory(KProcessAddress address, size_t size) {
// Lock the physical memory lock. // Lock the physical memory lock.
KScopedLightLock phys_lk(m_map_physical_memory_lock); KScopedLightLock phys_lk(m_map_physical_memory_lock);
@ -1762,13 +1780,13 @@ Result KPageTable::UnmapPhysicalMemory(VAddr address, size_t size) {
KScopedLightLock lk(m_general_lock); KScopedLightLock lk(m_general_lock);
// Calculate the last address for convenience. // Calculate the last address for convenience.
const VAddr last_address = address + size - 1; const KProcessAddress last_address = address + size - 1;
// Define iteration variables. // Define iteration variables.
VAddr map_start_address = 0; KProcessAddress map_start_address = 0;
VAddr map_last_address = 0; KProcessAddress map_last_address = 0;
VAddr cur_address; KProcessAddress cur_address;
size_t mapped_size; size_t mapped_size;
size_t num_allocator_blocks = 0; size_t num_allocator_blocks = 0;
@ -1801,7 +1819,7 @@ Result KPageTable::UnmapPhysicalMemory(VAddr address, size_t size) {
map_last_address = map_last_address =
(last_address >= info.GetLastAddress()) ? info.GetLastAddress() : last_address; (last_address >= info.GetLastAddress()) ? info.GetLastAddress() : last_address;
if (info.GetAddress() < address) { if (info.GetAddress() < GetInteger(address)) {
++num_allocator_blocks; ++num_allocator_blocks;
} }
if (last_address < info.GetLastAddress()) { if (last_address < info.GetLastAddress()) {
@ -1854,7 +1872,7 @@ Result KPageTable::UnmapPhysicalMemory(VAddr address, size_t size) {
// If the memory state is normal, we need to unmap it. // If the memory state is normal, we need to unmap it.
if (info.GetState() == KMemoryState::Normal) { if (info.GetState() == KMemoryState::Normal) {
// Determine the range to unmap. // Determine the range to unmap.
const size_t cur_pages = std::min(VAddr(info.GetEndAddress()) - cur_address, const size_t cur_pages = std::min(KProcessAddress(info.GetEndAddress()) - cur_address,
last_address + 1 - cur_address) / last_address + 1 - cur_address) /
PageSize; PageSize;
@ -2144,13 +2162,14 @@ void KPageTable::RemapPageGroup(PageLinkedList* page_list, KProcessAddress addre
const KMemoryInfo info = it->GetMemoryInfo(); const KMemoryInfo info = it->GetMemoryInfo();
// Determine the range to map. // Determine the range to map.
KProcessAddress map_address = std::max<VAddr>(info.GetAddress(), start_address); KProcessAddress map_address = std::max<KProcessAddress>(info.GetAddress(), start_address);
const KProcessAddress map_end_address = std::min<VAddr>(info.GetEndAddress(), end_address); const KProcessAddress map_end_address =
std::min<KProcessAddress>(info.GetEndAddress(), end_address);
ASSERT(map_end_address != map_address); ASSERT(map_end_address != map_address);
// Determine if we should disable head merge. // Determine if we should disable head merge.
const bool disable_head_merge = const bool disable_head_merge =
info.GetAddress() >= start_address && info.GetAddress() >= GetInteger(start_address) &&
True(info.GetDisableMergeAttribute() & KMemoryBlockDisableMergeAttribute::Normal); True(info.GetDisableMergeAttribute() & KMemoryBlockDisableMergeAttribute::Normal);
const KPageProperties map_properties = { const KPageProperties map_properties = {
info.GetPermission(), false, false, info.GetPermission(), false, false,
@ -2214,7 +2233,7 @@ Result KPageTable::MapPages(KProcessAddress* out_addr, size_t num_pages, size_t
KProcessAddress addr = this->FindFreeArea(region_start, region_num_pages, num_pages, alignment, KProcessAddress addr = this->FindFreeArea(region_start, region_num_pages, num_pages, alignment,
0, this->GetNumGuardPages()); 0, this->GetNumGuardPages());
R_UNLESS(addr != 0, ResultOutOfMemory); R_UNLESS(addr != 0, ResultOutOfMemory);
ASSERT(Common::IsAligned(addr, alignment)); ASSERT(Common::IsAligned(GetInteger(addr), alignment));
ASSERT(this->CanContain(addr, num_pages * PageSize, state)); ASSERT(this->CanContain(addr, num_pages * PageSize, state));
ASSERT(this->CheckMemoryState(addr, num_pages * PageSize, KMemoryState::All, KMemoryState::Free, ASSERT(this->CheckMemoryState(addr, num_pages * PageSize, KMemoryState::All, KMemoryState::Free,
KMemoryPermission::None, KMemoryPermission::None, KMemoryPermission::None, KMemoryPermission::None,
@ -2455,7 +2474,7 @@ Result KPageTable::UnmapPageGroup(KProcessAddress address, const KPageGroup& pg,
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::MakeAndOpenPageGroup(KPageGroup* out, VAddr address, size_t num_pages, Result KPageTable::MakeAndOpenPageGroup(KPageGroup* out, KProcessAddress address, size_t num_pages,
KMemoryState state_mask, KMemoryState state, KMemoryState state_mask, KMemoryState state,
KMemoryPermission perm_mask, KMemoryPermission perm, KMemoryPermission perm_mask, KMemoryPermission perm,
KMemoryAttribute attr_mask, KMemoryAttribute attr) { KMemoryAttribute attr_mask, KMemoryAttribute attr) {
@ -2480,7 +2499,7 @@ Result KPageTable::MakeAndOpenPageGroup(KPageGroup* out, VAddr address, size_t n
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::SetProcessMemoryPermission(VAddr addr, size_t size, Result KPageTable::SetProcessMemoryPermission(KProcessAddress addr, size_t size,
Svc::MemoryPermission svc_perm) { Svc::MemoryPermission svc_perm) {
const size_t num_pages = size / PageSize; const size_t num_pages = size / PageSize;
@ -2541,23 +2560,23 @@ Result KPageTable::SetProcessMemoryPermission(VAddr addr, size_t size,
// Ensure cache coherency, if we're setting pages as executable. // Ensure cache coherency, if we're setting pages as executable.
if (is_x) { if (is_x) {
m_system.InvalidateCpuInstructionCacheRange(addr, size); m_system.InvalidateCpuInstructionCacheRange(GetInteger(addr), size);
} }
R_SUCCEED(); R_SUCCEED();
} }
KMemoryInfo KPageTable::QueryInfoImpl(VAddr addr) { KMemoryInfo KPageTable::QueryInfoImpl(KProcessAddress addr) {
KScopedLightLock lk(m_general_lock); KScopedLightLock lk(m_general_lock);
return m_memory_block_manager.FindBlock(addr)->GetMemoryInfo(); return m_memory_block_manager.FindBlock(addr)->GetMemoryInfo();
} }
KMemoryInfo KPageTable::QueryInfo(VAddr addr) { KMemoryInfo KPageTable::QueryInfo(KProcessAddress addr) {
if (!Contains(addr, 1)) { if (!Contains(addr, 1)) {
return { return {
.m_address = m_address_space_end, .m_address = GetInteger(m_address_space_end),
.m_size = 0 - m_address_space_end, .m_size = 0 - GetInteger(m_address_space_end),
.m_state = static_cast<KMemoryState>(Svc::MemoryState::Inaccessible), .m_state = static_cast<KMemoryState>(Svc::MemoryState::Inaccessible),
.m_device_disable_merge_left_count = 0, .m_device_disable_merge_left_count = 0,
.m_device_disable_merge_right_count = 0, .m_device_disable_merge_right_count = 0,
@ -2574,7 +2593,8 @@ KMemoryInfo KPageTable::QueryInfo(VAddr addr) {
return QueryInfoImpl(addr); return QueryInfoImpl(addr);
} }
Result KPageTable::SetMemoryPermission(VAddr addr, size_t size, Svc::MemoryPermission svc_perm) { Result KPageTable::SetMemoryPermission(KProcessAddress addr, size_t size,
Svc::MemoryPermission svc_perm) {
const size_t num_pages = size / PageSize; const size_t num_pages = size / PageSize;
// Lock the table. // Lock the table.
@ -2611,7 +2631,7 @@ Result KPageTable::SetMemoryPermission(VAddr addr, size_t size, Svc::MemoryPermi
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::SetMemoryAttribute(VAddr addr, size_t size, u32 mask, u32 attr) { Result KPageTable::SetMemoryAttribute(KProcessAddress addr, size_t size, u32 mask, u32 attr) {
const size_t num_pages = size / PageSize; const size_t num_pages = size / PageSize;
ASSERT((static_cast<KMemoryAttribute>(mask) | KMemoryAttribute::SetMask) == ASSERT((static_cast<KMemoryAttribute>(mask) | KMemoryAttribute::SetMask) ==
KMemoryAttribute::SetMask); KMemoryAttribute::SetMask);
@ -2666,12 +2686,12 @@ Result KPageTable::SetMaxHeapSize(size_t size) {
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::SetHeapSize(VAddr* out, size_t size) { Result KPageTable::SetHeapSize(u64* out, size_t size) {
// Lock the physical memory mutex. // Lock the physical memory mutex.
KScopedLightLock map_phys_mem_lk(m_map_physical_memory_lock); KScopedLightLock map_phys_mem_lk(m_map_physical_memory_lock);
// Try to perform a reduction in heap, instead of an extension. // Try to perform a reduction in heap, instead of an extension.
VAddr cur_address{}; KProcessAddress cur_address{};
size_t allocation_size{}; size_t allocation_size{};
{ {
// Lock the table. // Lock the table.
@ -2722,11 +2742,11 @@ Result KPageTable::SetHeapSize(VAddr* out, size_t size) {
m_current_heap_end = m_heap_region_start + size; m_current_heap_end = m_heap_region_start + size;
// Set the output. // Set the output.
*out = m_heap_region_start; *out = GetInteger(m_heap_region_start);
R_SUCCEED(); R_SUCCEED();
} else if (size == GetHeapSize()) { } else if (size == GetHeapSize()) {
// The size requested is exactly the current size. // The size requested is exactly the current size.
*out = m_heap_region_start; *out = GetInteger(m_heap_region_start);
R_SUCCEED(); R_SUCCEED();
} else { } else {
// We have to allocate memory. Determine how much to allocate and where while the table // We have to allocate memory. Determine how much to allocate and where while the table
@ -2799,14 +2819,14 @@ Result KPageTable::SetHeapSize(VAddr* out, size_t size) {
m_current_heap_end = m_heap_region_start + size; m_current_heap_end = m_heap_region_start + size;
// Set the output. // Set the output.
*out = m_heap_region_start; *out = GetInteger(m_heap_region_start);
R_SUCCEED(); R_SUCCEED();
} }
} }
Result KPageTable::LockForMapDeviceAddressSpace(bool* out_is_io, VAddr address, size_t size, Result KPageTable::LockForMapDeviceAddressSpace(bool* out_is_io, KProcessAddress address,
KMemoryPermission perm, bool is_aligned, size_t size, KMemoryPermission perm,
bool check_heap) { bool is_aligned, bool check_heap) {
// Lightly validate the range before doing anything else. // Lightly validate the range before doing anything else.
const size_t num_pages = size / PageSize; const size_t num_pages = size / PageSize;
R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory); R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory);
@ -2842,7 +2862,8 @@ Result KPageTable::LockForMapDeviceAddressSpace(bool* out_is_io, VAddr address,
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::LockForUnmapDeviceAddressSpace(VAddr address, size_t size, bool check_heap) { Result KPageTable::LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size,
bool check_heap) {
// Lightly validate the range before doing anything else. // Lightly validate the range before doing anything else.
const size_t num_pages = size / PageSize; const size_t num_pages = size / PageSize;
R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory); R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory);
@ -2876,7 +2897,7 @@ Result KPageTable::LockForUnmapDeviceAddressSpace(VAddr address, size_t size, bo
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::UnlockForDeviceAddressSpace(VAddr address, size_t size) { Result KPageTable::UnlockForDeviceAddressSpace(KProcessAddress address, size_t size) {
// Lightly validate the range before doing anything else. // Lightly validate the range before doing anything else.
const size_t num_pages = size / PageSize; const size_t num_pages = size / PageSize;
R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory); R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory);
@ -2904,7 +2925,8 @@ Result KPageTable::UnlockForDeviceAddressSpace(VAddr address, size_t size) {
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::LockForIpcUserBuffer(PAddr* out, VAddr address, size_t size) { Result KPageTable::LockForIpcUserBuffer(KPhysicalAddress* out, KProcessAddress address,
size_t size) {
R_RETURN(this->LockMemoryAndOpen( R_RETURN(this->LockMemoryAndOpen(
nullptr, out, address, size, KMemoryState::FlagCanIpcUserBuffer, nullptr, out, address, size, KMemoryState::FlagCanIpcUserBuffer,
KMemoryState::FlagCanIpcUserBuffer, KMemoryPermission::All, KMemoryState::FlagCanIpcUserBuffer, KMemoryPermission::All,
@ -2913,7 +2935,7 @@ Result KPageTable::LockForIpcUserBuffer(PAddr* out, VAddr address, size_t size)
KMemoryAttribute::Locked)); KMemoryAttribute::Locked));
} }
Result KPageTable::UnlockForIpcUserBuffer(VAddr address, size_t size) { Result KPageTable::UnlockForIpcUserBuffer(KProcessAddress address, size_t size) {
R_RETURN(this->UnlockMemory(address, size, KMemoryState::FlagCanIpcUserBuffer, R_RETURN(this->UnlockMemory(address, size, KMemoryState::FlagCanIpcUserBuffer,
KMemoryState::FlagCanIpcUserBuffer, KMemoryPermission::None, KMemoryState::FlagCanIpcUserBuffer, KMemoryPermission::None,
KMemoryPermission::None, KMemoryAttribute::All, KMemoryPermission::None, KMemoryAttribute::All,
@ -2921,7 +2943,7 @@ Result KPageTable::UnlockForIpcUserBuffer(VAddr address, size_t size) {
KMemoryAttribute::Locked, nullptr)); KMemoryAttribute::Locked, nullptr));
} }
Result KPageTable::LockForCodeMemory(KPageGroup* out, VAddr addr, size_t size) { Result KPageTable::LockForCodeMemory(KPageGroup* out, KProcessAddress addr, size_t size) {
R_RETURN(this->LockMemoryAndOpen( R_RETURN(this->LockMemoryAndOpen(
out, nullptr, addr, size, KMemoryState::FlagCanCodeMemory, KMemoryState::FlagCanCodeMemory, out, nullptr, addr, size, KMemoryState::FlagCanCodeMemory, KMemoryState::FlagCanCodeMemory,
KMemoryPermission::All, KMemoryPermission::UserReadWrite, KMemoryAttribute::All, KMemoryPermission::All, KMemoryPermission::UserReadWrite, KMemoryAttribute::All,
@ -2929,17 +2951,17 @@ Result KPageTable::LockForCodeMemory(KPageGroup* out, VAddr addr, size_t size) {
KMemoryAttribute::Locked)); KMemoryAttribute::Locked));
} }
Result KPageTable::UnlockForCodeMemory(VAddr addr, size_t size, const KPageGroup& pg) { Result KPageTable::UnlockForCodeMemory(KProcessAddress addr, size_t size, const KPageGroup& pg) {
R_RETURN(this->UnlockMemory( R_RETURN(this->UnlockMemory(
addr, size, KMemoryState::FlagCanCodeMemory, KMemoryState::FlagCanCodeMemory, addr, size, KMemoryState::FlagCanCodeMemory, KMemoryState::FlagCanCodeMemory,
KMemoryPermission::None, KMemoryPermission::None, KMemoryAttribute::All, KMemoryPermission::None, KMemoryPermission::None, KMemoryAttribute::All,
KMemoryAttribute::Locked, KMemoryPermission::UserReadWrite, KMemoryAttribute::Locked, &pg)); KMemoryAttribute::Locked, KMemoryPermission::UserReadWrite, KMemoryAttribute::Locked, &pg));
} }
bool KPageTable::IsRegionContiguous(VAddr addr, u64 size) const { bool KPageTable::IsRegionContiguous(KProcessAddress addr, u64 size) const {
auto start_ptr = m_system.DeviceMemory().GetPointer<u8>(addr); auto start_ptr = m_system.DeviceMemory().GetPointer<u8>(GetInteger(addr));
for (u64 offset{}; offset < size; offset += PageSize) { for (u64 offset{}; offset < size; offset += PageSize) {
if (start_ptr != m_system.DeviceMemory().GetPointer<u8>(addr + offset)) { if (start_ptr != m_system.DeviceMemory().GetPointer<u8>(GetInteger(addr) + offset)) {
return false; return false;
} }
start_ptr += PageSize; start_ptr += PageSize;
@ -2947,18 +2969,19 @@ bool KPageTable::IsRegionContiguous(VAddr addr, u64 size) const {
return true; return true;
} }
void KPageTable::AddRegionToPages(VAddr start, size_t num_pages, KPageGroup& page_linked_list) { void KPageTable::AddRegionToPages(KProcessAddress start, size_t num_pages,
VAddr addr{start}; KPageGroup& page_linked_list) {
KProcessAddress addr{start};
while (addr < start + (num_pages * PageSize)) { while (addr < start + (num_pages * PageSize)) {
const PAddr paddr{GetPhysicalAddr(addr)}; const KPhysicalAddress paddr{GetPhysicalAddr(addr)};
ASSERT(paddr != 0); ASSERT(paddr != 0);
page_linked_list.AddBlock(paddr, 1); page_linked_list.AddBlock(paddr, 1);
addr += PageSize; addr += PageSize;
} }
} }
VAddr KPageTable::AllocateVirtualMemory(VAddr start, size_t region_num_pages, u64 needed_num_pages, KProcessAddress KPageTable::AllocateVirtualMemory(KProcessAddress start, size_t region_num_pages,
size_t align) { u64 needed_num_pages, size_t align) {
if (m_enable_aslr) { if (m_enable_aslr) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
@ -2966,11 +2989,11 @@ VAddr KPageTable::AllocateVirtualMemory(VAddr start, size_t region_num_pages, u6
IsKernel() ? 1 : 4); IsKernel() ? 1 : 4);
} }
Result KPageTable::Operate(VAddr addr, size_t num_pages, const KPageGroup& page_group, Result KPageTable::Operate(KProcessAddress addr, size_t num_pages, const KPageGroup& page_group,
OperationType operation) { OperationType operation) {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
ASSERT(Common::IsAligned(addr, PageSize)); ASSERT(Common::IsAligned(GetInteger(addr), PageSize));
ASSERT(num_pages > 0); ASSERT(num_pages > 0);
ASSERT(num_pages == page_group.GetNumPages()); ASSERT(num_pages == page_group.GetNumPages());
@ -3001,12 +3024,12 @@ Result KPageTable::Operate(VAddr addr, size_t num_pages, const KPageGroup& page_
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::Operate(VAddr addr, size_t num_pages, KMemoryPermission perm, Result KPageTable::Operate(KProcessAddress addr, size_t num_pages, KMemoryPermission perm,
OperationType operation, PAddr map_addr) { OperationType operation, KPhysicalAddress map_addr) {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
ASSERT(num_pages > 0); ASSERT(num_pages > 0);
ASSERT(Common::IsAligned(addr, PageSize)); ASSERT(Common::IsAligned(GetInteger(addr), PageSize));
ASSERT(ContainsPages(addr, num_pages)); ASSERT(ContainsPages(addr, num_pages));
switch (operation) { switch (operation) {
@ -3022,7 +3045,7 @@ Result KPageTable::Operate(VAddr addr, size_t num_pages, KMemoryPermission perm,
case OperationType::MapFirst: case OperationType::MapFirst:
case OperationType::Map: { case OperationType::Map: {
ASSERT(map_addr); ASSERT(map_addr);
ASSERT(Common::IsAligned(map_addr, PageSize)); ASSERT(Common::IsAligned(GetInteger(map_addr), PageSize));
m_system.Memory().MapMemoryRegion(*m_page_table_impl, addr, num_pages * PageSize, map_addr); m_system.Memory().MapMemoryRegion(*m_page_table_impl, addr, num_pages * PageSize, map_addr);
// Open references to pages, if we should. // Open references to pages, if we should.
@ -3060,7 +3083,7 @@ void KPageTable::FinalizeUpdate(PageLinkedList* page_list) {
} }
} }
VAddr KPageTable::GetRegionAddress(KMemoryState state) const { KProcessAddress KPageTable::GetRegionAddress(KMemoryState state) const {
switch (state) { switch (state) {
case KMemoryState::Free: case KMemoryState::Free:
case KMemoryState::Kernel: case KMemoryState::Kernel:
@ -3132,11 +3155,11 @@ size_t KPageTable::GetRegionSize(KMemoryState state) const {
} }
} }
bool KPageTable::CanContain(VAddr addr, size_t size, KMemoryState state) const { bool KPageTable::CanContain(KProcessAddress addr, size_t size, KMemoryState state) const {
const VAddr end = addr + size; const KProcessAddress end = addr + size;
const VAddr last = end - 1; const KProcessAddress last = end - 1;
const VAddr region_start = this->GetRegionAddress(state); const KProcessAddress region_start = this->GetRegionAddress(state);
const size_t region_size = this->GetRegionSize(state); const size_t region_size = this->GetRegionSize(state);
const bool is_in_region = const bool is_in_region =
@ -3191,21 +3214,21 @@ Result KPageTable::CheckMemoryState(const KMemoryInfo& info, KMemoryState state_
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::CheckMemoryStateContiguous(size_t* out_blocks_needed, VAddr addr, size_t size, Result KPageTable::CheckMemoryStateContiguous(size_t* out_blocks_needed, KProcessAddress addr,
KMemoryState state_mask, KMemoryState state, size_t size, KMemoryState state_mask,
KMemoryPermission perm_mask, KMemoryPermission perm, KMemoryState state, KMemoryPermission perm_mask,
KMemoryAttribute attr_mask, KMemoryPermission perm, KMemoryAttribute attr_mask,
KMemoryAttribute attr) const { KMemoryAttribute attr) const {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
// Get information about the first block. // Get information about the first block.
const VAddr last_addr = addr + size - 1; const KProcessAddress last_addr = addr + size - 1;
KMemoryBlockManager::const_iterator it = m_memory_block_manager.FindIterator(addr); KMemoryBlockManager::const_iterator it = m_memory_block_manager.FindIterator(addr);
KMemoryInfo info = it->GetMemoryInfo(); KMemoryInfo info = it->GetMemoryInfo();
// If the start address isn't aligned, we need a block. // If the start address isn't aligned, we need a block.
const size_t blocks_for_start_align = const size_t blocks_for_start_align =
(Common::AlignDown(addr, PageSize) != info.GetAddress()) ? 1 : 0; (Common::AlignDown(GetInteger(addr), PageSize) != info.GetAddress()) ? 1 : 0;
while (true) { while (true) {
// Validate against the provided masks. // Validate against the provided masks.
@ -3224,7 +3247,7 @@ Result KPageTable::CheckMemoryStateContiguous(size_t* out_blocks_needed, VAddr a
// If the end address isn't aligned, we need a block. // If the end address isn't aligned, we need a block.
const size_t blocks_for_end_align = const size_t blocks_for_end_align =
(Common::AlignUp(addr + size, PageSize) != info.GetEndAddress()) ? 1 : 0; (Common::AlignUp(GetInteger(addr) + size, PageSize) != info.GetEndAddress()) ? 1 : 0;
if (out_blocks_needed != nullptr) { if (out_blocks_needed != nullptr) {
*out_blocks_needed = blocks_for_start_align + blocks_for_end_align; *out_blocks_needed = blocks_for_start_align + blocks_for_end_align;
@ -3235,20 +3258,20 @@ Result KPageTable::CheckMemoryStateContiguous(size_t* out_blocks_needed, VAddr a
Result KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm, Result KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm,
KMemoryAttribute* out_attr, size_t* out_blocks_needed, KMemoryAttribute* out_attr, size_t* out_blocks_needed,
VAddr addr, size_t size, KMemoryState state_mask, KProcessAddress addr, size_t size, KMemoryState state_mask,
KMemoryState state, KMemoryPermission perm_mask, KMemoryState state, KMemoryPermission perm_mask,
KMemoryPermission perm, KMemoryAttribute attr_mask, KMemoryPermission perm, KMemoryAttribute attr_mask,
KMemoryAttribute attr, KMemoryAttribute ignore_attr) const { KMemoryAttribute attr, KMemoryAttribute ignore_attr) const {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
// Get information about the first block. // Get information about the first block.
const VAddr last_addr = addr + size - 1; const KProcessAddress last_addr = addr + size - 1;
KMemoryBlockManager::const_iterator it = m_memory_block_manager.FindIterator(addr); KMemoryBlockManager::const_iterator it = m_memory_block_manager.FindIterator(addr);
KMemoryInfo info = it->GetMemoryInfo(); KMemoryInfo info = it->GetMemoryInfo();
// If the start address isn't aligned, we need a block. // If the start address isn't aligned, we need a block.
const size_t blocks_for_start_align = const size_t blocks_for_start_align =
(Common::AlignDown(addr, PageSize) != info.GetAddress()) ? 1 : 0; (Common::AlignDown(GetInteger(addr), PageSize) != info.GetAddress()) ? 1 : 0;
// Validate all blocks in the range have correct state. // Validate all blocks in the range have correct state.
const KMemoryState first_state = info.m_state; const KMemoryState first_state = info.m_state;
@ -3277,7 +3300,7 @@ Result KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermission*
// If the end address isn't aligned, we need a block. // If the end address isn't aligned, we need a block.
const size_t blocks_for_end_align = const size_t blocks_for_end_align =
(Common::AlignUp(addr + size, PageSize) != info.GetEndAddress()) ? 1 : 0; (Common::AlignUp(GetInteger(addr) + size, PageSize) != info.GetEndAddress()) ? 1 : 0;
// Write output state. // Write output state.
if (out_state != nullptr) { if (out_state != nullptr) {
@ -3295,11 +3318,12 @@ Result KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermission*
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::LockMemoryAndOpen(KPageGroup* out_pg, PAddr* out_paddr, VAddr addr, size_t size, Result KPageTable::LockMemoryAndOpen(KPageGroup* out_pg, KPhysicalAddress* out_KPhysicalAddress,
KMemoryState state_mask, KMemoryState state, KProcessAddress addr, size_t size, KMemoryState state_mask,
KMemoryPermission perm_mask, KMemoryPermission perm, KMemoryState state, KMemoryPermission perm_mask,
KMemoryAttribute attr_mask, KMemoryAttribute attr, KMemoryPermission perm, KMemoryAttribute attr_mask,
KMemoryPermission new_perm, KMemoryAttribute lock_attr) { KMemoryAttribute attr, KMemoryPermission new_perm,
KMemoryAttribute lock_attr) {
// Validate basic preconditions. // Validate basic preconditions.
ASSERT((lock_attr & attr) == KMemoryAttribute::None); ASSERT((lock_attr & attr) == KMemoryAttribute::None);
ASSERT((lock_attr & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared)) == ASSERT((lock_attr & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared)) ==
@ -3329,8 +3353,8 @@ Result KPageTable::LockMemoryAndOpen(KPageGroup* out_pg, PAddr* out_paddr, VAddr
attr_mask, attr)); attr_mask, attr));
// Get the physical address, if we're supposed to. // Get the physical address, if we're supposed to.
if (out_paddr != nullptr) { if (out_KPhysicalAddress != nullptr) {
ASSERT(this->GetPhysicalAddressLocked(out_paddr, addr)); ASSERT(this->GetPhysicalAddressLocked(out_KPhysicalAddress, addr));
} }
// Make the page group, if we're supposed to. // Make the page group, if we're supposed to.
@ -3361,7 +3385,7 @@ Result KPageTable::LockMemoryAndOpen(KPageGroup* out_pg, PAddr* out_paddr, VAddr
R_SUCCEED(); R_SUCCEED();
} }
Result KPageTable::UnlockMemory(VAddr addr, size_t size, KMemoryState state_mask, Result KPageTable::UnlockMemory(KProcessAddress addr, size_t size, KMemoryState state_mask,
KMemoryState state, KMemoryPermission perm_mask, KMemoryState state, KMemoryPermission perm_mask,
KMemoryPermission perm, KMemoryAttribute attr_mask, KMemoryPermission perm, KMemoryAttribute attr_mask,
KMemoryAttribute attr, KMemoryPermission new_perm, KMemoryAttribute attr, KMemoryPermission new_perm,

@ -6,7 +6,6 @@
#include <memory> #include <memory>
#include "common/common_funcs.h" #include "common/common_funcs.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/k_dynamic_resource_manager.h" #include "core/hle/kernel/k_dynamic_resource_manager.h"
@ -15,6 +14,7 @@
#include "core/hle/kernel/k_memory_block_manager.h" #include "core/hle/kernel/k_memory_block_manager.h"
#include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_memory_manager.h" #include "core/hle/kernel/k_memory_manager.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/result.h" #include "core/hle/result.h"
#include "core/memory.h" #include "core/memory.h"
@ -65,45 +65,47 @@ public:
Result InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, Result InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr,
bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool,
VAddr code_addr, size_t code_size, KSystemResource* system_resource, KProcessAddress code_addr, size_t code_size,
KResourceLimit* resource_limit); KSystemResource* system_resource, KResourceLimit* resource_limit);
void Finalize(); void Finalize();
Result MapProcessCode(VAddr addr, size_t pages_count, KMemoryState state, Result MapProcessCode(KProcessAddress addr, size_t pages_count, KMemoryState state,
KMemoryPermission perm); KMemoryPermission perm);
Result MapCodeMemory(VAddr dst_address, VAddr src_address, size_t size); Result MapCodeMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size);
Result UnmapCodeMemory(VAddr dst_address, VAddr src_address, size_t size, Result UnmapCodeMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size,
ICacheInvalidationStrategy icache_invalidation_strategy); ICacheInvalidationStrategy icache_invalidation_strategy);
Result UnmapProcessMemory(VAddr dst_addr, size_t size, KPageTable& src_page_table, Result UnmapProcessMemory(KProcessAddress dst_addr, size_t size, KPageTable& src_page_table,
VAddr src_addr); KProcessAddress src_addr);
Result MapPhysicalMemory(VAddr addr, size_t size); Result MapPhysicalMemory(KProcessAddress addr, size_t size);
Result UnmapPhysicalMemory(VAddr addr, size_t size); Result UnmapPhysicalMemory(KProcessAddress addr, size_t size);
Result MapMemory(VAddr dst_addr, VAddr src_addr, size_t size); Result MapMemory(KProcessAddress dst_addr, KProcessAddress src_addr, size_t size);
Result UnmapMemory(VAddr dst_addr, VAddr src_addr, size_t size); Result UnmapMemory(KProcessAddress dst_addr, KProcessAddress src_addr, size_t size);
Result SetProcessMemoryPermission(VAddr addr, size_t size, Svc::MemoryPermission svc_perm); Result SetProcessMemoryPermission(KProcessAddress addr, size_t size,
KMemoryInfo QueryInfo(VAddr addr); Svc::MemoryPermission svc_perm);
Result SetMemoryPermission(VAddr addr, size_t size, Svc::MemoryPermission perm); KMemoryInfo QueryInfo(KProcessAddress addr);
Result SetMemoryAttribute(VAddr addr, size_t size, u32 mask, u32 attr); Result SetMemoryPermission(KProcessAddress addr, size_t size, Svc::MemoryPermission perm);
Result SetMemoryAttribute(KProcessAddress addr, size_t size, u32 mask, u32 attr);
Result SetMaxHeapSize(size_t size); Result SetMaxHeapSize(size_t size);
Result SetHeapSize(VAddr* out, size_t size); Result SetHeapSize(u64* out, size_t size);
Result LockForMapDeviceAddressSpace(bool* out_is_io, VAddr address, size_t size, Result LockForMapDeviceAddressSpace(bool* out_is_io, KProcessAddress address, size_t size,
KMemoryPermission perm, bool is_aligned, bool check_heap); KMemoryPermission perm, bool is_aligned, bool check_heap);
Result LockForUnmapDeviceAddressSpace(VAddr address, size_t size, bool check_heap); Result LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size, bool check_heap);
Result UnlockForDeviceAddressSpace(VAddr addr, size_t size); Result UnlockForDeviceAddressSpace(KProcessAddress addr, size_t size);
Result LockForIpcUserBuffer(PAddr* out, VAddr address, size_t size); Result LockForIpcUserBuffer(KPhysicalAddress* out, KProcessAddress address, size_t size);
Result UnlockForIpcUserBuffer(VAddr address, size_t size); Result UnlockForIpcUserBuffer(KProcessAddress address, size_t size);
Result SetupForIpc(VAddr* out_dst_addr, size_t size, VAddr src_addr, KPageTable& src_page_table, Result SetupForIpc(KProcessAddress* out_dst_addr, size_t size, KProcessAddress src_addr,
KMemoryPermission test_perm, KMemoryState dst_state, bool send); KPageTable& src_page_table, KMemoryPermission test_perm,
Result CleanupForIpcServer(VAddr address, size_t size, KMemoryState dst_state); KMemoryState dst_state, bool send);
Result CleanupForIpcClient(VAddr address, size_t size, KMemoryState dst_state); Result CleanupForIpcServer(KProcessAddress address, size_t size, KMemoryState dst_state);
Result CleanupForIpcClient(KProcessAddress address, size_t size, KMemoryState dst_state);
Result LockForCodeMemory(KPageGroup* out, VAddr addr, size_t size); Result LockForCodeMemory(KPageGroup* out, KProcessAddress addr, size_t size);
Result UnlockForCodeMemory(VAddr addr, size_t size, const KPageGroup& pg); Result UnlockForCodeMemory(KProcessAddress addr, size_t size, const KPageGroup& pg);
Result MakeAndOpenPageGroup(KPageGroup* out, VAddr address, size_t num_pages, Result MakeAndOpenPageGroup(KPageGroup* out, KProcessAddress address, size_t num_pages,
KMemoryState state_mask, KMemoryState state, KMemoryState state_mask, KMemoryState state,
KMemoryPermission perm_mask, KMemoryPermission perm, KMemoryPermission perm_mask, KMemoryPermission perm,
KMemoryAttribute attr_mask, KMemoryAttribute attr); KMemoryAttribute attr_mask, KMemoryAttribute attr);
@ -120,7 +122,7 @@ public:
return m_block_info_manager; return m_block_info_manager;
} }
bool CanContain(VAddr addr, size_t size, KMemoryState state) const; bool CanContain(KProcessAddress addr, size_t size, KMemoryState state) const;
Result MapPages(KProcessAddress* out_addr, size_t num_pages, size_t alignment, Result MapPages(KProcessAddress* out_addr, size_t num_pages, size_t alignment,
KPhysicalAddress phys_addr, KProcessAddress region_start, KPhysicalAddress phys_addr, KProcessAddress region_start,
@ -173,8 +175,8 @@ protected:
m_root = n; m_root = n;
} }
void Push(Core::Memory::Memory& memory, VAddr addr) { void Push(Core::Memory::Memory& memory, KVirtualAddress addr) {
this->Push(memory.GetPointer<Node>(addr)); this->Push(memory.GetPointer<Node>(GetInteger(addr)));
} }
Node* Peek() const { Node* Peek() const {
@ -212,27 +214,28 @@ private:
Result MapPages(KProcessAddress* out_addr, size_t num_pages, size_t alignment, Result MapPages(KProcessAddress* out_addr, size_t num_pages, size_t alignment,
KPhysicalAddress phys_addr, bool is_pa_valid, KProcessAddress region_start, KPhysicalAddress phys_addr, bool is_pa_valid, KProcessAddress region_start,
size_t region_num_pages, KMemoryState state, KMemoryPermission perm); size_t region_num_pages, KMemoryState state, KMemoryPermission perm);
bool IsRegionContiguous(VAddr addr, u64 size) const; bool IsRegionContiguous(KProcessAddress addr, u64 size) const;
void AddRegionToPages(VAddr start, size_t num_pages, KPageGroup& page_linked_list); void AddRegionToPages(KProcessAddress start, size_t num_pages, KPageGroup& page_linked_list);
KMemoryInfo QueryInfoImpl(VAddr addr); KMemoryInfo QueryInfoImpl(KProcessAddress addr);
VAddr AllocateVirtualMemory(VAddr start, size_t region_num_pages, u64 needed_num_pages, KProcessAddress AllocateVirtualMemory(KProcessAddress start, size_t region_num_pages,
size_t align); u64 needed_num_pages, size_t align);
Result Operate(VAddr addr, size_t num_pages, const KPageGroup& page_group, Result Operate(KProcessAddress addr, size_t num_pages, const KPageGroup& page_group,
OperationType operation); OperationType operation);
Result Operate(VAddr addr, size_t num_pages, KMemoryPermission perm, OperationType operation, Result Operate(KProcessAddress addr, size_t num_pages, KMemoryPermission perm,
PAddr map_addr = 0); OperationType operation, KPhysicalAddress map_addr = 0);
void FinalizeUpdate(PageLinkedList* page_list); void FinalizeUpdate(PageLinkedList* page_list);
VAddr GetRegionAddress(KMemoryState state) const; KProcessAddress GetRegionAddress(KMemoryState state) const;
size_t GetRegionSize(KMemoryState state) const; size_t GetRegionSize(KMemoryState state) const;
VAddr FindFreeArea(VAddr region_start, size_t region_num_pages, size_t num_pages, KProcessAddress FindFreeArea(KProcessAddress region_start, size_t region_num_pages,
size_t alignment, size_t offset, size_t guard_pages); size_t num_pages, size_t alignment, size_t offset,
size_t guard_pages);
Result CheckMemoryStateContiguous(size_t* out_blocks_needed, VAddr addr, size_t size, Result CheckMemoryStateContiguous(size_t* out_blocks_needed, KProcessAddress addr, size_t size,
KMemoryState state_mask, KMemoryState state, KMemoryState state_mask, KMemoryState state,
KMemoryPermission perm_mask, KMemoryPermission perm, KMemoryPermission perm_mask, KMemoryPermission perm,
KMemoryAttribute attr_mask, KMemoryAttribute attr) const; KMemoryAttribute attr_mask, KMemoryAttribute attr) const;
Result CheckMemoryStateContiguous(VAddr addr, size_t size, KMemoryState state_mask, Result CheckMemoryStateContiguous(KProcessAddress addr, size_t size, KMemoryState state_mask,
KMemoryState state, KMemoryPermission perm_mask, KMemoryState state, KMemoryPermission perm_mask,
KMemoryPermission perm, KMemoryAttribute attr_mask, KMemoryPermission perm, KMemoryAttribute attr_mask,
KMemoryAttribute attr) const { KMemoryAttribute attr) const {
@ -244,12 +247,12 @@ private:
KMemoryPermission perm_mask, KMemoryPermission perm, KMemoryPermission perm_mask, KMemoryPermission perm,
KMemoryAttribute attr_mask, KMemoryAttribute attr) const; KMemoryAttribute attr_mask, KMemoryAttribute attr) const;
Result CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm, Result CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm,
KMemoryAttribute* out_attr, size_t* out_blocks_needed, VAddr addr, KMemoryAttribute* out_attr, size_t* out_blocks_needed,
size_t size, KMemoryState state_mask, KMemoryState state, KProcessAddress addr, size_t size, KMemoryState state_mask,
KMemoryPermission perm_mask, KMemoryPermission perm, KMemoryState state, KMemoryPermission perm_mask, KMemoryPermission perm,
KMemoryAttribute attr_mask, KMemoryAttribute attr, KMemoryAttribute attr_mask, KMemoryAttribute attr,
KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) const; KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) const;
Result CheckMemoryState(size_t* out_blocks_needed, VAddr addr, size_t size, Result CheckMemoryState(size_t* out_blocks_needed, KProcessAddress addr, size_t size,
KMemoryState state_mask, KMemoryState state, KMemoryState state_mask, KMemoryState state,
KMemoryPermission perm_mask, KMemoryPermission perm, KMemoryPermission perm_mask, KMemoryPermission perm,
KMemoryAttribute attr_mask, KMemoryAttribute attr, KMemoryAttribute attr_mask, KMemoryAttribute attr,
@ -258,39 +261,40 @@ private:
state_mask, state, perm_mask, perm, attr_mask, attr, state_mask, state, perm_mask, perm, attr_mask, attr,
ignore_attr)); ignore_attr));
} }
Result CheckMemoryState(VAddr addr, size_t size, KMemoryState state_mask, KMemoryState state, Result CheckMemoryState(KProcessAddress addr, size_t size, KMemoryState state_mask,
KMemoryPermission perm_mask, KMemoryPermission perm, KMemoryState state, KMemoryPermission perm_mask, KMemoryPermission perm,
KMemoryAttribute attr_mask, KMemoryAttribute attr, KMemoryAttribute attr_mask, KMemoryAttribute attr,
KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) const { KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) const {
R_RETURN(this->CheckMemoryState(nullptr, addr, size, state_mask, state, perm_mask, perm, R_RETURN(this->CheckMemoryState(nullptr, addr, size, state_mask, state, perm_mask, perm,
attr_mask, attr, ignore_attr)); attr_mask, attr, ignore_attr));
} }
Result LockMemoryAndOpen(KPageGroup* out_pg, PAddr* out_paddr, VAddr addr, size_t size, Result LockMemoryAndOpen(KPageGroup* out_pg, KPhysicalAddress* out_KPhysicalAddress,
KMemoryState state_mask, KMemoryState state, KProcessAddress addr, size_t size, KMemoryState state_mask,
KMemoryPermission perm_mask, KMemoryPermission perm, KMemoryState state, KMemoryPermission perm_mask,
KMemoryAttribute attr_mask, KMemoryAttribute attr, KMemoryPermission perm, KMemoryAttribute attr_mask,
KMemoryPermission new_perm, KMemoryAttribute lock_attr); KMemoryAttribute attr, KMemoryPermission new_perm,
Result UnlockMemory(VAddr addr, size_t size, KMemoryState state_mask, KMemoryState state, KMemoryAttribute lock_attr);
KMemoryPermission perm_mask, KMemoryPermission perm, Result UnlockMemory(KProcessAddress addr, size_t size, KMemoryState state_mask,
KMemoryState state, KMemoryPermission perm_mask, KMemoryPermission perm,
KMemoryAttribute attr_mask, KMemoryAttribute attr, KMemoryAttribute attr_mask, KMemoryAttribute attr,
KMemoryPermission new_perm, KMemoryAttribute lock_attr, KMemoryPermission new_perm, KMemoryAttribute lock_attr,
const KPageGroup* pg); const KPageGroup* pg);
Result MakePageGroup(KPageGroup& pg, VAddr addr, size_t num_pages); Result MakePageGroup(KPageGroup& pg, KProcessAddress addr, size_t num_pages);
bool IsValidPageGroup(const KPageGroup& pg, VAddr addr, size_t num_pages); bool IsValidPageGroup(const KPageGroup& pg, KProcessAddress addr, size_t num_pages);
bool IsLockedByCurrentThread() const { bool IsLockedByCurrentThread() const {
return m_general_lock.IsLockedByCurrentThread(); return m_general_lock.IsLockedByCurrentThread();
} }
bool IsHeapPhysicalAddress(const KMemoryLayout& layout, PAddr phys_addr) { bool IsHeapPhysicalAddress(const KMemoryLayout& layout, KPhysicalAddress phys_addr) {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
return layout.IsHeapPhysicalAddress(m_cached_physical_heap_region, phys_addr); return layout.IsHeapPhysicalAddress(m_cached_physical_heap_region, phys_addr);
} }
bool GetPhysicalAddressLocked(PAddr* out, VAddr virt_addr) const { bool GetPhysicalAddressLocked(KPhysicalAddress* out, KProcessAddress virt_addr) const {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
*out = GetPhysicalAddr(virt_addr); *out = GetPhysicalAddr(virt_addr);
@ -298,12 +302,13 @@ private:
return *out != 0; return *out != 0;
} }
Result SetupForIpcClient(PageLinkedList* page_list, size_t* out_blocks_needed, VAddr address, Result SetupForIpcClient(PageLinkedList* page_list, size_t* out_blocks_needed,
size_t size, KMemoryPermission test_perm, KMemoryState dst_state); KProcessAddress address, size_t size, KMemoryPermission test_perm,
Result SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_addr, KMemoryState dst_state);
Result SetupForIpcServer(KProcessAddress* out_addr, size_t size, KProcessAddress src_addr,
KMemoryPermission test_perm, KMemoryState dst_state, KMemoryPermission test_perm, KMemoryState dst_state,
KPageTable& src_page_table, bool send); KPageTable& src_page_table, bool send);
void CleanupForIpcClientOnServerSetupFailure(PageLinkedList* page_list, VAddr address, void CleanupForIpcClientOnServerSetupFailure(PageLinkedList* page_list, KProcessAddress address,
size_t size, KMemoryPermission prot_perm); size_t size, KMemoryPermission prot_perm);
Result AllocateAndMapPagesImpl(PageLinkedList* page_list, KProcessAddress address, Result AllocateAndMapPagesImpl(PageLinkedList* page_list, KProcessAddress address,
@ -315,61 +320,61 @@ private:
mutable KLightLock m_map_physical_memory_lock; mutable KLightLock m_map_physical_memory_lock;
public: public:
constexpr VAddr GetAddressSpaceStart() const { constexpr KProcessAddress GetAddressSpaceStart() const {
return m_address_space_start; return m_address_space_start;
} }
constexpr VAddr GetAddressSpaceEnd() const { constexpr KProcessAddress GetAddressSpaceEnd() const {
return m_address_space_end; return m_address_space_end;
} }
constexpr size_t GetAddressSpaceSize() const { constexpr size_t GetAddressSpaceSize() const {
return m_address_space_end - m_address_space_start; return m_address_space_end - m_address_space_start;
} }
constexpr VAddr GetHeapRegionStart() const { constexpr KProcessAddress GetHeapRegionStart() const {
return m_heap_region_start; return m_heap_region_start;
} }
constexpr VAddr GetHeapRegionEnd() const { constexpr KProcessAddress GetHeapRegionEnd() const {
return m_heap_region_end; return m_heap_region_end;
} }
constexpr size_t GetHeapRegionSize() const { constexpr size_t GetHeapRegionSize() const {
return m_heap_region_end - m_heap_region_start; return m_heap_region_end - m_heap_region_start;
} }
constexpr VAddr GetAliasRegionStart() const { constexpr KProcessAddress GetAliasRegionStart() const {
return m_alias_region_start; return m_alias_region_start;
} }
constexpr VAddr GetAliasRegionEnd() const { constexpr KProcessAddress GetAliasRegionEnd() const {
return m_alias_region_end; return m_alias_region_end;
} }
constexpr size_t GetAliasRegionSize() const { constexpr size_t GetAliasRegionSize() const {
return m_alias_region_end - m_alias_region_start; return m_alias_region_end - m_alias_region_start;
} }
constexpr VAddr GetStackRegionStart() const { constexpr KProcessAddress GetStackRegionStart() const {
return m_stack_region_start; return m_stack_region_start;
} }
constexpr VAddr GetStackRegionEnd() const { constexpr KProcessAddress GetStackRegionEnd() const {
return m_stack_region_end; return m_stack_region_end;
} }
constexpr size_t GetStackRegionSize() const { constexpr size_t GetStackRegionSize() const {
return m_stack_region_end - m_stack_region_start; return m_stack_region_end - m_stack_region_start;
} }
constexpr VAddr GetKernelMapRegionStart() const { constexpr KProcessAddress GetKernelMapRegionStart() const {
return m_kernel_map_region_start; return m_kernel_map_region_start;
} }
constexpr VAddr GetKernelMapRegionEnd() const { constexpr KProcessAddress GetKernelMapRegionEnd() const {
return m_kernel_map_region_end; return m_kernel_map_region_end;
} }
constexpr VAddr GetCodeRegionStart() const { constexpr KProcessAddress GetCodeRegionStart() const {
return m_code_region_start; return m_code_region_start;
} }
constexpr VAddr GetCodeRegionEnd() const { constexpr KProcessAddress GetCodeRegionEnd() const {
return m_code_region_end; return m_code_region_end;
} }
constexpr VAddr GetAliasCodeRegionStart() const { constexpr KProcessAddress GetAliasCodeRegionStart() const {
return m_alias_code_region_start; return m_alias_code_region_start;
} }
constexpr VAddr GetAliasCodeRegionEnd() const { constexpr KProcessAddress GetAliasCodeRegionEnd() const {
return m_alias_code_region_end; return m_alias_code_region_end;
} }
constexpr VAddr GetAliasCodeRegionSize() const { constexpr size_t GetAliasCodeRegionSize() const {
return m_alias_code_region_end - m_alias_code_region_start; return m_alias_code_region_end - m_alias_code_region_start;
} }
size_t GetNormalMemorySize() { size_t GetNormalMemorySize() {
@ -382,25 +387,25 @@ public:
constexpr size_t GetHeapSize() const { constexpr size_t GetHeapSize() const {
return m_current_heap_end - m_heap_region_start; return m_current_heap_end - m_heap_region_start;
} }
constexpr bool IsInsideAddressSpace(VAddr address, size_t size) const { constexpr bool IsInsideAddressSpace(KProcessAddress address, size_t size) const {
return m_address_space_start <= address && address + size - 1 <= m_address_space_end - 1; return m_address_space_start <= address && address + size - 1 <= m_address_space_end - 1;
} }
constexpr bool IsOutsideAliasRegion(VAddr address, size_t size) const { constexpr bool IsOutsideAliasRegion(KProcessAddress address, size_t size) const {
return m_alias_region_start > address || address + size - 1 > m_alias_region_end - 1; return m_alias_region_start > address || address + size - 1 > m_alias_region_end - 1;
} }
constexpr bool IsOutsideStackRegion(VAddr address, size_t size) const { constexpr bool IsOutsideStackRegion(KProcessAddress address, size_t size) const {
return m_stack_region_start > address || address + size - 1 > m_stack_region_end - 1; return m_stack_region_start > address || address + size - 1 > m_stack_region_end - 1;
} }
constexpr bool IsInvalidRegion(VAddr address, size_t size) const { constexpr bool IsInvalidRegion(KProcessAddress address, size_t size) const {
return address + size - 1 > GetAliasCodeRegionStart() + GetAliasCodeRegionSize() - 1; return address + size - 1 > GetAliasCodeRegionStart() + GetAliasCodeRegionSize() - 1;
} }
constexpr bool IsInsideHeapRegion(VAddr address, size_t size) const { constexpr bool IsInsideHeapRegion(KProcessAddress address, size_t size) const {
return address + size > m_heap_region_start && m_heap_region_end > address; return address + size > m_heap_region_start && m_heap_region_end > address;
} }
constexpr bool IsInsideAliasRegion(VAddr address, size_t size) const { constexpr bool IsInsideAliasRegion(KProcessAddress address, size_t size) const {
return address + size > m_alias_region_start && m_alias_region_end > address; return address + size > m_alias_region_start && m_alias_region_end > address;
} }
constexpr bool IsOutsideASLRRegion(VAddr address, size_t size) const { constexpr bool IsOutsideASLRRegion(KProcessAddress address, size_t size) const {
if (IsInvalidRegion(address, size)) { if (IsInvalidRegion(address, size)) {
return true; return true;
} }
@ -412,47 +417,53 @@ public:
} }
return {}; return {};
} }
constexpr bool IsInsideASLRRegion(VAddr address, size_t size) const { constexpr bool IsInsideASLRRegion(KProcessAddress address, size_t size) const {
return !IsOutsideASLRRegion(address, size); return !IsOutsideASLRRegion(address, size);
} }
constexpr size_t GetNumGuardPages() const { constexpr size_t GetNumGuardPages() const {
return IsKernel() ? 1 : 4; return IsKernel() ? 1 : 4;
} }
PAddr GetPhysicalAddr(VAddr addr) const { KPhysicalAddress GetPhysicalAddr(KProcessAddress addr) const {
const auto backing_addr = m_page_table_impl->backing_addr[addr >> PageBits]; const auto backing_addr = m_page_table_impl->backing_addr[addr >> PageBits];
ASSERT(backing_addr); ASSERT(backing_addr);
return backing_addr + addr; return backing_addr + GetInteger(addr);
} }
constexpr bool Contains(VAddr addr) const { constexpr bool Contains(KProcessAddress addr) const {
return m_address_space_start <= addr && addr <= m_address_space_end - 1; return m_address_space_start <= addr && addr <= m_address_space_end - 1;
} }
constexpr bool Contains(VAddr addr, size_t size) const { constexpr bool Contains(KProcessAddress addr, size_t size) const {
return m_address_space_start <= addr && addr < addr + size && return m_address_space_start <= addr && addr < addr + size &&
addr + size - 1 <= m_address_space_end - 1; addr + size - 1 <= m_address_space_end - 1;
} }
public: public:
static VAddr GetLinearMappedVirtualAddress(const KMemoryLayout& layout, PAddr addr) { static KVirtualAddress GetLinearMappedVirtualAddress(const KMemoryLayout& layout,
KPhysicalAddress addr) {
return layout.GetLinearVirtualAddress(addr); return layout.GetLinearVirtualAddress(addr);
} }
static PAddr GetLinearMappedPhysicalAddress(const KMemoryLayout& layout, VAddr addr) { static KPhysicalAddress GetLinearMappedPhysicalAddress(const KMemoryLayout& layout,
KVirtualAddress addr) {
return layout.GetLinearPhysicalAddress(addr); return layout.GetLinearPhysicalAddress(addr);
} }
static VAddr GetHeapVirtualAddress(const KMemoryLayout& layout, PAddr addr) { static KVirtualAddress GetHeapVirtualAddress(const KMemoryLayout& layout,
KPhysicalAddress addr) {
return GetLinearMappedVirtualAddress(layout, addr); return GetLinearMappedVirtualAddress(layout, addr);
} }
static PAddr GetHeapPhysicalAddress(const KMemoryLayout& layout, VAddr addr) { static KPhysicalAddress GetHeapPhysicalAddress(const KMemoryLayout& layout,
KVirtualAddress addr) {
return GetLinearMappedPhysicalAddress(layout, addr); return GetLinearMappedPhysicalAddress(layout, addr);
} }
static VAddr GetPageTableVirtualAddress(const KMemoryLayout& layout, PAddr addr) { static KVirtualAddress GetPageTableVirtualAddress(const KMemoryLayout& layout,
KPhysicalAddress addr) {
return GetLinearMappedVirtualAddress(layout, addr); return GetLinearMappedVirtualAddress(layout, addr);
} }
static PAddr GetPageTablePhysicalAddress(const KMemoryLayout& layout, VAddr addr) { static KPhysicalAddress GetPageTablePhysicalAddress(const KMemoryLayout& layout,
KVirtualAddress addr) {
return GetLinearMappedPhysicalAddress(layout, addr); return GetLinearMappedPhysicalAddress(layout, addr);
} }
@ -464,7 +475,7 @@ private:
return m_enable_aslr; return m_enable_aslr;
} }
constexpr bool ContainsPages(VAddr addr, size_t num_pages) const { constexpr bool ContainsPages(KProcessAddress addr, size_t num_pages) const {
return (m_address_space_start <= addr) && return (m_address_space_start <= addr) &&
(num_pages <= (m_address_space_end - m_address_space_start) / PageSize) && (num_pages <= (m_address_space_end - m_address_space_start) / PageSize) &&
(addr + num_pages * PageSize - 1 <= m_address_space_end - 1); (addr + num_pages * PageSize - 1 <= m_address_space_end - 1);
@ -489,21 +500,21 @@ private:
}; };
private: private:
VAddr m_address_space_start{}; KProcessAddress m_address_space_start{};
VAddr m_address_space_end{}; KProcessAddress m_address_space_end{};
VAddr m_heap_region_start{}; KProcessAddress m_heap_region_start{};
VAddr m_heap_region_end{}; KProcessAddress m_heap_region_end{};
VAddr m_current_heap_end{}; KProcessAddress m_current_heap_end{};
VAddr m_alias_region_start{}; KProcessAddress m_alias_region_start{};
VAddr m_alias_region_end{}; KProcessAddress m_alias_region_end{};
VAddr m_stack_region_start{}; KProcessAddress m_stack_region_start{};
VAddr m_stack_region_end{}; KProcessAddress m_stack_region_end{};
VAddr m_kernel_map_region_start{}; KProcessAddress m_kernel_map_region_start{};
VAddr m_kernel_map_region_end{}; KProcessAddress m_kernel_map_region_end{};
VAddr m_code_region_start{}; KProcessAddress m_code_region_start{};
VAddr m_code_region_end{}; KProcessAddress m_code_region_end{};
VAddr m_alias_code_region_start{}; KProcessAddress m_alias_code_region_start{};
VAddr m_alias_code_region_end{}; KProcessAddress m_alias_code_region_end{};
size_t m_max_heap_size{}; size_t m_max_heap_size{};
size_t m_mapped_physical_memory_size{}; size_t m_mapped_physical_memory_size{};

@ -5,9 +5,9 @@
#include <atomic> #include <atomic>
#include "common/common_types.h"
#include "core/hle/kernel/k_dynamic_resource_manager.h" #include "core/hle/kernel/k_dynamic_resource_manager.h"
#include "core/hle/kernel/k_page_table_slab_heap.h" #include "core/hle/kernel/k_page_table_slab_heap.h"
#include "core/hle/kernel/k_typed_address.h"
namespace Kernel { namespace Kernel {
@ -26,23 +26,23 @@ public:
BaseHeap::Initialize(page_allocator, pt_heap); BaseHeap::Initialize(page_allocator, pt_heap);
} }
VAddr Allocate() { KVirtualAddress Allocate() {
return VAddr(BaseHeap::Allocate()); return KVirtualAddress(BaseHeap::Allocate());
} }
RefCount GetRefCount(VAddr addr) const { RefCount GetRefCount(KVirtualAddress addr) const {
return m_pt_heap->GetRefCount(addr); return m_pt_heap->GetRefCount(addr);
} }
void Open(VAddr addr, int count) { void Open(KVirtualAddress addr, int count) {
return m_pt_heap->Open(addr, count); return m_pt_heap->Open(addr, count);
} }
bool Close(VAddr addr, int count) { bool Close(KVirtualAddress addr, int count) {
return m_pt_heap->Close(addr, count); return m_pt_heap->Close(addr, count);
} }
bool IsInPageTableHeap(VAddr addr) const { bool IsInPageTableHeap(KVirtualAddress addr) const {
return m_pt_heap->IsInRange(addr); return m_pt_heap->IsInRange(addr);
} }

@ -6,8 +6,8 @@
#include <array> #include <array>
#include <vector> #include <vector>
#include "common/common_types.h"
#include "core/hle/kernel/k_dynamic_slab_heap.h" #include "core/hle/kernel/k_dynamic_slab_heap.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/slab_helpers.h" #include "core/hle/kernel/slab_helpers.h"
namespace Kernel { namespace Kernel {
@ -45,12 +45,12 @@ public:
this->Initialize(rc); this->Initialize(rc);
} }
RefCount GetRefCount(VAddr addr) { RefCount GetRefCount(KVirtualAddress addr) {
ASSERT(this->IsInRange(addr)); ASSERT(this->IsInRange(addr));
return *this->GetRefCountPointer(addr); return *this->GetRefCountPointer(addr);
} }
void Open(VAddr addr, int count) { void Open(KVirtualAddress addr, int count) {
ASSERT(this->IsInRange(addr)); ASSERT(this->IsInRange(addr));
*this->GetRefCountPointer(addr) += static_cast<RefCount>(count); *this->GetRefCountPointer(addr) += static_cast<RefCount>(count);
@ -58,7 +58,7 @@ public:
ASSERT(this->GetRefCount(addr) > 0); ASSERT(this->GetRefCount(addr) > 0);
} }
bool Close(VAddr addr, int count) { bool Close(KVirtualAddress addr, int count) {
ASSERT(this->IsInRange(addr)); ASSERT(this->IsInRange(addr));
ASSERT(this->GetRefCount(addr) >= count); ASSERT(this->GetRefCount(addr) >= count);
@ -66,7 +66,7 @@ public:
return this->GetRefCount(addr) == 0; return this->GetRefCount(addr) == 0;
} }
bool IsInPageTableHeap(VAddr addr) const { bool IsInPageTableHeap(KVirtualAddress addr) const {
return this->IsInRange(addr); return this->IsInRange(addr);
} }
@ -81,7 +81,7 @@ private:
} }
} }
RefCount* GetRefCountPointer(VAddr addr) { RefCount* GetRefCountPointer(KVirtualAddress addr) {
return m_ref_counts.data() + ((addr - this->GetAddress()) / PageSize); return m_ref_counts.data() + ((addr - this->GetAddress()) / PageSize);
} }

@ -36,8 +36,9 @@ namespace {
* @param owner_process The parent process for the main thread * @param owner_process The parent process for the main thread
* @param priority The priority to give the main thread * @param priority The priority to give the main thread
*/ */
void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, VAddr stack_top) { void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority,
const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart(); KProcessAddress stack_top) {
const KProcessAddress entry_point = owner_process.PageTable().GetCodeRegionStart();
ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1)); ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1));
KThread* thread = KThread::Create(system.Kernel()); KThread* thread = KThread::Create(system.Kernel());
@ -219,7 +220,7 @@ void KProcess::UnpinThread(KThread* thread) {
KScheduler::SetSchedulerUpdateNeeded(m_kernel); KScheduler::SetSchedulerUpdateNeeded(m_kernel);
} }
Result KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr address, Result KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] KProcessAddress address,
[[maybe_unused]] size_t size) { [[maybe_unused]] size_t size) {
// Lock ourselves, to prevent concurrent access. // Lock ourselves, to prevent concurrent access.
KScopedLightLock lk(m_state_lock); KScopedLightLock lk(m_state_lock);
@ -248,7 +249,7 @@ Result KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr ad
R_SUCCEED(); R_SUCCEED();
} }
void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr address, void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] KProcessAddress address,
[[maybe_unused]] size_t size) { [[maybe_unused]] size_t size) {
// Lock ourselves, to prevent concurrent access. // Lock ourselves, to prevent concurrent access.
KScopedLightLock lk(m_state_lock); KScopedLightLock lk(m_state_lock);
@ -399,8 +400,8 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
case FileSys::ProgramAddressSpaceType::Is32BitNoMap: case FileSys::ProgramAddressSpaceType::Is32BitNoMap:
m_memory_usage_capacity = m_memory_usage_capacity =
m_page_table.GetHeapRegionEnd() - m_page_table.GetHeapRegionStart() + (m_page_table.GetHeapRegionEnd() - m_page_table.GetHeapRegionStart()) +
m_page_table.GetAliasRegionEnd() - m_page_table.GetAliasRegionStart(); (m_page_table.GetAliasRegionEnd() - m_page_table.GetAliasRegionStart());
break; break;
default: default:
@ -492,9 +493,9 @@ void KProcess::Finalize() {
KSynchronizationObject::Finalize(); KSynchronizationObject::Finalize();
} }
Result KProcess::CreateThreadLocalRegion(VAddr* out) { Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) {
KThreadLocalPage* tlp = nullptr; KThreadLocalPage* tlp = nullptr;
VAddr tlr = 0; KProcessAddress tlr = 0;
// See if we can get a region from a partially used TLP. // See if we can get a region from a partially used TLP.
{ {
@ -543,7 +544,7 @@ Result KProcess::CreateThreadLocalRegion(VAddr* out) {
R_SUCCEED(); R_SUCCEED();
} }
Result KProcess::DeleteThreadLocalRegion(VAddr addr) { Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) {
KThreadLocalPage* page_to_free = nullptr; KThreadLocalPage* page_to_free = nullptr;
// Release the region. // Release the region.
@ -551,10 +552,10 @@ Result KProcess::DeleteThreadLocalRegion(VAddr addr) {
KScopedSchedulerLock sl{m_kernel}; KScopedSchedulerLock sl{m_kernel};
// Try to find the page in the partially used list. // Try to find the page in the partially used list.
auto it = m_partially_used_tlp_tree.find_key(Common::AlignDown(addr, PageSize)); auto it = m_partially_used_tlp_tree.find_key(Common::AlignDown(GetInteger(addr), PageSize));
if (it == m_partially_used_tlp_tree.end()) { if (it == m_partially_used_tlp_tree.end()) {
// If we don't find it, it has to be in the fully used list. // If we don't find it, it has to be in the fully used list.
it = m_fully_used_tlp_tree.find_key(Common::AlignDown(addr, PageSize)); it = m_fully_used_tlp_tree.find_key(Common::AlignDown(GetInteger(addr), PageSize));
R_UNLESS(it != m_fully_used_tlp_tree.end(), ResultInvalidAddress); R_UNLESS(it != m_fully_used_tlp_tree.end(), ResultInvalidAddress);
// Release the region. // Release the region.
@ -591,7 +592,7 @@ Result KProcess::DeleteThreadLocalRegion(VAddr addr) {
R_SUCCEED(); R_SUCCEED();
} }
bool KProcess::InsertWatchpoint(Core::System& system, VAddr addr, u64 size, bool KProcess::InsertWatchpoint(Core::System& system, KProcessAddress addr, u64 size,
DebugWatchpointType type) { DebugWatchpointType type) {
const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) {
return wp.type == DebugWatchpointType::None; return wp.type == DebugWatchpointType::None;
@ -605,7 +606,8 @@ bool KProcess::InsertWatchpoint(Core::System& system, VAddr addr, u64 size,
watch->end_address = addr + size; watch->end_address = addr + size;
watch->type = type; watch->type = type;
for (VAddr page = Common::AlignDown(addr, PageSize); page < addr + size; page += PageSize) { for (KProcessAddress page = Common::AlignDown(GetInteger(addr), PageSize); page < addr + size;
page += PageSize) {
m_debug_page_refcounts[page]++; m_debug_page_refcounts[page]++;
system.Memory().MarkRegionDebug(page, PageSize, true); system.Memory().MarkRegionDebug(page, PageSize, true);
} }
@ -613,7 +615,7 @@ bool KProcess::InsertWatchpoint(Core::System& system, VAddr addr, u64 size,
return true; return true;
} }
bool KProcess::RemoveWatchpoint(Core::System& system, VAddr addr, u64 size, bool KProcess::RemoveWatchpoint(Core::System& system, KProcessAddress addr, u64 size,
DebugWatchpointType type) { DebugWatchpointType type) {
const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) {
return wp.start_address == addr && wp.end_address == addr + size && wp.type == type; return wp.start_address == addr && wp.end_address == addr + size && wp.type == type;
@ -627,7 +629,8 @@ bool KProcess::RemoveWatchpoint(Core::System& system, VAddr addr, u64 size,
watch->end_address = 0; watch->end_address = 0;
watch->type = DebugWatchpointType::None; watch->type = DebugWatchpointType::None;
for (VAddr page = Common::AlignDown(addr, PageSize); page < addr + size; page += PageSize) { for (KProcessAddress page = Common::AlignDown(GetInteger(addr), PageSize); page < addr + size;
page += PageSize) {
m_debug_page_refcounts[page]--; m_debug_page_refcounts[page]--;
if (!m_debug_page_refcounts[page]) { if (!m_debug_page_refcounts[page]) {
system.Memory().MarkRegionDebug(page, PageSize, false); system.Memory().MarkRegionDebug(page, PageSize, false);
@ -637,7 +640,7 @@ bool KProcess::RemoveWatchpoint(Core::System& system, VAddr addr, u64 size,
return true; return true;
} }
void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) {
const auto ReprotectSegment = [&](const CodeSet::Segment& segment, const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
Svc::MemoryPermission permission) { Svc::MemoryPermission permission) {
m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission); m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission);

@ -8,7 +8,6 @@
#include <list> #include <list>
#include <map> #include <map>
#include <string> #include <string>
#include "common/common_types.h"
#include "core/hle/kernel/k_address_arbiter.h" #include "core/hle/kernel/k_address_arbiter.h"
#include "core/hle/kernel/k_auto_object.h" #include "core/hle/kernel/k_auto_object.h"
#include "core/hle/kernel/k_condition_variable.h" #include "core/hle/kernel/k_condition_variable.h"
@ -16,6 +15,7 @@
#include "core/hle/kernel/k_page_table.h" #include "core/hle/kernel/k_page_table.h"
#include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/k_thread_local_page.h" #include "core/hle/kernel/k_thread_local_page.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/k_worker_task.h" #include "core/hle/kernel/k_worker_task.h"
#include "core/hle/kernel/process_capability.h" #include "core/hle/kernel/process_capability.h"
#include "core/hle/kernel/slab_helpers.h" #include "core/hle/kernel/slab_helpers.h"
@ -59,8 +59,8 @@ enum class DebugWatchpointType : u8 {
DECLARE_ENUM_FLAG_OPERATORS(DebugWatchpointType); DECLARE_ENUM_FLAG_OPERATORS(DebugWatchpointType);
struct DebugWatchpoint { struct DebugWatchpoint {
VAddr start_address; KProcessAddress start_address;
VAddr end_address; KProcessAddress end_address;
DebugWatchpointType type; DebugWatchpointType type;
}; };
@ -135,11 +135,11 @@ public:
return m_handle_table; return m_handle_table;
} }
Result SignalToAddress(VAddr address) { Result SignalToAddress(KProcessAddress address) {
return m_condition_var.SignalToAddress(address); return m_condition_var.SignalToAddress(address);
} }
Result WaitForAddress(Handle handle, VAddr address, u32 tag) { Result WaitForAddress(Handle handle, KProcessAddress address, u32 tag) {
return m_condition_var.WaitForAddress(handle, address, tag); return m_condition_var.WaitForAddress(handle, address, tag);
} }
@ -147,20 +147,21 @@ public:
return m_condition_var.Signal(cv_key, count); return m_condition_var.Signal(cv_key, count);
} }
Result WaitConditionVariable(VAddr address, u64 cv_key, u32 tag, s64 ns) { Result WaitConditionVariable(KProcessAddress address, u64 cv_key, u32 tag, s64 ns) {
R_RETURN(m_condition_var.Wait(address, cv_key, tag, ns)); R_RETURN(m_condition_var.Wait(address, cv_key, tag, ns));
} }
Result SignalAddressArbiter(VAddr address, Svc::SignalType signal_type, s32 value, s32 count) { Result SignalAddressArbiter(uint64_t address, Svc::SignalType signal_type, s32 value,
s32 count) {
R_RETURN(m_address_arbiter.SignalToAddress(address, signal_type, value, count)); R_RETURN(m_address_arbiter.SignalToAddress(address, signal_type, value, count));
} }
Result WaitAddressArbiter(VAddr address, Svc::ArbitrationType arb_type, s32 value, Result WaitAddressArbiter(uint64_t address, Svc::ArbitrationType arb_type, s32 value,
s64 timeout) { s64 timeout) {
R_RETURN(m_address_arbiter.WaitForAddress(address, arb_type, value, timeout)); R_RETURN(m_address_arbiter.WaitForAddress(address, arb_type, value, timeout));
} }
VAddr GetProcessLocalRegionAddress() const { KProcessAddress GetProcessLocalRegionAddress() const {
return m_plr_address; return m_plr_address;
} }
@ -352,7 +353,7 @@ public:
*/ */
void PrepareForTermination(); void PrepareForTermination();
void LoadModule(CodeSet code_set, VAddr base_addr); void LoadModule(CodeSet code_set, KProcessAddress base_addr);
bool IsInitialized() const override { bool IsInitialized() const override {
return m_is_initialized; return m_is_initialized;
@ -380,26 +381,28 @@ public:
return m_state_lock; return m_state_lock;
} }
Result AddSharedMemory(KSharedMemory* shmem, VAddr address, size_t size); Result AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size);
void RemoveSharedMemory(KSharedMemory* shmem, VAddr address, size_t size); void RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size);
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
// Thread-local storage management // Thread-local storage management
// Marks the next available region as used and returns the address of the slot. // Marks the next available region as used and returns the address of the slot.
[[nodiscard]] Result CreateThreadLocalRegion(VAddr* out); [[nodiscard]] Result CreateThreadLocalRegion(KProcessAddress* out);
// Frees a used TLS slot identified by the given address // Frees a used TLS slot identified by the given address
Result DeleteThreadLocalRegion(VAddr addr); Result DeleteThreadLocalRegion(KProcessAddress addr);
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
// Debug watchpoint management // Debug watchpoint management
// Attempts to insert a watchpoint into a free slot. Returns false if none are available. // Attempts to insert a watchpoint into a free slot. Returns false if none are available.
bool InsertWatchpoint(Core::System& system, VAddr addr, u64 size, DebugWatchpointType type); bool InsertWatchpoint(Core::System& system, KProcessAddress addr, u64 size,
DebugWatchpointType type);
// Attempts to remove the watchpoint specified by the given parameters. // Attempts to remove the watchpoint specified by the given parameters.
bool RemoveWatchpoint(Core::System& system, VAddr addr, u64 size, DebugWatchpointType type); bool RemoveWatchpoint(Core::System& system, KProcessAddress addr, u64 size,
DebugWatchpointType type);
const std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>& GetWatchpoints() const { const std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>& GetWatchpoints() const {
return m_watchpoints; return m_watchpoints;
@ -457,7 +460,7 @@ private:
/// Resource limit descriptor for this process /// Resource limit descriptor for this process
KResourceLimit* m_resource_limit{}; KResourceLimit* m_resource_limit{};
VAddr m_system_resource_address{}; KVirtualAddress m_system_resource_address{};
/// The ideal CPU core for this process, threads are scheduled on this core by default. /// The ideal CPU core for this process, threads are scheduled on this core by default.
u8 m_ideal_core = 0; u8 m_ideal_core = 0;
@ -485,7 +488,7 @@ private:
KConditionVariable m_condition_var; KConditionVariable m_condition_var;
/// Address indicating the location of the process' dedicated TLS region. /// Address indicating the location of the process' dedicated TLS region.
VAddr m_plr_address = 0; KProcessAddress m_plr_address = 0;
/// Random values for svcGetInfo RandomEntropy /// Random values for svcGetInfo RandomEntropy
std::array<u64, RANDOM_ENTROPY_SIZE> m_random_entropy{}; std::array<u64, RANDOM_ENTROPY_SIZE> m_random_entropy{};
@ -497,7 +500,7 @@ private:
std::list<KSharedMemoryInfo*> m_shared_memory_list; std::list<KSharedMemoryInfo*> m_shared_memory_list;
/// Address of the top of the main thread's stack /// Address of the top of the main thread's stack
VAddr m_main_thread_stack_top{}; KProcessAddress m_main_thread_stack_top{};
/// Size of the main thread's stack /// Size of the main thread's stack
std::size_t m_main_thread_stack_size{}; std::size_t m_main_thread_stack_size{};
@ -527,7 +530,7 @@ private:
std::array<u64, Core::Hardware::NUM_CPU_CORES> m_running_thread_idle_counts{}; std::array<u64, Core::Hardware::NUM_CPU_CORES> m_running_thread_idle_counts{};
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_pinned_threads{}; std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_pinned_threads{};
std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS> m_watchpoints{}; std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS> m_watchpoints{};
std::map<VAddr, u64> m_debug_page_refcounts; std::map<KProcessAddress, u64> m_debug_page_refcounts;
KThread* m_exception_thread{}; KThread* m_exception_thread{};

@ -511,7 +511,7 @@ void KScheduler::Reload(KThread* thread) {
auto& cpu_core = m_kernel.System().ArmInterface(m_core_id); auto& cpu_core = m_kernel.System().ArmInterface(m_core_id);
cpu_core.LoadContext(thread->GetContext32()); cpu_core.LoadContext(thread->GetContext32());
cpu_core.LoadContext(thread->GetContext64()); cpu_core.LoadContext(thread->GetContext64());
cpu_core.SetTlsAddress(thread->GetTlsAddress()); cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress()));
cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0()); cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0());
cpu_core.LoadWatchpointArray(thread->GetOwnerProcess()->GetWatchpoints()); cpu_core.LoadWatchpointArray(thread->GetOwnerProcess()->GetWatchpoints());
cpu_core.ClearExclusiveState(); cpu_core.ClearExclusiveState();

@ -6,8 +6,8 @@
namespace Kernel { namespace Kernel {
Result KSessionRequest::SessionMappings::PushMap(VAddr client, VAddr server, size_t size, Result KSessionRequest::SessionMappings::PushMap(KProcessAddress client, KProcessAddress server,
KMemoryState state, size_t index) { size_t size, KMemoryState state, size_t index) {
// At most 15 buffers of each type (4-bit descriptor counts). // At most 15 buffers of each type (4-bit descriptor counts).
ASSERT(index < ((1ul << 4) - 1) * 3); ASSERT(index < ((1ul << 4) - 1) * 3);
@ -33,20 +33,21 @@ Result KSessionRequest::SessionMappings::PushMap(VAddr client, VAddr server, siz
R_SUCCEED(); R_SUCCEED();
} }
Result KSessionRequest::SessionMappings::PushSend(VAddr client, VAddr server, size_t size, Result KSessionRequest::SessionMappings::PushSend(KProcessAddress client, KProcessAddress server,
KMemoryState state) { size_t size, KMemoryState state) {
ASSERT(m_num_recv == 0); ASSERT(m_num_recv == 0);
ASSERT(m_num_exch == 0); ASSERT(m_num_exch == 0);
R_RETURN(this->PushMap(client, server, size, state, m_num_send++)); R_RETURN(this->PushMap(client, server, size, state, m_num_send++));
} }
Result KSessionRequest::SessionMappings::PushReceive(VAddr client, VAddr server, size_t size, Result KSessionRequest::SessionMappings::PushReceive(KProcessAddress client, KProcessAddress server,
KMemoryState state) { size_t size, KMemoryState state) {
ASSERT(m_num_exch == 0); ASSERT(m_num_exch == 0);
R_RETURN(this->PushMap(client, server, size, state, m_num_send + m_num_recv++)); R_RETURN(this->PushMap(client, server, size, state, m_num_send + m_num_recv++));
} }
Result KSessionRequest::SessionMappings::PushExchange(VAddr client, VAddr server, size_t size, Result KSessionRequest::SessionMappings::PushExchange(KProcessAddress client,
KProcessAddress server, size_t size,
KMemoryState state) { KMemoryState state) {
R_RETURN(this->PushMap(client, server, size, state, m_num_send + m_num_recv + m_num_exch++)); R_RETURN(this->PushMap(client, server, size, state, m_num_send + m_num_recv + m_num_exch++));
} }

@ -26,17 +26,17 @@ public:
class Mapping { class Mapping {
public: public:
constexpr void Set(VAddr c, VAddr s, size_t sz, KMemoryState st) { constexpr void Set(KProcessAddress c, KProcessAddress s, size_t sz, KMemoryState st) {
m_client_address = c; m_client_address = c;
m_server_address = s; m_server_address = s;
m_size = sz; m_size = sz;
m_state = st; m_state = st;
} }
constexpr VAddr GetClientAddress() const { constexpr KProcessAddress GetClientAddress() const {
return m_client_address; return m_client_address;
} }
constexpr VAddr GetServerAddress() const { constexpr KProcessAddress GetServerAddress() const {
return m_server_address; return m_server_address;
} }
constexpr size_t GetSize() const { constexpr size_t GetSize() const {
@ -47,8 +47,8 @@ public:
} }
private: private:
VAddr m_client_address{}; KProcessAddress m_client_address{};
VAddr m_server_address{}; KProcessAddress m_server_address{};
size_t m_size{}; size_t m_size{};
KMemoryState m_state{}; KMemoryState m_state{};
}; };
@ -69,14 +69,17 @@ public:
return m_num_exch; return m_num_exch;
} }
Result PushSend(VAddr client, VAddr server, size_t size, KMemoryState state); Result PushSend(KProcessAddress client, KProcessAddress server, size_t size,
Result PushReceive(VAddr client, VAddr server, size_t size, KMemoryState state); KMemoryState state);
Result PushExchange(VAddr client, VAddr server, size_t size, KMemoryState state); Result PushReceive(KProcessAddress client, KProcessAddress server, size_t size,
KMemoryState state);
Result PushExchange(KProcessAddress client, KProcessAddress server, size_t size,
KMemoryState state);
VAddr GetSendClientAddress(size_t i) const { KProcessAddress GetSendClientAddress(size_t i) const {
return GetSendMapping(i).GetClientAddress(); return GetSendMapping(i).GetClientAddress();
} }
VAddr GetSendServerAddress(size_t i) const { KProcessAddress GetSendServerAddress(size_t i) const {
return GetSendMapping(i).GetServerAddress(); return GetSendMapping(i).GetServerAddress();
} }
size_t GetSendSize(size_t i) const { size_t GetSendSize(size_t i) const {
@ -86,10 +89,10 @@ public:
return GetSendMapping(i).GetMemoryState(); return GetSendMapping(i).GetMemoryState();
} }
VAddr GetReceiveClientAddress(size_t i) const { KProcessAddress GetReceiveClientAddress(size_t i) const {
return GetReceiveMapping(i).GetClientAddress(); return GetReceiveMapping(i).GetClientAddress();
} }
VAddr GetReceiveServerAddress(size_t i) const { KProcessAddress GetReceiveServerAddress(size_t i) const {
return GetReceiveMapping(i).GetServerAddress(); return GetReceiveMapping(i).GetServerAddress();
} }
size_t GetReceiveSize(size_t i) const { size_t GetReceiveSize(size_t i) const {
@ -99,10 +102,10 @@ public:
return GetReceiveMapping(i).GetMemoryState(); return GetReceiveMapping(i).GetMemoryState();
} }
VAddr GetExchangeClientAddress(size_t i) const { KProcessAddress GetExchangeClientAddress(size_t i) const {
return GetExchangeMapping(i).GetClientAddress(); return GetExchangeMapping(i).GetClientAddress();
} }
VAddr GetExchangeServerAddress(size_t i) const { KProcessAddress GetExchangeServerAddress(size_t i) const {
return GetExchangeMapping(i).GetServerAddress(); return GetExchangeMapping(i).GetServerAddress();
} }
size_t GetExchangeSize(size_t i) const { size_t GetExchangeSize(size_t i) const {
@ -113,7 +116,8 @@ public:
} }
private: private:
Result PushMap(VAddr client, VAddr server, size_t size, KMemoryState state, size_t index); Result PushMap(KProcessAddress client, KProcessAddress server, size_t size,
KMemoryState state, size_t index);
const Mapping& GetSendMapping(size_t i) const { const Mapping& GetSendMapping(size_t i) const {
ASSERT(i < m_num_send); ASSERT(i < m_num_send);
@ -227,22 +231,25 @@ public:
return m_mappings.GetExchangeCount(); return m_mappings.GetExchangeCount();
} }
Result PushSend(VAddr client, VAddr server, size_t size, KMemoryState state) { Result PushSend(KProcessAddress client, KProcessAddress server, size_t size,
KMemoryState state) {
return m_mappings.PushSend(client, server, size, state); return m_mappings.PushSend(client, server, size, state);
} }
Result PushReceive(VAddr client, VAddr server, size_t size, KMemoryState state) { Result PushReceive(KProcessAddress client, KProcessAddress server, size_t size,
KMemoryState state) {
return m_mappings.PushReceive(client, server, size, state); return m_mappings.PushReceive(client, server, size, state);
} }
Result PushExchange(VAddr client, VAddr server, size_t size, KMemoryState state) { Result PushExchange(KProcessAddress client, KProcessAddress server, size_t size,
KMemoryState state) {
return m_mappings.PushExchange(client, server, size, state); return m_mappings.PushExchange(client, server, size, state);
} }
VAddr GetSendClientAddress(size_t i) const { KProcessAddress GetSendClientAddress(size_t i) const {
return m_mappings.GetSendClientAddress(i); return m_mappings.GetSendClientAddress(i);
} }
VAddr GetSendServerAddress(size_t i) const { KProcessAddress GetSendServerAddress(size_t i) const {
return m_mappings.GetSendServerAddress(i); return m_mappings.GetSendServerAddress(i);
} }
size_t GetSendSize(size_t i) const { size_t GetSendSize(size_t i) const {
@ -252,10 +259,10 @@ public:
return m_mappings.GetSendMemoryState(i); return m_mappings.GetSendMemoryState(i);
} }
VAddr GetReceiveClientAddress(size_t i) const { KProcessAddress GetReceiveClientAddress(size_t i) const {
return m_mappings.GetReceiveClientAddress(i); return m_mappings.GetReceiveClientAddress(i);
} }
VAddr GetReceiveServerAddress(size_t i) const { KProcessAddress GetReceiveServerAddress(size_t i) const {
return m_mappings.GetReceiveServerAddress(i); return m_mappings.GetReceiveServerAddress(i);
} }
size_t GetReceiveSize(size_t i) const { size_t GetReceiveSize(size_t i) const {
@ -265,10 +272,10 @@ public:
return m_mappings.GetReceiveMemoryState(i); return m_mappings.GetReceiveMemoryState(i);
} }
VAddr GetExchangeClientAddress(size_t i) const { KProcessAddress GetExchangeClientAddress(size_t i) const {
return m_mappings.GetExchangeClientAddress(i); return m_mappings.GetExchangeClientAddress(i);
} }
VAddr GetExchangeServerAddress(size_t i) const { KProcessAddress GetExchangeServerAddress(size_t i) const {
return m_mappings.GetExchangeServerAddress(i); return m_mappings.GetExchangeServerAddress(i);
} }
size_t GetExchangeSize(size_t i) const { size_t GetExchangeSize(size_t i) const {

@ -76,7 +76,7 @@ void KSharedMemory::Finalize() {
m_resource_limit->Close(); m_resource_limit->Close();
} }
Result KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t map_size, Result KSharedMemory::Map(KProcess& target_process, KProcessAddress address, std::size_t map_size,
Svc::MemoryPermission map_perm) { Svc::MemoryPermission map_perm) {
// Validate the size. // Validate the size.
R_UNLESS(m_size == map_size, ResultInvalidSize); R_UNLESS(m_size == map_size, ResultInvalidSize);
@ -94,7 +94,8 @@ Result KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t m
ConvertToKMemoryPermission(map_perm))); ConvertToKMemoryPermission(map_perm)));
} }
Result KSharedMemory::Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size) { Result KSharedMemory::Unmap(KProcess& target_process, KProcessAddress address,
std::size_t unmap_size) {
// Validate the size. // Validate the size.
R_UNLESS(m_size == unmap_size, ResultInvalidSize); R_UNLESS(m_size == unmap_size, ResultInvalidSize);

@ -6,11 +6,11 @@
#include <optional> #include <optional>
#include <string> #include <string>
#include "common/common_types.h"
#include "core/device_memory.h" #include "core/device_memory.h"
#include "core/hle/kernel/k_memory_block.h" #include "core/hle/kernel/k_memory_block.h"
#include "core/hle/kernel/k_page_group.h" #include "core/hle/kernel/k_page_group.h"
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/slab_helpers.h" #include "core/hle/kernel/slab_helpers.h"
#include "core/hle/result.h" #include "core/hle/result.h"
@ -37,7 +37,7 @@ public:
* @param map_size Size of the shared memory block to map * @param map_size Size of the shared memory block to map
* @param permissions Memory block map permissions (specified by SVC field) * @param permissions Memory block map permissions (specified by SVC field)
*/ */
Result Map(KProcess& target_process, VAddr address, std::size_t map_size, Result Map(KProcess& target_process, KProcessAddress address, std::size_t map_size,
Svc::MemoryPermission permissions); Svc::MemoryPermission permissions);
/** /**
@ -46,7 +46,7 @@ public:
* @param address Address in system memory to unmap shared memory block * @param address Address in system memory to unmap shared memory block
* @param unmap_size Size of the shared memory block to unmap * @param unmap_size Size of the shared memory block to unmap
*/ */
Result Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size); Result Unmap(KProcess& target_process, KProcessAddress address, std::size_t unmap_size);
/** /**
* Gets a pointer to the shared memory block * Gets a pointer to the shared memory block
@ -79,7 +79,7 @@ private:
std::optional<KPageGroup> m_page_group{}; std::optional<KPageGroup> m_page_group{};
Svc::MemoryPermission m_owner_permission{}; Svc::MemoryPermission m_owner_permission{};
Svc::MemoryPermission m_user_permission{}; Svc::MemoryPermission m_user_permission{};
PAddr m_physical_address{}; KPhysicalAddress m_physical_address{};
std::size_t m_size{}; std::size_t m_size{};
KResourceLimit* m_resource_limit{}; KResourceLimit* m_resource_limit{};
bool m_is_initialized{}; bool m_is_initialized{};

@ -130,7 +130,7 @@ private:
KBlockInfoSlabHeap m_block_info_heap; KBlockInfoSlabHeap m_block_info_heap;
KPageTableSlabHeap m_page_table_heap; KPageTableSlabHeap m_page_table_heap;
KResourceLimit* m_resource_limit{}; KResourceLimit* m_resource_limit{};
VAddr m_resource_address{}; KVirtualAddress m_resource_address{};
size_t m_resource_size{}; size_t m_resource_size{};
}; };

@ -48,8 +48,8 @@ static void ResetThreadContext32(Kernel::KThread::ThreadContext32& context, u32
context.fpscr = 0; context.fpscr = 0;
} }
static void ResetThreadContext64(Kernel::KThread::ThreadContext64& context, VAddr stack_top, static void ResetThreadContext64(Kernel::KThread::ThreadContext64& context, u64 stack_top,
VAddr entry_point, u64 arg) { u64 entry_point, u64 arg) {
context = {}; context = {};
context.cpu_registers[0] = arg; context.cpu_registers[0] = arg;
context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1; context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1;
@ -100,8 +100,8 @@ KThread::KThread(KernelCore& kernel)
: KAutoObjectWithSlabHeapAndContainer{kernel}, m_activity_pause_lock{kernel} {} : KAutoObjectWithSlabHeapAndContainer{kernel}, m_activity_pause_lock{kernel} {}
KThread::~KThread() = default; KThread::~KThread() = default;
Result KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, Result KThread::Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top,
s32 virt_core, KProcess* owner, ThreadType type) { s32 prio, s32 virt_core, KProcess* owner, ThreadType type) {
// Assert parameters are valid. // Assert parameters are valid.
ASSERT((type == ThreadType::Main) || (type == ThreadType::Dummy) || ASSERT((type == ThreadType::Main) || (type == ThreadType::Dummy) ||
(Svc::HighestThreadPriority <= prio && prio <= Svc::LowestThreadPriority)); (Svc::HighestThreadPriority <= prio && prio <= Svc::LowestThreadPriority));
@ -221,9 +221,9 @@ Result KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack
} }
// Initialize thread context. // Initialize thread context.
ResetThreadContext64(m_thread_context_64, user_stack_top, func, arg); ResetThreadContext64(m_thread_context_64, GetInteger(user_stack_top), GetInteger(func), arg);
ResetThreadContext32(m_thread_context_32, static_cast<u32>(user_stack_top), ResetThreadContext32(m_thread_context_32, static_cast<u32>(GetInteger(user_stack_top)),
static_cast<u32>(func), static_cast<u32>(arg)); static_cast<u32>(GetInteger(func)), static_cast<u32>(arg));
// Setup the stack parameters. // Setup the stack parameters.
StackParameters& sp = this->GetStackParameters(); StackParameters& sp = this->GetStackParameters();
@ -249,8 +249,9 @@ Result KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack
} }
Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg,
VAddr user_stack_top, s32 prio, s32 core, KProcess* owner, KProcessAddress user_stack_top, s32 prio, s32 core,
ThreadType type, std::function<void()>&& init_func) { KProcess* owner, ThreadType type,
std::function<void()>&& init_func) {
// Initialize the thread. // Initialize the thread.
R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type)); R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type));
@ -288,8 +289,8 @@ Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thre
} }
Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func, Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func,
uintptr_t arg, VAddr user_stack_top, s32 prio, s32 virt_core, uintptr_t arg, KProcessAddress user_stack_top, s32 prio,
KProcess* owner) { s32 virt_core, KProcess* owner) {
system.Kernel().GlobalSchedulerContext().AddThread(thread); system.Kernel().GlobalSchedulerContext().AddThread(thread);
R_RETURN(InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, R_RETURN(InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner,
ThreadType::User, system.GetCpuManager().GetGuestThreadFunc())); ThreadType::User, system.GetCpuManager().GetGuestThreadFunc()));
@ -951,7 +952,7 @@ void KThread::AddHeldLock(LockWithPriorityInheritanceInfo* lock_info) {
m_held_lock_info_list.push_front(*lock_info); m_held_lock_info_list.push_front(*lock_info);
} }
KThread::LockWithPriorityInheritanceInfo* KThread::FindHeldLock(VAddr address_key, KThread::LockWithPriorityInheritanceInfo* KThread::FindHeldLock(KProcessAddress address_key,
bool is_kernel_address_key) { bool is_kernel_address_key) {
ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
@ -1087,7 +1088,8 @@ void KThread::RemoveWaiter(KThread* thread) {
} }
} }
KThread* KThread::RemoveWaiterByKey(bool* out_has_waiters, VAddr key, bool is_kernel_address_key_) { KThread* KThread::RemoveWaiterByKey(bool* out_has_waiters, KProcessAddress key,
bool is_kernel_address_key_) {
ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
// Get the relevant lock info. // Get the relevant lock info.

@ -14,7 +14,6 @@
#include <boost/intrusive/list.hpp> #include <boost/intrusive/list.hpp>
#include "common/common_types.h"
#include "common/intrusive_red_black_tree.h" #include "common/intrusive_red_black_tree.h"
#include "common/spin_lock.h" #include "common/spin_lock.h"
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
@ -23,6 +22,7 @@
#include "core/hle/kernel/k_spin_lock.h" #include "core/hle/kernel/k_spin_lock.h"
#include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/k_timer_task.h" #include "core/hle/kernel/k_timer_task.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/k_worker_task.h" #include "core/hle/kernel/k_worker_task.h"
#include "core/hle/kernel/slab_helpers.h" #include "core/hle/kernel/slab_helpers.h"
#include "core/hle/kernel/svc_common.h" #include "core/hle/kernel/svc_common.h"
@ -46,7 +46,7 @@ class KProcess;
class KScheduler; class KScheduler;
class KThreadQueue; class KThreadQueue;
using KThreadFunction = VAddr; using KThreadFunction = KProcessAddress;
enum class ThreadType : u32 { enum class ThreadType : u32 {
Main = 0, Main = 0,
@ -230,9 +230,9 @@ public:
/* /*
* Returns the Thread Local Storage address of the current thread * Returns the Thread Local Storage address of the current thread
* @returns VAddr of the thread's TLS * @returns Address of the thread's TLS
*/ */
VAddr GetTlsAddress() const { KProcessAddress GetTlsAddress() const {
return m_tls_address; return m_tls_address;
} }
@ -419,8 +419,8 @@ public:
KThreadFunction func, uintptr_t arg, s32 virt_core); KThreadFunction func, uintptr_t arg, s32 virt_core);
static Result InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func, static Result InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func,
uintptr_t arg, VAddr user_stack_top, s32 prio, s32 virt_core, uintptr_t arg, KProcessAddress user_stack_top, s32 prio,
KProcess* owner); s32 virt_core, KProcess* owner);
static Result InitializeServiceThread(Core::System& system, KThread* thread, static Result InitializeServiceThread(Core::System& system, KThread* thread,
std::function<void()>&& thread_func, s32 prio, std::function<void()>&& thread_func, s32 prio,
@ -565,15 +565,15 @@ public:
Result GetThreadContext3(std::vector<u8>& out); Result GetThreadContext3(std::vector<u8>& out);
KThread* RemoveUserWaiterByKey(bool* out_has_waiters, VAddr key) { KThread* RemoveUserWaiterByKey(bool* out_has_waiters, KProcessAddress key) {
return this->RemoveWaiterByKey(out_has_waiters, key, false); return this->RemoveWaiterByKey(out_has_waiters, key, false);
} }
KThread* RemoveKernelWaiterByKey(bool* out_has_waiters, VAddr key) { KThread* RemoveKernelWaiterByKey(bool* out_has_waiters, KProcessAddress key) {
return this->RemoveWaiterByKey(out_has_waiters, key, true); return this->RemoveWaiterByKey(out_has_waiters, key, true);
} }
VAddr GetAddressKey() const { KProcessAddress GetAddressKey() const {
return m_address_key; return m_address_key;
} }
@ -591,14 +591,14 @@ public:
// to cope with arbitrary host pointers making their way // to cope with arbitrary host pointers making their way
// into things. // into things.
void SetUserAddressKey(VAddr key, u32 val) { void SetUserAddressKey(KProcessAddress key, u32 val) {
ASSERT(m_waiting_lock_info == nullptr); ASSERT(m_waiting_lock_info == nullptr);
m_address_key = key; m_address_key = key;
m_address_key_value = val; m_address_key_value = val;
m_is_kernel_address_key = false; m_is_kernel_address_key = false;
} }
void SetKernelAddressKey(VAddr key) { void SetKernelAddressKey(KProcessAddress key) {
ASSERT(m_waiting_lock_info == nullptr); ASSERT(m_waiting_lock_info == nullptr);
m_address_key = key; m_address_key = key;
m_is_kernel_address_key = true; m_is_kernel_address_key = true;
@ -637,12 +637,13 @@ public:
return m_argument; return m_argument;
} }
VAddr GetUserStackTop() const { KProcessAddress GetUserStackTop() const {
return m_stack_top; return m_stack_top;
} }
private: private:
KThread* RemoveWaiterByKey(bool* out_has_waiters, VAddr key, bool is_kernel_address_key); KThread* RemoveWaiterByKey(bool* out_has_waiters, KProcessAddress key,
bool is_kernel_address_key);
static constexpr size_t PriorityInheritanceCountMax = 10; static constexpr size_t PriorityInheritanceCountMax = 10;
union SyncObjectBuffer { union SyncObjectBuffer {
@ -695,12 +696,13 @@ private:
void IncreaseBasePriority(s32 priority); void IncreaseBasePriority(s32 priority);
Result Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, Result Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio,
s32 virt_core, KProcess* owner, ThreadType type); s32 virt_core, KProcess* owner, ThreadType type);
static Result InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, static Result InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg,
VAddr user_stack_top, s32 prio, s32 core, KProcess* owner, KProcessAddress user_stack_top, s32 prio, s32 core,
ThreadType type, std::function<void()>&& init_func); KProcess* owner, ThreadType type,
std::function<void()>&& init_func);
// For core KThread implementation // For core KThread implementation
ThreadContext32 m_thread_context_32{}; ThreadContext32 m_thread_context_32{};
@ -749,7 +751,8 @@ public:
public: public:
explicit LockWithPriorityInheritanceInfo(KernelCore&) {} explicit LockWithPriorityInheritanceInfo(KernelCore&) {}
static LockWithPriorityInheritanceInfo* Create(KernelCore& kernel, VAddr address_key, static LockWithPriorityInheritanceInfo* Create(KernelCore& kernel,
KProcessAddress address_key,
bool is_kernel_address_key) { bool is_kernel_address_key) {
// Create a new lock info. // Create a new lock info.
auto* new_lock = LockWithPriorityInheritanceInfo::Allocate(kernel); auto* new_lock = LockWithPriorityInheritanceInfo::Allocate(kernel);
@ -797,7 +800,7 @@ public:
return m_tree; return m_tree;
} }
VAddr GetAddressKey() const { KProcessAddress GetAddressKey() const {
return m_address_key; return m_address_key;
} }
bool GetIsKernelAddressKey() const { bool GetIsKernelAddressKey() const {
@ -812,7 +815,7 @@ public:
private: private:
LockWithPriorityInheritanceThreadTree m_tree{}; LockWithPriorityInheritanceThreadTree m_tree{};
VAddr m_address_key{}; KProcessAddress m_address_key{};
KThread* m_owner{}; KThread* m_owner{};
u32 m_waiter_count{}; u32 m_waiter_count{};
bool m_is_kernel_address_key{}; bool m_is_kernel_address_key{};
@ -827,7 +830,8 @@ public:
} }
void AddHeldLock(LockWithPriorityInheritanceInfo* lock_info); void AddHeldLock(LockWithPriorityInheritanceInfo* lock_info);
LockWithPriorityInheritanceInfo* FindHeldLock(VAddr address_key, bool is_kernel_address_key); LockWithPriorityInheritanceInfo* FindHeldLock(KProcessAddress address_key,
bool is_kernel_address_key);
private: private:
using LockWithPriorityInheritanceInfoList = using LockWithPriorityInheritanceInfoList =
@ -839,11 +843,11 @@ private:
KAffinityMask m_physical_affinity_mask{}; KAffinityMask m_physical_affinity_mask{};
u64 m_thread_id{}; u64 m_thread_id{};
std::atomic<s64> m_cpu_time{}; std::atomic<s64> m_cpu_time{};
VAddr m_address_key{}; KProcessAddress m_address_key{};
KProcess* m_parent{}; KProcess* m_parent{};
VAddr m_kernel_stack_top{}; KVirtualAddress m_kernel_stack_top{};
u32* m_light_ipc_data{}; u32* m_light_ipc_data{};
VAddr m_tls_address{}; KProcessAddress m_tls_address{};
KLightLock m_activity_pause_lock; KLightLock m_activity_pause_lock;
s64 m_schedule_count{}; s64 m_schedule_count{};
s64 m_last_scheduled_tick{}; s64 m_last_scheduled_tick{};
@ -887,16 +891,16 @@ private:
// For debugging // For debugging
std::vector<KSynchronizationObject*> m_wait_objects_for_debugging{}; std::vector<KSynchronizationObject*> m_wait_objects_for_debugging{};
VAddr m_mutex_wait_address_for_debugging{}; KProcessAddress m_mutex_wait_address_for_debugging{};
ThreadWaitReasonForDebugging m_wait_reason_for_debugging{}; ThreadWaitReasonForDebugging m_wait_reason_for_debugging{};
uintptr_t m_argument{}; uintptr_t m_argument{};
VAddr m_stack_top{}; KProcessAddress m_stack_top{};
public: public:
using ConditionVariableThreadTreeType = ConditionVariableThreadTree; using ConditionVariableThreadTreeType = ConditionVariableThreadTree;
void SetConditionVariable(ConditionVariableThreadTree* tree, VAddr address, u64 cv_key, void SetConditionVariable(ConditionVariableThreadTree* tree, KProcessAddress address,
u32 value) { u64 cv_key, u32 value) {
ASSERT(m_waiting_lock_info == nullptr); ASSERT(m_waiting_lock_info == nullptr);
m_condvar_tree = tree; m_condvar_tree = tree;
m_condvar_key = cv_key; m_condvar_key = cv_key;

@ -37,7 +37,7 @@ Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) {
Result KThreadLocalPage::Finalize() { Result KThreadLocalPage::Finalize() {
// Get the physical address of the page. // Get the physical address of the page.
const PAddr phys_addr = m_owner->PageTable().GetPhysicalAddr(m_virt_addr); const KPhysicalAddress phys_addr = m_owner->PageTable().GetPhysicalAddr(m_virt_addr);
ASSERT(phys_addr); ASSERT(phys_addr);
// Unmap the page. // Unmap the page.
@ -49,7 +49,7 @@ Result KThreadLocalPage::Finalize() {
return ResultSuccess; return ResultSuccess;
} }
VAddr KThreadLocalPage::Reserve() { KProcessAddress KThreadLocalPage::Reserve() {
for (size_t i = 0; i < m_is_region_free.size(); i++) { for (size_t i = 0; i < m_is_region_free.size(); i++) {
if (m_is_region_free[i]) { if (m_is_region_free[i]) {
m_is_region_free[i] = false; m_is_region_free[i] = false;
@ -60,7 +60,7 @@ VAddr KThreadLocalPage::Reserve() {
return 0; return 0;
} }
void KThreadLocalPage::Release(VAddr addr) { void KThreadLocalPage::Release(KProcessAddress addr) {
m_is_region_free[this->GetRegionIndex(addr)] = true; m_is_region_free[this->GetRegionIndex(addr)] = true;
} }

@ -27,19 +27,20 @@ public:
static_assert(RegionsPerPage > 0); static_assert(RegionsPerPage > 0);
public: public:
constexpr explicit KThreadLocalPage(KernelCore&, VAddr addr = {}) : m_virt_addr(addr) { constexpr explicit KThreadLocalPage(KernelCore&, KProcessAddress addr = {})
: m_virt_addr(addr) {
m_is_region_free.fill(true); m_is_region_free.fill(true);
} }
constexpr VAddr GetAddress() const { constexpr KProcessAddress GetAddress() const {
return m_virt_addr; return m_virt_addr;
} }
Result Initialize(KernelCore& kernel, KProcess* process); Result Initialize(KernelCore& kernel, KProcess* process);
Result Finalize(); Result Finalize();
VAddr Reserve(); KProcessAddress Reserve();
void Release(VAddr addr); void Release(KProcessAddress addr);
bool IsAllUsed() const { bool IsAllUsed() const {
return std::ranges::all_of(m_is_region_free.begin(), m_is_region_free.end(), return std::ranges::all_of(m_is_region_free.begin(), m_is_region_free.end(),
@ -60,7 +61,7 @@ public:
} }
public: public:
using RedBlackKeyType = VAddr; using RedBlackKeyType = KProcessAddress;
static constexpr RedBlackKeyType GetRedBlackKey(const RedBlackKeyType& v) { static constexpr RedBlackKeyType GetRedBlackKey(const RedBlackKeyType& v) {
return v; return v;
@ -72,8 +73,8 @@ public:
template <typename T> template <typename T>
requires(std::same_as<T, KThreadLocalPage> || std::same_as<T, RedBlackKeyType>) requires(std::same_as<T, KThreadLocalPage> || std::same_as<T, RedBlackKeyType>)
static constexpr int Compare(const T& lhs, const KThreadLocalPage& rhs) { static constexpr int Compare(const T& lhs, const KThreadLocalPage& rhs) {
const VAddr lval = GetRedBlackKey(lhs); const KProcessAddress lval = GetRedBlackKey(lhs);
const VAddr rval = GetRedBlackKey(rhs); const KProcessAddress rval = GetRedBlackKey(rhs);
if (lval < rval) { if (lval < rval) {
return -1; return -1;
@ -85,22 +86,22 @@ public:
} }
private: private:
constexpr VAddr GetRegionAddress(size_t i) const { constexpr KProcessAddress GetRegionAddress(size_t i) const {
return this->GetAddress() + i * Svc::ThreadLocalRegionSize; return this->GetAddress() + i * Svc::ThreadLocalRegionSize;
} }
constexpr bool Contains(VAddr addr) const { constexpr bool Contains(KProcessAddress addr) const {
return this->GetAddress() <= addr && addr < this->GetAddress() + PageSize; return this->GetAddress() <= addr && addr < this->GetAddress() + PageSize;
} }
constexpr size_t GetRegionIndex(VAddr addr) const { constexpr size_t GetRegionIndex(KProcessAddress addr) const {
ASSERT(Common::IsAligned(addr, Svc::ThreadLocalRegionSize)); ASSERT(Common::IsAligned(GetInteger(addr), Svc::ThreadLocalRegionSize));
ASSERT(this->Contains(addr)); ASSERT(this->Contains(addr));
return (addr - this->GetAddress()) / Svc::ThreadLocalRegionSize; return (addr - this->GetAddress()) / Svc::ThreadLocalRegionSize;
} }
private: private:
VAddr m_virt_addr{}; KProcessAddress m_virt_addr{};
KProcess* m_owner{}; KProcess* m_owner{};
KernelCore* m_kernel{}; KernelCore* m_kernel{};
std::array<bool, RegionsPerPage> m_is_region_free{}; std::array<bool, RegionsPerPage> m_is_region_free{};

@ -13,7 +13,7 @@ KTransferMemory::KTransferMemory(KernelCore& kernel)
KTransferMemory::~KTransferMemory() = default; KTransferMemory::~KTransferMemory() = default;
Result KTransferMemory::Initialize(VAddr address, std::size_t size, Result KTransferMemory::Initialize(KProcessAddress address, std::size_t size,
Svc::MemoryPermission owner_perm) { Svc::MemoryPermission owner_perm) {
// Set members. // Set members.
m_owner = GetCurrentProcessPointer(m_kernel); m_owner = GetCurrentProcessPointer(m_kernel);

@ -26,7 +26,7 @@ public:
explicit KTransferMemory(KernelCore& kernel); explicit KTransferMemory(KernelCore& kernel);
~KTransferMemory() override; ~KTransferMemory() override;
Result Initialize(VAddr address, std::size_t size, Svc::MemoryPermission owner_perm); Result Initialize(KProcessAddress address, std::size_t size, Svc::MemoryPermission owner_perm);
void Finalize() override; void Finalize() override;
@ -44,7 +44,7 @@ public:
return m_owner; return m_owner;
} }
VAddr GetSourceAddress() const { KProcessAddress GetSourceAddress() const {
return m_address; return m_address;
} }
@ -54,7 +54,7 @@ public:
private: private:
KProcess* m_owner{}; KProcess* m_owner{};
VAddr m_address{}; KProcessAddress m_address{};
Svc::MemoryPermission m_owner_perm{}; Svc::MemoryPermission m_owner_perm{};
size_t m_size{}; size_t m_size{};
bool m_is_initialized{}; bool m_is_initialized{};

@ -0,0 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/typed_address.h"
namespace Kernel {
using KPhysicalAddress = Common::PhysicalAddress;
using KVirtualAddress = Common::VirtualAddress;
using KProcessAddress = Common::ProcessAddress;
} // namespace Kernel

@ -271,9 +271,9 @@ struct KernelCore::Impl {
system.CoreTiming().ScheduleLoopingEvent(time_interval, time_interval, preemption_event); system.CoreTiming().ScheduleLoopingEvent(time_interval, time_interval, preemption_event);
} }
void InitializeResourceManagers(KernelCore& kernel, VAddr address, size_t size) { void InitializeResourceManagers(KernelCore& kernel, KVirtualAddress address, size_t size) {
// Ensure that the buffer is suitable for our use. // Ensure that the buffer is suitable for our use.
ASSERT(Common::IsAligned(address, PageSize)); ASSERT(Common::IsAligned(GetInteger(address), PageSize));
ASSERT(Common::IsAligned(size, PageSize)); ASSERT(Common::IsAligned(size, PageSize));
// Ensure that we have space for our reference counts. // Ensure that we have space for our reference counts.
@ -462,29 +462,30 @@ struct KernelCore::Impl {
KernelPhysicalAddressSpaceBase + KernelPhysicalAddressSpaceSize - 1); KernelPhysicalAddressSpaceBase + KernelPhysicalAddressSpaceSize - 1);
// Save start and end for ease of use. // Save start and end for ease of use.
const VAddr code_start_virt_addr = KernelVirtualAddressCodeBase; constexpr KVirtualAddress code_start_virt_addr = KernelVirtualAddressCodeBase;
const VAddr code_end_virt_addr = KernelVirtualAddressCodeEnd; constexpr KVirtualAddress code_end_virt_addr = KernelVirtualAddressCodeEnd;
// Setup the containing kernel region. // Setup the containing kernel region.
constexpr size_t KernelRegionSize = 1_GiB; constexpr size_t KernelRegionSize = 1_GiB;
constexpr size_t KernelRegionAlign = 1_GiB; constexpr size_t KernelRegionAlign = 1_GiB;
constexpr VAddr kernel_region_start = constexpr KVirtualAddress kernel_region_start =
Common::AlignDown(code_start_virt_addr, KernelRegionAlign); Common::AlignDown(GetInteger(code_start_virt_addr), KernelRegionAlign);
size_t kernel_region_size = KernelRegionSize; size_t kernel_region_size = KernelRegionSize;
if (!(kernel_region_start + KernelRegionSize - 1 <= KernelVirtualAddressSpaceLast)) { if (!(kernel_region_start + KernelRegionSize - 1 <= KernelVirtualAddressSpaceLast)) {
kernel_region_size = KernelVirtualAddressSpaceEnd - kernel_region_start; kernel_region_size = KernelVirtualAddressSpaceEnd - GetInteger(kernel_region_start);
} }
ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert( ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert(
kernel_region_start, kernel_region_size, KMemoryRegionType_Kernel)); GetInteger(kernel_region_start), kernel_region_size, KMemoryRegionType_Kernel));
// Setup the code region. // Setup the code region.
constexpr size_t CodeRegionAlign = PageSize; constexpr size_t CodeRegionAlign = PageSize;
constexpr VAddr code_region_start = constexpr KVirtualAddress code_region_start =
Common::AlignDown(code_start_virt_addr, CodeRegionAlign); Common::AlignDown(GetInteger(code_start_virt_addr), CodeRegionAlign);
constexpr VAddr code_region_end = Common::AlignUp(code_end_virt_addr, CodeRegionAlign); constexpr KVirtualAddress code_region_end =
Common::AlignUp(GetInteger(code_end_virt_addr), CodeRegionAlign);
constexpr size_t code_region_size = code_region_end - code_region_start; constexpr size_t code_region_size = code_region_end - code_region_start;
ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert( ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert(
code_region_start, code_region_size, KMemoryRegionType_KernelCode)); GetInteger(code_region_start), code_region_size, KMemoryRegionType_KernelCode));
// Setup board-specific device physical regions. // Setup board-specific device physical regions.
Init::SetupDevicePhysicalMemoryRegions(*memory_layout); Init::SetupDevicePhysicalMemoryRegions(*memory_layout);
@ -520,11 +521,11 @@ struct KernelCore::Impl {
ASSERT(misc_region_size > 0); ASSERT(misc_region_size > 0);
// Setup the misc region. // Setup the misc region.
const VAddr misc_region_start = const KVirtualAddress misc_region_start =
memory_layout->GetVirtualMemoryRegionTree().GetRandomAlignedRegion( memory_layout->GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
misc_region_size, MiscRegionAlign, KMemoryRegionType_Kernel); misc_region_size, MiscRegionAlign, KMemoryRegionType_Kernel);
ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert( ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert(
misc_region_start, misc_region_size, KMemoryRegionType_KernelMisc)); GetInteger(misc_region_start), misc_region_size, KMemoryRegionType_KernelMisc));
// Determine if we'll use extra thread resources. // Determine if we'll use extra thread resources.
const bool use_extra_resources = KSystemControl::Init::ShouldIncreaseThreadResourceLimit(); const bool use_extra_resources = KSystemControl::Init::ShouldIncreaseThreadResourceLimit();
@ -532,11 +533,11 @@ struct KernelCore::Impl {
// Setup the stack region. // Setup the stack region.
constexpr size_t StackRegionSize = 14_MiB; constexpr size_t StackRegionSize = 14_MiB;
constexpr size_t StackRegionAlign = KernelAslrAlignment; constexpr size_t StackRegionAlign = KernelAslrAlignment;
const VAddr stack_region_start = const KVirtualAddress stack_region_start =
memory_layout->GetVirtualMemoryRegionTree().GetRandomAlignedRegion( memory_layout->GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
StackRegionSize, StackRegionAlign, KMemoryRegionType_Kernel); StackRegionSize, StackRegionAlign, KMemoryRegionType_Kernel);
ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert( ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert(
stack_region_start, StackRegionSize, KMemoryRegionType_KernelStack)); GetInteger(stack_region_start), StackRegionSize, KMemoryRegionType_KernelStack));
// Determine the size of the resource region. // Determine the size of the resource region.
const size_t resource_region_size = const size_t resource_region_size =
@ -548,29 +549,29 @@ struct KernelCore::Impl {
ASSERT(slab_region_size <= resource_region_size); ASSERT(slab_region_size <= resource_region_size);
// Setup the slab region. // Setup the slab region.
const PAddr code_start_phys_addr = KernelPhysicalAddressCodeBase; const KPhysicalAddress code_start_phys_addr = KernelPhysicalAddressCodeBase;
const PAddr code_end_phys_addr = code_start_phys_addr + code_region_size; const KPhysicalAddress code_end_phys_addr = code_start_phys_addr + code_region_size;
const PAddr slab_start_phys_addr = code_end_phys_addr; const KPhysicalAddress slab_start_phys_addr = code_end_phys_addr;
const PAddr slab_end_phys_addr = slab_start_phys_addr + slab_region_size; const KPhysicalAddress slab_end_phys_addr = slab_start_phys_addr + slab_region_size;
constexpr size_t SlabRegionAlign = KernelAslrAlignment; constexpr size_t SlabRegionAlign = KernelAslrAlignment;
const size_t slab_region_needed_size = const size_t slab_region_needed_size =
Common::AlignUp(code_end_phys_addr + slab_region_size, SlabRegionAlign) - Common::AlignUp(GetInteger(code_end_phys_addr) + slab_region_size, SlabRegionAlign) -
Common::AlignDown(code_end_phys_addr, SlabRegionAlign); Common::AlignDown(GetInteger(code_end_phys_addr), SlabRegionAlign);
const VAddr slab_region_start = const KVirtualAddress slab_region_start =
memory_layout->GetVirtualMemoryRegionTree().GetRandomAlignedRegion( memory_layout->GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
slab_region_needed_size, SlabRegionAlign, KMemoryRegionType_Kernel) + slab_region_needed_size, SlabRegionAlign, KMemoryRegionType_Kernel) +
(code_end_phys_addr % SlabRegionAlign); (GetInteger(code_end_phys_addr) % SlabRegionAlign);
ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert( ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert(
slab_region_start, slab_region_size, KMemoryRegionType_KernelSlab)); GetInteger(slab_region_start), slab_region_size, KMemoryRegionType_KernelSlab));
// Setup the temp region. // Setup the temp region.
constexpr size_t TempRegionSize = 128_MiB; constexpr size_t TempRegionSize = 128_MiB;
constexpr size_t TempRegionAlign = KernelAslrAlignment; constexpr size_t TempRegionAlign = KernelAslrAlignment;
const VAddr temp_region_start = const KVirtualAddress temp_region_start =
memory_layout->GetVirtualMemoryRegionTree().GetRandomAlignedRegion( memory_layout->GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
TempRegionSize, TempRegionAlign, KMemoryRegionType_Kernel); TempRegionSize, TempRegionAlign, KMemoryRegionType_Kernel);
ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert(temp_region_start, TempRegionSize, ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert(
KMemoryRegionType_KernelTemp)); GetInteger(temp_region_start), TempRegionSize, KMemoryRegionType_KernelTemp));
// Automatically map in devices that have auto-map attributes. // Automatically map in devices that have auto-map attributes.
for (auto& region : memory_layout->GetPhysicalMemoryRegionTree()) { for (auto& region : memory_layout->GetPhysicalMemoryRegionTree()) {
@ -596,35 +597,37 @@ struct KernelCore::Impl {
region.SetTypeAttribute(KMemoryRegionAttr_DidKernelMap); region.SetTypeAttribute(KMemoryRegionAttr_DidKernelMap);
// Create a virtual pair region and insert it into the tree. // Create a virtual pair region and insert it into the tree.
const PAddr map_phys_addr = Common::AlignDown(region.GetAddress(), PageSize); const KPhysicalAddress map_phys_addr = Common::AlignDown(region.GetAddress(), PageSize);
const size_t map_size = const size_t map_size =
Common::AlignUp(region.GetEndAddress(), PageSize) - map_phys_addr; Common::AlignUp(region.GetEndAddress(), PageSize) - GetInteger(map_phys_addr);
const VAddr map_virt_addr = const KVirtualAddress map_virt_addr =
memory_layout->GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard( memory_layout->GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(
map_size, PageSize, KMemoryRegionType_KernelMisc, PageSize); map_size, PageSize, KMemoryRegionType_KernelMisc, PageSize);
ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert( ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert(
map_virt_addr, map_size, KMemoryRegionType_KernelMiscMappedDevice)); GetInteger(map_virt_addr), map_size, KMemoryRegionType_KernelMiscMappedDevice));
region.SetPairAddress(map_virt_addr + region.GetAddress() - map_phys_addr); region.SetPairAddress(GetInteger(map_virt_addr) + region.GetAddress() -
GetInteger(map_phys_addr));
} }
Init::SetupDramPhysicalMemoryRegions(*memory_layout); Init::SetupDramPhysicalMemoryRegions(*memory_layout);
// Insert a physical region for the kernel code region. // Insert a physical region for the kernel code region.
ASSERT(memory_layout->GetPhysicalMemoryRegionTree().Insert( ASSERT(memory_layout->GetPhysicalMemoryRegionTree().Insert(
code_start_phys_addr, code_region_size, KMemoryRegionType_DramKernelCode)); GetInteger(code_start_phys_addr), code_region_size, KMemoryRegionType_DramKernelCode));
// Insert a physical region for the kernel slab region. // Insert a physical region for the kernel slab region.
ASSERT(memory_layout->GetPhysicalMemoryRegionTree().Insert( ASSERT(memory_layout->GetPhysicalMemoryRegionTree().Insert(
slab_start_phys_addr, slab_region_size, KMemoryRegionType_DramKernelSlab)); GetInteger(slab_start_phys_addr), slab_region_size, KMemoryRegionType_DramKernelSlab));
// Determine size available for kernel page table heaps, requiring > 8 MB. // Determine size available for kernel page table heaps, requiring > 8 MB.
const PAddr resource_end_phys_addr = slab_start_phys_addr + resource_region_size; const KPhysicalAddress resource_end_phys_addr = slab_start_phys_addr + resource_region_size;
const size_t page_table_heap_size = resource_end_phys_addr - slab_end_phys_addr; const size_t page_table_heap_size = resource_end_phys_addr - slab_end_phys_addr;
ASSERT(page_table_heap_size / 4_MiB > 2); ASSERT(page_table_heap_size / 4_MiB > 2);
// Insert a physical region for the kernel page table heap region // Insert a physical region for the kernel page table heap region
ASSERT(memory_layout->GetPhysicalMemoryRegionTree().Insert( ASSERT(memory_layout->GetPhysicalMemoryRegionTree().Insert(
slab_end_phys_addr, page_table_heap_size, KMemoryRegionType_DramKernelPtHeap)); GetInteger(slab_end_phys_addr), page_table_heap_size,
KMemoryRegionType_DramKernelPtHeap));
// All DRAM regions that we haven't tagged by this point will be mapped under the linear // All DRAM regions that we haven't tagged by this point will be mapped under the linear
// mapping. Tag them. // mapping. Tag them.
@ -646,20 +649,21 @@ struct KernelCore::Impl {
// Setup the linear mapping region. // Setup the linear mapping region.
constexpr size_t LinearRegionAlign = 1_GiB; constexpr size_t LinearRegionAlign = 1_GiB;
const PAddr aligned_linear_phys_start = const KPhysicalAddress aligned_linear_phys_start =
Common::AlignDown(linear_extents.GetAddress(), LinearRegionAlign); Common::AlignDown(linear_extents.GetAddress(), LinearRegionAlign);
const size_t linear_region_size = const size_t linear_region_size =
Common::AlignUp(linear_extents.GetEndAddress(), LinearRegionAlign) - Common::AlignUp(linear_extents.GetEndAddress(), LinearRegionAlign) -
aligned_linear_phys_start; GetInteger(aligned_linear_phys_start);
const VAddr linear_region_start = const KVirtualAddress linear_region_start =
memory_layout->GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard( memory_layout->GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(
linear_region_size, LinearRegionAlign, KMemoryRegionType_None, LinearRegionAlign); linear_region_size, LinearRegionAlign, KMemoryRegionType_None, LinearRegionAlign);
const u64 linear_region_phys_to_virt_diff = linear_region_start - aligned_linear_phys_start; const u64 linear_region_phys_to_virt_diff =
GetInteger(linear_region_start) - GetInteger(aligned_linear_phys_start);
// Map and create regions for all the linearly-mapped data. // Map and create regions for all the linearly-mapped data.
{ {
PAddr cur_phys_addr = 0; KPhysicalAddress cur_phys_addr = 0;
u64 cur_size = 0; u64 cur_size = 0;
for (auto& region : memory_layout->GetPhysicalMemoryRegionTree()) { for (auto& region : memory_layout->GetPhysicalMemoryRegionTree()) {
if (!region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) { if (!region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) {
@ -678,15 +682,16 @@ struct KernelCore::Impl {
cur_size = region.GetSize(); cur_size = region.GetSize();
} }
const VAddr region_virt_addr = const KVirtualAddress region_virt_addr =
region.GetAddress() + linear_region_phys_to_virt_diff; region.GetAddress() + linear_region_phys_to_virt_diff;
ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert( ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert(
region_virt_addr, region.GetSize(), GetInteger(region_virt_addr), region.GetSize(),
GetTypeForVirtualLinearMapping(region.GetType()))); GetTypeForVirtualLinearMapping(region.GetType())));
region.SetPairAddress(region_virt_addr); region.SetPairAddress(GetInteger(region_virt_addr));
KMemoryRegion* virt_region = KMemoryRegion* virt_region =
memory_layout->GetVirtualMemoryRegionTree().FindModifiable(region_virt_addr); memory_layout->GetVirtualMemoryRegionTree().FindModifiable(
GetInteger(region_virt_addr));
ASSERT(virt_region != nullptr); ASSERT(virt_region != nullptr);
virt_region->SetPairAddress(region.GetAddress()); virt_region->SetPairAddress(region.GetAddress());
} }
@ -694,10 +699,11 @@ struct KernelCore::Impl {
// Insert regions for the initial page table region. // Insert regions for the initial page table region.
ASSERT(memory_layout->GetPhysicalMemoryRegionTree().Insert( ASSERT(memory_layout->GetPhysicalMemoryRegionTree().Insert(
resource_end_phys_addr, KernelPageTableHeapSize, KMemoryRegionType_DramKernelInitPt)); GetInteger(resource_end_phys_addr), KernelPageTableHeapSize,
KMemoryRegionType_DramKernelInitPt));
ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert( ASSERT(memory_layout->GetVirtualMemoryRegionTree().Insert(
resource_end_phys_addr + linear_region_phys_to_virt_diff, KernelPageTableHeapSize, GetInteger(resource_end_phys_addr) + linear_region_phys_to_virt_diff,
KMemoryRegionType_VirtualDramKernelInitPt)); KernelPageTableHeapSize, KMemoryRegionType_VirtualDramKernelInitPt));
// All linear-mapped DRAM regions that we haven't tagged by this point will be allocated to // All linear-mapped DRAM regions that we haven't tagged by this point will be allocated to
// some pool partition. Tag them. // some pool partition. Tag them.
@ -969,12 +975,12 @@ void KernelCore::InvalidateAllInstructionCaches() {
} }
} }
void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) { void KernelCore::InvalidateCpuInstructionCacheRange(KProcessAddress addr, std::size_t size) {
for (auto& physical_core : impl->cores) { for (auto& physical_core : impl->cores) {
if (!physical_core->IsInitialized()) { if (!physical_core->IsInitialized()) {
continue; continue;
} }
physical_core->ArmInterface().InvalidateCacheRange(addr, size); physical_core->ArmInterface().InvalidateCacheRange(GetInteger(addr), size);
} }
} }

@ -14,6 +14,7 @@
#include "core/hardware_properties.h" #include "core/hardware_properties.h"
#include "core/hle/kernel/k_auto_object.h" #include "core/hle/kernel/k_auto_object.h"
#include "core/hle/kernel/k_slab_heap.h" #include "core/hle/kernel/k_slab_heap.h"
#include "core/hle/kernel/k_typed_address.h"
#include "core/hle/kernel/svc_common.h" #include "core/hle/kernel/svc_common.h"
namespace Core { namespace Core {
@ -185,7 +186,7 @@ public:
void InvalidateAllInstructionCaches(); void InvalidateAllInstructionCaches();
void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); void InvalidateCpuInstructionCacheRange(KProcessAddress addr, std::size_t size);
/// Registers all kernel objects with the global emulation state, this is purely for tracking /// Registers all kernel objects with the global emulation state, this is purely for tracking
/// leaks after emulation has been shutdown. /// leaks after emulation has been shutdown.

@ -6,6 +6,7 @@
#include <array> #include <array>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/kernel/k_typed_address.h"
namespace Kernel { namespace Kernel {
@ -14,7 +15,4 @@ constexpr std::size_t PageSize{1 << PageBits};
using Page = std::array<u8, PageSize>; using Page = std::array<u8, PageSize>;
using KPhysicalAddress = PAddr;
using KProcessAddress = VAddr;
} // namespace Kernel } // namespace Kernel

@ -37,7 +37,7 @@ constexpr bool IsValidArbitrationType(Svc::ArbitrationType type) {
} // namespace } // namespace
// Wait for an address (via Address Arbiter) // Wait for an address (via Address Arbiter)
Result WaitForAddress(Core::System& system, VAddr address, ArbitrationType arb_type, s32 value, Result WaitForAddress(Core::System& system, u64 address, ArbitrationType arb_type, s32 value,
s64 timeout_ns) { s64 timeout_ns) {
LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, arb_type=0x{:X}, value=0x{:X}, timeout_ns={}", LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, arb_type=0x{:X}, value=0x{:X}, timeout_ns={}",
address, arb_type, value, timeout_ns); address, arb_type, value, timeout_ns);
@ -68,7 +68,7 @@ Result WaitForAddress(Core::System& system, VAddr address, ArbitrationType arb_t
} }
// Signals to an address (via Address Arbiter) // Signals to an address (via Address Arbiter)
Result SignalToAddress(Core::System& system, VAddr address, SignalType signal_type, s32 value, Result SignalToAddress(Core::System& system, u64 address, SignalType signal_type, s32 value,
s32 count) { s32 count) {
LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, signal_type=0x{:X}, value=0x{:X}, count=0x{:X}", LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, signal_type=0x{:X}, value=0x{:X}, count=0x{:X}",
address, signal_type, value, count); address, signal_type, value, count);
@ -82,12 +82,12 @@ Result SignalToAddress(Core::System& system, VAddr address, SignalType signal_ty
.SignalAddressArbiter(address, signal_type, value, count)); .SignalAddressArbiter(address, signal_type, value, count));
} }
Result WaitForAddress64(Core::System& system, VAddr address, ArbitrationType arb_type, s32 value, Result WaitForAddress64(Core::System& system, u64 address, ArbitrationType arb_type, s32 value,
s64 timeout_ns) { s64 timeout_ns) {
R_RETURN(WaitForAddress(system, address, arb_type, value, timeout_ns)); R_RETURN(WaitForAddress(system, address, arb_type, value, timeout_ns));
} }
Result SignalToAddress64(Core::System& system, VAddr address, SignalType signal_type, s32 value, Result SignalToAddress64(Core::System& system, u64 address, SignalType signal_type, s32 value,
s32 count) { s32 count) {
R_RETURN(SignalToAddress(system, address, signal_type, value, count)); R_RETURN(SignalToAddress(system, address, signal_type, value, count));
} }

@ -29,7 +29,7 @@ constexpr bool IsValidUnmapFromOwnerCodeMemoryPermission(MemoryPermission perm)
} // namespace } // namespace
Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, uint64_t size) { Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t size) {
LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, size=0x{:X}", address, size); LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, size=0x{:X}", address, size);
// Get kernel instance. // Get kernel instance.
@ -64,7 +64,7 @@ Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, uint64
} }
Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
CodeMemoryOperation operation, VAddr address, uint64_t size, CodeMemoryOperation operation, u64 address, uint64_t size,
MemoryPermission perm) { MemoryPermission perm) {
LOG_TRACE(Kernel_SVC, LOG_TRACE(Kernel_SVC,

@ -11,7 +11,7 @@
namespace Kernel::Svc { namespace Kernel::Svc {
/// Wait process wide key atomic /// Wait process wide key atomic
Result WaitProcessWideKeyAtomic(Core::System& system, VAddr address, VAddr cv_key, u32 tag, Result WaitProcessWideKeyAtomic(Core::System& system, u64 address, u64 cv_key, u32 tag,
s64 timeout_ns) { s64 timeout_ns) {
LOG_TRACE(Kernel_SVC, "called address={:X}, cv_key={:X}, tag=0x{:08X}, timeout_ns={}", address, LOG_TRACE(Kernel_SVC, "called address={:X}, cv_key={:X}, tag=0x{:08X}, timeout_ns={}", address,
cv_key, tag, timeout_ns); cv_key, tag, timeout_ns);
@ -43,7 +43,7 @@ Result WaitProcessWideKeyAtomic(Core::System& system, VAddr address, VAddr cv_ke
} }
/// Signal process wide key /// Signal process wide key
void SignalProcessWideKey(Core::System& system, VAddr cv_key, s32 count) { void SignalProcessWideKey(Core::System& system, u64 cv_key, s32 count) {
LOG_TRACE(Kernel_SVC, "called, cv_key=0x{:X}, count=0x{:08X}", cv_key, count); LOG_TRACE(Kernel_SVC, "called, cv_key=0x{:X}, count=0x{:08X}", cv_key, count);
// Signal the condition variable. // Signal the condition variable.

@ -8,7 +8,7 @@
namespace Kernel::Svc { namespace Kernel::Svc {
/// Used to output a message on a debug hardware unit - does nothing on a retail unit /// Used to output a message on a debug hardware unit - does nothing on a retail unit
Result OutputDebugString(Core::System& system, VAddr address, u64 len) { Result OutputDebugString(Core::System& system, u64 address, u64 len) {
R_SUCCEED_IF(len == 0); R_SUCCEED_IF(len == 0);
std::string str(len, '\0'); std::string str(len, '\0');

@ -20,7 +20,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
bool has_dumped_buffer{}; bool has_dumped_buffer{};
std::vector<u8> debug_buffer; std::vector<u8> debug_buffer;
const auto handle_debug_buffer = [&](VAddr addr, u64 sz) { const auto handle_debug_buffer = [&](u64 addr, u64 sz) {
if (sz == 0 || addr == 0 || has_dumped_buffer) { if (sz == 0 || addr == 0 || has_dumped_buffer) {
return; return;
} }

@ -54,7 +54,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
R_SUCCEED(); R_SUCCEED();
case InfoType::AliasRegionAddress: case InfoType::AliasRegionAddress:
*result = process->PageTable().GetAliasRegionStart(); *result = GetInteger(process->PageTable().GetAliasRegionStart());
R_SUCCEED(); R_SUCCEED();
case InfoType::AliasRegionSize: case InfoType::AliasRegionSize:
@ -62,7 +62,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
R_SUCCEED(); R_SUCCEED();
case InfoType::HeapRegionAddress: case InfoType::HeapRegionAddress:
*result = process->PageTable().GetHeapRegionStart(); *result = GetInteger(process->PageTable().GetHeapRegionStart());
R_SUCCEED(); R_SUCCEED();
case InfoType::HeapRegionSize: case InfoType::HeapRegionSize:
@ -70,7 +70,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
R_SUCCEED(); R_SUCCEED();
case InfoType::AslrRegionAddress: case InfoType::AslrRegionAddress:
*result = process->PageTable().GetAliasCodeRegionStart(); *result = GetInteger(process->PageTable().GetAliasCodeRegionStart());
R_SUCCEED(); R_SUCCEED();
case InfoType::AslrRegionSize: case InfoType::AslrRegionSize:
@ -78,7 +78,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
R_SUCCEED(); R_SUCCEED();
case InfoType::StackRegionAddress: case InfoType::StackRegionAddress:
*result = process->PageTable().GetStackRegionStart(); *result = GetInteger(process->PageTable().GetStackRegionStart());
R_SUCCEED(); R_SUCCEED();
case InfoType::StackRegionSize: case InfoType::StackRegionSize:
@ -107,7 +107,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
R_SUCCEED(); R_SUCCEED();
case InfoType::UserExceptionContextAddress: case InfoType::UserExceptionContextAddress:
*result = process->GetProcessLocalRegionAddress(); *result = GetInteger(process->GetProcessLocalRegionAddress());
R_SUCCEED(); R_SUCCEED();
case InfoType::TotalNonSystemMemorySize: case InfoType::TotalNonSystemMemorySize:

@ -9,7 +9,7 @@
namespace Kernel::Svc { namespace Kernel::Svc {
/// Attempts to locks a mutex /// Attempts to locks a mutex
Result ArbitrateLock(Core::System& system, Handle thread_handle, VAddr address, u32 tag) { Result ArbitrateLock(Core::System& system, Handle thread_handle, u64 address, u32 tag) {
LOG_TRACE(Kernel_SVC, "called thread_handle=0x{:08X}, address=0x{:X}, tag=0x{:08X}", LOG_TRACE(Kernel_SVC, "called thread_handle=0x{:08X}, address=0x{:X}, tag=0x{:08X}",
thread_handle, address, tag); thread_handle, address, tag);
@ -21,7 +21,7 @@ Result ArbitrateLock(Core::System& system, Handle thread_handle, VAddr address,
} }
/// Unlock a mutex /// Unlock a mutex
Result ArbitrateUnlock(Core::System& system, VAddr address) { Result ArbitrateUnlock(Core::System& system, u64 address) {
LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address); LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address);
// Validate the input address. // Validate the input address.

@ -22,15 +22,14 @@ constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
// Checks if address + size is greater than the given address // Checks if address + size is greater than the given address
// This can return false if the size causes an overflow of a 64-bit type // This can return false if the size causes an overflow of a 64-bit type
// or if the given size is zero. // or if the given size is zero.
constexpr bool IsValidAddressRange(VAddr address, u64 size) { constexpr bool IsValidAddressRange(u64 address, u64 size) {
return address + size > address; return address + size > address;
} }
// Helper function that performs the common sanity checks for svcMapMemory // Helper function that performs the common sanity checks for svcMapMemory
// and svcUnmapMemory. This is doable, as both functions perform their sanitizing // and svcUnmapMemory. This is doable, as both functions perform their sanitizing
// in the same order. // in the same order.
Result MapUnmapMemorySanityChecks(const KPageTable& manager, VAddr dst_addr, VAddr src_addr, Result MapUnmapMemorySanityChecks(const KPageTable& manager, u64 dst_addr, u64 src_addr, u64 size) {
u64 size) {
if (!Common::Is4KBAligned(dst_addr)) { if (!Common::Is4KBAligned(dst_addr)) {
LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr); LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr);
R_THROW(ResultInvalidAddress); R_THROW(ResultInvalidAddress);
@ -99,7 +98,7 @@ Result MapUnmapMemorySanityChecks(const KPageTable& manager, VAddr dst_addr, VAd
} // namespace } // namespace
Result SetMemoryPermission(Core::System& system, VAddr address, u64 size, MemoryPermission perm) { Result SetMemoryPermission(Core::System& system, u64 address, u64 size, MemoryPermission perm) {
LOG_DEBUG(Kernel_SVC, "called, address=0x{:016X}, size=0x{:X}, perm=0x{:08X", address, size, LOG_DEBUG(Kernel_SVC, "called, address=0x{:016X}, size=0x{:X}, perm=0x{:08X", address, size,
perm); perm);
@ -120,7 +119,7 @@ Result SetMemoryPermission(Core::System& system, VAddr address, u64 size, Memory
R_RETURN(page_table.SetMemoryPermission(address, size, perm)); R_RETURN(page_table.SetMemoryPermission(address, size, perm));
} }
Result SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, u32 attr) { Result SetMemoryAttribute(Core::System& system, u64 address, u64 size, u32 mask, u32 attr) {
LOG_DEBUG(Kernel_SVC, LOG_DEBUG(Kernel_SVC,
"called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address, "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address,
size, mask, attr); size, mask, attr);
@ -145,7 +144,7 @@ Result SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mas
} }
/// Maps a memory range into a different range. /// Maps a memory range into a different range.
Result MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { Result MapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size); src_addr, size);
@ -160,7 +159,7 @@ Result MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size)
} }
/// Unmaps a region that was previously mapped with svcMapMemory /// Unmaps a region that was previously mapped with svcMapMemory
Result UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { Result UnmapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size); src_addr, size);

@ -8,7 +8,7 @@
namespace Kernel::Svc { namespace Kernel::Svc {
/// Set the process heap to a given Size. It can both extend and shrink the heap. /// Set the process heap to a given Size. It can both extend and shrink the heap.
Result SetHeapSize(Core::System& system, VAddr* out_address, u64 size) { Result SetHeapSize(Core::System& system, u64* out_address, u64 size) {
LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", size); LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", size);
// Validate size. // Validate size.
@ -20,7 +20,7 @@ Result SetHeapSize(Core::System& system, VAddr* out_address, u64 size) {
} }
/// Maps memory at a desired address /// Maps memory at a desired address
Result MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
if (!Common::Is4KBAligned(addr)) { if (!Common::Is4KBAligned(addr)) {
@ -69,7 +69,7 @@ Result MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
} }
/// Unmaps memory previously mapped via MapPhysicalMemory /// Unmaps memory previously mapped via MapPhysicalMemory
Result UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { Result UnmapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
if (!Common::Is4KBAligned(addr)) { if (!Common::Is4KBAligned(addr)) {

@ -12,7 +12,7 @@
namespace Kernel::Svc { namespace Kernel::Svc {
Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr user_name) { Result ConnectToNamedPort(Core::System& system, Handle* out, u64 user_name) {
// Copy the provided name from user memory to kernel memory. // Copy the provided name from user memory to kernel memory.
auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax); auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax);

@ -50,7 +50,7 @@ Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) {
R_SUCCEED(); R_SUCCEED();
} }
Result GetProcessList(Core::System& system, s32* out_num_processes, VAddr out_process_ids, Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_process_ids,
int32_t out_process_ids_size) { int32_t out_process_ids_size) {
LOG_DEBUG(Kernel_SVC, "called. out_process_ids=0x{:016X}, out_process_ids_size={}", LOG_DEBUG(Kernel_SVC, "called. out_process_ids=0x{:016X}, out_process_ids_size={}",
out_process_ids, out_process_ids_size); out_process_ids, out_process_ids_size);

@ -8,7 +8,7 @@
namespace Kernel::Svc { namespace Kernel::Svc {
namespace { namespace {
constexpr bool IsValidAddressRange(VAddr address, u64 size) { constexpr bool IsValidAddressRange(u64 address, u64 size) {
return address + size > address; return address + size > address;
} }
@ -26,7 +26,7 @@ constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) {
} // namespace } // namespace
Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, VAddr address, Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u64 address,
u64 size, Svc::MemoryPermission perm) { u64 size, Svc::MemoryPermission perm) {
LOG_TRACE(Kernel_SVC, LOG_TRACE(Kernel_SVC,
"called, process_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", "called, process_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
@ -56,8 +56,8 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, V
R_RETURN(page_table.SetProcessMemoryPermission(address, size, perm)); R_RETURN(page_table.SetProcessMemoryPermission(address, size, perm));
} }
Result MapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle, Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_handle,
VAddr src_address, u64 size) { u64 src_address, u64 size) {
LOG_TRACE(Kernel_SVC, LOG_TRACE(Kernel_SVC,
"called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}", "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}",
dst_address, process_handle, src_address, size); dst_address, process_handle, src_address, size);
@ -97,8 +97,8 @@ Result MapProcessMemory(Core::System& system, VAddr dst_address, Handle process_
KMemoryPermission::UserReadWrite)); KMemoryPermission::UserReadWrite));
} }
Result UnmapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle, Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_handle,
VAddr src_address, u64 size) { u64 src_address, u64 size) {
LOG_TRACE(Kernel_SVC, LOG_TRACE(Kernel_SVC,
"called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}", "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}",
dst_address, process_handle, src_address, size); dst_address, process_handle, src_address, size);

@ -8,7 +8,7 @@
namespace Kernel::Svc { namespace Kernel::Svc {
Result QueryMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, Result QueryMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
VAddr query_address) { u64 query_address) {
LOG_TRACE(Kernel_SVC, LOG_TRACE(Kernel_SVC,
"called, out_memory_info=0x{:016X}, " "called, out_memory_info=0x{:016X}, "
"query_address=0x{:016X}", "query_address=0x{:016X}",

@ -26,7 +26,7 @@ constexpr bool IsValidSharedMemoryPermission(MemoryPermission perm) {
} // namespace } // namespace
Result MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size, Result MapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, u64 size,
Svc::MemoryPermission map_perm) { Svc::MemoryPermission map_perm) {
LOG_TRACE(Kernel_SVC, LOG_TRACE(Kernel_SVC,
"called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
@ -64,7 +64,7 @@ Result MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address,
R_RETURN(shmem->Map(process, address, size, map_perm)); R_RETURN(shmem->Map(process, address, size, map_perm));
} }
Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size) { Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, u64 size) {
// Validate the address/size. // Validate the address/size.
R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);

@ -80,7 +80,7 @@ static Result WaitSynchronization(Core::System& system, int32_t* out_index, cons
} }
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds /// Wait for the given handles to synchronize, timeout after the specified nanoseconds
Result WaitSynchronization(Core::System& system, int32_t* out_index, VAddr user_handles, Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_handles,
int32_t num_handles, int64_t timeout_ns) { int32_t num_handles, int64_t timeout_ns) {
LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles, LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles,
num_handles, timeout_ns); num_handles, timeout_ns);

@ -19,8 +19,8 @@ constexpr bool IsValidVirtualCoreId(int32_t core_id) {
} // Anonymous namespace } // Anonymous namespace
/// Creates a new thread /// Creates a new thread
Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg, Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u64 arg,
VAddr stack_bottom, s32 priority, s32 core_id) { u64 stack_bottom, s32 priority, s32 core_id) {
LOG_DEBUG(Kernel_SVC, LOG_DEBUG(Kernel_SVC,
"called entry_point=0x{:08X}, arg=0x{:08X}, stack_bottom=0x{:08X}, " "called entry_point=0x{:08X}, arg=0x{:08X}, stack_bottom=0x{:08X}, "
"priority=0x{:08X}, core_id=0x{:08X}", "priority=0x{:08X}, core_id=0x{:08X}",
@ -129,7 +129,7 @@ void SleepThread(Core::System& system, s64 nanoseconds) {
} }
/// Gets the thread context /// Gets the thread context
Result GetThreadContext3(Core::System& system, VAddr out_context, Handle thread_handle) { Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_handle) {
LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context, LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context,
thread_handle); thread_handle);
@ -217,7 +217,7 @@ Result SetThreadPriority(Core::System& system, Handle thread_handle, s32 priorit
R_SUCCEED(); R_SUCCEED();
} }
Result GetThreadList(Core::System& system, s32* out_num_threads, VAddr out_thread_ids, Result GetThreadList(Core::System& system, s32* out_num_threads, u64 out_thread_ids,
s32 out_thread_ids_size, Handle debug_handle) { s32 out_thread_ids_size, Handle debug_handle) {
// TODO: Handle this case when debug events are supported. // TODO: Handle this case when debug events are supported.
UNIMPLEMENTED_IF(debug_handle != InvalidHandle); UNIMPLEMENTED_IF(debug_handle != InvalidHandle);

@ -25,7 +25,7 @@ constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) {
} // Anonymous namespace } // Anonymous namespace
/// Creates a TransferMemory object /// Creates a TransferMemory object
Result CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size, Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64 size,
MemoryPermission map_perm) { MemoryPermission map_perm) {
auto& kernel = system.Kernel(); auto& kernel = system.Kernel();

@ -253,7 +253,7 @@ struct LastThreadContext {
}; };
struct PhysicalMemoryInfo { struct PhysicalMemoryInfo {
PAddr physical_address; u64 physical_address;
u64 virtual_address; u64 virtual_address;
u64 size; u64 size;
}; };
@ -359,7 +359,7 @@ struct LastThreadContext {
}; };
struct PhysicalMemoryInfo { struct PhysicalMemoryInfo {
PAddr physical_address; u64 physical_address;
u32 virtual_address; u32 virtual_address;
u32 size; u32 size;
}; };

@ -63,7 +63,7 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
system.Memory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo)); system.Memory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo));
} }
void Controller_ConsoleSixAxis::SetTransferMemoryAddress(VAddr t_mem) { void Controller_ConsoleSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) {
transfer_memory = t_mem; transfer_memory = t_mem;
} }

@ -5,8 +5,8 @@
#include <array> #include <array>
#include "common/common_types.h"
#include "common/quaternion.h" #include "common/quaternion.h"
#include "common/typed_address.h"
#include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/controllers/controller_base.h"
#include "core/hle/service/hid/ring_lifo.h" #include "core/hle/service/hid/ring_lifo.h"
@ -34,7 +34,7 @@ public:
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
// Called on InitializeSevenSixAxisSensor // Called on InitializeSevenSixAxisSensor
void SetTransferMemoryAddress(VAddr t_mem); void SetTransferMemoryAddress(Common::ProcessAddress t_mem);
// Called on ResetSevenSixAxisSensorTimestamp // Called on ResetSevenSixAxisSensorTimestamp
void ResetTimestamp(); void ResetTimestamp();
@ -66,7 +66,7 @@ private:
static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size"); static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size");
SevenSixAxisState next_seven_sixaxis_state{}; SevenSixAxisState next_seven_sixaxis_state{};
VAddr transfer_memory{}; Common::ProcessAddress transfer_memory{};
ConsoleSharedMemory* shared_memory = nullptr; ConsoleSharedMemory* shared_memory = nullptr;
Core::HID::EmulatedConsole* console = nullptr; Core::HID::EmulatedConsole* console = nullptr;

@ -152,7 +152,7 @@ Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandl
} }
Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave,
VAddr t_mem, u64 size) { Common::ProcessAddress t_mem, u64 size) {
if (handle.npad_id != active_handle.npad_id) { if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle; return InvalidPalmaHandle;
} }

@ -5,7 +5,7 @@
#include <array> #include <array>
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/typed_address.h"
#include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/controllers/controller_base.h"
#include "core/hle/service/hid/errors.h" #include "core/hle/service/hid/errors.h"
@ -125,8 +125,8 @@ public:
Result ReadPalmaUniqueCode(const PalmaConnectionHandle& handle); Result ReadPalmaUniqueCode(const PalmaConnectionHandle& handle);
Result SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle); Result SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle);
Result WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown); Result WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown);
Result WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, VAddr t_mem, Result WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave,
u64 size); Common::ProcessAddress t_mem, u64 size);
Result SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, Result SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle,
s32 database_id_version_); s32 database_id_version_);
Result GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle); Result GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle);

@ -59,7 +59,7 @@ void HidbusBase::DisablePollingMode() {
polling_mode_enabled = false; polling_mode_enabled = false;
} }
void HidbusBase::SetTransferMemoryAddress(VAddr t_mem) { void HidbusBase::SetTransferMemoryAddress(Common::ProcessAddress t_mem) {
transfer_memory = t_mem; transfer_memory = t_mem;
} }

@ -5,7 +5,7 @@
#include <array> #include <array>
#include <span> #include <span>
#include "common/common_types.h" #include "common/typed_address.h"
#include "core/hle/result.h" #include "core/hle/result.h"
namespace Core { namespace Core {
@ -138,7 +138,7 @@ public:
void DisablePollingMode(); void DisablePollingMode();
// Called on EnableJoyPollingReceiveMode // Called on EnableJoyPollingReceiveMode
void SetTransferMemoryAddress(VAddr t_mem); void SetTransferMemoryAddress(Common::ProcessAddress t_mem);
Kernel::KReadableEvent& GetSendCommandAsycEvent() const; Kernel::KReadableEvent& GetSendCommandAsycEvent() const;
@ -174,7 +174,7 @@ protected:
JoyEnableSixAxisDataAccessor enable_sixaxis_data{}; JoyEnableSixAxisDataAccessor enable_sixaxis_data{};
ButtonOnlyPollingDataAccessor button_only_data{}; ButtonOnlyPollingDataAccessor button_only_data{};
VAddr transfer_memory{}; Common::ProcessAddress transfer_memory{};
Core::System& system; Core::System& system;
Kernel::KEvent* send_command_async_event; Kernel::KEvent* send_command_async_event;

@ -140,7 +140,7 @@ void ImageTransferProcessor::SetConfig(
npad_device->SetCameraFormat(current_config.origin_format); npad_device->SetCameraFormat(current_config.origin_format);
} }
void ImageTransferProcessor::SetTransferMemoryAddress(VAddr t_mem) { void ImageTransferProcessor::SetTransferMemoryAddress(Common::ProcessAddress t_mem) {
transfer_memory = t_mem; transfer_memory = t_mem;
} }

@ -3,7 +3,7 @@
#pragma once #pragma once
#include "common/common_types.h" #include "common/typed_address.h"
#include "core/hid/irs_types.h" #include "core/hid/irs_types.h"
#include "core/hle/service/hid/irsensor/processor_base.h" #include "core/hle/service/hid/irsensor/processor_base.h"
@ -37,7 +37,7 @@ public:
void SetConfig(Core::IrSensor::PackedImageTransferProcessorExConfig config); void SetConfig(Core::IrSensor::PackedImageTransferProcessorExConfig config);
// Transfer memory where the image data will be stored // Transfer memory where the image data will be stored
void SetTransferMemoryAddress(VAddr t_mem); void SetTransferMemoryAddress(Common::ProcessAddress t_mem);
Core::IrSensor::ImageTransferProcessorState GetState(std::vector<u8>& data) const; Core::IrSensor::ImageTransferProcessorState GetState(std::vector<u8>& data) const;
@ -72,6 +72,6 @@ private:
int callback_key{}; int callback_key{};
Core::System& system; Core::System& system;
VAddr transfer_memory{}; Common::ProcessAddress transfer_memory{};
}; };
} // namespace Service::IRS } // namespace Service::IRS

@ -195,7 +195,7 @@ public:
} }
// Set up the configuration with the required TransferMemory address // Set up the configuration with the required TransferMemory address
configuration.transfer_memory.offset = tmem->GetSourceAddress(); configuration.transfer_memory.offset = GetInteger(tmem->GetSourceAddress());
configuration.transfer_memory.size = tmem_size; configuration.transfer_memory.size = tmem_size;
// Gather up all the callbacks from the loaded plugin // Gather up all the callbacks from the loaded plugin
@ -383,12 +383,12 @@ public:
} }
const CodeRange user_rx{ const CodeRange user_rx{
.offset = rx_mem->GetSourceAddress(), .offset = GetInteger(rx_mem->GetSourceAddress()),
.size = parameters.rx_size, .size = parameters.rx_size,
}; };
const CodeRange user_ro{ const CodeRange user_ro{
.offset = ro_mem->GetSourceAddress(), .offset = GetInteger(ro_mem->GetSourceAddress()),
.size = parameters.ro_size, .size = parameters.ro_size,
}; };

@ -337,7 +337,7 @@ public:
bool succeeded = false; bool succeeded = false;
const auto map_region_end = const auto map_region_end =
page_table.GetAliasCodeRegionStart() + page_table.GetAliasCodeRegionSize(); GetInteger(page_table.GetAliasCodeRegionStart()) + page_table.GetAliasCodeRegionSize();
while (current_map_addr < map_region_end) { while (current_map_addr < map_region_end) {
if (is_region_available(current_map_addr)) { if (is_region_available(current_map_addr)) {
succeeded = true; succeeded = true;
@ -642,7 +642,8 @@ public:
LOG_WARNING(Service_LDR, "(STUBBED) called"); LOG_WARNING(Service_LDR, "(STUBBED) called");
initialized = true; initialized = true;
current_map_addr = system.ApplicationProcess()->PageTable().GetAliasCodeRegionStart(); current_map_addr =
GetInteger(system.ApplicationProcess()->PageTable().GetAliasCodeRegionStart());
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);

@ -153,7 +153,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
// Load NSO modules // Load NSO modules
modules.clear(); modules.clear();
const VAddr base_address{process.PageTable().GetCodeRegionStart()}; const VAddr base_address{GetInteger(process.PageTable().GetCodeRegionStart())};
VAddr next_load_addr{base_address}; VAddr next_load_addr{base_address};
const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(), const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(),
system.GetContentProvider()}; system.GetContentProvider()};

@ -96,7 +96,7 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
} }
codeset.memory = std::move(program_image); codeset.memory = std::move(program_image);
const VAddr base_address = process.PageTable().GetCodeRegionStart(); const VAddr base_address = GetInteger(process.PageTable().GetCodeRegionStart());
process.LoadModule(std::move(codeset), base_address); process.LoadModule(std::move(codeset), base_address);
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address); LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);

@ -167,7 +167,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::S
modules.clear(); modules.clear();
// Load module // Load module
const VAddr base_address = process.PageTable().GetCodeRegionStart(); const VAddr base_address = GetInteger(process.PageTable().GetCodeRegionStart());
if (!LoadModule(process, system, *file, base_address, true, true)) { if (!LoadModule(process, system, *file, base_address, true, true)) {
return {ResultStatus::ErrorLoadingNSO, {}}; return {ResultStatus::ErrorLoadingNSO, {}};
} }

@ -35,31 +35,35 @@ struct Memory::Impl {
system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width); system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width);
} }
void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) { void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
Common::PhysicalAddress target) {
ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size);
ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", base); ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", GetInteger(base));
ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}", target); ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}",
GetInteger(target));
MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, target, MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, target,
Common::PageType::Memory); Common::PageType::Memory);
if (Settings::IsFastmemEnabled()) { if (Settings::IsFastmemEnabled()) {
system.DeviceMemory().buffer.Map(base, target - DramMemoryMap::Base, size); system.DeviceMemory().buffer.Map(GetInteger(base),
GetInteger(target) - DramMemoryMap::Base, size);
} }
} }
void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) { void UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size) {
ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size);
ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", base); ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", GetInteger(base));
MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, 0, MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, 0,
Common::PageType::Unmapped); Common::PageType::Unmapped);
if (Settings::IsFastmemEnabled()) { if (Settings::IsFastmemEnabled()) {
system.DeviceMemory().buffer.Unmap(base, size); system.DeviceMemory().buffer.Unmap(GetInteger(base), size);
} }
} }
[[nodiscard]] u8* GetPointerFromRasterizerCachedMemory(VAddr vaddr) const { [[nodiscard]] u8* GetPointerFromRasterizerCachedMemory(u64 vaddr) const {
const PAddr paddr{current_page_table->backing_addr[vaddr >> YUZU_PAGEBITS]}; const Common::PhysicalAddress paddr{
current_page_table->backing_addr[vaddr >> YUZU_PAGEBITS]};
if (!paddr) { if (!paddr) {
return {}; return {};
@ -68,8 +72,9 @@ struct Memory::Impl {
return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr; return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr;
} }
[[nodiscard]] u8* GetPointerFromDebugMemory(VAddr vaddr) const { [[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const {
const PAddr paddr{current_page_table->backing_addr[vaddr >> YUZU_PAGEBITS]}; const Common::PhysicalAddress paddr{
current_page_table->backing_addr[vaddr >> YUZU_PAGEBITS]};
if (paddr == 0) { if (paddr == 0) {
return {}; return {};
@ -78,11 +83,11 @@ struct Memory::Impl {
return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr; return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr;
} }
u8 Read8(const VAddr addr) { u8 Read8(const Common::ProcessAddress addr) {
return Read<u8>(addr); return Read<u8>(addr);
} }
u16 Read16(const VAddr addr) { u16 Read16(const Common::ProcessAddress addr) {
if ((addr & 1) == 0) { if ((addr & 1) == 0) {
return Read<u16_le>(addr); return Read<u16_le>(addr);
} else { } else {
@ -92,7 +97,7 @@ struct Memory::Impl {
} }
} }
u32 Read32(const VAddr addr) { u32 Read32(const Common::ProcessAddress addr) {
if ((addr & 3) == 0) { if ((addr & 3) == 0) {
return Read<u32_le>(addr); return Read<u32_le>(addr);
} else { } else {
@ -102,7 +107,7 @@ struct Memory::Impl {
} }
} }
u64 Read64(const VAddr addr) { u64 Read64(const Common::ProcessAddress addr) {
if ((addr & 7) == 0) { if ((addr & 7) == 0) {
return Read<u64_le>(addr); return Read<u64_le>(addr);
} else { } else {
@ -112,11 +117,11 @@ struct Memory::Impl {
} }
} }
void Write8(const VAddr addr, const u8 data) { void Write8(const Common::ProcessAddress addr, const u8 data) {
Write<u8>(addr, data); Write<u8>(addr, data);
} }
void Write16(const VAddr addr, const u16 data) { void Write16(const Common::ProcessAddress addr, const u16 data) {
if ((addr & 1) == 0) { if ((addr & 1) == 0) {
Write<u16_le>(addr, data); Write<u16_le>(addr, data);
} else { } else {
@ -125,7 +130,7 @@ struct Memory::Impl {
} }
} }
void Write32(const VAddr addr, const u32 data) { void Write32(const Common::ProcessAddress addr, const u32 data) {
if ((addr & 3) == 0) { if ((addr & 3) == 0) {
Write<u32_le>(addr, data); Write<u32_le>(addr, data);
} else { } else {
@ -134,7 +139,7 @@ struct Memory::Impl {
} }
} }
void Write64(const VAddr addr, const u64 data) { void Write64(const Common::ProcessAddress addr, const u64 data) {
if ((addr & 7) == 0) { if ((addr & 7) == 0) {
Write<u64_le>(addr, data); Write<u64_le>(addr, data);
} else { } else {
@ -143,23 +148,23 @@ struct Memory::Impl {
} }
} }
bool WriteExclusive8(const VAddr addr, const u8 data, const u8 expected) { bool WriteExclusive8(const Common::ProcessAddress addr, const u8 data, const u8 expected) {
return WriteExclusive<u8>(addr, data, expected); return WriteExclusive<u8>(addr, data, expected);
} }
bool WriteExclusive16(const VAddr addr, const u16 data, const u16 expected) { bool WriteExclusive16(const Common::ProcessAddress addr, const u16 data, const u16 expected) {
return WriteExclusive<u16_le>(addr, data, expected); return WriteExclusive<u16_le>(addr, data, expected);
} }
bool WriteExclusive32(const VAddr addr, const u32 data, const u32 expected) { bool WriteExclusive32(const Common::ProcessAddress addr, const u32 data, const u32 expected) {
return WriteExclusive<u32_le>(addr, data, expected); return WriteExclusive<u32_le>(addr, data, expected);
} }
bool WriteExclusive64(const VAddr addr, const u64 data, const u64 expected) { bool WriteExclusive64(const Common::ProcessAddress addr, const u64 data, const u64 expected) {
return WriteExclusive<u64_le>(addr, data, expected); return WriteExclusive<u64_le>(addr, data, expected);
} }
std::string ReadCString(VAddr vaddr, std::size_t max_length) { std::string ReadCString(Common::ProcessAddress vaddr, std::size_t max_length) {
std::string string; std::string string;
string.reserve(max_length); string.reserve(max_length);
for (std::size_t i = 0; i < max_length; ++i) { for (std::size_t i = 0; i < max_length; ++i) {
@ -174,8 +179,9 @@ struct Memory::Impl {
return string; return string;
} }
void WalkBlock(const Kernel::KProcess& process, const VAddr addr, const std::size_t size, void WalkBlock(const Kernel::KProcess& process, const Common::ProcessAddress addr,
auto on_unmapped, auto on_memory, auto on_rasterizer, auto increment) { const std::size_t size, auto on_unmapped, auto on_memory, auto on_rasterizer,
auto increment) {
const auto& page_table = process.PageTable().PageTableImpl(); const auto& page_table = process.PageTable().PageTableImpl();
std::size_t remaining_size = size; std::size_t remaining_size = size;
std::size_t page_index = addr >> YUZU_PAGEBITS; std::size_t page_index = addr >> YUZU_PAGEBITS;
@ -185,7 +191,7 @@ struct Memory::Impl {
const std::size_t copy_amount = const std::size_t copy_amount =
std::min(static_cast<std::size_t>(YUZU_PAGESIZE) - page_offset, remaining_size); std::min(static_cast<std::size_t>(YUZU_PAGESIZE) - page_offset, remaining_size);
const auto current_vaddr = const auto current_vaddr =
static_cast<VAddr>((page_index << YUZU_PAGEBITS) + page_offset); static_cast<u64>((page_index << YUZU_PAGEBITS) + page_offset);
const auto [pointer, type] = page_table.pointers[page_index].PointerType(); const auto [pointer, type] = page_table.pointers[page_index].PointerType();
switch (type) { switch (type) {
@ -220,24 +226,24 @@ struct Memory::Impl {
} }
template <bool UNSAFE> template <bool UNSAFE>
void ReadBlockImpl(const Kernel::KProcess& process, const VAddr src_addr, void* dest_buffer, void ReadBlockImpl(const Kernel::KProcess& process, const Common::ProcessAddress src_addr,
const std::size_t size) { void* dest_buffer, const std::size_t size) {
WalkBlock( WalkBlock(
process, src_addr, size, process, src_addr, size,
[src_addr, size, &dest_buffer](const std::size_t copy_amount, [src_addr, size, &dest_buffer](const std::size_t copy_amount,
const VAddr current_vaddr) { const Common::ProcessAddress current_vaddr) {
LOG_ERROR(HW_Memory, LOG_ERROR(HW_Memory,
"Unmapped ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", "Unmapped ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
current_vaddr, src_addr, size); GetInteger(current_vaddr), GetInteger(src_addr), size);
std::memset(dest_buffer, 0, copy_amount); std::memset(dest_buffer, 0, copy_amount);
}, },
[&](const std::size_t copy_amount, const u8* const src_ptr) { [&](const std::size_t copy_amount, const u8* const src_ptr) {
std::memcpy(dest_buffer, src_ptr, copy_amount); std::memcpy(dest_buffer, src_ptr, copy_amount);
}, },
[&](const VAddr current_vaddr, const std::size_t copy_amount, [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
const u8* const host_ptr) { const u8* const host_ptr) {
if constexpr (!UNSAFE) { if constexpr (!UNSAFE) {
system.GPU().FlushRegion(current_vaddr, copy_amount); system.GPU().FlushRegion(GetInteger(current_vaddr), copy_amount);
} }
std::memcpy(dest_buffer, host_ptr, copy_amount); std::memcpy(dest_buffer, host_ptr, copy_amount);
}, },
@ -246,30 +252,34 @@ struct Memory::Impl {
}); });
} }
void ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_t size) { void ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
const std::size_t size) {
ReadBlockImpl<false>(*system.ApplicationProcess(), src_addr, dest_buffer, size); ReadBlockImpl<false>(*system.ApplicationProcess(), src_addr, dest_buffer, size);
} }
void ReadBlockUnsafe(const VAddr src_addr, void* dest_buffer, const std::size_t size) { void ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer,
const std::size_t size) {
ReadBlockImpl<true>(*system.ApplicationProcess(), src_addr, dest_buffer, size); ReadBlockImpl<true>(*system.ApplicationProcess(), src_addr, dest_buffer, size);
} }
template <bool UNSAFE> template <bool UNSAFE>
void WriteBlockImpl(const Kernel::KProcess& process, const VAddr dest_addr, void WriteBlockImpl(const Kernel::KProcess& process, const Common::ProcessAddress dest_addr,
const void* src_buffer, const std::size_t size) { const void* src_buffer, const std::size_t size) {
WalkBlock( WalkBlock(
process, dest_addr, size, process, dest_addr, size,
[dest_addr, size](const std::size_t copy_amount, const VAddr current_vaddr) { [dest_addr, size](const std::size_t copy_amount,
const Common::ProcessAddress current_vaddr) {
LOG_ERROR(HW_Memory, LOG_ERROR(HW_Memory,
"Unmapped WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", "Unmapped WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
current_vaddr, dest_addr, size); GetInteger(current_vaddr), GetInteger(dest_addr), size);
}, },
[&](const std::size_t copy_amount, u8* const dest_ptr) { [&](const std::size_t copy_amount, u8* const dest_ptr) {
std::memcpy(dest_ptr, src_buffer, copy_amount); std::memcpy(dest_ptr, src_buffer, copy_amount);
}, },
[&](const VAddr current_vaddr, const std::size_t copy_amount, u8* const host_ptr) { [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
u8* const host_ptr) {
if constexpr (!UNSAFE) { if constexpr (!UNSAFE) {
system.GPU().InvalidateRegion(current_vaddr, copy_amount); system.GPU().InvalidateRegion(GetInteger(current_vaddr), copy_amount);
} }
std::memcpy(host_ptr, src_buffer, copy_amount); std::memcpy(host_ptr, src_buffer, copy_amount);
}, },
@ -278,71 +288,77 @@ struct Memory::Impl {
}); });
} }
void WriteBlock(const VAddr dest_addr, const void* src_buffer, const std::size_t size) { void WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
const std::size_t size) {
WriteBlockImpl<false>(*system.ApplicationProcess(), dest_addr, src_buffer, size); WriteBlockImpl<false>(*system.ApplicationProcess(), dest_addr, src_buffer, size);
} }
void WriteBlockUnsafe(const VAddr dest_addr, const void* src_buffer, const std::size_t size) { void WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer,
const std::size_t size) {
WriteBlockImpl<true>(*system.ApplicationProcess(), dest_addr, src_buffer, size); WriteBlockImpl<true>(*system.ApplicationProcess(), dest_addr, src_buffer, size);
} }
void ZeroBlock(const Kernel::KProcess& process, const VAddr dest_addr, const std::size_t size) { void ZeroBlock(const Kernel::KProcess& process, const Common::ProcessAddress dest_addr,
const std::size_t size) {
WalkBlock( WalkBlock(
process, dest_addr, size, process, dest_addr, size,
[dest_addr, size](const std::size_t copy_amount, const VAddr current_vaddr) { [dest_addr, size](const std::size_t copy_amount,
const Common::ProcessAddress current_vaddr) {
LOG_ERROR(HW_Memory, LOG_ERROR(HW_Memory,
"Unmapped ZeroBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", "Unmapped ZeroBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
current_vaddr, dest_addr, size); GetInteger(current_vaddr), GetInteger(dest_addr), size);
}, },
[](const std::size_t copy_amount, u8* const dest_ptr) { [](const std::size_t copy_amount, u8* const dest_ptr) {
std::memset(dest_ptr, 0, copy_amount); std::memset(dest_ptr, 0, copy_amount);
}, },
[&](const VAddr current_vaddr, const std::size_t copy_amount, u8* const host_ptr) { [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
system.GPU().InvalidateRegion(current_vaddr, copy_amount); u8* const host_ptr) {
system.GPU().InvalidateRegion(GetInteger(current_vaddr), copy_amount);
std::memset(host_ptr, 0, copy_amount); std::memset(host_ptr, 0, copy_amount);
}, },
[](const std::size_t copy_amount) {}); [](const std::size_t copy_amount) {});
} }
void CopyBlock(const Kernel::KProcess& process, VAddr dest_addr, VAddr src_addr, void CopyBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
const std::size_t size) { Common::ProcessAddress src_addr, const std::size_t size) {
WalkBlock( WalkBlock(
process, dest_addr, size, process, dest_addr, size,
[&](const std::size_t copy_amount, const VAddr current_vaddr) { [&](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
LOG_ERROR(HW_Memory, LOG_ERROR(HW_Memory,
"Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
current_vaddr, src_addr, size); GetInteger(current_vaddr), GetInteger(src_addr), size);
ZeroBlock(process, dest_addr, copy_amount); ZeroBlock(process, dest_addr, copy_amount);
}, },
[&](const std::size_t copy_amount, const u8* const src_ptr) { [&](const std::size_t copy_amount, const u8* const src_ptr) {
WriteBlockImpl<false>(process, dest_addr, src_ptr, copy_amount); WriteBlockImpl<false>(process, dest_addr, src_ptr, copy_amount);
}, },
[&](const VAddr current_vaddr, const std::size_t copy_amount, u8* const host_ptr) { [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
system.GPU().FlushRegion(current_vaddr, copy_amount); u8* const host_ptr) {
system.GPU().FlushRegion(GetInteger(current_vaddr), copy_amount);
WriteBlockImpl<false>(process, dest_addr, host_ptr, copy_amount); WriteBlockImpl<false>(process, dest_addr, host_ptr, copy_amount);
}, },
[&](const std::size_t copy_amount) { [&](const std::size_t copy_amount) {
dest_addr += static_cast<VAddr>(copy_amount); dest_addr += copy_amount;
src_addr += static_cast<VAddr>(copy_amount); src_addr += copy_amount;
}); });
} }
template <typename Callback> template <typename Callback>
Result PerformCacheOperation(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size, Result PerformCacheOperation(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
Callback&& cb) { std::size_t size, Callback&& cb) {
class InvalidMemoryException : public std::exception {}; class InvalidMemoryException : public std::exception {};
try { try {
WalkBlock( WalkBlock(
process, dest_addr, size, process, dest_addr, size,
[&](const std::size_t block_size, const VAddr current_vaddr) { [&](const std::size_t block_size, const Common::ProcessAddress current_vaddr) {
LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}", current_vaddr); LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}",
GetInteger(current_vaddr));
throw InvalidMemoryException(); throw InvalidMemoryException();
}, },
[&](const std::size_t block_size, u8* const host_ptr) {}, [&](const std::size_t block_size, u8* const host_ptr) {},
[&](const VAddr current_vaddr, const std::size_t block_size, u8* const host_ptr) { [&](const Common::ProcessAddress current_vaddr, const std::size_t block_size,
cb(current_vaddr, block_size); u8* const host_ptr) { cb(current_vaddr, block_size); },
},
[](const std::size_t block_size) {}); [](const std::size_t block_size) {});
} catch (InvalidMemoryException&) { } catch (InvalidMemoryException&) {
return Kernel::ResultInvalidCurrentMemory; return Kernel::ResultInvalidCurrentMemory;
@ -351,34 +367,40 @@ struct Memory::Impl {
return ResultSuccess; return ResultSuccess;
} }
Result InvalidateDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { Result InvalidateDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
auto on_rasterizer = [&](const VAddr current_vaddr, const std::size_t block_size) { std::size_t size) {
auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
const std::size_t block_size) {
// dc ivac: Invalidate to point of coherency // dc ivac: Invalidate to point of coherency
// GPU flush -> CPU invalidate // GPU flush -> CPU invalidate
system.GPU().FlushRegion(current_vaddr, block_size); system.GPU().FlushRegion(GetInteger(current_vaddr), block_size);
}; };
return PerformCacheOperation(process, dest_addr, size, on_rasterizer); return PerformCacheOperation(process, dest_addr, size, on_rasterizer);
} }
Result StoreDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { Result StoreDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
auto on_rasterizer = [&](const VAddr current_vaddr, const std::size_t block_size) { std::size_t size) {
auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
const std::size_t block_size) {
// dc cvac: Store to point of coherency // dc cvac: Store to point of coherency
// CPU flush -> GPU invalidate // CPU flush -> GPU invalidate
system.GPU().InvalidateRegion(current_vaddr, block_size); system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
}; };
return PerformCacheOperation(process, dest_addr, size, on_rasterizer); return PerformCacheOperation(process, dest_addr, size, on_rasterizer);
} }
Result FlushDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { Result FlushDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
auto on_rasterizer = [&](const VAddr current_vaddr, const std::size_t block_size) { std::size_t size) {
auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
const std::size_t block_size) {
// dc civac: Store to point of coherency, and invalidate from cache // dc civac: Store to point of coherency, and invalidate from cache
// CPU flush -> GPU invalidate // CPU flush -> GPU invalidate
system.GPU().InvalidateRegion(current_vaddr, block_size); system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
}; };
return PerformCacheOperation(process, dest_addr, size, on_rasterizer); return PerformCacheOperation(process, dest_addr, size, on_rasterizer);
} }
void MarkRegionDebug(VAddr vaddr, u64 size, bool debug) { void MarkRegionDebug(u64 vaddr, u64 size, bool debug) {
if (vaddr == 0) { if (vaddr == 0) {
return; return;
} }
@ -434,7 +456,7 @@ struct Memory::Impl {
} }
} }
void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) { void RasterizerMarkRegionCached(u64 vaddr, u64 size, bool cached) {
if (vaddr == 0) { if (vaddr == 0) {
return; return;
} }
@ -514,10 +536,12 @@ struct Memory::Impl {
* @param target The target address to begin mapping from. * @param target The target address to begin mapping from.
* @param type The page type to map the memory as. * @param type The page type to map the memory as.
*/ */
void MapPages(Common::PageTable& page_table, VAddr base, u64 size, PAddr target, void MapPages(Common::PageTable& page_table, Common::ProcessAddress base_address, u64 size,
Common::PageType type) { Common::PhysicalAddress target, Common::PageType type) {
LOG_DEBUG(HW_Memory, "Mapping {:016X} onto {:016X}-{:016X}", target, base * YUZU_PAGESIZE, auto base = GetInteger(base_address);
(base + size) * YUZU_PAGESIZE);
LOG_DEBUG(HW_Memory, "Mapping {:016X} onto {:016X}-{:016X}", GetInteger(target),
base * YUZU_PAGESIZE, (base + size) * YUZU_PAGESIZE);
// During boot, current_page_table might not be set yet, in which case we need not flush // During boot, current_page_table might not be set yet, in which case we need not flush
if (system.IsPoweredOn()) { if (system.IsPoweredOn()) {
@ -530,7 +554,7 @@ struct Memory::Impl {
} }
} }
const VAddr end = base + size; const Common::ProcessAddress end = base + size;
ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}", ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}",
base + page_table.pointers.size()); base + page_table.pointers.size());
@ -548,7 +572,7 @@ struct Memory::Impl {
while (base != end) { while (base != end) {
page_table.pointers[base].Store( page_table.pointers[base].Store(
system.DeviceMemory().GetPointer<u8>(target) - (base << YUZU_PAGEBITS), type); system.DeviceMemory().GetPointer<u8>(target) - (base << YUZU_PAGEBITS), type);
page_table.backing_addr[base] = target - (base << YUZU_PAGEBITS); page_table.backing_addr[base] = GetInteger(target) - (base << YUZU_PAGEBITS);
ASSERT_MSG(page_table.pointers[base].Pointer(), ASSERT_MSG(page_table.pointers[base].Pointer(),
"memory mapping base yield a nullptr within the table"); "memory mapping base yield a nullptr within the table");
@ -559,9 +583,9 @@ struct Memory::Impl {
} }
} }
[[nodiscard]] u8* GetPointerImpl(VAddr vaddr, auto on_unmapped, auto on_rasterizer) const { [[nodiscard]] u8* GetPointerImpl(u64 vaddr, auto on_unmapped, auto on_rasterizer) const {
// AARCH64 masks the upper 16 bit of all memory accesses // AARCH64 masks the upper 16 bit of all memory accesses
vaddr &= 0xffffffffffffULL; vaddr = vaddr & 0xffffffffffffULL;
if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) { if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) {
on_unmapped(); on_unmapped();
@ -593,15 +617,18 @@ struct Memory::Impl {
return nullptr; return nullptr;
} }
[[nodiscard]] u8* GetPointer(const VAddr vaddr) const { [[nodiscard]] u8* GetPointer(const Common::ProcessAddress vaddr) const {
return GetPointerImpl( return GetPointerImpl(
vaddr, [vaddr]() { LOG_ERROR(HW_Memory, "Unmapped GetPointer @ 0x{:016X}", vaddr); }, GetInteger(vaddr),
[vaddr]() {
LOG_ERROR(HW_Memory, "Unmapped GetPointer @ 0x{:016X}", GetInteger(vaddr));
},
[]() {}); []() {});
} }
[[nodiscard]] u8* GetPointerSilent(const VAddr vaddr) const { [[nodiscard]] u8* GetPointerSilent(const Common::ProcessAddress vaddr) const {
return GetPointerImpl( return GetPointerImpl(
vaddr, []() {}, []() {}); GetInteger(vaddr), []() {}, []() {});
} }
/** /**
@ -616,14 +643,15 @@ struct Memory::Impl {
* @returns The instance of T read from the specified virtual address. * @returns The instance of T read from the specified virtual address.
*/ */
template <typename T> template <typename T>
T Read(VAddr vaddr) { T Read(Common::ProcessAddress vaddr) {
T result = 0; T result = 0;
const u8* const ptr = GetPointerImpl( const u8* const ptr = GetPointerImpl(
vaddr, GetInteger(vaddr),
[vaddr]() { [vaddr]() {
LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, vaddr); LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8,
GetInteger(vaddr));
}, },
[&]() { system.GPU().FlushRegion(vaddr, sizeof(T)); }); [&]() { system.GPU().FlushRegion(GetInteger(vaddr), sizeof(T)); });
if (ptr) { if (ptr) {
std::memcpy(&result, ptr, sizeof(T)); std::memcpy(&result, ptr, sizeof(T));
} }
@ -640,28 +668,28 @@ struct Memory::Impl {
* is undefined. * is undefined.
*/ */
template <typename T> template <typename T>
void Write(VAddr vaddr, const T data) { void Write(Common::ProcessAddress vaddr, const T data) {
u8* const ptr = GetPointerImpl( u8* const ptr = GetPointerImpl(
vaddr, GetInteger(vaddr),
[vaddr, data]() { [vaddr, data]() {
LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8, LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8,
vaddr, static_cast<u64>(data)); GetInteger(vaddr), static_cast<u64>(data));
}, },
[&]() { system.GPU().InvalidateRegion(vaddr, sizeof(T)); }); [&]() { system.GPU().InvalidateRegion(GetInteger(vaddr), sizeof(T)); });
if (ptr) { if (ptr) {
std::memcpy(ptr, &data, sizeof(T)); std::memcpy(ptr, &data, sizeof(T));
} }
} }
template <typename T> template <typename T>
bool WriteExclusive(VAddr vaddr, const T data, const T expected) { bool WriteExclusive(Common::ProcessAddress vaddr, const T data, const T expected) {
u8* const ptr = GetPointerImpl( u8* const ptr = GetPointerImpl(
vaddr, GetInteger(vaddr),
[vaddr, data]() { [vaddr, data]() {
LOG_ERROR(HW_Memory, "Unmapped WriteExclusive{} @ 0x{:016X} = 0x{:016X}", LOG_ERROR(HW_Memory, "Unmapped WriteExclusive{} @ 0x{:016X} = 0x{:016X}",
sizeof(T) * 8, vaddr, static_cast<u64>(data)); sizeof(T) * 8, GetInteger(vaddr), static_cast<u64>(data));
}, },
[&]() { system.GPU().InvalidateRegion(vaddr, sizeof(T)); }); [&]() { system.GPU().InvalidateRegion(GetInteger(vaddr), sizeof(T)); });
if (ptr) { if (ptr) {
const auto volatile_pointer = reinterpret_cast<volatile T*>(ptr); const auto volatile_pointer = reinterpret_cast<volatile T*>(ptr);
return Common::AtomicCompareAndSwap(volatile_pointer, data, expected); return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
@ -669,14 +697,14 @@ struct Memory::Impl {
return true; return true;
} }
bool WriteExclusive128(VAddr vaddr, const u128 data, const u128 expected) { bool WriteExclusive128(Common::ProcessAddress vaddr, const u128 data, const u128 expected) {
u8* const ptr = GetPointerImpl( u8* const ptr = GetPointerImpl(
vaddr, GetInteger(vaddr),
[vaddr, data]() { [vaddr, data]() {
LOG_ERROR(HW_Memory, "Unmapped WriteExclusive128 @ 0x{:016X} = 0x{:016X}{:016X}", LOG_ERROR(HW_Memory, "Unmapped WriteExclusive128 @ 0x{:016X} = 0x{:016X}{:016X}",
vaddr, static_cast<u64>(data[1]), static_cast<u64>(data[0])); GetInteger(vaddr), static_cast<u64>(data[1]), static_cast<u64>(data[0]));
}, },
[&]() { system.GPU().InvalidateRegion(vaddr, sizeof(u128)); }); [&]() { system.GPU().InvalidateRegion(GetInteger(vaddr), sizeof(u128)); });
if (ptr) { if (ptr) {
const auto volatile_pointer = reinterpret_cast<volatile u64*>(ptr); const auto volatile_pointer = reinterpret_cast<volatile u64*>(ptr);
return Common::AtomicCompareAndSwap(volatile_pointer, data, expected); return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
@ -702,15 +730,16 @@ void Memory::SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) {
impl->SetCurrentPageTable(process, core_id); impl->SetCurrentPageTable(process, core_id);
} }
void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) { void Memory::MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
Common::PhysicalAddress target) {
impl->MapMemoryRegion(page_table, base, size, target); impl->MapMemoryRegion(page_table, base, size, target);
} }
void Memory::UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) { void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size) {
impl->UnmapRegion(page_table, base, size); impl->UnmapRegion(page_table, base, size);
} }
bool Memory::IsValidVirtualAddress(const VAddr vaddr) const { bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const {
const Kernel::KProcess& process = *system.ApplicationProcess(); const Kernel::KProcess& process = *system.ApplicationProcess();
const auto& page_table = process.PageTable().PageTableImpl(); const auto& page_table = process.PageTable().PageTableImpl();
const size_t page = vaddr >> YUZU_PAGEBITS; const size_t page = vaddr >> YUZU_PAGEBITS;
@ -722,9 +751,9 @@ bool Memory::IsValidVirtualAddress(const VAddr vaddr) const {
type == Common::PageType::DebugMemory; type == Common::PageType::DebugMemory;
} }
bool Memory::IsValidVirtualAddressRange(VAddr base, u64 size) const { bool Memory::IsValidVirtualAddressRange(Common::ProcessAddress base, u64 size) const {
VAddr end = base + size; Common::ProcessAddress end = base + size;
VAddr page = Common::AlignDown(base, YUZU_PAGESIZE); Common::ProcessAddress page = Common::AlignDown(GetInteger(base), YUZU_PAGESIZE);
for (; page < end; page += YUZU_PAGESIZE) { for (; page < end; page += YUZU_PAGESIZE) {
if (!IsValidVirtualAddress(page)) { if (!IsValidVirtualAddress(page)) {
@ -735,131 +764,135 @@ bool Memory::IsValidVirtualAddressRange(VAddr base, u64 size) const {
return true; return true;
} }
u8* Memory::GetPointer(VAddr vaddr) { u8* Memory::GetPointer(Common::ProcessAddress vaddr) {
return impl->GetPointer(vaddr); return impl->GetPointer(vaddr);
} }
u8* Memory::GetPointerSilent(VAddr vaddr) { u8* Memory::GetPointerSilent(Common::ProcessAddress vaddr) {
return impl->GetPointerSilent(vaddr); return impl->GetPointerSilent(vaddr);
} }
const u8* Memory::GetPointer(VAddr vaddr) const { const u8* Memory::GetPointer(Common::ProcessAddress vaddr) const {
return impl->GetPointer(vaddr); return impl->GetPointer(vaddr);
} }
u8 Memory::Read8(const VAddr addr) { u8 Memory::Read8(const Common::ProcessAddress addr) {
return impl->Read8(addr); return impl->Read8(addr);
} }
u16 Memory::Read16(const VAddr addr) { u16 Memory::Read16(const Common::ProcessAddress addr) {
return impl->Read16(addr); return impl->Read16(addr);
} }
u32 Memory::Read32(const VAddr addr) { u32 Memory::Read32(const Common::ProcessAddress addr) {
return impl->Read32(addr); return impl->Read32(addr);
} }
u64 Memory::Read64(const VAddr addr) { u64 Memory::Read64(const Common::ProcessAddress addr) {
return impl->Read64(addr); return impl->Read64(addr);
} }
void Memory::Write8(VAddr addr, u8 data) { void Memory::Write8(Common::ProcessAddress addr, u8 data) {
impl->Write8(addr, data); impl->Write8(addr, data);
} }
void Memory::Write16(VAddr addr, u16 data) { void Memory::Write16(Common::ProcessAddress addr, u16 data) {
impl->Write16(addr, data); impl->Write16(addr, data);
} }
void Memory::Write32(VAddr addr, u32 data) { void Memory::Write32(Common::ProcessAddress addr, u32 data) {
impl->Write32(addr, data); impl->Write32(addr, data);
} }
void Memory::Write64(VAddr addr, u64 data) { void Memory::Write64(Common::ProcessAddress addr, u64 data) {
impl->Write64(addr, data); impl->Write64(addr, data);
} }
bool Memory::WriteExclusive8(VAddr addr, u8 data, u8 expected) { bool Memory::WriteExclusive8(Common::ProcessAddress addr, u8 data, u8 expected) {
return impl->WriteExclusive8(addr, data, expected); return impl->WriteExclusive8(addr, data, expected);
} }
bool Memory::WriteExclusive16(VAddr addr, u16 data, u16 expected) { bool Memory::WriteExclusive16(Common::ProcessAddress addr, u16 data, u16 expected) {
return impl->WriteExclusive16(addr, data, expected); return impl->WriteExclusive16(addr, data, expected);
} }
bool Memory::WriteExclusive32(VAddr addr, u32 data, u32 expected) { bool Memory::WriteExclusive32(Common::ProcessAddress addr, u32 data, u32 expected) {
return impl->WriteExclusive32(addr, data, expected); return impl->WriteExclusive32(addr, data, expected);
} }
bool Memory::WriteExclusive64(VAddr addr, u64 data, u64 expected) { bool Memory::WriteExclusive64(Common::ProcessAddress addr, u64 data, u64 expected) {
return impl->WriteExclusive64(addr, data, expected); return impl->WriteExclusive64(addr, data, expected);
} }
bool Memory::WriteExclusive128(VAddr addr, u128 data, u128 expected) { bool Memory::WriteExclusive128(Common::ProcessAddress addr, u128 data, u128 expected) {
return impl->WriteExclusive128(addr, data, expected); return impl->WriteExclusive128(addr, data, expected);
} }
std::string Memory::ReadCString(VAddr vaddr, std::size_t max_length) { std::string Memory::ReadCString(Common::ProcessAddress vaddr, std::size_t max_length) {
return impl->ReadCString(vaddr, max_length); return impl->ReadCString(vaddr, max_length);
} }
void Memory::ReadBlock(const Kernel::KProcess& process, const VAddr src_addr, void* dest_buffer, void Memory::ReadBlock(const Kernel::KProcess& process, const Common::ProcessAddress src_addr,
const std::size_t size) { void* dest_buffer, const std::size_t size) {
impl->ReadBlockImpl<false>(process, src_addr, dest_buffer, size); impl->ReadBlockImpl<false>(process, src_addr, dest_buffer, size);
} }
void Memory::ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_t size) { void Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
const std::size_t size) {
impl->ReadBlock(src_addr, dest_buffer, size); impl->ReadBlock(src_addr, dest_buffer, size);
} }
void Memory::ReadBlockUnsafe(const VAddr src_addr, void* dest_buffer, const std::size_t size) { void Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer,
const std::size_t size) {
impl->ReadBlockUnsafe(src_addr, dest_buffer, size); impl->ReadBlockUnsafe(src_addr, dest_buffer, size);
} }
void Memory::WriteBlock(const Kernel::KProcess& process, VAddr dest_addr, const void* src_buffer, void Memory::WriteBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
std::size_t size) { const void* src_buffer, std::size_t size) {
impl->WriteBlockImpl<false>(process, dest_addr, src_buffer, size); impl->WriteBlockImpl<false>(process, dest_addr, src_buffer, size);
} }
void Memory::WriteBlock(const VAddr dest_addr, const void* src_buffer, const std::size_t size) { void Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
const std::size_t size) {
impl->WriteBlock(dest_addr, src_buffer, size); impl->WriteBlock(dest_addr, src_buffer, size);
} }
void Memory::WriteBlockUnsafe(const VAddr dest_addr, const void* src_buffer, void Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer,
const std::size_t size) { const std::size_t size) {
impl->WriteBlockUnsafe(dest_addr, src_buffer, size); impl->WriteBlockUnsafe(dest_addr, src_buffer, size);
} }
void Memory::CopyBlock(const Kernel::KProcess& process, VAddr dest_addr, VAddr src_addr, void Memory::CopyBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
const std::size_t size) { Common::ProcessAddress src_addr, const std::size_t size) {
impl->CopyBlock(process, dest_addr, src_addr, size); impl->CopyBlock(process, dest_addr, src_addr, size);
} }
void Memory::ZeroBlock(const Kernel::KProcess& process, VAddr dest_addr, const std::size_t size) { void Memory::ZeroBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
const std::size_t size) {
impl->ZeroBlock(process, dest_addr, size); impl->ZeroBlock(process, dest_addr, size);
} }
Result Memory::InvalidateDataCache(const Kernel::KProcess& process, VAddr dest_addr, Result Memory::InvalidateDataCache(const Kernel::KProcess& process,
const std::size_t size) { Common::ProcessAddress dest_addr, const std::size_t size) {
return impl->InvalidateDataCache(process, dest_addr, size); return impl->InvalidateDataCache(process, dest_addr, size);
} }
Result Memory::StoreDataCache(const Kernel::KProcess& process, VAddr dest_addr, Result Memory::StoreDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
const std::size_t size) { const std::size_t size) {
return impl->StoreDataCache(process, dest_addr, size); return impl->StoreDataCache(process, dest_addr, size);
} }
Result Memory::FlushDataCache(const Kernel::KProcess& process, VAddr dest_addr, Result Memory::FlushDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
const std::size_t size) { const std::size_t size) {
return impl->FlushDataCache(process, dest_addr, size); return impl->FlushDataCache(process, dest_addr, size);
} }
void Memory::RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) { void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) {
impl->RasterizerMarkRegionCached(vaddr, size, cached); impl->RasterizerMarkRegionCached(GetInteger(vaddr), size, cached);
} }
void Memory::MarkRegionDebug(VAddr vaddr, u64 size, bool debug) { void Memory::MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug) {
impl->MarkRegionDebug(vaddr, size, debug); impl->MarkRegionDebug(GetInteger(vaddr), size, debug);
} }
} // namespace Core::Memory } // namespace Core::Memory

@ -6,7 +6,7 @@
#include <cstddef> #include <cstddef>
#include <memory> #include <memory>
#include <string> #include <string>
#include "common/common_types.h" #include "common/typed_address.h"
#include "core/hle/result.h" #include "core/hle/result.h"
namespace Common { namespace Common {
@ -33,7 +33,7 @@ constexpr u64 YUZU_PAGESIZE = 1ULL << YUZU_PAGEBITS;
constexpr u64 YUZU_PAGEMASK = YUZU_PAGESIZE - 1; constexpr u64 YUZU_PAGEMASK = YUZU_PAGESIZE - 1;
/// Virtual user-space memory regions /// Virtual user-space memory regions
enum : VAddr { enum : u64 {
/// TLS (Thread-Local Storage) related. /// TLS (Thread-Local Storage) related.
TLS_ENTRY_SIZE = 0x200, TLS_ENTRY_SIZE = 0x200,
@ -74,7 +74,8 @@ public:
* @param target Buffer with the memory backing the mapping. Must be of length at least * @param target Buffer with the memory backing the mapping. Must be of length at least
* `size`. * `size`.
*/ */
void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target); void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
Common::PhysicalAddress target);
/** /**
* Unmaps a region of the emulated process address space. * Unmaps a region of the emulated process address space.
@ -83,7 +84,7 @@ public:
* @param base The address to begin unmapping at. * @param base The address to begin unmapping at.
* @param size The amount of bytes to unmap. * @param size The amount of bytes to unmap.
*/ */
void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size); void UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size);
/** /**
* Checks whether or not the supplied address is a valid virtual * Checks whether or not the supplied address is a valid virtual
@ -93,7 +94,7 @@ public:
* *
* @returns True if the given virtual address is valid, false otherwise. * @returns True if the given virtual address is valid, false otherwise.
*/ */
[[nodiscard]] bool IsValidVirtualAddress(VAddr vaddr) const; [[nodiscard]] bool IsValidVirtualAddress(Common::ProcessAddress vaddr) const;
/** /**
* Checks whether or not the supplied range of addresses are all valid * Checks whether or not the supplied range of addresses are all valid
@ -104,7 +105,7 @@ public:
* *
* @returns True if all bytes in the given range are valid, false otherwise. * @returns True if all bytes in the given range are valid, false otherwise.
*/ */
[[nodiscard]] bool IsValidVirtualAddressRange(VAddr base, u64 size) const; [[nodiscard]] bool IsValidVirtualAddressRange(Common::ProcessAddress base, u64 size) const;
/** /**
* Gets a pointer to the given address. * Gets a pointer to the given address.
@ -114,11 +115,11 @@ public:
* @returns The pointer to the given address, if the address is valid. * @returns The pointer to the given address, if the address is valid.
* If the address is not valid, nullptr will be returned. * If the address is not valid, nullptr will be returned.
*/ */
u8* GetPointer(VAddr vaddr); u8* GetPointer(Common::ProcessAddress vaddr);
u8* GetPointerSilent(VAddr vaddr); u8* GetPointerSilent(Common::ProcessAddress vaddr);
template <typename T> template <typename T>
T* GetPointer(VAddr vaddr) { T* GetPointer(Common::ProcessAddress vaddr) {
return reinterpret_cast<T*>(GetPointer(vaddr)); return reinterpret_cast<T*>(GetPointer(vaddr));
} }
@ -130,10 +131,10 @@ public:
* @returns The pointer to the given address, if the address is valid. * @returns The pointer to the given address, if the address is valid.
* If the address is not valid, nullptr will be returned. * If the address is not valid, nullptr will be returned.
*/ */
[[nodiscard]] const u8* GetPointer(VAddr vaddr) const; [[nodiscard]] const u8* GetPointer(Common::ProcessAddress vaddr) const;
template <typename T> template <typename T>
const T* GetPointer(VAddr vaddr) const { const T* GetPointer(Common::ProcessAddress vaddr) const {
return reinterpret_cast<T*>(GetPointer(vaddr)); return reinterpret_cast<T*>(GetPointer(vaddr));
} }
@ -145,7 +146,7 @@ public:
* *
* @returns the read 8-bit unsigned value. * @returns the read 8-bit unsigned value.
*/ */
u8 Read8(VAddr addr); u8 Read8(Common::ProcessAddress addr);
/** /**
* Reads a 16-bit unsigned value from the current process' address space * Reads a 16-bit unsigned value from the current process' address space
@ -155,7 +156,7 @@ public:
* *
* @returns the read 16-bit unsigned value. * @returns the read 16-bit unsigned value.
*/ */
u16 Read16(VAddr addr); u16 Read16(Common::ProcessAddress addr);
/** /**
* Reads a 32-bit unsigned value from the current process' address space * Reads a 32-bit unsigned value from the current process' address space
@ -165,7 +166,7 @@ public:
* *
* @returns the read 32-bit unsigned value. * @returns the read 32-bit unsigned value.
*/ */
u32 Read32(VAddr addr); u32 Read32(Common::ProcessAddress addr);
/** /**
* Reads a 64-bit unsigned value from the current process' address space * Reads a 64-bit unsigned value from the current process' address space
@ -175,7 +176,7 @@ public:
* *
* @returns the read 64-bit value. * @returns the read 64-bit value.
*/ */
u64 Read64(VAddr addr); u64 Read64(Common::ProcessAddress addr);
/** /**
* Writes an 8-bit unsigned integer to the given virtual address in * Writes an 8-bit unsigned integer to the given virtual address in
@ -186,7 +187,7 @@ public:
* *
* @post The memory at the given virtual address contains the specified data value. * @post The memory at the given virtual address contains the specified data value.
*/ */
void Write8(VAddr addr, u8 data); void Write8(Common::ProcessAddress addr, u8 data);
/** /**
* Writes a 16-bit unsigned integer to the given virtual address in * Writes a 16-bit unsigned integer to the given virtual address in
@ -197,7 +198,7 @@ public:
* *
* @post The memory range [addr, sizeof(data)) contains the given data value. * @post The memory range [addr, sizeof(data)) contains the given data value.
*/ */
void Write16(VAddr addr, u16 data); void Write16(Common::ProcessAddress addr, u16 data);
/** /**
* Writes a 32-bit unsigned integer to the given virtual address in * Writes a 32-bit unsigned integer to the given virtual address in
@ -208,7 +209,7 @@ public:
* *
* @post The memory range [addr, sizeof(data)) contains the given data value. * @post The memory range [addr, sizeof(data)) contains the given data value.
*/ */
void Write32(VAddr addr, u32 data); void Write32(Common::ProcessAddress addr, u32 data);
/** /**
* Writes a 64-bit unsigned integer to the given virtual address in * Writes a 64-bit unsigned integer to the given virtual address in
@ -219,7 +220,7 @@ public:
* *
* @post The memory range [addr, sizeof(data)) contains the given data value. * @post The memory range [addr, sizeof(data)) contains the given data value.
*/ */
void Write64(VAddr addr, u64 data); void Write64(Common::ProcessAddress addr, u64 data);
/** /**
* Writes a 8-bit unsigned integer to the given virtual address in * Writes a 8-bit unsigned integer to the given virtual address in
@ -232,7 +233,7 @@ public:
* *
* @post The memory range [addr, sizeof(data)) contains the given data value. * @post The memory range [addr, sizeof(data)) contains the given data value.
*/ */
bool WriteExclusive8(VAddr addr, u8 data, u8 expected); bool WriteExclusive8(Common::ProcessAddress addr, u8 data, u8 expected);
/** /**
* Writes a 16-bit unsigned integer to the given virtual address in * Writes a 16-bit unsigned integer to the given virtual address in
@ -245,7 +246,7 @@ public:
* *
* @post The memory range [addr, sizeof(data)) contains the given data value. * @post The memory range [addr, sizeof(data)) contains the given data value.
*/ */
bool WriteExclusive16(VAddr addr, u16 data, u16 expected); bool WriteExclusive16(Common::ProcessAddress addr, u16 data, u16 expected);
/** /**
* Writes a 32-bit unsigned integer to the given virtual address in * Writes a 32-bit unsigned integer to the given virtual address in
@ -258,7 +259,7 @@ public:
* *
* @post The memory range [addr, sizeof(data)) contains the given data value. * @post The memory range [addr, sizeof(data)) contains the given data value.
*/ */
bool WriteExclusive32(VAddr addr, u32 data, u32 expected); bool WriteExclusive32(Common::ProcessAddress addr, u32 data, u32 expected);
/** /**
* Writes a 64-bit unsigned integer to the given virtual address in * Writes a 64-bit unsigned integer to the given virtual address in
@ -271,7 +272,7 @@ public:
* *
* @post The memory range [addr, sizeof(data)) contains the given data value. * @post The memory range [addr, sizeof(data)) contains the given data value.
*/ */
bool WriteExclusive64(VAddr addr, u64 data, u64 expected); bool WriteExclusive64(Common::ProcessAddress addr, u64 data, u64 expected);
/** /**
* Writes a 128-bit unsigned integer to the given virtual address in * Writes a 128-bit unsigned integer to the given virtual address in
@ -284,7 +285,7 @@ public:
* *
* @post The memory range [addr, sizeof(data)) contains the given data value. * @post The memory range [addr, sizeof(data)) contains the given data value.
*/ */
bool WriteExclusive128(VAddr addr, u128 data, u128 expected); bool WriteExclusive128(Common::ProcessAddress addr, u128 data, u128 expected);
/** /**
* Reads a null-terminated string from the given virtual address. * Reads a null-terminated string from the given virtual address.
@ -301,7 +302,7 @@ public:
* *
* @returns The read string. * @returns The read string.
*/ */
std::string ReadCString(VAddr vaddr, std::size_t max_length); std::string ReadCString(Common::ProcessAddress vaddr, std::size_t max_length);
/** /**
* Reads a contiguous block of bytes from a specified process' address space. * Reads a contiguous block of bytes from a specified process' address space.
@ -320,8 +321,8 @@ public:
* @post The range [dest_buffer, size) contains the read bytes from the * @post The range [dest_buffer, size) contains the read bytes from the
* process' address space. * process' address space.
*/ */
void ReadBlock(const Kernel::KProcess& process, VAddr src_addr, void* dest_buffer, void ReadBlock(const Kernel::KProcess& process, Common::ProcessAddress src_addr,
std::size_t size); void* dest_buffer, std::size_t size);
/** /**
* Reads a contiguous block of bytes from the current process' address space. * Reads a contiguous block of bytes from the current process' address space.
@ -339,7 +340,7 @@ public:
* @post The range [dest_buffer, size) contains the read bytes from the * @post The range [dest_buffer, size) contains the read bytes from the
* current process' address space. * current process' address space.
*/ */
void ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size); void ReadBlock(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size);
/** /**
* Reads a contiguous block of bytes from the current process' address space. * Reads a contiguous block of bytes from the current process' address space.
@ -358,7 +359,7 @@ public:
* @post The range [dest_buffer, size) contains the read bytes from the * @post The range [dest_buffer, size) contains the read bytes from the
* current process' address space. * current process' address space.
*/ */
void ReadBlockUnsafe(VAddr src_addr, void* dest_buffer, std::size_t size); void ReadBlockUnsafe(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size);
/** /**
* Writes a range of bytes into a given process' address space at the specified * Writes a range of bytes into a given process' address space at the specified
@ -380,8 +381,8 @@ public:
* and will mark that region as invalidated to caches that the active * and will mark that region as invalidated to caches that the active
* graphics backend may be maintaining over the course of execution. * graphics backend may be maintaining over the course of execution.
*/ */
void WriteBlock(const Kernel::KProcess& process, VAddr dest_addr, const void* src_buffer, void WriteBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
std::size_t size); const void* src_buffer, std::size_t size);
/** /**
* Writes a range of bytes into the current process' address space at the specified * Writes a range of bytes into the current process' address space at the specified
@ -402,7 +403,7 @@ public:
* and will mark that region as invalidated to caches that the active * and will mark that region as invalidated to caches that the active
* graphics backend may be maintaining over the course of execution. * graphics backend may be maintaining over the course of execution.
*/ */
void WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size); void WriteBlock(Common::ProcessAddress dest_addr, const void* src_buffer, std::size_t size);
/** /**
* Writes a range of bytes into the current process' address space at the specified * Writes a range of bytes into the current process' address space at the specified
@ -420,7 +421,8 @@ public:
* will be ignored and an error will be logged. * will be ignored and an error will be logged.
* *
*/ */
void WriteBlockUnsafe(VAddr dest_addr, const void* src_buffer, std::size_t size); void WriteBlockUnsafe(Common::ProcessAddress dest_addr, const void* src_buffer,
std::size_t size);
/** /**
* Copies data within a process' address space to another location within the * Copies data within a process' address space to another location within the
@ -434,8 +436,8 @@ public:
* @post The range [dest_addr, size) within the process' address space contains the * @post The range [dest_addr, size) within the process' address space contains the
* same data within the range [src_addr, size). * same data within the range [src_addr, size).
*/ */
void CopyBlock(const Kernel::KProcess& process, VAddr dest_addr, VAddr src_addr, void CopyBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
std::size_t size); Common::ProcessAddress src_addr, std::size_t size);
/** /**
* Zeros a range of bytes within the current process' address space at the specified * Zeros a range of bytes within the current process' address space at the specified
@ -448,7 +450,8 @@ public:
* @post The range [dest_addr, size) within the process' address space contains the * @post The range [dest_addr, size) within the process' address space contains the
* value 0. * value 0.
*/ */
void ZeroBlock(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size); void ZeroBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
std::size_t size);
/** /**
* Invalidates a range of bytes within the current process' address space at the specified * Invalidates a range of bytes within the current process' address space at the specified
@ -459,7 +462,8 @@ public:
* @param size The size of the range to invalidate, in bytes. * @param size The size of the range to invalidate, in bytes.
* *
*/ */
Result InvalidateDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size); Result InvalidateDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
std::size_t size);
/** /**
* Stores a range of bytes within the current process' address space at the specified * Stores a range of bytes within the current process' address space at the specified
@ -470,7 +474,8 @@ public:
* @param size The size of the range to store, in bytes. * @param size The size of the range to store, in bytes.
* *
*/ */
Result StoreDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size); Result StoreDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
std::size_t size);
/** /**
* Flushes a range of bytes within the current process' address space at the specified * Flushes a range of bytes within the current process' address space at the specified
@ -481,7 +486,8 @@ public:
* @param size The size of the range to flush, in bytes. * @param size The size of the range to flush, in bytes.
* *
*/ */
Result FlushDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size); Result FlushDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
std::size_t size);
/** /**
* Marks each page within the specified address range as cached or uncached. * Marks each page within the specified address range as cached or uncached.
@ -491,7 +497,7 @@ public:
* @param cached Whether or not any pages within the address range should be * @param cached Whether or not any pages within the address range should be
* marked as cached or uncached. * marked as cached or uncached.
*/ */
void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached); void RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached);
/** /**
* Marks each page within the specified address range as debug or non-debug. * Marks each page within the specified address range as debug or non-debug.
@ -502,7 +508,7 @@ public:
* @param debug Whether or not any pages within the address range should be * @param debug Whether or not any pages within the address range should be
* marked as debug or non-debug. * marked as debug or non-debug.
*/ */
void MarkRegionDebug(VAddr vaddr, u64 size, bool debug); void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug);
private: private:
Core::System& system; Core::System& system;

@ -201,17 +201,17 @@ void CheatEngine::Initialize() {
const auto& page_table = system.ApplicationProcess()->PageTable(); const auto& page_table = system.ApplicationProcess()->PageTable();
metadata.heap_extents = { metadata.heap_extents = {
.base = page_table.GetHeapRegionStart(), .base = GetInteger(page_table.GetHeapRegionStart()),
.size = page_table.GetHeapRegionSize(), .size = page_table.GetHeapRegionSize(),
}; };
metadata.address_space_extents = { metadata.address_space_extents = {
.base = page_table.GetAddressSpaceStart(), .base = GetInteger(page_table.GetAddressSpaceStart()),
.size = page_table.GetAddressSpaceSize(), .size = page_table.GetAddressSpaceSize(),
}; };
metadata.alias_extents = { metadata.alias_extents = {
.base = page_table.GetAliasCodeRegionStart(), .base = GetInteger(page_table.GetAliasCodeRegionStart()),
.size = page_table.GetAliasCodeRegionSize(), .size = page_table.GetAliasCodeRegionSize(),
}; };

Some files were not shown because too many files have changed in this diff Show More