diff options
| -rw-r--r-- | .codespellrc | 2 | ||||
| -rw-r--r-- | src/common/host_memory.cpp | 3 | ||||
| -rw-r--r-- | src/common/settings.h | 2 | ||||
| -rw-r--r-- | src/common/signal_chain.h | 4 | ||||
| -rw-r--r-- | src/core/arm/nce/arm_nce.cpp | 5 | ||||
| -rw-r--r-- | src/core/arm/nce/patch.cpp | 5 | ||||
| -rw-r--r-- | src/core/arm/nce/patch.h | 16 | ||||
| -rw-r--r-- | src/core/core.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.h | 4 | ||||
| -rw-r--r-- | src/core/loader/nro.cpp | 6 | ||||
| -rw-r--r-- | src/core/loader/nso.cpp | 15 |
12 files changed, 30 insertions, 35 deletions
diff --git a/.codespellrc b/.codespellrc index 9ff49898b..d1f998449 100644 --- a/.codespellrc +++ b/.codespellrc | |||
| @@ -3,4 +3,4 @@ | |||
| 3 | 3 | ||
| 4 | [codespell] | 4 | [codespell] |
| 5 | skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES,./src/android/app/src/main/res | 5 | skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES,./src/android/app/src/main/res |
| 6 | ignore-words-list = aci,allright,ba,canonicalizations,deques,froms,hda,inout,lod,masia,nam,nax,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,vas,zink,nce | 6 | ignore-words-list = aci,allright,ba,canonicalizations,deques,froms,hda,inout,lod,masia,nam,nax,nce,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,vas,zink |
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 8a869e558..f14077750 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp | |||
| @@ -409,11 +409,14 @@ static void* ChooseVirtualBase(size_t virtual_size) { | |||
| 409 | 409 | ||
| 410 | return MAP_FAILED; | 410 | return MAP_FAILED; |
| 411 | } | 411 | } |
| 412 | |||
| 412 | #else | 413 | #else |
| 414 | |||
| 413 | static void* ChooseVirtualBase(size_t virtual_size) { | 415 | static void* ChooseVirtualBase(size_t virtual_size) { |
| 414 | return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, | 416 | return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, |
| 415 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); | 417 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); |
| 416 | } | 418 | } |
| 419 | |||
| 417 | #endif | 420 | #endif |
| 418 | 421 | ||
| 419 | class HostMemory::Impl { | 422 | class HostMemory::Impl { |
diff --git a/src/common/settings.h b/src/common/settings.h index 648e0be0d..fea639ee3 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -181,7 +181,7 @@ struct Values { | |||
| 181 | 181 | ||
| 182 | // Cpu | 182 | // Cpu |
| 183 | SwitchableSetting<CpuBackend, true> cpu_backend{ | 183 | SwitchableSetting<CpuBackend, true> cpu_backend{ |
| 184 | linkage, CpuBackend::Nce, CpuBackend::Dynarmic, | 184 | linkage, CpuBackend::Dynarmic, CpuBackend::Dynarmic, |
| 185 | #ifdef ARCHITECTURE_arm64 | 185 | #ifdef ARCHITECTURE_arm64 |
| 186 | CpuBackend::Nce, | 186 | CpuBackend::Nce, |
| 187 | #else | 187 | #else |
diff --git a/src/common/signal_chain.h b/src/common/signal_chain.h index e3bfe6882..8d06a1bd1 100644 --- a/src/common/signal_chain.h +++ b/src/common/signal_chain.h | |||
| @@ -10,8 +10,8 @@ | |||
| 10 | namespace Common { | 10 | namespace Common { |
| 11 | 11 | ||
| 12 | // Android's ART overrides sigaction with its own wrapper. This is problematic for SIGSEGV | 12 | // Android's ART overrides sigaction with its own wrapper. This is problematic for SIGSEGV |
| 13 | // in particular, because ARTs handler access TPIDR_EL0, so this extracts the libc version | 13 | // in particular, because ART's handler accesses tpidr_el0, which conflicts with NCE. |
| 14 | // and calls it directly. | 14 | // This extracts the libc symbol and calls it directly. |
| 15 | int SigAction(int signum, const struct sigaction* act, struct sigaction* oldact); | 15 | int SigAction(int signum, const struct sigaction* act, struct sigaction* oldact); |
| 16 | 16 | ||
| 17 | } // namespace Common | 17 | } // namespace Common |
diff --git a/src/core/arm/nce/arm_nce.cpp b/src/core/arm/nce/arm_nce.cpp index 511248a0d..fd82f3b0e 100644 --- a/src/core/arm/nce/arm_nce.cpp +++ b/src/core/arm/nce/arm_nce.cpp | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | #include <cinttypes> | 4 | #include <cinttypes> |
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | 6 | ||
| 7 | #include "common/scope_exit.h" | ||
| 8 | #include "common/signal_chain.h" | 7 | #include "common/signal_chain.h" |
| 9 | #include "core/arm/nce/arm_nce.h" | 8 | #include "core/arm/nce/arm_nce.h" |
| 10 | #include "core/arm/nce/patch.h" | 9 | #include "core/arm/nce/patch.h" |
| @@ -32,7 +31,7 @@ static_assert(offsetof(NativeExecutionParameters, magic) == TpidrEl0TlsMagic); | |||
| 32 | fpsimd_context* GetFloatingPointState(mcontext_t& host_ctx) { | 31 | fpsimd_context* GetFloatingPointState(mcontext_t& host_ctx) { |
| 33 | _aarch64_ctx* header = reinterpret_cast<_aarch64_ctx*>(&host_ctx.__reserved); | 32 | _aarch64_ctx* header = reinterpret_cast<_aarch64_ctx*>(&host_ctx.__reserved); |
| 34 | while (header->magic != FPSIMD_MAGIC) { | 33 | while (header->magic != FPSIMD_MAGIC) { |
| 35 | header = reinterpret_cast<_aarch64_ctx*>((char*)header + header->size); | 34 | header = reinterpret_cast<_aarch64_ctx*>(reinterpret_cast<char*>(header) + header->size); |
| 36 | } | 35 | } |
| 37 | return reinterpret_cast<fpsimd_context*>(header); | 36 | return reinterpret_cast<fpsimd_context*>(header); |
| 38 | } | 37 | } |
| @@ -124,7 +123,7 @@ bool ARM_NCE::HandleGuestFault(GuestContext* guest_ctx, void* raw_info, void* ra | |||
| 124 | 123 | ||
| 125 | // Forcibly mark the context as locked. We are still running. | 124 | // Forcibly mark the context as locked. We are still running. |
| 126 | // We may race with SignalInterrupt here: | 125 | // We may race with SignalInterrupt here: |
| 127 | // - If we lose the race, then SignalInterrupt will send us a signal which are masking, | 126 | // - If we lose the race, then SignalInterrupt will send us a signal we are masking, |
| 128 | // and it will do nothing when it is unmasked, as we have already left guest code. | 127 | // and it will do nothing when it is unmasked, as we have already left guest code. |
| 129 | // - If we win the race, then SignalInterrupt will wait for us to unlock first. | 128 | // - If we win the race, then SignalInterrupt will wait for us to unlock first. |
| 130 | auto& thread_params = guest_ctx->parent->running_thread->GetNativeExecutionParameters(); | 129 | auto& thread_params = guest_ctx->parent->running_thread->GetNativeExecutionParameters(); |
diff --git a/src/core/arm/nce/patch.cpp b/src/core/arm/nce/patch.cpp index c79399c2b..bc4b73634 100644 --- a/src/core/arm/nce/patch.cpp +++ b/src/core/arm/nce/patch.cpp | |||
| @@ -100,7 +100,7 @@ void Patcher::RelocateAndCopy(Common::ProcessAddress load_base, | |||
| 100 | const Kernel::CodeSet::Segment& code, | 100 | const Kernel::CodeSet::Segment& code, |
| 101 | Kernel::PhysicalMemory& program_image, | 101 | Kernel::PhysicalMemory& program_image, |
| 102 | EntryTrampolines* out_trampolines) { | 102 | EntryTrampolines* out_trampolines) { |
| 103 | const size_t patch_size = SectionSize(); | 103 | const size_t patch_size = GetSectionSize(); |
| 104 | const size_t image_size = program_image.size(); | 104 | const size_t image_size = program_image.size(); |
| 105 | 105 | ||
| 106 | // Retrieve text segment data. | 106 | // Retrieve text segment data. |
| @@ -180,7 +180,7 @@ void Patcher::RelocateAndCopy(Common::ProcessAddress load_base, | |||
| 180 | } | 180 | } |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | size_t Patcher::SectionSize() const noexcept { | 183 | size_t Patcher::GetSectionSize() const noexcept { |
| 184 | return Common::AlignUp(m_patch_instructions.size() * sizeof(u32), Core::Memory::YUZU_PAGESIZE); | 184 | return Common::AlignUp(m_patch_instructions.size() * sizeof(u32), Core::Memory::YUZU_PAGESIZE); |
| 185 | } | 185 | } |
| 186 | 186 | ||
| @@ -256,7 +256,6 @@ void Patcher::WriteSaveContext() { | |||
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | void Patcher::WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id) { | 258 | void Patcher::WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id) { |
| 259 | LOG_ERROR(Core_ARM, "Patching SVC {:#x} at {:#x}", svc_id, module_dest - 4); | ||
| 260 | // We are about to start saving state, so we need to lock the context. | 259 | // We are about to start saving state, so we need to lock the context. |
| 261 | this->LockContext(); | 260 | this->LockContext(); |
| 262 | 261 | ||
diff --git a/src/core/arm/nce/patch.h b/src/core/arm/nce/patch.h index b727d4e48..dcce1bfc6 100644 --- a/src/core/arm/nce/patch.h +++ b/src/core/arm/nce/patch.h | |||
| @@ -7,23 +7,17 @@ | |||
| 7 | #include <unordered_map> | 7 | #include <unordered_map> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #pragma clang diagnostic push | 10 | #pragma GCC diagnostic push |
| 11 | #pragma clang diagnostic ignored "-Wshorten-64-to-32" | 11 | #pragma GCC diagnostic ignored "-Wshorten-64-to-32" |
| 12 | #include <oaknut/code_block.hpp> | 12 | #include <oaknut/code_block.hpp> |
| 13 | #include <oaknut/oaknut.hpp> | 13 | #include <oaknut/oaknut.hpp> |
| 14 | #pragma clang diagnostic pop | 14 | #pragma GCC diagnostic pop |
| 15 | 15 | ||
| 16 | #include "common/common_types.h" | 16 | #include "common/common_types.h" |
| 17 | #include "core/hle/kernel/code_set.h" | 17 | #include "core/hle/kernel/code_set.h" |
| 18 | #include "core/hle/kernel/k_typed_address.h" | 18 | #include "core/hle/kernel/k_typed_address.h" |
| 19 | #include "core/hle/kernel/physical_memory.h" | 19 | #include "core/hle/kernel/physical_memory.h" |
| 20 | 20 | ||
| 21 | #include <signal.h> | ||
| 22 | |||
| 23 | namespace Core { | ||
| 24 | struct GuestContext; | ||
| 25 | } | ||
| 26 | |||
| 27 | namespace Core::NCE { | 21 | namespace Core::NCE { |
| 28 | 22 | ||
| 29 | enum class PatchMode : u32 { | 23 | enum class PatchMode : u32 { |
| @@ -45,9 +39,9 @@ public: | |||
| 45 | const Kernel::CodeSet::Segment& code); | 39 | const Kernel::CodeSet::Segment& code); |
| 46 | void RelocateAndCopy(Common::ProcessAddress load_base, const Kernel::CodeSet::Segment& code, | 40 | void RelocateAndCopy(Common::ProcessAddress load_base, const Kernel::CodeSet::Segment& code, |
| 47 | Kernel::PhysicalMemory& program_image, EntryTrampolines* out_trampolines); | 41 | Kernel::PhysicalMemory& program_image, EntryTrampolines* out_trampolines); |
| 48 | size_t SectionSize() const noexcept; | 42 | size_t GetSectionSize() const noexcept; |
| 49 | 43 | ||
| 50 | [[nodiscard]] PatchMode Mode() const noexcept { | 44 | [[nodiscard]] PatchMode GetPatchMode() const noexcept { |
| 51 | return mode; | 45 | return mode; |
| 52 | } | 46 | } |
| 53 | 47 | ||
diff --git a/src/core/core.cpp b/src/core/core.cpp index 408479019..14d6c8c27 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -137,6 +137,7 @@ struct System::Impl { | |||
| 137 | 137 | ||
| 138 | void Initialize(System& system) { | 138 | void Initialize(System& system) { |
| 139 | device_memory = std::make_unique<Core::DeviceMemory>(); | 139 | device_memory = std::make_unique<Core::DeviceMemory>(); |
| 140 | |||
| 140 | is_multicore = Settings::values.use_multi_core.GetValue(); | 141 | is_multicore = Settings::values.use_multi_core.GetValue(); |
| 141 | extended_memory_layout = | 142 | extended_memory_layout = |
| 142 | Settings::values.memory_layout_mode.GetValue() != Settings::MemoryLayout::Memory_4Gb; | 143 | Settings::values.memory_layout_mode.GetValue() != Settings::MemoryLayout::Memory_4Gb; |
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index f2ffc39c1..f7f1e8a3b 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp | |||
| @@ -96,9 +96,11 @@ constexpr Common::MemoryPermission ConvertToMemoryPermission(KMemoryPermission p | |||
| 96 | if (True(perm & KMemoryPermission::UserWrite)) { | 96 | if (True(perm & KMemoryPermission::UserWrite)) { |
| 97 | perms |= Common::MemoryPermission::Write; | 97 | perms |= Common::MemoryPermission::Write; |
| 98 | } | 98 | } |
| 99 | #ifdef ARCHITECTURE_arm64 | ||
| 99 | if (True(perm & KMemoryPermission::UserExecute)) { | 100 | if (True(perm & KMemoryPermission::UserExecute)) { |
| 100 | perms |= Common::MemoryPermission::Execute; | 101 | perms |= Common::MemoryPermission::Execute; |
| 101 | } | 102 | } |
| 103 | #endif | ||
| 102 | return perms; | 104 | return perms; |
| 103 | } | 105 | } |
| 104 | 106 | ||
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 7b97d452b..e5f796ac7 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h | |||
| @@ -472,10 +472,6 @@ public: | |||
| 472 | return m_post_handlers; | 472 | return m_post_handlers; |
| 473 | } | 473 | } |
| 474 | 474 | ||
| 475 | KernelCore& GetKernel() noexcept { | ||
| 476 | return m_kernel; | ||
| 477 | } | ||
| 478 | |||
| 479 | public: | 475 | public: |
| 480 | // Attempts to insert a watchpoint into a free slot. Returns false if none are available. | 476 | // Attempts to insert a watchpoint into a free slot. Returns false if none are available. |
| 481 | bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); | 477 | bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); |
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 76ff38041..49d4d7e43 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -204,7 +204,7 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, | |||
| 204 | #ifdef ARCHITECTURE_arm64 | 204 | #ifdef ARCHITECTURE_arm64 |
| 205 | const auto& code = codeset.CodeSegment(); | 205 | const auto& code = codeset.CodeSegment(); |
| 206 | 206 | ||
| 207 | // NROs are always 64-bit programs. | 207 | // NROs always have a 39-bit address space. |
| 208 | Settings::SetNceEnabled(true); | 208 | Settings::SetNceEnabled(true); |
| 209 | 209 | ||
| 210 | // Create NCE patcher | 210 | // Create NCE patcher |
| @@ -215,12 +215,12 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, | |||
| 215 | patch.PatchText(program_image, code); | 215 | patch.PatchText(program_image, code); |
| 216 | 216 | ||
| 217 | // We only support PostData patching for NROs. | 217 | // We only support PostData patching for NROs. |
| 218 | ASSERT(patch.Mode() == Core::NCE::PatchMode::PostData); | 218 | ASSERT(patch.GetPatchMode() == Core::NCE::PatchMode::PostData); |
| 219 | 219 | ||
| 220 | // Update patch section. | 220 | // Update patch section. |
| 221 | auto& patch_segment = codeset.PatchSegment(); | 221 | auto& patch_segment = codeset.PatchSegment(); |
| 222 | patch_segment.addr = image_size; | 222 | patch_segment.addr = image_size; |
| 223 | patch_segment.size = static_cast<u32>(patch.SectionSize()); | 223 | patch_segment.size = static_cast<u32>(patch.GetSectionSize()); |
| 224 | 224 | ||
| 225 | // Add patch section size to the module size. | 225 | // Add patch section size to the module size. |
| 226 | image_size += patch_segment.size; | 226 | image_size += patch_segment.size; |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 34b10ef2e..1ad2e917c 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -94,8 +94,8 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core:: | |||
| 94 | // Allocate some space at the beginning if we are patching in PreText mode. | 94 | // Allocate some space at the beginning if we are patching in PreText mode. |
| 95 | const size_t module_start = [&]() -> size_t { | 95 | const size_t module_start = [&]() -> size_t { |
| 96 | #ifdef ARCHITECTURE_arm64 | 96 | #ifdef ARCHITECTURE_arm64 |
| 97 | if (patch && patch->Mode() == Core::NCE::PatchMode::PreText) { | 97 | if (patch && patch->GetPatchMode() == Core::NCE::PatchMode::PreText) { |
| 98 | return patch->SectionSize(); | 98 | return patch->GetSectionSize(); |
| 99 | } | 99 | } |
| 100 | #endif | 100 | #endif |
| 101 | return 0; | 101 | return 0; |
| @@ -158,24 +158,25 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core:: | |||
| 158 | #ifdef ARCHITECTURE_arm64 | 158 | #ifdef ARCHITECTURE_arm64 |
| 159 | // If we are computing the process code layout and using nce backend, patch. | 159 | // If we are computing the process code layout and using nce backend, patch. |
| 160 | const auto& code = codeset.CodeSegment(); | 160 | const auto& code = codeset.CodeSegment(); |
| 161 | if (patch && patch->Mode() == Core::NCE::PatchMode::None) { | 161 | if (patch && patch->GetPatchMode() == Core::NCE::PatchMode::None) { |
| 162 | // Patch SVCs and MRS calls in the guest code | 162 | // Patch SVCs and MRS calls in the guest code |
| 163 | patch->PatchText(program_image, code); | 163 | patch->PatchText(program_image, code); |
| 164 | 164 | ||
| 165 | // Add patch section size to the module size. | 165 | // Add patch section size to the module size. |
| 166 | image_size += patch->SectionSize(); | 166 | image_size += patch->GetSectionSize(); |
| 167 | } else if (patch) { | 167 | } else if (patch) { |
| 168 | // Relocate code patch and copy to the program_image. | 168 | // Relocate code patch and copy to the program_image. |
| 169 | patch->RelocateAndCopy(load_base, code, program_image, &process.GetPostHandlers()); | 169 | patch->RelocateAndCopy(load_base, code, program_image, &process.GetPostHandlers()); |
| 170 | 170 | ||
| 171 | // Update patch section. | 171 | // Update patch section. |
| 172 | auto& patch_segment = codeset.PatchSegment(); | 172 | auto& patch_segment = codeset.PatchSegment(); |
| 173 | patch_segment.addr = patch->Mode() == Core::NCE::PatchMode::PreText ? 0 : image_size; | 173 | patch_segment.addr = |
| 174 | patch_segment.size = static_cast<u32>(patch->SectionSize()); | 174 | patch->GetPatchMode() == Core::NCE::PatchMode::PreText ? 0 : image_size; |
| 175 | patch_segment.size = static_cast<u32>(patch->GetSectionSize()); | ||
| 175 | 176 | ||
| 176 | // Add patch section size to the module size. In PreText mode image_size | 177 | // Add patch section size to the module size. In PreText mode image_size |
| 177 | // already contains the patch segment as part of module_start. | 178 | // already contains the patch segment as part of module_start. |
| 178 | if (patch->Mode() == Core::NCE::PatchMode::PostData) { | 179 | if (patch->GetPatchMode() == Core::NCE::PatchMode::PostData) { |
| 179 | image_size += patch_segment.size; | 180 | image_size += patch_segment.size; |
| 180 | } | 181 | } |
| 181 | } | 182 | } |