summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Narr the Reg2024-01-01 13:55:51 -0600
committerGravatar GitHub2024-01-01 13:55:51 -0600
commitf47d618e549a79d0d57122eb734dba109bbd1f77 (patch)
tree6259b511c0e5d99aa85f0813d849e083c80850c0 /src
parentMerge pull request #12509 from liamwhite/ktrace (diff)
parentjit: use code memory handles correctly (diff)
downloadyuzu-f47d618e549a79d0d57122eb734dba109bbd1f77.tar.gz
yuzu-f47d618e549a79d0d57122eb734dba109bbd1f77.tar.xz
yuzu-f47d618e549a79d0d57122eb734dba109bbd1f77.zip
Merge pull request #12513 from liamwhite/jit-fix
jit: use code memory handles correctly
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/service/jit/jit.cpp59
-rw-r--r--src/core/hle/service/jit/jit_code_memory.cpp54
-rw-r--r--src/core/hle/service/jit/jit_code_memory.h49
4 files changed, 146 insertions, 18 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 96ab39cb8..a8b3d480c 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -987,6 +987,8 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
987 arm/dynarmic/dynarmic_cp15.h 987 arm/dynarmic/dynarmic_cp15.h
988 arm/dynarmic/dynarmic_exclusive_monitor.cpp 988 arm/dynarmic/dynarmic_exclusive_monitor.cpp
989 arm/dynarmic/dynarmic_exclusive_monitor.h 989 arm/dynarmic/dynarmic_exclusive_monitor.h
990 hle/service/jit/jit_code_memory.cpp
991 hle/service/jit/jit_code_memory.h
990 hle/service/jit/jit_context.cpp 992 hle/service/jit/jit_context.cpp
991 hle/service/jit/jit_context.h 993 hle/service/jit/jit_context.h
992 hle/service/jit/jit.cpp 994 hle/service/jit/jit.cpp
diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp
index a94d05e19..77aa6d7d1 100644
--- a/src/core/hle/service/jit/jit.cpp
+++ b/src/core/hle/service/jit/jit.cpp
@@ -4,11 +4,11 @@
4#include "core/arm/debug.h" 4#include "core/arm/debug.h"
5#include "core/arm/symbols.h" 5#include "core/arm/symbols.h"
6#include "core/core.h" 6#include "core/core.h"
7#include "core/hle/kernel/k_code_memory.h"
8#include "core/hle/kernel/k_transfer_memory.h" 7#include "core/hle/kernel/k_transfer_memory.h"
9#include "core/hle/result.h" 8#include "core/hle/result.h"
10#include "core/hle/service/ipc_helpers.h" 9#include "core/hle/service/ipc_helpers.h"
11#include "core/hle/service/jit/jit.h" 10#include "core/hle/service/jit/jit.h"
11#include "core/hle/service/jit/jit_code_memory.h"
12#include "core/hle/service/jit/jit_context.h" 12#include "core/hle/service/jit/jit_context.h"
13#include "core/hle/service/server_manager.h" 13#include "core/hle/service/server_manager.h"
14#include "core/hle/service/service.h" 14#include "core/hle/service/service.h"
@@ -23,10 +23,12 @@ struct CodeRange {
23 23
24class IJitEnvironment final : public ServiceFramework<IJitEnvironment> { 24class IJitEnvironment final : public ServiceFramework<IJitEnvironment> {
25public: 25public:
26 explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx, 26 explicit IJitEnvironment(Core::System& system_,
27 CodeRange user_ro) 27 Kernel::KScopedAutoObject<Kernel::KProcess>&& process_,
28 : ServiceFramework{system_, "IJitEnvironment"}, process{&process_}, 28 CodeMemory&& user_rx_, CodeMemory&& user_ro_)
29 context{process->GetMemory()} { 29 : ServiceFramework{system_, "IJitEnvironment"}, process{std::move(process_)},
30 user_rx{std::move(user_rx_)}, user_ro{std::move(user_ro_)},
31 context{system_.ApplicationMemory()} {
30 // clang-format off 32 // clang-format off
31 static const FunctionInfo functions[] = { 33 static const FunctionInfo functions[] = {
32 {0, &IJitEnvironment::GenerateCode, "GenerateCode"}, 34 {0, &IJitEnvironment::GenerateCode, "GenerateCode"},
@@ -39,10 +41,13 @@ public:
39 RegisterHandlers(functions); 41 RegisterHandlers(functions);
40 42
41 // Identity map user code range into sysmodule context 43 // Identity map user code range into sysmodule context
42 configuration.user_ro_memory = user_ro; 44 configuration.user_rx_memory.size = user_rx.GetSize();
43 configuration.user_rx_memory = user_rx; 45 configuration.user_rx_memory.offset = user_rx.GetAddress();
44 configuration.sys_ro_memory = user_ro; 46 configuration.user_ro_memory.size = user_ro.GetSize();
45 configuration.sys_rx_memory = user_rx; 47 configuration.user_ro_memory.offset = user_ro.GetAddress();
48
49 configuration.sys_rx_memory = configuration.user_rx_memory;
50 configuration.sys_ro_memory = configuration.user_ro_memory;
46 } 51 }
47 52
48 void GenerateCode(HLERequestContext& ctx) { 53 void GenerateCode(HLERequestContext& ctx) {
@@ -318,6 +323,8 @@ private:
318 } 323 }
319 324
320 Kernel::KScopedAutoObject<Kernel::KProcess> process; 325 Kernel::KScopedAutoObject<Kernel::KProcess> process;
326 CodeMemory user_rx;
327 CodeMemory user_ro;
321 GuestCallbacks callbacks; 328 GuestCallbacks callbacks;
322 JITConfiguration configuration; 329 JITConfiguration configuration;
323 JITContext context; 330 JITContext context;
@@ -335,6 +342,7 @@ public:
335 RegisterHandlers(functions); 342 RegisterHandlers(functions);
336 } 343 }
337 344
345private:
338 void CreateJitEnvironment(HLERequestContext& ctx) { 346 void CreateJitEnvironment(HLERequestContext& ctx) {
339 LOG_DEBUG(Service_JIT, "called"); 347 LOG_DEBUG(Service_JIT, "called");
340 348
@@ -380,20 +388,35 @@ public:
380 return; 388 return;
381 } 389 }
382 390
383 const CodeRange user_rx{ 391 CodeMemory rx, ro;
384 .offset = GetInteger(rx_mem->GetSourceAddress()), 392 Result res;
385 .size = parameters.rx_size,
386 };
387 393
388 const CodeRange user_ro{ 394 res = rx.Initialize(*process, *rx_mem, parameters.rx_size,
389 .offset = GetInteger(ro_mem->GetSourceAddress()), 395 Kernel::Svc::MemoryPermission::ReadExecute, generate_random);
390 .size = parameters.ro_size, 396 if (R_FAILED(res)) {
391 }; 397 LOG_ERROR(Service_JIT, "rx_mem could not be mapped for handle=0x{:08X}", rx_mem_handle);
398 IPC::ResponseBuilder rb{ctx, 2};
399 rb.Push(res);
400 return;
401 }
402
403 res = ro.Initialize(*process, *ro_mem, parameters.ro_size,
404 Kernel::Svc::MemoryPermission::Read, generate_random);
405 if (R_FAILED(res)) {
406 LOG_ERROR(Service_JIT, "ro_mem could not be mapped for handle=0x{:08X}", ro_mem_handle);
407 IPC::ResponseBuilder rb{ctx, 2};
408 rb.Push(res);
409 return;
410 }
392 411
393 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 412 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
394 rb.Push(ResultSuccess); 413 rb.Push(ResultSuccess);
395 rb.PushIpcInterface<IJitEnvironment>(system, *process, user_rx, user_ro); 414 rb.PushIpcInterface<IJitEnvironment>(system, std::move(process), std::move(rx),
415 std::move(ro));
396 } 416 }
417
418private:
419 std::mt19937_64 generate_random{};
397}; 420};
398 421
399void LoopProcess(Core::System& system) { 422void LoopProcess(Core::System& system) {
diff --git a/src/core/hle/service/jit/jit_code_memory.cpp b/src/core/hle/service/jit/jit_code_memory.cpp
new file mode 100644
index 000000000..2b480488a
--- /dev/null
+++ b/src/core/hle/service/jit/jit_code_memory.cpp
@@ -0,0 +1,54 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/jit/jit_code_memory.h"
5
6namespace Service::JIT {
7
8Result CodeMemory::Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& code_memory,
9 size_t size, Kernel::Svc::MemoryPermission perm,
10 std::mt19937_64& generate_random) {
11 auto& page_table = process.GetPageTable();
12 const u64 alias_code_start =
13 GetInteger(page_table.GetAliasCodeRegionStart()) / Kernel::PageSize;
14 const u64 alias_code_size = page_table.GetAliasCodeRegionSize() / Kernel::PageSize;
15
16 // NOTE: This will retry indefinitely until mapping the code memory succeeds.
17 while (true) {
18 // Generate a new trial address.
19 const u64 mapped_address =
20 (alias_code_start + (generate_random() % alias_code_size)) * Kernel::PageSize;
21
22 // Try to map the address
23 R_TRY_CATCH(code_memory.MapToOwner(mapped_address, size, perm)) {
24 R_CATCH(Kernel::ResultInvalidMemoryRegion) {
25 // If we could not map here, retry.
26 continue;
27 }
28 }
29 R_END_TRY_CATCH;
30
31 // Set members.
32 m_code_memory = std::addressof(code_memory);
33 m_size = size;
34 m_address = mapped_address;
35 m_perm = perm;
36
37 // Open a new reference to the code memory.
38 m_code_memory->Open();
39
40 // We succeeded.
41 R_SUCCEED();
42 }
43}
44
45void CodeMemory::Finalize() {
46 if (m_code_memory) {
47 R_ASSERT(m_code_memory->UnmapFromOwner(m_address, m_size));
48 m_code_memory->Close();
49 }
50
51 m_code_memory = nullptr;
52}
53
54} // namespace Service::JIT
diff --git a/src/core/hle/service/jit/jit_code_memory.h b/src/core/hle/service/jit/jit_code_memory.h
new file mode 100644
index 000000000..6376d4c4e
--- /dev/null
+++ b/src/core/hle/service/jit/jit_code_memory.h
@@ -0,0 +1,49 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <random>
7
8#include "core/hle/kernel/k_code_memory.h"
9
10namespace Service::JIT {
11
12class CodeMemory {
13public:
14 YUZU_NON_COPYABLE(CodeMemory);
15
16 explicit CodeMemory() = default;
17
18 CodeMemory(CodeMemory&& rhs) {
19 std::swap(m_code_memory, rhs.m_code_memory);
20 std::swap(m_size, rhs.m_size);
21 std::swap(m_address, rhs.m_address);
22 std::swap(m_perm, rhs.m_perm);
23 }
24
25 ~CodeMemory() {
26 this->Finalize();
27 }
28
29public:
30 Result Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, size_t size,
31 Kernel::Svc::MemoryPermission perm, std::mt19937_64& generate_random);
32 void Finalize();
33
34 size_t GetSize() const {
35 return m_size;
36 }
37
38 u64 GetAddress() const {
39 return m_address;
40 }
41
42private:
43 Kernel::KCodeMemory* m_code_memory{};
44 size_t m_size{};
45 u64 m_address{};
46 Kernel::Svc::MemoryPermission m_perm{};
47};
48
49} // namespace Service::JIT