Address some review comments
This commit is contained in:
parent
8fab363237
commit
6de2edcca1
|
@ -3,4 +3,4 @@
|
||||||
|
|
||||||
[codespell]
|
[codespell]
|
||||||
skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES,./src/android/app/src/main/res
|
skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES,./src/android/app/src/main/res
|
||||||
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
|
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
|
||||||
|
|
|
@ -409,11 +409,14 @@ static void* ChooseVirtualBase(size_t virtual_size) {
|
||||||
|
|
||||||
return MAP_FAILED;
|
return MAP_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static void* ChooseVirtualBase(size_t virtual_size) {
|
static void* ChooseVirtualBase(size_t virtual_size) {
|
||||||
return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE,
|
return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class HostMemory::Impl {
|
class HostMemory::Impl {
|
||||||
|
|
|
@ -181,7 +181,7 @@ struct Values {
|
||||||
|
|
||||||
// Cpu
|
// Cpu
|
||||||
SwitchableSetting<CpuBackend, true> cpu_backend{
|
SwitchableSetting<CpuBackend, true> cpu_backend{
|
||||||
linkage, CpuBackend::Nce, CpuBackend::Dynarmic,
|
linkage, CpuBackend::Dynarmic, CpuBackend::Dynarmic,
|
||||||
#ifdef ARCHITECTURE_arm64
|
#ifdef ARCHITECTURE_arm64
|
||||||
CpuBackend::Nce,
|
CpuBackend::Nce,
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
// Android's ART overrides sigaction with its own wrapper. This is problematic for SIGSEGV
|
// Android's ART overrides sigaction with its own wrapper. This is problematic for SIGSEGV
|
||||||
// in particular, because ARTs handler access TPIDR_EL0, so this extracts the libc version
|
// in particular, because ART's handler accesses tpidr_el0, which conflicts with NCE.
|
||||||
// and calls it directly.
|
// This extracts the libc symbol and calls it directly.
|
||||||
int SigAction(int signum, const struct sigaction* act, struct sigaction* oldact);
|
int SigAction(int signum, const struct sigaction* act, struct sigaction* oldact);
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "common/scope_exit.h"
|
|
||||||
#include "common/signal_chain.h"
|
#include "common/signal_chain.h"
|
||||||
#include "core/arm/nce/arm_nce.h"
|
#include "core/arm/nce/arm_nce.h"
|
||||||
#include "core/arm/nce/patch.h"
|
#include "core/arm/nce/patch.h"
|
||||||
|
@ -32,7 +31,7 @@ static_assert(offsetof(NativeExecutionParameters, magic) == TpidrEl0TlsMagic);
|
||||||
fpsimd_context* GetFloatingPointState(mcontext_t& host_ctx) {
|
fpsimd_context* GetFloatingPointState(mcontext_t& host_ctx) {
|
||||||
_aarch64_ctx* header = reinterpret_cast<_aarch64_ctx*>(&host_ctx.__reserved);
|
_aarch64_ctx* header = reinterpret_cast<_aarch64_ctx*>(&host_ctx.__reserved);
|
||||||
while (header->magic != FPSIMD_MAGIC) {
|
while (header->magic != FPSIMD_MAGIC) {
|
||||||
header = reinterpret_cast<_aarch64_ctx*>((char*)header + header->size);
|
header = reinterpret_cast<_aarch64_ctx*>(reinterpret_cast<char*>(header) + header->size);
|
||||||
}
|
}
|
||||||
return reinterpret_cast<fpsimd_context*>(header);
|
return reinterpret_cast<fpsimd_context*>(header);
|
||||||
}
|
}
|
||||||
|
@ -124,7 +123,7 @@ bool ARM_NCE::HandleGuestFault(GuestContext* guest_ctx, void* raw_info, void* ra
|
||||||
|
|
||||||
// Forcibly mark the context as locked. We are still running.
|
// Forcibly mark the context as locked. We are still running.
|
||||||
// We may race with SignalInterrupt here:
|
// We may race with SignalInterrupt here:
|
||||||
// - If we lose the race, then SignalInterrupt will send us a signal which are masking,
|
// - If we lose the race, then SignalInterrupt will send us a signal we are masking,
|
||||||
// and it will do nothing when it is unmasked, as we have already left guest code.
|
// and it will do nothing when it is unmasked, as we have already left guest code.
|
||||||
// - If we win the race, then SignalInterrupt will wait for us to unlock first.
|
// - If we win the race, then SignalInterrupt will wait for us to unlock first.
|
||||||
auto& thread_params = guest_ctx->parent->running_thread->GetNativeExecutionParameters();
|
auto& thread_params = guest_ctx->parent->running_thread->GetNativeExecutionParameters();
|
||||||
|
|
|
@ -100,7 +100,7 @@ void Patcher::RelocateAndCopy(Common::ProcessAddress load_base,
|
||||||
const Kernel::CodeSet::Segment& code,
|
const Kernel::CodeSet::Segment& code,
|
||||||
Kernel::PhysicalMemory& program_image,
|
Kernel::PhysicalMemory& program_image,
|
||||||
EntryTrampolines* out_trampolines) {
|
EntryTrampolines* out_trampolines) {
|
||||||
const size_t patch_size = SectionSize();
|
const size_t patch_size = GetSectionSize();
|
||||||
const size_t image_size = program_image.size();
|
const size_t image_size = program_image.size();
|
||||||
|
|
||||||
// Retrieve text segment data.
|
// Retrieve text segment data.
|
||||||
|
@ -180,7 +180,7 @@ void Patcher::RelocateAndCopy(Common::ProcessAddress load_base,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Patcher::SectionSize() const noexcept {
|
size_t Patcher::GetSectionSize() const noexcept {
|
||||||
return Common::AlignUp(m_patch_instructions.size() * sizeof(u32), Core::Memory::YUZU_PAGESIZE);
|
return Common::AlignUp(m_patch_instructions.size() * sizeof(u32), Core::Memory::YUZU_PAGESIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +256,6 @@ void Patcher::WriteSaveContext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Patcher::WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id) {
|
void Patcher::WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id) {
|
||||||
LOG_ERROR(Core_ARM, "Patching SVC {:#x} at {:#x}", svc_id, module_dest - 4);
|
|
||||||
// We are about to start saving state, so we need to lock the context.
|
// We are about to start saving state, so we need to lock the context.
|
||||||
this->LockContext();
|
this->LockContext();
|
||||||
|
|
||||||
|
|
|
@ -7,23 +7,17 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
|
#pragma GCC diagnostic ignored "-Wshorten-64-to-32"
|
||||||
#include <oaknut/code_block.hpp>
|
#include <oaknut/code_block.hpp>
|
||||||
#include <oaknut/oaknut.hpp>
|
#include <oaknut/oaknut.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/kernel/code_set.h"
|
#include "core/hle/kernel/code_set.h"
|
||||||
#include "core/hle/kernel/k_typed_address.h"
|
#include "core/hle/kernel/k_typed_address.h"
|
||||||
#include "core/hle/kernel/physical_memory.h"
|
#include "core/hle/kernel/physical_memory.h"
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
struct GuestContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Core::NCE {
|
namespace Core::NCE {
|
||||||
|
|
||||||
enum class PatchMode : u32 {
|
enum class PatchMode : u32 {
|
||||||
|
@ -45,9 +39,9 @@ public:
|
||||||
const Kernel::CodeSet::Segment& code);
|
const Kernel::CodeSet::Segment& code);
|
||||||
void RelocateAndCopy(Common::ProcessAddress load_base, const Kernel::CodeSet::Segment& code,
|
void RelocateAndCopy(Common::ProcessAddress load_base, const Kernel::CodeSet::Segment& code,
|
||||||
Kernel::PhysicalMemory& program_image, EntryTrampolines* out_trampolines);
|
Kernel::PhysicalMemory& program_image, EntryTrampolines* out_trampolines);
|
||||||
size_t SectionSize() const noexcept;
|
size_t GetSectionSize() const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] PatchMode Mode() const noexcept {
|
[[nodiscard]] PatchMode GetPatchMode() const noexcept {
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,7 @@ struct System::Impl {
|
||||||
|
|
||||||
void Initialize(System& system) {
|
void Initialize(System& system) {
|
||||||
device_memory = std::make_unique<Core::DeviceMemory>();
|
device_memory = std::make_unique<Core::DeviceMemory>();
|
||||||
|
|
||||||
is_multicore = Settings::values.use_multi_core.GetValue();
|
is_multicore = Settings::values.use_multi_core.GetValue();
|
||||||
extended_memory_layout =
|
extended_memory_layout =
|
||||||
Settings::values.memory_layout_mode.GetValue() != Settings::MemoryLayout::Memory_4Gb;
|
Settings::values.memory_layout_mode.GetValue() != Settings::MemoryLayout::Memory_4Gb;
|
||||||
|
|
|
@ -96,9 +96,11 @@ constexpr Common::MemoryPermission ConvertToMemoryPermission(KMemoryPermission p
|
||||||
if (True(perm & KMemoryPermission::UserWrite)) {
|
if (True(perm & KMemoryPermission::UserWrite)) {
|
||||||
perms |= Common::MemoryPermission::Write;
|
perms |= Common::MemoryPermission::Write;
|
||||||
}
|
}
|
||||||
|
#ifdef ARCHITECTURE_arm64
|
||||||
if (True(perm & KMemoryPermission::UserExecute)) {
|
if (True(perm & KMemoryPermission::UserExecute)) {
|
||||||
perms |= Common::MemoryPermission::Execute;
|
perms |= Common::MemoryPermission::Execute;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return perms;
|
return perms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -472,10 +472,6 @@ public:
|
||||||
return m_post_handlers;
|
return m_post_handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelCore& GetKernel() noexcept {
|
|
||||||
return m_kernel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// 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(KProcessAddress addr, u64 size, DebugWatchpointType type);
|
bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
|
||||||
|
|
|
@ -204,7 +204,7 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process,
|
||||||
#ifdef ARCHITECTURE_arm64
|
#ifdef ARCHITECTURE_arm64
|
||||||
const auto& code = codeset.CodeSegment();
|
const auto& code = codeset.CodeSegment();
|
||||||
|
|
||||||
// NROs are always 64-bit programs.
|
// NROs always have a 39-bit address space.
|
||||||
Settings::SetNceEnabled(true);
|
Settings::SetNceEnabled(true);
|
||||||
|
|
||||||
// Create NCE patcher
|
// Create NCE patcher
|
||||||
|
@ -215,12 +215,12 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process,
|
||||||
patch.PatchText(program_image, code);
|
patch.PatchText(program_image, code);
|
||||||
|
|
||||||
// We only support PostData patching for NROs.
|
// We only support PostData patching for NROs.
|
||||||
ASSERT(patch.Mode() == Core::NCE::PatchMode::PostData);
|
ASSERT(patch.GetPatchMode() == Core::NCE::PatchMode::PostData);
|
||||||
|
|
||||||
// Update patch section.
|
// Update patch section.
|
||||||
auto& patch_segment = codeset.PatchSegment();
|
auto& patch_segment = codeset.PatchSegment();
|
||||||
patch_segment.addr = image_size;
|
patch_segment.addr = image_size;
|
||||||
patch_segment.size = static_cast<u32>(patch.SectionSize());
|
patch_segment.size = static_cast<u32>(patch.GetSectionSize());
|
||||||
|
|
||||||
// Add patch section size to the module size.
|
// Add patch section size to the module size.
|
||||||
image_size += patch_segment.size;
|
image_size += patch_segment.size;
|
||||||
|
|
|
@ -94,8 +94,8 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
|
||||||
// Allocate some space at the beginning if we are patching in PreText mode.
|
// Allocate some space at the beginning if we are patching in PreText mode.
|
||||||
const size_t module_start = [&]() -> size_t {
|
const size_t module_start = [&]() -> size_t {
|
||||||
#ifdef ARCHITECTURE_arm64
|
#ifdef ARCHITECTURE_arm64
|
||||||
if (patch && patch->Mode() == Core::NCE::PatchMode::PreText) {
|
if (patch && patch->GetPatchMode() == Core::NCE::PatchMode::PreText) {
|
||||||
return patch->SectionSize();
|
return patch->GetSectionSize();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -158,24 +158,25 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
|
||||||
#ifdef ARCHITECTURE_arm64
|
#ifdef ARCHITECTURE_arm64
|
||||||
// If we are computing the process code layout and using nce backend, patch.
|
// If we are computing the process code layout and using nce backend, patch.
|
||||||
const auto& code = codeset.CodeSegment();
|
const auto& code = codeset.CodeSegment();
|
||||||
if (patch && patch->Mode() == Core::NCE::PatchMode::None) {
|
if (patch && patch->GetPatchMode() == Core::NCE::PatchMode::None) {
|
||||||
// Patch SVCs and MRS calls in the guest code
|
// Patch SVCs and MRS calls in the guest code
|
||||||
patch->PatchText(program_image, code);
|
patch->PatchText(program_image, code);
|
||||||
|
|
||||||
// Add patch section size to the module size.
|
// Add patch section size to the module size.
|
||||||
image_size += patch->SectionSize();
|
image_size += patch->GetSectionSize();
|
||||||
} else if (patch) {
|
} else if (patch) {
|
||||||
// Relocate code patch and copy to the program_image.
|
// Relocate code patch and copy to the program_image.
|
||||||
patch->RelocateAndCopy(load_base, code, program_image, &process.GetPostHandlers());
|
patch->RelocateAndCopy(load_base, code, program_image, &process.GetPostHandlers());
|
||||||
|
|
||||||
// Update patch section.
|
// Update patch section.
|
||||||
auto& patch_segment = codeset.PatchSegment();
|
auto& patch_segment = codeset.PatchSegment();
|
||||||
patch_segment.addr = patch->Mode() == Core::NCE::PatchMode::PreText ? 0 : image_size;
|
patch_segment.addr =
|
||||||
patch_segment.size = static_cast<u32>(patch->SectionSize());
|
patch->GetPatchMode() == Core::NCE::PatchMode::PreText ? 0 : image_size;
|
||||||
|
patch_segment.size = static_cast<u32>(patch->GetSectionSize());
|
||||||
|
|
||||||
// Add patch section size to the module size. In PreText mode image_size
|
// Add patch section size to the module size. In PreText mode image_size
|
||||||
// already contains the patch segment as part of module_start.
|
// already contains the patch segment as part of module_start.
|
||||||
if (patch->Mode() == Core::NCE::PatchMode::PostData) {
|
if (patch->GetPatchMode() == Core::NCE::PatchMode::PostData) {
|
||||||
image_size += patch_segment.size;
|
image_size += patch_segment.size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue