early-access version 3471
This commit is contained in:
parent
723613f367
commit
5116aade0e
56 changed files with 284 additions and 239 deletions
|
@ -210,7 +210,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||||
# =======================================================================
|
# =======================================================================
|
||||||
|
|
||||||
# Enforce the search mode of non-required packages for better and shorter failure messages
|
# Enforce the search mode of non-required packages for better and shorter failure messages
|
||||||
find_package(Boost 1.73.0 REQUIRED context)
|
find_package(Boost 1.81.0 REQUIRED context)
|
||||||
find_package(enet 1.3 MODULE)
|
find_package(enet 1.3 MODULE)
|
||||||
find_package(fmt 9 REQUIRED)
|
find_package(fmt 9 REQUIRED)
|
||||||
find_package(inih 52 MODULE COMPONENTS INIReader)
|
find_package(inih 52 MODULE COMPONENTS INIReader)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3470.
|
This is the source code for early-access 3471.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) const {
|
||||||
stream->AppendBuffer(new_buffer, samples);
|
stream->AppendBuffer(new_buffer, samples);
|
||||||
} else {
|
} else {
|
||||||
std::vector<s16> samples(buffer.size / sizeof(s16));
|
std::vector<s16> samples(buffer.size / sizeof(s16));
|
||||||
system.Memory().ReadBlockUnsafe(buffer.samples, samples.data(), buffer.size);
|
system.ApplicationMemory().ReadBlockUnsafe(buffer.samples, samples.data(), buffer.size);
|
||||||
stream->AppendBuffer(new_buffer, samples);
|
stream->AppendBuffer(new_buffer, samples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) const {
|
||||||
void DeviceSession::ReleaseBuffer(const AudioBuffer& buffer) const {
|
void DeviceSession::ReleaseBuffer(const AudioBuffer& buffer) const {
|
||||||
if (type == Sink::StreamType::In) {
|
if (type == Sink::StreamType::In) {
|
||||||
auto samples{stream->ReleaseBuffer(buffer.size / sizeof(s16))};
|
auto samples{stream->ReleaseBuffer(buffer.size / sizeof(s16))};
|
||||||
system.Memory().WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size);
|
system.ApplicationMemory().WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
namespace AudioCore::AudioRenderer::ADSP {
|
namespace AudioCore::AudioRenderer::ADSP {
|
||||||
|
|
||||||
ADSP::ADSP(Core::System& system_, Sink::Sink& sink_)
|
ADSP::ADSP(Core::System& system_, Sink::Sink& sink_)
|
||||||
: system{system_}, memory{system.Memory()}, sink{sink_} {}
|
: system{system_}, memory{system.ApplicationMemory()}, sink{sink_} {}
|
||||||
|
|
||||||
ADSP::~ADSP() {
|
ADSP::~ADSP() {
|
||||||
ClearCommandBuffers();
|
ClearCommandBuffers();
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace AudioCore::AudioRenderer::ADSP {
|
||||||
void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size,
|
void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size,
|
||||||
Sink::SinkStream* stream_) {
|
Sink::SinkStream* stream_) {
|
||||||
system = &system_;
|
system = &system_;
|
||||||
memory = &system->Memory();
|
memory = &system->ApplicationMemory();
|
||||||
stream = stream_;
|
stream = stream_;
|
||||||
header = reinterpret_cast<CommandListHeader*>(buffer);
|
header = reinterpret_cast<CommandListHeader*>(buffer);
|
||||||
commands = reinterpret_cast<u8*>(buffer + sizeof(CommandListHeader));
|
commands = reinterpret_cast<u8*>(buffer + sizeof(CommandListHeader));
|
||||||
|
|
|
@ -127,8 +127,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
|
||||||
render_device = params.rendering_device;
|
render_device = params.rendering_device;
|
||||||
execution_mode = params.execution_mode;
|
execution_mode = params.execution_mode;
|
||||||
|
|
||||||
core.Memory().ZeroBlock(*core.ApplicationProcess(), transfer_memory->GetSourceAddress(),
|
core.ApplicationMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
|
||||||
transfer_memory_size);
|
|
||||||
|
|
||||||
// Note: We're not actually using the transfer memory because it's a pain to code for.
|
// Note: We're not actually using the transfer memory because it's a pain to code for.
|
||||||
// Allocate the memory normally instead and hope the game doesn't try to read anything back
|
// Allocate the memory normally instead and hope the game doesn't try to read anything back
|
||||||
|
|
|
@ -159,6 +159,8 @@ if(ARCHITECTURE_x86_64)
|
||||||
PRIVATE
|
PRIVATE
|
||||||
x64/cpu_detect.cpp
|
x64/cpu_detect.cpp
|
||||||
x64/cpu_detect.h
|
x64/cpu_detect.h
|
||||||
|
x64/cpu_wait.cpp
|
||||||
|
x64/cpu_wait.h
|
||||||
x64/native_clock.cpp
|
x64/native_clock.cpp
|
||||||
x64/native_clock.h
|
x64/native_clock.h
|
||||||
x64/xbyak_abi.h
|
x64/xbyak_abi.h
|
||||||
|
|
|
@ -97,6 +97,7 @@ void AppendCPUInfo(FieldCollection& fc) {
|
||||||
add_field("CPU_Extension_x64_PCLMULQDQ", caps.pclmulqdq);
|
add_field("CPU_Extension_x64_PCLMULQDQ", caps.pclmulqdq);
|
||||||
add_field("CPU_Extension_x64_POPCNT", caps.popcnt);
|
add_field("CPU_Extension_x64_POPCNT", caps.popcnt);
|
||||||
add_field("CPU_Extension_x64_SHA", caps.sha);
|
add_field("CPU_Extension_x64_SHA", caps.sha);
|
||||||
|
add_field("CPU_Extension_x64_WAITPKG", caps.waitpkg);
|
||||||
#else
|
#else
|
||||||
fc.AddField(FieldType::UserSystem, "CPU_Model", "Other");
|
fc.AddField(FieldType::UserSystem, "CPU_Model", "Other");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -144,6 +144,7 @@ static CPUCaps Detect() {
|
||||||
caps.bmi2 = Common::Bit<8>(cpu_id[1]);
|
caps.bmi2 = Common::Bit<8>(cpu_id[1]);
|
||||||
caps.sha = Common::Bit<29>(cpu_id[1]);
|
caps.sha = Common::Bit<29>(cpu_id[1]);
|
||||||
|
|
||||||
|
caps.waitpkg = Common::Bit<5>(cpu_id[2]);
|
||||||
caps.gfni = Common::Bit<8>(cpu_id[2]);
|
caps.gfni = Common::Bit<8>(cpu_id[2]);
|
||||||
|
|
||||||
__cpuidex(cpu_id, 0x00000007, 0x00000001);
|
__cpuidex(cpu_id, 0x00000007, 0x00000001);
|
||||||
|
|
|
@ -67,6 +67,7 @@ struct CPUCaps {
|
||||||
bool pclmulqdq : 1;
|
bool pclmulqdq : 1;
|
||||||
bool popcnt : 1;
|
bool popcnt : 1;
|
||||||
bool sha : 1;
|
bool sha : 1;
|
||||||
|
bool waitpkg : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
66
src/common/x64/cpu_wait.cpp
Executable file
66
src/common/x64/cpu_wait.cpp
Executable file
|
@ -0,0 +1,66 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include <intrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common/x64/cpu_detect.h"
|
||||||
|
#include "common/x64/cpu_wait.h"
|
||||||
|
|
||||||
|
namespace Common::X64 {
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
__forceinline static u64 FencedRDTSC() {
|
||||||
|
_mm_lfence();
|
||||||
|
_ReadWriteBarrier();
|
||||||
|
const u64 result = __rdtsc();
|
||||||
|
_mm_lfence();
|
||||||
|
_ReadWriteBarrier();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline static void TPAUSE() {
|
||||||
|
// 100,000 cycles is a reasonable amount of time to wait to save on CPU resources.
|
||||||
|
// For reference:
|
||||||
|
// At 1 GHz, 100K cycles is 100us
|
||||||
|
// At 2 GHz, 100K cycles is 50us
|
||||||
|
// At 4 GHz, 100K cycles is 25us
|
||||||
|
static constexpr auto PauseCycles = 100'000;
|
||||||
|
_tpause(0, FencedRDTSC() + PauseCycles);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static u64 FencedRDTSC() {
|
||||||
|
u64 eax;
|
||||||
|
u64 edx;
|
||||||
|
asm volatile("lfence\n\t"
|
||||||
|
"rdtsc\n\t"
|
||||||
|
"lfence\n\t"
|
||||||
|
: "=a"(eax), "=d"(edx));
|
||||||
|
return (edx << 32) | eax;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TPAUSE() {
|
||||||
|
// 100,000 cycles is a reasonable amount of time to wait to save on CPU resources.
|
||||||
|
// For reference:
|
||||||
|
// At 1 GHz, 100K cycles is 100us
|
||||||
|
// At 2 GHz, 100K cycles is 50us
|
||||||
|
// At 4 GHz, 100K cycles is 25us
|
||||||
|
static constexpr auto PauseCycles = 100'000;
|
||||||
|
asm volatile("tpause %%ecx" : : "c"(0), "d"((FencedRDTSC() + PauseCycles) >> 32));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void MicroSleep() {
|
||||||
|
static const bool has_waitpkg = GetCPUCaps().waitpkg;
|
||||||
|
|
||||||
|
if (has_waitpkg) {
|
||||||
|
TPAUSE();
|
||||||
|
} else {
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Common::X64
|
10
src/common/x64/cpu_wait.h
Executable file
10
src/common/x64/cpu_wait.h
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Common::X64 {
|
||||||
|
|
||||||
|
void MicroSleep();
|
||||||
|
|
||||||
|
} // namespace Common::X64
|
|
@ -27,16 +27,13 @@ __forceinline static u64 FencedRDTSC() {
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static u64 FencedRDTSC() {
|
static u64 FencedRDTSC() {
|
||||||
u64 result;
|
u64 eax;
|
||||||
|
u64 edx;
|
||||||
asm volatile("lfence\n\t"
|
asm volatile("lfence\n\t"
|
||||||
"rdtsc\n\t"
|
"rdtsc\n\t"
|
||||||
"shl $32, %%rdx\n\t"
|
"lfence\n\t"
|
||||||
"or %%rdx, %0\n\t"
|
: "=a"(eax), "=d"(edx));
|
||||||
"lfence"
|
return (edx << 32) | eax;
|
||||||
: "=a"(result)
|
|
||||||
:
|
|
||||||
: "rdx", "memory", "cc");
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ std::vector<u8> CompressDataZSTDDefault(const u8* source, std::size_t source_siz
|
||||||
|
|
||||||
std::vector<u8> DecompressDataZSTD(std::span<const u8> compressed) {
|
std::vector<u8> DecompressDataZSTD(std::span<const u8> compressed) {
|
||||||
const std::size_t decompressed_size =
|
const std::size_t decompressed_size =
|
||||||
ZSTD_getDecompressedSize(compressed.data(), compressed.size());
|
ZSTD_getFrameContentSize(compressed.data(), compressed.size());
|
||||||
std::vector<u8> decompressed(decompressed_size);
|
std::vector<u8> decompressed(decompressed_size);
|
||||||
|
|
||||||
const std::size_t uncompressed_result_size = ZSTD_decompress(
|
const std::size_t uncompressed_result_size = ZSTD_decompress(
|
||||||
|
|
|
@ -44,7 +44,7 @@ void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<Backt
|
||||||
std::map<std::string, Symbols::Symbols> symbols;
|
std::map<std::string, Symbols::Symbols> symbols;
|
||||||
for (const auto& module : modules) {
|
for (const auto& module : modules) {
|
||||||
symbols.insert_or_assign(
|
symbols.insert_or_assign(
|
||||||
module.second, Symbols::GetSymbols(module.first, system.Memory(),
|
module.second, Symbols::GetSymbols(module.first, system.ApplicationMemory(),
|
||||||
system.ApplicationProcess()->Is64BitProcess()));
|
system.ApplicationProcess()->Is64BitProcess()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@ using namespace Common::Literals;
|
||||||
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
|
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
|
||||||
public:
|
public:
|
||||||
explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
|
explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
|
||||||
: parent{parent_},
|
: parent{parent_}, memory(parent.system.ApplicationMemory()),
|
||||||
memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()},
|
debugger_enabled{parent.system.DebuggerEnabled()},
|
||||||
check_memory_access{debugger_enabled ||
|
check_memory_access{debugger_enabled ||
|
||||||
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
||||||
|
|
||||||
|
@ -468,7 +468,7 @@ void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table,
|
||||||
std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::System& system,
|
std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::System& system,
|
||||||
u64 fp, u64 lr, u64 pc) {
|
u64 fp, u64 lr, u64 pc) {
|
||||||
std::vector<BacktraceEntry> out;
|
std::vector<BacktraceEntry> out;
|
||||||
auto& memory = system.Memory();
|
auto& memory = system.ApplicationMemory();
|
||||||
|
|
||||||
out.push_back({"", 0, pc, 0, ""});
|
out.push_back({"", 0, pc, 0, ""});
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@ using namespace Common::Literals;
|
||||||
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
|
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
|
||||||
public:
|
public:
|
||||||
explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)
|
explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)
|
||||||
: parent{parent_},
|
: parent{parent_}, memory(parent.system.ApplicationMemory()),
|
||||||
memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()},
|
debugger_enabled{parent.system.DebuggerEnabled()},
|
||||||
check_memory_access{debugger_enabled ||
|
check_memory_access{debugger_enabled ||
|
||||||
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
||||||
|
|
||||||
|
@ -529,7 +529,7 @@ void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table,
|
||||||
std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::System& system,
|
std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::System& system,
|
||||||
u64 fp, u64 lr, u64 pc) {
|
u64 fp, u64 lr, u64 pc) {
|
||||||
std::vector<BacktraceEntry> out;
|
std::vector<BacktraceEntry> out;
|
||||||
auto& memory = system.Memory();
|
auto& memory = system.ApplicationMemory();
|
||||||
|
|
||||||
out.push_back({"", 0, pc, 0, ""});
|
out.push_back({"", 0, pc, 0, ""});
|
||||||
|
|
||||||
|
|
|
@ -293,6 +293,7 @@ struct System::Impl {
|
||||||
ASSERT(Kernel::KProcess::Initialize(main_process, system, "main",
|
ASSERT(Kernel::KProcess::Initialize(main_process, system, "main",
|
||||||
Kernel::KProcess::ProcessType::Userland, resource_limit)
|
Kernel::KProcess::ProcessType::Userland, resource_limit)
|
||||||
.IsSuccess());
|
.IsSuccess());
|
||||||
|
kernel.MakeApplicationProcess(main_process);
|
||||||
const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
|
const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
|
||||||
if (load_result != Loader::ResultStatus::Success) {
|
if (load_result != Loader::ResultStatus::Success) {
|
||||||
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result);
|
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result);
|
||||||
|
@ -302,7 +303,6 @@ struct System::Impl {
|
||||||
static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
|
static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
|
||||||
}
|
}
|
||||||
AddGlueRegistrationForProcess(*app_loader, *main_process);
|
AddGlueRegistrationForProcess(*app_loader, *main_process);
|
||||||
kernel.MakeApplicationProcess(main_process);
|
|
||||||
kernel.InitializeCores();
|
kernel.InitializeCores();
|
||||||
|
|
||||||
// Initialize cheat engine
|
// Initialize cheat engine
|
||||||
|
@ -681,11 +681,11 @@ const ExclusiveMonitor& System::Monitor() const {
|
||||||
return impl->kernel.GetExclusiveMonitor();
|
return impl->kernel.GetExclusiveMonitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Memory& System::Memory() {
|
Memory::Memory& System::ApplicationMemory() {
|
||||||
return impl->memory;
|
return impl->memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Core::Memory::Memory& System::Memory() const {
|
const Core::Memory::Memory& System::ApplicationMemory() const {
|
||||||
return impl->memory;
|
return impl->memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -256,10 +256,10 @@ public:
|
||||||
[[nodiscard]] const ExclusiveMonitor& Monitor() const;
|
[[nodiscard]] const ExclusiveMonitor& Monitor() const;
|
||||||
|
|
||||||
/// Gets a mutable reference to the system memory instance.
|
/// Gets a mutable reference to the system memory instance.
|
||||||
[[nodiscard]] Core::Memory::Memory& Memory();
|
[[nodiscard]] Core::Memory::Memory& ApplicationMemory();
|
||||||
|
|
||||||
/// Gets a constant reference to the system memory instance.
|
/// Gets a constant reference to the system memory instance.
|
||||||
[[nodiscard]] const Core::Memory::Memory& Memory() const;
|
[[nodiscard]] const Core::Memory::Memory& ApplicationMemory() const;
|
||||||
|
|
||||||
/// Gets a mutable reference to the GPU interface
|
/// Gets a mutable reference to the GPU interface
|
||||||
[[nodiscard]] Tegra::GPU& GPU();
|
[[nodiscard]] Tegra::GPU& GPU();
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
#include "common/windows/timer_resolution.h"
|
#include "common/windows/timer_resolution.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ARCHITECTURE_x86_64
|
||||||
|
#include "common/x64/cpu_wait.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/core_timing_util.h"
|
#include "core/core_timing_util.h"
|
||||||
|
@ -269,7 +273,11 @@ void CoreTiming::ThreadLoop() {
|
||||||
if (wait_time >= timer_resolution_ns) {
|
if (wait_time >= timer_resolution_ns) {
|
||||||
Common::Windows::SleepForOneTick();
|
Common::Windows::SleepForOneTick();
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef ARCHITECTURE_x86_64
|
||||||
|
Common::X64::MicroSleep();
|
||||||
|
#else
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -261,9 +261,9 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
|
||||||
const size_t addr{static_cast<size_t>(strtoll(command.data(), nullptr, 16))};
|
const size_t addr{static_cast<size_t>(strtoll(command.data(), nullptr, 16))};
|
||||||
const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))};
|
const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))};
|
||||||
|
|
||||||
if (system.Memory().IsValidVirtualAddressRange(addr, size)) {
|
if (system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
|
||||||
std::vector<u8> mem(size);
|
std::vector<u8> mem(size);
|
||||||
system.Memory().ReadBlock(addr, mem.data(), size);
|
system.ApplicationMemory().ReadBlock(addr, mem.data(), size);
|
||||||
|
|
||||||
SendReply(Common::HexToString(mem));
|
SendReply(Common::HexToString(mem));
|
||||||
} else {
|
} else {
|
||||||
|
@ -281,8 +281,8 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
|
||||||
const auto mem_substr{std::string_view(command).substr(mem_sep)};
|
const auto mem_substr{std::string_view(command).substr(mem_sep)};
|
||||||
const auto mem{Common::HexStringToVector(mem_substr, false)};
|
const auto mem{Common::HexStringToVector(mem_substr, false)};
|
||||||
|
|
||||||
if (system.Memory().IsValidVirtualAddressRange(addr, size)) {
|
if (system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
|
||||||
system.Memory().WriteBlock(addr, mem.data(), size);
|
system.ApplicationMemory().WriteBlock(addr, mem.data(), size);
|
||||||
system.InvalidateCpuInstructionCacheRange(addr, size);
|
system.InvalidateCpuInstructionCacheRange(addr, size);
|
||||||
SendReply(GDB_STUB_REPLY_OK);
|
SendReply(GDB_STUB_REPLY_OK);
|
||||||
} else {
|
} else {
|
||||||
|
@ -325,7 +325,7 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
|
||||||
const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
|
const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
|
||||||
const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
|
const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
|
||||||
|
|
||||||
if (!system.Memory().IsValidVirtualAddressRange(addr, size)) {
|
if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
|
||||||
SendReply(GDB_STUB_REPLY_ERR);
|
SendReply(GDB_STUB_REPLY_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -334,22 +334,22 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BreakpointType::Software:
|
case BreakpointType::Software:
|
||||||
replaced_instructions[addr] = system.Memory().Read32(addr);
|
replaced_instructions[addr] = system.ApplicationMemory().Read32(addr);
|
||||||
system.Memory().Write32(addr, arch->BreakpointInstruction());
|
system.ApplicationMemory().Write32(addr, arch->BreakpointInstruction());
|
||||||
system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32));
|
system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32));
|
||||||
success = true;
|
success = true;
|
||||||
break;
|
break;
|
||||||
case BreakpointType::WriteWatch:
|
case BreakpointType::WriteWatch:
|
||||||
success = system.ApplicationProcess()->InsertWatchpoint(system, addr, size,
|
success = system.ApplicationProcess()->InsertWatchpoint(addr, size,
|
||||||
Kernel::DebugWatchpointType::Write);
|
Kernel::DebugWatchpointType::Write);
|
||||||
break;
|
break;
|
||||||
case BreakpointType::ReadWatch:
|
case BreakpointType::ReadWatch:
|
||||||
success = system.ApplicationProcess()->InsertWatchpoint(system, addr, size,
|
success = system.ApplicationProcess()->InsertWatchpoint(addr, size,
|
||||||
Kernel::DebugWatchpointType::Read);
|
Kernel::DebugWatchpointType::Read);
|
||||||
break;
|
break;
|
||||||
case BreakpointType::AccessWatch:
|
case BreakpointType::AccessWatch:
|
||||||
success = system.ApplicationProcess()->InsertWatchpoint(
|
success = system.ApplicationProcess()->InsertWatchpoint(
|
||||||
system, addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
|
addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
|
||||||
break;
|
break;
|
||||||
case BreakpointType::Hardware:
|
case BreakpointType::Hardware:
|
||||||
default:
|
default:
|
||||||
|
@ -372,7 +372,7 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
|
||||||
const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
|
const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
|
||||||
const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
|
const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
|
||||||
|
|
||||||
if (!system.Memory().IsValidVirtualAddressRange(addr, size)) {
|
if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
|
||||||
SendReply(GDB_STUB_REPLY_ERR);
|
SendReply(GDB_STUB_REPLY_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -383,7 +383,7 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
|
||||||
case BreakpointType::Software: {
|
case BreakpointType::Software: {
|
||||||
const auto orig_insn{replaced_instructions.find(addr)};
|
const auto orig_insn{replaced_instructions.find(addr)};
|
||||||
if (orig_insn != replaced_instructions.end()) {
|
if (orig_insn != replaced_instructions.end()) {
|
||||||
system.Memory().Write32(addr, orig_insn->second);
|
system.ApplicationMemory().Write32(addr, orig_insn->second);
|
||||||
system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32));
|
system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32));
|
||||||
replaced_instructions.erase(addr);
|
replaced_instructions.erase(addr);
|
||||||
success = true;
|
success = true;
|
||||||
|
@ -391,16 +391,16 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BreakpointType::WriteWatch:
|
case BreakpointType::WriteWatch:
|
||||||
success = system.ApplicationProcess()->RemoveWatchpoint(system, addr, size,
|
success = system.ApplicationProcess()->RemoveWatchpoint(addr, size,
|
||||||
Kernel::DebugWatchpointType::Write);
|
Kernel::DebugWatchpointType::Write);
|
||||||
break;
|
break;
|
||||||
case BreakpointType::ReadWatch:
|
case BreakpointType::ReadWatch:
|
||||||
success = system.ApplicationProcess()->RemoveWatchpoint(system, addr, size,
|
success = system.ApplicationProcess()->RemoveWatchpoint(addr, size,
|
||||||
Kernel::DebugWatchpointType::Read);
|
Kernel::DebugWatchpointType::Read);
|
||||||
break;
|
break;
|
||||||
case BreakpointType::AccessWatch:
|
case BreakpointType::AccessWatch:
|
||||||
success = system.ApplicationProcess()->RemoveWatchpoint(
|
success = system.ApplicationProcess()->RemoveWatchpoint(
|
||||||
system, addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
|
addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
|
||||||
break;
|
break;
|
||||||
case BreakpointType::Hardware:
|
case BreakpointType::Hardware:
|
||||||
default:
|
default:
|
||||||
|
@ -483,9 +483,9 @@ static std::optional<std::string> GetNameFromThreadType64(Core::Memory::Memory&
|
||||||
static std::optional<std::string> GetThreadName(Core::System& system,
|
static std::optional<std::string> GetThreadName(Core::System& system,
|
||||||
const Kernel::KThread* thread) {
|
const Kernel::KThread* thread) {
|
||||||
if (system.ApplicationProcess()->Is64BitProcess()) {
|
if (system.ApplicationProcess()->Is64BitProcess()) {
|
||||||
return GetNameFromThreadType64(system.Memory(), thread);
|
return GetNameFromThreadType64(system.ApplicationMemory(), thread);
|
||||||
} else {
|
} else {
|
||||||
return GetNameFromThreadType32(system.Memory(), thread);
|
return GetNameFromThreadType32(system.ApplicationMemory(), thread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ KAddressArbiter::~KAddressArbiter() = default;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool ReadFromUser(Core::System& system, s32* out, KProcessAddress address) {
|
bool ReadFromUser(KernelCore& kernel, s32* out, KProcessAddress address) {
|
||||||
*out = system.Memory().Read32(GetInteger(address));
|
*out = GetCurrentMemory(kernel).Read32(GetInteger(address));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32
|
||||||
if (value != new_value) {
|
if (value != new_value) {
|
||||||
succeeded = UpdateIfEqual(m_system, std::addressof(user_value), addr, value, new_value);
|
succeeded = UpdateIfEqual(m_system, std::addressof(user_value), addr, value, new_value);
|
||||||
} else {
|
} else {
|
||||||
succeeded = ReadFromUser(m_system, std::addressof(user_value), addr);
|
succeeded = ReadFromUser(m_kernel, std::addressof(user_value), addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
R_UNLESS(succeeded, ResultInvalidCurrentMemory);
|
R_UNLESS(succeeded, ResultInvalidCurrentMemory);
|
||||||
|
@ -252,7 +252,7 @@ Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement,
|
||||||
if (decrement) {
|
if (decrement) {
|
||||||
succeeded = DecrementIfLessThan(m_system, std::addressof(user_value), addr, value);
|
succeeded = DecrementIfLessThan(m_system, std::addressof(user_value), addr, value);
|
||||||
} else {
|
} else {
|
||||||
succeeded = ReadFromUser(m_system, std::addressof(user_value), addr);
|
succeeded = ReadFromUser(m_kernel, std::addressof(user_value), addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
|
@ -303,7 +303,7 @@ Result KAddressArbiter::WaitIfEqual(uint64_t addr, s32 value, s64 timeout) {
|
||||||
|
|
||||||
// Read the value from userspace.
|
// Read the value from userspace.
|
||||||
s32 user_value{};
|
s32 user_value{};
|
||||||
if (!ReadFromUser(m_system, std::addressof(user_value), addr)) {
|
if (!ReadFromUser(m_kernel, std::addressof(user_value), addr)) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,13 @@ namespace Kernel {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool ReadFromUser(Core::System& system, u32* out, KProcessAddress address) {
|
bool ReadFromUser(KernelCore& kernel, u32* out, KProcessAddress address) {
|
||||||
*out = system.Memory().Read32(GetInteger(address));
|
*out = GetCurrentMemory(kernel).Read32(GetInteger(address));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteToUser(Core::System& system, KProcessAddress address, const u32* p) {
|
bool WriteToUser(KernelCore& kernel, KProcessAddress address, const u32* p) {
|
||||||
system.Memory().Write32(GetInteger(address), *p);
|
GetCurrentMemory(kernel).Write32(GetInteger(address), *p);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ Result KConditionVariable::SignalToAddress(KProcessAddress addr) {
|
||||||
|
|
||||||
// Write the value to userspace.
|
// Write the value to userspace.
|
||||||
Result result{ResultSuccess};
|
Result result{ResultSuccess};
|
||||||
if (WriteToUser(m_system, addr, std::addressof(next_value))) [[likely]] {
|
if (WriteToUser(m_kernel, addr, std::addressof(next_value))) [[likely]] {
|
||||||
result = ResultSuccess;
|
result = ResultSuccess;
|
||||||
} else {
|
} else {
|
||||||
result = ResultInvalidCurrentMemory;
|
result = ResultInvalidCurrentMemory;
|
||||||
|
@ -157,7 +157,7 @@ Result KConditionVariable::WaitForAddress(Handle handle, KProcessAddress addr, u
|
||||||
|
|
||||||
// Read the tag from userspace.
|
// Read the tag from userspace.
|
||||||
u32 test_tag{};
|
u32 test_tag{};
|
||||||
R_UNLESS(ReadFromUser(m_system, std::addressof(test_tag), addr),
|
R_UNLESS(ReadFromUser(m_kernel, std::addressof(test_tag), addr),
|
||||||
ResultInvalidCurrentMemory);
|
ResultInvalidCurrentMemory);
|
||||||
|
|
||||||
// If the tag isn't the handle (with wait mask), we're done.
|
// If the tag isn't the handle (with wait mask), we're done.
|
||||||
|
@ -257,7 +257,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
|
||||||
// If we have no waiters, clear the has waiter flag.
|
// If we have no waiters, clear the has waiter flag.
|
||||||
if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) {
|
if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) {
|
||||||
const u32 has_waiter_flag{};
|
const u32 has_waiter_flag{};
|
||||||
WriteToUser(m_system, cv_key, std::addressof(has_waiter_flag));
|
WriteToUser(m_kernel, cv_key, std::addressof(has_waiter_flag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,12 +301,12 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti
|
||||||
// Write to the cv key.
|
// Write to the cv key.
|
||||||
{
|
{
|
||||||
const u32 has_waiter_flag = 1;
|
const u32 has_waiter_flag = 1;
|
||||||
WriteToUser(m_system, key, std::addressof(has_waiter_flag));
|
WriteToUser(m_kernel, key, std::addressof(has_waiter_flag));
|
||||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the value to userspace.
|
// Write the value to userspace.
|
||||||
if (!WriteToUser(m_system, addr, std::addressof(next_value))) {
|
if (!WriteToUser(m_kernel, addr, std::addressof(next_value))) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,8 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
|
||||||
bool enable_das_merge, bool from_back,
|
bool enable_das_merge, bool from_back,
|
||||||
KMemoryManager::Pool pool, KProcessAddress 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,
|
||||||
|
Core::Memory::Memory& memory) {
|
||||||
|
|
||||||
const auto GetSpaceStart = [this](KAddressSpaceInfo::Type type) {
|
const auto GetSpaceStart = [this](KAddressSpaceInfo::Type type) {
|
||||||
return KAddressSpaceInfo::GetAddressSpaceStart(m_address_space_width, type);
|
return KAddressSpaceInfo::GetAddressSpaceStart(m_address_space_width, type);
|
||||||
|
@ -117,6 +118,9 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
|
||||||
return KAddressSpaceInfo::GetAddressSpaceSize(m_address_space_width, type);
|
return KAddressSpaceInfo::GetAddressSpaceSize(m_address_space_width, type);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Set the tracking memory
|
||||||
|
m_memory = std::addressof(memory);
|
||||||
|
|
||||||
// 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 KProcessAddress start = 0;
|
const KProcessAddress start = 0;
|
||||||
|
@ -334,9 +338,9 @@ 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_manager.Finalize(m_memory_block_slab_manager,
|
||||||
m_memory_block_slab_manager, [&](KProcessAddress addr, u64 size) {
|
[&](KProcessAddress addr, u64 size) {
|
||||||
m_system.Memory().UnmapRegion(*m_page_table_impl, addr, size);
|
m_memory->UnmapRegion(*m_page_table_impl, addr, size);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Release any insecure mapped memory.
|
// Release any insecure mapped memory.
|
||||||
|
@ -1010,23 +1014,22 @@ Result KPageTable::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
|
||||||
clear_size = 0;
|
clear_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memset(m_system.Memory().GetPointer<void>(GetInteger(start_partial_virt)),
|
std::memset(m_memory->GetPointer<void>(GetInteger(start_partial_virt)), fill_val,
|
||||||
fill_val, partial_offset);
|
partial_offset);
|
||||||
std::memcpy(
|
std::memcpy(
|
||||||
m_system.Memory().GetPointer<void>(GetInteger(start_partial_virt) + partial_offset),
|
m_memory->GetPointer<void>(GetInteger(start_partial_virt) + partial_offset),
|
||||||
m_system.Memory().GetPointer<void>(
|
m_memory->GetPointer<void>(GetInteger(GetHeapVirtualAddress(
|
||||||
GetInteger(
|
m_system.Kernel().MemoryLayout(), cur_block_addr)) +
|
||||||
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>(GetInteger(start_partial_virt) +
|
std::memset(m_memory->GetPointer<void>(GetInteger(start_partial_virt) +
|
||||||
partial_offset + copy_size),
|
partial_offset + copy_size),
|
||||||
fill_val, clear_size);
|
fill_val, clear_size);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::memset(m_system.Memory().GetPointer<void>(GetInteger(start_partial_virt)),
|
std::memset(m_memory->GetPointer<void>(GetInteger(start_partial_virt)), fill_val,
|
||||||
fill_val, PageSize);
|
PageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map the page.
|
// Map the page.
|
||||||
|
@ -1099,15 +1102,14 @@ Result KPageTable::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
|
||||||
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>(GetInteger(end_partial_virt)),
|
std::memcpy(m_memory->GetPointer<void>(GetInteger(end_partial_virt)),
|
||||||
m_system.Memory().GetPointer<void>(GetInteger(GetHeapVirtualAddress(
|
m_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(
|
std::memset(m_memory->GetPointer<void>(GetInteger(end_partial_virt) + copy_size),
|
||||||
m_system.Memory().GetPointer<void>(GetInteger(end_partial_virt) + copy_size),
|
|
||||||
fill_val, PageSize - copy_size);
|
fill_val, PageSize - copy_size);
|
||||||
} else {
|
} else {
|
||||||
std::memset(m_system.Memory().GetPointer<void>(GetInteger(end_partial_virt)), fill_val,
|
std::memset(m_memory->GetPointer<void>(GetInteger(end_partial_virt)), fill_val,
|
||||||
PageSize);
|
PageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2800,7 +2802,7 @@ Result KPageTable::SetHeapSize(u64* out, size_t size) {
|
||||||
|
|
||||||
// Clear all the newly allocated pages.
|
// Clear all the newly allocated pages.
|
||||||
for (size_t cur_page = 0; cur_page < num_pages; ++cur_page) {
|
for (size_t cur_page = 0; cur_page < num_pages; ++cur_page) {
|
||||||
std::memset(m_system.Memory().GetPointer(m_current_heap_end + (cur_page * PageSize)), 0,
|
std::memset(m_memory->GetPointer(m_current_heap_end + (cur_page * PageSize)), 0,
|
||||||
PageSize);
|
PageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3006,7 +3008,7 @@ Result KPageTable::Operate(KProcessAddress addr, size_t num_pages, const KPageGr
|
||||||
const size_t size{node.GetNumPages() * PageSize};
|
const size_t size{node.GetNumPages() * PageSize};
|
||||||
|
|
||||||
// Map the pages.
|
// Map the pages.
|
||||||
m_system.Memory().MapMemoryRegion(*m_page_table_impl, addr, size, node.GetAddress());
|
m_memory->MapMemoryRegion(*m_page_table_impl, addr, size, node.GetAddress());
|
||||||
|
|
||||||
addr += size;
|
addr += size;
|
||||||
}
|
}
|
||||||
|
@ -3039,14 +3041,14 @@ Result KPageTable::Operate(KProcessAddress addr, size_t num_pages, KMemoryPermis
|
||||||
SCOPE_EXIT({ pages_to_close.CloseAndReset(); });
|
SCOPE_EXIT({ pages_to_close.CloseAndReset(); });
|
||||||
|
|
||||||
this->AddRegionToPages(addr, num_pages, pages_to_close);
|
this->AddRegionToPages(addr, num_pages, pages_to_close);
|
||||||
m_system.Memory().UnmapRegion(*m_page_table_impl, addr, num_pages * PageSize);
|
m_memory->UnmapRegion(*m_page_table_impl, addr, num_pages * PageSize);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OperationType::MapFirst:
|
case OperationType::MapFirst:
|
||||||
case OperationType::Map: {
|
case OperationType::Map: {
|
||||||
ASSERT(map_addr);
|
ASSERT(map_addr);
|
||||||
ASSERT(Common::IsAligned(GetInteger(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_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.
|
||||||
if (IsHeapPhysicalAddress(m_kernel.MemoryLayout(), map_addr)) {
|
if (IsHeapPhysicalAddress(m_kernel.MemoryLayout(), map_addr)) {
|
||||||
|
|
|
@ -66,7 +66,8 @@ 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,
|
||||||
KProcessAddress code_addr, size_t code_size,
|
KProcessAddress code_addr, size_t code_size,
|
||||||
KSystemResource* system_resource, KResourceLimit* resource_limit);
|
KSystemResource* system_resource, KResourceLimit* resource_limit,
|
||||||
|
Core::Memory::Memory& memory);
|
||||||
|
|
||||||
void Finalize();
|
void Finalize();
|
||||||
|
|
||||||
|
@ -546,6 +547,7 @@ private:
|
||||||
|
|
||||||
Core::System& m_system;
|
Core::System& m_system;
|
||||||
KernelCore& m_kernel;
|
KernelCore& m_kernel;
|
||||||
|
Core::Memory::Memory* m_memory{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -367,8 +367,8 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
|
||||||
// Initialize process address space
|
// Initialize process address space
|
||||||
if (const Result result{m_page_table.InitializeForProcess(
|
if (const Result result{m_page_table.InitializeForProcess(
|
||||||
metadata.GetAddressSpaceType(), false, false, false, KMemoryManager::Pool::Application,
|
metadata.GetAddressSpaceType(), false, false, false, KMemoryManager::Pool::Application,
|
||||||
0x8000000, code_size, std::addressof(m_kernel.GetAppSystemResource()),
|
0x8000000, code_size, std::addressof(m_kernel.GetAppSystemResource()), m_resource_limit,
|
||||||
m_resource_limit)};
|
m_kernel.System().ApplicationMemory())};
|
||||||
result.IsError()) {
|
result.IsError()) {
|
||||||
R_RETURN(result);
|
R_RETURN(result);
|
||||||
}
|
}
|
||||||
|
@ -592,8 +592,7 @@ Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KProcess::InsertWatchpoint(Core::System& system, KProcessAddress addr, u64 size,
|
bool KProcess::InsertWatchpoint(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;
|
||||||
})};
|
})};
|
||||||
|
@ -609,14 +608,13 @@ bool KProcess::InsertWatchpoint(Core::System& system, KProcessAddress addr, u64
|
||||||
for (KProcessAddress page = Common::AlignDown(GetInteger(addr), PageSize); page < addr + size;
|
for (KProcessAddress page = Common::AlignDown(GetInteger(addr), PageSize); page < addr + size;
|
||||||
page += PageSize) {
|
page += PageSize) {
|
||||||
m_debug_page_refcounts[page]++;
|
m_debug_page_refcounts[page]++;
|
||||||
system.Memory().MarkRegionDebug(page, PageSize, true);
|
this->GetMemory().MarkRegionDebug(page, PageSize, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KProcess::RemoveWatchpoint(Core::System& system, KProcessAddress addr, u64 size,
|
bool KProcess::RemoveWatchpoint(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;
|
||||||
})};
|
})};
|
||||||
|
@ -633,7 +631,7 @@ bool KProcess::RemoveWatchpoint(Core::System& system, KProcessAddress addr, u64
|
||||||
page += PageSize) {
|
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);
|
this->GetMemory().MarkRegionDebug(page, PageSize, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,8 +644,7 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) {
|
||||||
m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission);
|
m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission);
|
||||||
};
|
};
|
||||||
|
|
||||||
m_kernel.System().Memory().WriteBlock(*this, base_addr, code_set.memory.data(),
|
this->GetMemory().WriteBlock(base_addr, code_set.memory.data(), code_set.memory.size());
|
||||||
code_set.memory.size());
|
|
||||||
|
|
||||||
ReprotectSegment(code_set.CodeSegment(), Svc::MemoryPermission::ReadExecute);
|
ReprotectSegment(code_set.CodeSegment(), Svc::MemoryPermission::ReadExecute);
|
||||||
ReprotectSegment(code_set.RODataSegment(), Svc::MemoryPermission::Read);
|
ReprotectSegment(code_set.RODataSegment(), Svc::MemoryPermission::Read);
|
||||||
|
@ -706,4 +703,9 @@ Result KProcess::AllocateMainThreadStack(std::size_t stack_size) {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Core::Memory::Memory& KProcess::GetMemory() const {
|
||||||
|
// TODO: per-process memory
|
||||||
|
return m_kernel.System().ApplicationMemory();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -22,8 +22,12 @@
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
namespace Memory {
|
||||||
|
class Memory;
|
||||||
|
};
|
||||||
|
|
||||||
class System;
|
class System;
|
||||||
}
|
} // namespace Core
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
class ProgramMetadata;
|
class ProgramMetadata;
|
||||||
|
@ -135,6 +139,9 @@ public:
|
||||||
return m_handle_table;
|
return m_handle_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a reference to process's memory.
|
||||||
|
Core::Memory::Memory& GetMemory() const;
|
||||||
|
|
||||||
Result SignalToAddress(KProcessAddress address) {
|
Result SignalToAddress(KProcessAddress address) {
|
||||||
return m_condition_var.SignalToAddress(address);
|
return m_condition_var.SignalToAddress(address);
|
||||||
}
|
}
|
||||||
|
@ -397,12 +404,10 @@ public:
|
||||||
// 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, KProcessAddress addr, u64 size,
|
bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
|
||||||
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, KProcessAddress addr, u64 size,
|
bool RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
|
||||||
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;
|
||||||
|
|
|
@ -222,7 +222,7 @@ Result KServerSession::SendReply(bool is_hle) {
|
||||||
// HLE servers write directly to a pointer to the thread command buffer. Therefore
|
// HLE servers write directly to a pointer to the thread command buffer. Therefore
|
||||||
// the reply has already been written in this case.
|
// the reply has already been written in this case.
|
||||||
} else {
|
} else {
|
||||||
Core::Memory::Memory& memory{m_kernel.System().Memory()};
|
Core::Memory::Memory& memory{client_thread->GetOwnerProcess()->GetMemory()};
|
||||||
KThread* server_thread{GetCurrentThreadPointer(m_kernel)};
|
KThread* server_thread{GetCurrentThreadPointer(m_kernel)};
|
||||||
UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
|
UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ Result KServerSession::ReceiveRequest(std::shared_ptr<Service::HLERequestContext
|
||||||
// bool recv_list_broken = false;
|
// bool recv_list_broken = false;
|
||||||
|
|
||||||
// Receive the message.
|
// Receive the message.
|
||||||
Core::Memory::Memory& memory{m_kernel.System().Memory()};
|
Core::Memory::Memory& memory{client_thread->GetOwnerProcess()->GetMemory()};
|
||||||
if (out_context != nullptr) {
|
if (out_context != nullptr) {
|
||||||
// HLE request.
|
// HLE request.
|
||||||
u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(client_message))};
|
u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(client_message))};
|
||||||
|
|
|
@ -546,7 +546,7 @@ u16 KThread::GetUserDisableCount() const {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& memory = m_kernel.System().Memory();
|
auto& memory = this->GetOwnerProcess()->GetMemory();
|
||||||
return memory.Read16(m_tls_address + offsetof(ThreadLocalRegion, disable_count));
|
return memory.Read16(m_tls_address + offsetof(ThreadLocalRegion, disable_count));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,7 +556,7 @@ void KThread::SetInterruptFlag() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& memory = m_kernel.System().Memory();
|
auto& memory = this->GetOwnerProcess()->GetMemory();
|
||||||
memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 1);
|
memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,7 +566,7 @@ void KThread::ClearInterruptFlag() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& memory = m_kernel.System().Memory();
|
auto& memory = this->GetOwnerProcess()->GetMemory();
|
||||||
memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0);
|
memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1422,6 +1422,11 @@ s32 GetCurrentCoreId(KernelCore& kernel) {
|
||||||
return GetCurrentThread(kernel).GetCurrentCore();
|
return GetCurrentThread(kernel).GetCurrentCore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Core::Memory::Memory& GetCurrentMemory(KernelCore& kernel) {
|
||||||
|
// TODO: per-process memory
|
||||||
|
return kernel.System().ApplicationMemory();
|
||||||
|
}
|
||||||
|
|
||||||
KScopedDisableDispatch::~KScopedDisableDispatch() {
|
KScopedDisableDispatch::~KScopedDisableDispatch() {
|
||||||
// If we are shutting down the kernel, none of this is relevant anymore.
|
// If we are shutting down the kernel, none of this is relevant anymore.
|
||||||
if (m_kernel.IsShuttingDown()) {
|
if (m_kernel.IsShuttingDown()) {
|
||||||
|
|
|
@ -34,6 +34,9 @@ class Fiber;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
namespace Memory {
|
||||||
|
class Memory;
|
||||||
|
}
|
||||||
class ARM_Interface;
|
class ARM_Interface;
|
||||||
class System;
|
class System;
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
@ -113,6 +116,7 @@ KThread& GetCurrentThread(KernelCore& kernel);
|
||||||
KProcess* GetCurrentProcessPointer(KernelCore& kernel);
|
KProcess* GetCurrentProcessPointer(KernelCore& kernel);
|
||||||
KProcess& GetCurrentProcess(KernelCore& kernel);
|
KProcess& GetCurrentProcess(KernelCore& kernel);
|
||||||
s32 GetCurrentCoreId(KernelCore& kernel);
|
s32 GetCurrentCoreId(KernelCore& kernel);
|
||||||
|
Core::Memory::Memory& GetCurrentMemory(KernelCore& kernel);
|
||||||
|
|
||||||
class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>,
|
class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>,
|
||||||
public boost::intrusive::list_base_hook<>,
|
public boost::intrusive::list_base_hook<>,
|
||||||
|
|
|
@ -102,7 +102,7 @@ struct KernelCore::Impl {
|
||||||
void InitializeCores() {
|
void InitializeCores() {
|
||||||
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
|
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
|
||||||
cores[core_id]->Initialize((*application_process).Is64BitProcess());
|
cores[core_id]->Initialize((*application_process).Is64BitProcess());
|
||||||
system.Memory().SetCurrentPageTable(*application_process, core_id);
|
system.ApplicationMemory().SetCurrentPageTable(*application_process, core_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ struct KernelCore::Impl {
|
||||||
|
|
||||||
void InitializePhysicalCores() {
|
void InitializePhysicalCores() {
|
||||||
exclusive_monitor =
|
exclusive_monitor =
|
||||||
Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES);
|
Core::MakeExclusiveMonitor(system.ApplicationMemory(), Core::Hardware::NUM_CPU_CORES);
|
||||||
for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
|
for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
|
||||||
const s32 core{static_cast<s32>(i)};
|
const s32 core{static_cast<s32>(i)};
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 ad
|
||||||
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
|
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
|
||||||
|
|
||||||
// Perform the operation.
|
// Perform the operation.
|
||||||
R_RETURN(system.Memory().FlushDataCache(*process, address, size));
|
R_RETURN(GetCurrentMemory(system.Kernel()).FlushDataCache(address, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlushEntireDataCache64(Core::System& system) {
|
void FlushEntireDataCache64(Core::System& system) {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/hle/kernel/k_thread.h"
|
||||||
#include "core/hle/kernel/svc.h"
|
#include "core/hle/kernel/svc.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
|
@ -12,7 +13,7 @@ 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');
|
||||||
system.Memory().ReadBlock(address, str.data(), str.size());
|
GetCurrentMemory(system.Kernel()).ReadBlock(address, str.data(), str.size());
|
||||||
LOG_DEBUG(Debug_Emulated, "{}", str);
|
LOG_DEBUG(Debug_Emulated, "{}", str);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
|
@ -25,7 +25,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& memory = system.Memory();
|
auto& memory = GetCurrentMemory(system.Kernel());
|
||||||
|
|
||||||
// This typically is an error code so we're going to assume this is the case
|
// This typically is an error code so we're going to assume this is the case
|
||||||
if (sz == sizeof(u32)) {
|
if (sz == sizeof(u32)) {
|
||||||
|
|
|
@ -41,12 +41,12 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad
|
||||||
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
|
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
|
||||||
|
|
||||||
R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
|
R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
|
||||||
R_UNLESS(system.Memory().IsValidVirtualAddressRange(
|
R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
|
||||||
handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
|
handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
|
||||||
ResultInvalidPointer);
|
ResultInvalidPointer);
|
||||||
|
|
||||||
std::vector<Handle> handles(num_handles);
|
std::vector<Handle> handles(num_handles);
|
||||||
system.Memory().ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles);
|
GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles);
|
||||||
|
|
||||||
// Convert handle list to object table.
|
// Convert handle list to object table.
|
||||||
std::vector<KSynchronizationObject*> objs(num_handles);
|
std::vector<KSynchronizationObject*> objs(num_handles);
|
||||||
|
|
|
@ -14,7 +14,8 @@ namespace Kernel::Svc {
|
||||||
|
|
||||||
Result ConnectToNamedPort(Core::System& system, Handle* out, u64 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 =
|
||||||
|
GetCurrentMemory(system.Kernel()).ReadCString(user_name, KObjectName::NameLengthMax);
|
||||||
|
|
||||||
std::array<char, KObjectName::NameLengthMax> name{};
|
std::array<char, KObjectName::NameLengthMax> name{};
|
||||||
std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
|
std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
|
||||||
|
@ -62,7 +63,8 @@ Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) {
|
||||||
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name,
|
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name,
|
||||||
int32_t max_sessions) {
|
int32_t max_sessions) {
|
||||||
// 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 =
|
||||||
|
GetCurrentMemory(system.Kernel()).ReadCString(user_name, KObjectName::NameLengthMax);
|
||||||
|
|
||||||
// Copy the provided name from user memory to kernel memory.
|
// Copy the provided name from user memory to kernel memory.
|
||||||
std::array<char, KObjectName::NameLengthMax> name{};
|
std::array<char, KObjectName::NameLengthMax> name{};
|
||||||
|
|
|
@ -73,7 +73,7 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& memory = system.Memory();
|
auto& memory = GetCurrentMemory(kernel);
|
||||||
const auto& process_list = kernel.GetProcessList();
|
const auto& process_list = kernel.GetProcessList();
|
||||||
const auto num_processes = process_list.size();
|
const auto num_processes = process_list.size();
|
||||||
const auto copy_amount =
|
const auto copy_amount =
|
||||||
|
|
|
@ -30,10 +30,10 @@ Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageIn
|
||||||
R_THROW(ResultInvalidHandle);
|
R_THROW(ResultInvalidHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& memory{system.Memory()};
|
auto& current_memory{GetCurrentMemory(system.Kernel())};
|
||||||
const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()};
|
const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()};
|
||||||
|
|
||||||
memory.WriteBlock(out_memory_info, std::addressof(memory_info), sizeof(memory_info));
|
current_memory.WriteBlock(out_memory_info, std::addressof(memory_info), sizeof(memory_info));
|
||||||
|
|
||||||
//! This is supposed to be part of the QueryInfo call.
|
//! This is supposed to be part of the QueryInfo call.
|
||||||
*out_page_info = {};
|
*out_page_info = {};
|
||||||
|
|
|
@ -90,7 +90,8 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha
|
||||||
|
|
||||||
std::vector<Handle> handles(num_handles);
|
std::vector<Handle> handles(num_handles);
|
||||||
if (num_handles > 0) {
|
if (num_handles > 0) {
|
||||||
system.Memory().ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle));
|
GetCurrentMemory(system.Kernel())
|
||||||
|
.ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns));
|
R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns));
|
||||||
|
|
|
@ -178,7 +178,7 @@ Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_ha
|
||||||
R_TRY(thread->GetThreadContext3(context));
|
R_TRY(thread->GetThreadContext3(context));
|
||||||
|
|
||||||
// Copy the thread context to user space.
|
// Copy the thread context to user space.
|
||||||
system.Memory().WriteBlock(out_context, context.data(), context.size());
|
GetCurrentMemory(kernel).WriteBlock(out_context, context.data(), context.size());
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ Result GetThreadList(Core::System& system, s32* out_num_threads, u64 out_thread_
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& memory = system.Memory();
|
auto& memory = GetCurrentMemory(system.Kernel());
|
||||||
const auto& thread_list = current_process->GetThreadList();
|
const auto& thread_list = current_process->GetThreadList();
|
||||||
const auto num_threads = thread_list.size();
|
const auto num_threads = thread_list.size();
|
||||||
const auto copy_amount = std::min(static_cast<std::size_t>(out_thread_ids_size), num_threads);
|
const auto copy_amount = std::min(static_cast<std::size_t>(out_thread_ids_size), num_threads);
|
||||||
|
|
|
@ -1265,7 +1265,8 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> memory(transfer_mem->GetSize());
|
std::vector<u8> memory(transfer_mem->GetSize());
|
||||||
system.Memory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size());
|
system.ApplicationMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(),
|
||||||
|
memory.size());
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -1298,7 +1299,8 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> memory(transfer_mem->GetSize());
|
std::vector<u8> memory(transfer_mem->GetSize());
|
||||||
system.Memory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size());
|
system.ApplicationMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(),
|
||||||
|
memory.size());
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
|
|
@ -60,7 +60,8 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
|
||||||
|
|
||||||
// Update seven six axis transfer memory
|
// Update seven six axis transfer memory
|
||||||
seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
|
seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
|
||||||
system.Memory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo));
|
system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo,
|
||||||
|
sizeof(seven_sixaxis_lifo));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller_ConsoleSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) {
|
void Controller_ConsoleSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) {
|
||||||
|
|
|
@ -64,7 +64,7 @@ void RingController::OnUpdate() {
|
||||||
curr_entry.polling_data.out_size = sizeof(ringcon_value);
|
curr_entry.polling_data.out_size = sizeof(ringcon_value);
|
||||||
std::memcpy(curr_entry.polling_data.data.data(), &ringcon_value, sizeof(ringcon_value));
|
std::memcpy(curr_entry.polling_data.data.data(), &ringcon_value, sizeof(ringcon_value));
|
||||||
|
|
||||||
system.Memory().WriteBlock(transfer_memory, &enable_sixaxis_data,
|
system.ApplicationMemory().WriteBlock(transfer_memory, &enable_sixaxis_data,
|
||||||
sizeof(enable_sixaxis_data));
|
sizeof(enable_sixaxis_data));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType
|
||||||
if (camera_data.format != current_config.origin_format) {
|
if (camera_data.format != current_config.origin_format) {
|
||||||
LOG_WARNING(Service_IRS, "Wrong Input format {} expected {}", camera_data.format,
|
LOG_WARNING(Service_IRS, "Wrong Input format {} expected {}", camera_data.format,
|
||||||
current_config.origin_format);
|
current_config.origin_format);
|
||||||
system.Memory().ZeroBlock(*system.ApplicationProcess(), transfer_memory,
|
system.ApplicationMemory().ZeroBlock(transfer_memory,
|
||||||
GetDataSize(current_config.trimming_format));
|
GetDataSize(current_config.trimming_format));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType
|
||||||
if (current_config.origin_format > current_config.trimming_format) {
|
if (current_config.origin_format > current_config.trimming_format) {
|
||||||
LOG_WARNING(Service_IRS, "Origin format {} is smaller than trimming format {}",
|
LOG_WARNING(Service_IRS, "Origin format {} is smaller than trimming format {}",
|
||||||
current_config.origin_format, current_config.trimming_format);
|
current_config.origin_format, current_config.trimming_format);
|
||||||
system.Memory().ZeroBlock(*system.ApplicationProcess(), transfer_memory,
|
system.ApplicationMemory().ZeroBlock(transfer_memory,
|
||||||
GetDataSize(current_config.trimming_format));
|
GetDataSize(current_config.trimming_format));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType
|
||||||
"Trimming area ({}, {}, {}, {}) is outside of origin area ({}, {})",
|
"Trimming area ({}, {}, {}, {}) is outside of origin area ({}, {})",
|
||||||
current_config.trimming_start_x, current_config.trimming_start_y,
|
current_config.trimming_start_x, current_config.trimming_start_y,
|
||||||
trimming_width, trimming_height, origin_width, origin_height);
|
trimming_width, trimming_height, origin_width, origin_height);
|
||||||
system.Memory().ZeroBlock(*system.ApplicationProcess(), transfer_memory,
|
system.ApplicationMemory().ZeroBlock(transfer_memory,
|
||||||
GetDataSize(current_config.trimming_format));
|
GetDataSize(current_config.trimming_format));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
system.Memory().WriteBlock(transfer_memory, window_data.data(),
|
system.ApplicationMemory().WriteBlock(transfer_memory, window_data.data(),
|
||||||
GetDataSize(current_config.trimming_format));
|
GetDataSize(current_config.trimming_format));
|
||||||
|
|
||||||
if (!IsProcessorActive()) {
|
if (!IsProcessorActive()) {
|
||||||
|
@ -148,7 +148,7 @@ Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState(
|
||||||
std::vector<u8>& data) const {
|
std::vector<u8>& data) const {
|
||||||
const auto size = GetDataSize(current_config.trimming_format);
|
const auto size = GetDataSize(current_config.trimming_format);
|
||||||
data.resize(size);
|
data.resize(size);
|
||||||
system.Memory().ReadBlock(transfer_memory, data.data(), size);
|
system.ApplicationMemory().ReadBlock(transfer_memory, data.data(), size);
|
||||||
return processor_state;
|
return processor_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -303,8 +303,7 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer(Kernel::KThread& requesti
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the translated command buffer back into the thread's command buffer area.
|
// Copy the translated command buffer back into the thread's command buffer area.
|
||||||
memory.WriteBlock(owner_process, requesting_thread.GetTlsAddress(), cmd_buf.data(),
|
memory.WriteBlock(requesting_thread.GetTlsAddress(), cmd_buf.data(), write_size * sizeof(u32));
|
||||||
write_size * sizeof(u32));
|
|
||||||
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,8 @@ class IJitEnvironment final : public ServiceFramework<IJitEnvironment> {
|
||||||
public:
|
public:
|
||||||
explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx,
|
explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx,
|
||||||
CodeRange user_ro)
|
CodeRange user_ro)
|
||||||
: ServiceFramework{system_, "IJitEnvironment"}, process{&process_}, context{
|
: ServiceFramework{system_, "IJitEnvironment"}, process{&process_},
|
||||||
system_.Memory()} {
|
context{system_.ApplicationMemory()} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IJitEnvironment::GenerateCode, "GenerateCode"},
|
{0, &IJitEnvironment::GenerateCode, "GenerateCode"},
|
||||||
|
|
|
@ -225,7 +225,7 @@ public:
|
||||||
|
|
||||||
// Read NRR data from memory
|
// Read NRR data from memory
|
||||||
std::vector<u8> nrr_data(nrr_size);
|
std::vector<u8> nrr_data(nrr_size);
|
||||||
system.Memory().ReadBlock(nrr_address, nrr_data.data(), nrr_size);
|
system.ApplicationMemory().ReadBlock(nrr_address, nrr_data.data(), nrr_size);
|
||||||
NRRHeader header;
|
NRRHeader header;
|
||||||
std::memcpy(&header, nrr_data.data(), sizeof(NRRHeader));
|
std::memcpy(&header, nrr_data.data(), sizeof(NRRHeader));
|
||||||
|
|
||||||
|
@ -314,7 +314,7 @@ public:
|
||||||
const auto is_region_available = [&](VAddr addr) {
|
const auto is_region_available = [&](VAddr addr) {
|
||||||
const auto end_addr = addr + size;
|
const auto end_addr = addr + size;
|
||||||
while (addr < end_addr) {
|
while (addr < end_addr) {
|
||||||
if (system.Memory().IsValidVirtualAddress(addr)) {
|
if (system.ApplicationMemory().IsValidVirtualAddress(addr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,8 +427,8 @@ public:
|
||||||
const VAddr bss_end_addr{
|
const VAddr bss_end_addr{
|
||||||
Common::AlignUp(bss_start + nro_header.bss_size, Kernel::PageSize)};
|
Common::AlignUp(bss_start + nro_header.bss_size, Kernel::PageSize)};
|
||||||
|
|
||||||
const auto CopyCode = [this, process](VAddr src_addr, VAddr dst_addr, u64 size) {
|
const auto CopyCode = [this](VAddr src_addr, VAddr dst_addr, u64 size) {
|
||||||
system.Memory().CopyBlock(*process, dst_addr, src_addr, size);
|
system.ApplicationMemory().CopyBlock(dst_addr, src_addr, size);
|
||||||
};
|
};
|
||||||
CopyCode(nro_addr + nro_header.segment_headers[TEXT_INDEX].memory_offset, text_start,
|
CopyCode(nro_addr + nro_header.segment_headers[TEXT_INDEX].memory_offset, text_start,
|
||||||
nro_header.segment_headers[TEXT_INDEX].memory_size);
|
nro_header.segment_headers[TEXT_INDEX].memory_size);
|
||||||
|
@ -506,7 +506,7 @@ public:
|
||||||
|
|
||||||
// Read NRO data from memory
|
// Read NRO data from memory
|
||||||
std::vector<u8> nro_data(nro_size);
|
std::vector<u8> nro_data(nro_size);
|
||||||
system.Memory().ReadBlock(nro_address, nro_data.data(), nro_size);
|
system.ApplicationMemory().ReadBlock(nro_address, nro_data.data(), nro_size);
|
||||||
|
|
||||||
SHA256Hash hash{};
|
SHA256Hash hash{};
|
||||||
mbedtls_sha256_ret(nro_data.data(), nro_data.size(), hash.data(), 0);
|
mbedtls_sha256_ret(nro_data.data(), nro_data.size(), hash.data(), 0);
|
||||||
|
|
|
@ -304,7 +304,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>
|
||||||
Tegra::CommandList entries(params.num_entries);
|
Tegra::CommandList entries(params.num_entries);
|
||||||
|
|
||||||
if (kickoff) {
|
if (kickoff) {
|
||||||
system.Memory().ReadBlock(params.address, entries.command_lists.data(),
|
system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(),
|
||||||
params.num_entries * sizeof(Tegra::CommandListHeader));
|
params.num_entries * sizeof(Tegra::CommandListHeader));
|
||||||
} else {
|
} else {
|
||||||
std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)],
|
std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)],
|
||||||
|
|
|
@ -105,7 +105,7 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input,
|
||||||
const auto object = nvmap.GetHandle(cmd_buffer.memory_id);
|
const auto object = nvmap.GetHandle(cmd_buffer.memory_id);
|
||||||
ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;);
|
ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;);
|
||||||
Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count);
|
Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count);
|
||||||
system.Memory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(),
|
system.ApplicationMemory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(),
|
||||||
cmdlist.size() * sizeof(u32));
|
cmdlist.size() * sizeof(u32));
|
||||||
gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist);
|
gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist);
|
||||||
}
|
}
|
||||||
|
|
|
@ -832,11 +832,6 @@ std::string Memory::ReadCString(Common::ProcessAddress vaddr, std::size_t max_le
|
||||||
return impl->ReadCString(vaddr, max_length);
|
return impl->ReadCString(vaddr, max_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::ReadBlock(const Kernel::KProcess& process, const Common::ProcessAddress src_addr,
|
|
||||||
void* dest_buffer, const std::size_t size) {
|
|
||||||
impl->ReadBlockImpl<false>(process, src_addr, dest_buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
|
void Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
impl->ReadBlock(src_addr, dest_buffer, size);
|
impl->ReadBlock(src_addr, dest_buffer, size);
|
||||||
|
@ -847,11 +842,6 @@ void Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_b
|
||||||
impl->ReadBlockUnsafe(src_addr, dest_buffer, size);
|
impl->ReadBlockUnsafe(src_addr, dest_buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::WriteBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
|
|
||||||
const void* src_buffer, std::size_t size) {
|
|
||||||
impl->WriteBlockImpl<false>(process, dest_addr, src_buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
|
void Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
impl->WriteBlock(dest_addr, src_buffer, size);
|
impl->WriteBlock(dest_addr, src_buffer, size);
|
||||||
|
@ -862,29 +852,25 @@ void Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void
|
||||||
impl->WriteBlockUnsafe(dest_addr, src_buffer, size);
|
impl->WriteBlockUnsafe(dest_addr, src_buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::CopyBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
|
void Memory::CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
|
||||||
Common::ProcessAddress src_addr, const std::size_t size) {
|
|
||||||
impl->CopyBlock(process, dest_addr, src_addr, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Memory::ZeroBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
|
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
impl->ZeroBlock(process, dest_addr, size);
|
impl->CopyBlock(*system.ApplicationProcess(), dest_addr, src_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Memory::InvalidateDataCache(const Kernel::KProcess& process,
|
void Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) {
|
||||||
Common::ProcessAddress dest_addr, const std::size_t size) {
|
impl->ZeroBlock(*system.ApplicationProcess(), dest_addr, size);
|
||||||
return impl->InvalidateDataCache(process, dest_addr, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Memory::StoreDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
|
Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
|
||||||
const std::size_t size) {
|
return impl->InvalidateDataCache(*system.ApplicationProcess(), dest_addr, size);
|
||||||
return impl->StoreDataCache(process, dest_addr, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Memory::FlushDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
|
Result Memory::StoreDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
|
||||||
const std::size_t size) {
|
return impl->StoreDataCache(*system.ApplicationProcess(), dest_addr, size);
|
||||||
return impl->FlushDataCache(process, dest_addr, size);
|
}
|
||||||
|
|
||||||
|
Result Memory::FlushDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
|
||||||
|
return impl->FlushDataCache(*system.ApplicationProcess(), dest_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) {
|
void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) {
|
||||||
|
|
|
@ -304,26 +304,6 @@ public:
|
||||||
*/
|
*/
|
||||||
std::string ReadCString(Common::ProcessAddress 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.
|
|
||||||
*
|
|
||||||
* @param process The process to read the data from.
|
|
||||||
* @param src_addr The virtual address to begin reading from.
|
|
||||||
* @param dest_buffer The buffer to place the read bytes into.
|
|
||||||
* @param size The amount of data to read, in bytes.
|
|
||||||
*
|
|
||||||
* @note If a size of 0 is specified, then this function reads nothing and
|
|
||||||
* no attempts to access memory are made at all.
|
|
||||||
*
|
|
||||||
* @pre dest_buffer must be at least size bytes in length, otherwise a
|
|
||||||
* buffer overrun will occur.
|
|
||||||
*
|
|
||||||
* @post The range [dest_buffer, size) contains the read bytes from the
|
|
||||||
* process' address space.
|
|
||||||
*/
|
|
||||||
void ReadBlock(const Kernel::KProcess& process, 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.
|
||||||
*
|
*
|
||||||
|
@ -361,29 +341,6 @@ public:
|
||||||
*/
|
*/
|
||||||
void ReadBlockUnsafe(Common::ProcessAddress 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
|
|
||||||
* virtual address.
|
|
||||||
*
|
|
||||||
* @param process The process to write data into the address space of.
|
|
||||||
* @param dest_addr The destination virtual address to begin writing the data at.
|
|
||||||
* @param src_buffer The data to write into the process' address space.
|
|
||||||
* @param size The size of the data to write, in bytes.
|
|
||||||
*
|
|
||||||
* @post The address range [dest_addr, size) in the process' address space
|
|
||||||
* contains the data that was within src_buffer.
|
|
||||||
*
|
|
||||||
* @post If an attempt is made to write into an unmapped region of memory, the writes
|
|
||||||
* will be ignored and an error will be logged.
|
|
||||||
*
|
|
||||||
* @post If a write is performed into a region of memory that is considered cached
|
|
||||||
* rasterizer memory, will cause the currently active rasterizer to be notified
|
|
||||||
* and will mark that region as invalidated to caches that the active
|
|
||||||
* graphics backend may be maintaining over the course of execution.
|
|
||||||
*/
|
|
||||||
void WriteBlock(const Kernel::KProcess& process, 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
|
||||||
* virtual address.
|
* virtual address.
|
||||||
|
@ -428,7 +385,6 @@ public:
|
||||||
* Copies data within a process' address space to another location within the
|
* Copies data within a process' address space to another location within the
|
||||||
* same address space.
|
* same address space.
|
||||||
*
|
*
|
||||||
* @param process The process that will have data copied within its address space.
|
|
||||||
* @param dest_addr The destination virtual address to begin copying the data into.
|
* @param dest_addr The destination virtual address to begin copying the data into.
|
||||||
* @param src_addr The source virtual address to begin copying the data from.
|
* @param src_addr The source virtual address to begin copying the data from.
|
||||||
* @param size The size of the data to copy, in bytes.
|
* @param size The size of the data to copy, in bytes.
|
||||||
|
@ -436,58 +392,50 @@ 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, Common::ProcessAddress dest_addr,
|
void CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
|
||||||
Common::ProcessAddress src_addr, std::size_t size);
|
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
|
||||||
* virtual address.
|
* virtual address.
|
||||||
*
|
*
|
||||||
* @param process The process that will have data zeroed within its address space.
|
|
||||||
* @param dest_addr The destination virtual address to zero the data from.
|
* @param dest_addr The destination virtual address to zero the data from.
|
||||||
* @param size The size of the range to zero out, in bytes.
|
* @param size The size of the range to zero out, in bytes.
|
||||||
*
|
*
|
||||||
* @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, Common::ProcessAddress dest_addr,
|
void ZeroBlock(Common::ProcessAddress dest_addr, std::size_t size);
|
||||||
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
|
||||||
* virtual address.
|
* virtual address.
|
||||||
*
|
*
|
||||||
* @param process The process that will have data invalidated within its address space.
|
|
||||||
* @param dest_addr The destination virtual address to invalidate the data from.
|
* @param dest_addr The destination virtual address to invalidate the data from.
|
||||||
* @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, Common::ProcessAddress dest_addr,
|
Result InvalidateDataCache(Common::ProcessAddress dest_addr, std::size_t size);
|
||||||
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
|
||||||
* virtual address.
|
* virtual address.
|
||||||
*
|
*
|
||||||
* @param process The process that will have data stored within its address space.
|
|
||||||
* @param dest_addr The destination virtual address to store the data from.
|
* @param dest_addr The destination virtual address to store the data from.
|
||||||
* @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, Common::ProcessAddress dest_addr,
|
Result StoreDataCache(Common::ProcessAddress dest_addr, std::size_t size);
|
||||||
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
|
||||||
* virtual address.
|
* virtual address.
|
||||||
*
|
*
|
||||||
* @param process The process that will have data flushed within its address space.
|
|
||||||
* @param dest_addr The destination virtual address to flush the data from.
|
* @param dest_addr The destination virtual address to flush the data from.
|
||||||
* @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, Common::ProcessAddress dest_addr,
|
Result FlushDataCache(Common::ProcessAddress dest_addr, std::size_t size);
|
||||||
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.
|
||||||
|
|
|
@ -39,11 +39,11 @@ StandardVmCallbacks::StandardVmCallbacks(System& system_, const CheatProcessMeta
|
||||||
StandardVmCallbacks::~StandardVmCallbacks() = default;
|
StandardVmCallbacks::~StandardVmCallbacks() = default;
|
||||||
|
|
||||||
void StandardVmCallbacks::MemoryRead(VAddr address, void* data, u64 size) {
|
void StandardVmCallbacks::MemoryRead(VAddr address, void* data, u64 size) {
|
||||||
system.Memory().ReadBlock(SanitizeAddress(address), data, size);
|
system.ApplicationMemory().ReadBlock(SanitizeAddress(address), data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StandardVmCallbacks::MemoryWrite(VAddr address, const void* data, u64 size) {
|
void StandardVmCallbacks::MemoryWrite(VAddr address, const void* data, u64 size) {
|
||||||
system.Memory().WriteBlock(SanitizeAddress(address), data, size);
|
system.ApplicationMemory().WriteBlock(SanitizeAddress(address), data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 StandardVmCallbacks::HidKeysDown() {
|
u64 StandardVmCallbacks::HidKeysDown() {
|
||||||
|
|
|
@ -264,7 +264,7 @@ void Reporter::SaveUnimplementedFunctionReport(Service::HLERequestContext& ctx,
|
||||||
const auto title_id = system.GetApplicationProcessProgramID();
|
const auto title_id = system.GetApplicationProcessProgramID();
|
||||||
auto out = GetFullDataAuto(timestamp, title_id, system);
|
auto out = GetFullDataAuto(timestamp, title_id, system);
|
||||||
|
|
||||||
auto function_out = GetHLERequestContextData(ctx, system.Memory());
|
auto function_out = GetHLERequestContextData(ctx, system.ApplicationMemory());
|
||||||
function_out["command_id"] = command_id;
|
function_out["command_id"] = command_id;
|
||||||
function_out["function_name"] = name;
|
function_out["function_name"] = name;
|
||||||
function_out["service_name"] = service_name;
|
function_out["service_name"] = service_name;
|
||||||
|
|
|
@ -22,7 +22,7 @@ std::atomic<size_t> MemoryManager::unique_identifier_generator{};
|
||||||
|
|
||||||
MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 big_page_bits_,
|
MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 big_page_bits_,
|
||||||
u64 page_bits_)
|
u64 page_bits_)
|
||||||
: system{system_}, memory{system.Memory()}, device_memory{system.DeviceMemory()},
|
: system{system_}, memory{system.ApplicationMemory()}, device_memory{system.DeviceMemory()},
|
||||||
address_space_bits{address_space_bits_}, page_bits{page_bits_}, big_page_bits{big_page_bits_},
|
address_space_bits{address_space_bits_}, page_bits{page_bits_}, big_page_bits{big_page_bits_},
|
||||||
entries{}, big_entries{}, page_table{address_space_bits, address_space_bits + page_bits - 38,
|
entries{}, big_entries{}, page_table{address_space_bits, address_space_bits + page_bits - 38,
|
||||||
page_bits != big_page_bits ? page_bits : 0},
|
page_bits != big_page_bits ? page_bits : 0},
|
||||||
|
|
|
@ -18,7 +18,7 @@ std::unique_ptr<VideoCore::RendererBase> CreateRenderer(
|
||||||
Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu,
|
Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu,
|
||||||
std::unique_ptr<Core::Frontend::GraphicsContext> context) {
|
std::unique_ptr<Core::Frontend::GraphicsContext> context) {
|
||||||
auto& telemetry_session = system.TelemetrySession();
|
auto& telemetry_session = system.TelemetrySession();
|
||||||
auto& cpu_memory = system.Memory();
|
auto& cpu_memory = system.ApplicationMemory();
|
||||||
|
|
||||||
switch (Settings::values.renderer_backend.GetValue()) {
|
switch (Settings::values.renderer_backend.GetValue()) {
|
||||||
case Settings::RendererBackend::OpenGL:
|
case Settings::RendererBackend::OpenGL:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
|
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
|
||||||
"name": "yuzu",
|
"name": "yuzu",
|
||||||
"builtin-baseline": "9b22b40c6c61bf0da2d46346dd44a11e90972cc9",
|
"builtin-baseline": "a7b6122f6b6504d16d96117336a0562693579933",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"boost-algorithm",
|
"boost-algorithm",
|
||||||
|
|
Loading…
Reference in a new issue