aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp53
1 files changed, 52 insertions, 1 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 3542d5a3b6..53d964ecbc 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -6,6 +6,8 @@
// This file is automatically generated using svc_generator.py.
// DO NOT MODIFY IT MANUALLY
+#include <cstdlib>
+#include <cstring>
#include <type_traits>
#include "core/arm/arm_interface.h"
@@ -2505,11 +2507,60 @@ void Call(Core::System& system, u32 imm) {
LOG_TRACE(Kernel_SVC, "{} [0]={:#x} [1]={:#x} [2]={:#x} [3]={:#x} [4]={:#x} [5]={:#x} [6]={:#x}",
imm, GetArg64(args, 0), GetArg64(args, 1), GetArg64(args, 2),
GetArg64(args, 3), GetArg64(args, 4), GetArg64(args, 5), GetArg64(args, 6));
- if (process.Is64Bit()) {
+ // Set EDEN_NX2_SVC_TRACE=1 to log every SVC with its arguments and results, or
+ // EDEN_NX2_SVC_TRACE=<first>:<last> for presents first..last only (a frame-time profile).
+ static const std::pair<u64, u64> trace_range = [] {
+ const char* text = std::getenv("EDEN_NX2_SVC_TRACE");
+ if (text == nullptr) return std::pair<u64, u64>{1, 0};
+ const char* colon = std::strchr(text, ':');
+ if (colon == nullptr) return std::pair<u64, u64>{0, ~u64{}};
+ return std::pair<u64, u64>{std::strtoull(text, nullptr, 10), std::strtoull(colon + 1, nullptr, 10)};
+ }();
+ const u64 presents = Core::g_nx2_present_count.load(std::memory_order_relaxed);
+ const bool svc_trace = presents >= trace_range.first && presents <= trace_range.second;
+ if (svc_trace) {
+ LOG_INFO(Kernel_SVC, "svc {:#04x} in t{} [0]={:#x} [1]={:#x} [2]={:#x} [3]={:#x}", imm,
+ GetCurrentThread(kernel).GetThreadId(),
+ GetArg64(args, 0), GetArg64(args, 1), GetArg64(args, 2), GetArg64(args, 3));
+ }
+ if (imm == 0x80) {
+ // Switch 2 only: svcSetGpuMemoryAttribute(address, size, mask, attr). nn::gpu::sdk and
+ // nn::gs native memory set the new "GPU accessible" attribute (0x20) before registering
+ // memory with the GPU and clear it on destruction; NVN can see it through QueryMemory.
+ // Same checks as svcSetMemoryAttribute, restricted to that bit (as in changes.patch).
+ const u64 address = GetArg64(args, 0);
+ const u64 size = GetArg64(args, 1);
+ const u32 mask = static_cast<u32>(GetArg64(args, 2));
+ const u32 attr = static_cast<u32>(GetArg64(args, 3));
+ constexpr u32 Supported = static_cast<u32>(Svc::MemoryAttribute::GpuAccessible);
+ auto& page_table = process.GetPageTable();
+ Result result = ResultSuccess;
+ if (!Common::IsAligned(address, PageSize)) {
+ result = ResultInvalidAddress;
+ } else if (size == 0 || !Common::IsAligned(size, PageSize)) {
+ result = ResultInvalidSize;
+ } else if ((attr & ~mask) != 0 || ((mask | attr) & ~Supported) != 0) {
+ result = ResultInvalidCombination;
+ } else if (address + size <= address || !page_table.Contains(address, size)) {
+ result = ResultInvalidCurrentMemory;
+ } else {
+ result = page_table.SetMemoryAttribute(address, size,
+ static_cast<KMemoryAttribute>(mask),
+ static_cast<KMemoryAttribute>(attr));
+ }
+ LOG_DEBUG(Kernel_SVC, "Switch 2 svc 0x80 addr={:#x} size={:#x} mask={:#x} attr={:#x} -> {:#x}",
+ address, size, mask, attr, result.raw);
+ args[0] = result.raw;
+ } else if (process.Is64Bit()) {
Call64(system, imm, args);
} else {
Call32(system, imm, args);
}
+ if (svc_trace) {
+ LOG_INFO(Kernel_SVC, "svc {:#04x} out t{} [0]={:#x} [1]={:#x} [2]={:#x}", imm,
+ GetCurrentThread(kernel).GetThreadId(), GetArg64(args, 0), GetArg64(args, 1),
+ GetArg64(args, 2));
+ }
//kernel.ExitSVCProfile();
kernel.CurrentPhysicalCore().LoadSvcArguments(process, args);
}