diff options
26 files changed, 1068 insertions, 235 deletions
| diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 54be7dc0c..b31a0328c 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -595,8 +595,12 @@ endif()  if (ARCHITECTURE_x86_64)      target_sources(core PRIVATE -        arm/dynarmic/arm_dynarmic.cpp -        arm/dynarmic/arm_dynarmic.h +        arm/dynarmic/arm_dynarmic_32.cpp +        arm/dynarmic/arm_dynarmic_32.h +        arm/dynarmic/arm_dynarmic_64.cpp +        arm/dynarmic/arm_dynarmic_64.h +        arm/dynarmic/arm_dynarmic_cp15.cpp +        arm/dynarmic/arm_dynarmic_cp15.h      )      target_link_libraries(core PRIVATE dynarmic)  endif() diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 47b964eb7..57eae839e 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -25,7 +25,20 @@ public:      explicit ARM_Interface(System& system_) : system{system_} {}      virtual ~ARM_Interface() = default; -    struct ThreadContext { +    struct ThreadContext32 { +        std::array<u32, 16> cpu_registers; +        u32 cpsr; +        std::array<u8, 4> padding; +        std::array<u64, 32> fprs; +        u32 fpscr; +        u32 fpexc; +        u32 tpidr; +    }; +    // Internally within the kernel, it expects the AArch32 version of the +    // thread context to be 344 bytes in size. +    static_assert(sizeof(ThreadContext32) == 0x158); + +    struct ThreadContext64 {          std::array<u64, 31> cpu_registers;          u64 sp;          u64 pc; @@ -38,7 +51,7 @@ public:      };      // Internally within the kernel, it expects the AArch64 version of the      // thread context to be 800 bytes in size. -    static_assert(sizeof(ThreadContext) == 0x320); +    static_assert(sizeof(ThreadContext64) == 0x320);      /// Runs the CPU until an event happens      virtual void Run() = 0; @@ -130,17 +143,10 @@ public:       */      virtual void SetTPIDR_EL0(u64 value) = 0; -    /** -     * Saves the current CPU context -     * @param ctx Thread context to save -     */ -    virtual void SaveContext(ThreadContext& ctx) = 0; - -    /** -     * Loads a CPU context -     * @param ctx Thread context to load -     */ -    virtual void LoadContext(const ThreadContext& ctx) = 0; +    virtual void SaveContext(ThreadContext32& ctx) = 0; +    virtual void SaveContext(ThreadContext64& ctx) = 0; +    virtual void LoadContext(const ThreadContext32& ctx) = 0; +    virtual void LoadContext(const ThreadContext64& ctx) = 0;      /// Clears the exclusive monitor's state.      virtual void ClearExclusiveState() = 0; diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp new file mode 100644 index 000000000..187a972ac --- /dev/null +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -0,0 +1,208 @@ +// Copyright 2020 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <cinttypes> +#include <memory> +#include <dynarmic/A32/a32.h> +#include <dynarmic/A32/config.h> +#include <dynarmic/A32/context.h> +#include "common/microprofile.h" +#include "core/arm/dynarmic/arm_dynarmic_32.h" +#include "core/arm/dynarmic/arm_dynarmic_64.h" +#include "core/arm/dynarmic/arm_dynarmic_cp15.h" +#include "core/core.h" +#include "core/core_manager.h" +#include "core/core_timing.h" +#include "core/hle/kernel/svc.h" +#include "core/memory.h" + +namespace Core { + +class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { +public: +    explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent) : parent(parent) {} + +    u8 MemoryRead8(u32 vaddr) override { +        return parent.system.Memory().Read8(vaddr); +    } +    u16 MemoryRead16(u32 vaddr) override { +        return parent.system.Memory().Read16(vaddr); +    } +    u32 MemoryRead32(u32 vaddr) override { +        return parent.system.Memory().Read32(vaddr); +    } +    u64 MemoryRead64(u32 vaddr) override { +        return parent.system.Memory().Read64(vaddr); +    } + +    void MemoryWrite8(u32 vaddr, u8 value) override { +        parent.system.Memory().Write8(vaddr, value); +    } +    void MemoryWrite16(u32 vaddr, u16 value) override { +        parent.system.Memory().Write16(vaddr, value); +    } +    void MemoryWrite32(u32 vaddr, u32 value) override { +        parent.system.Memory().Write32(vaddr, value); +    } +    void MemoryWrite64(u32 vaddr, u64 value) override { +        parent.system.Memory().Write64(vaddr, value); +    } + +    void InterpreterFallback(u32 pc, std::size_t num_instructions) override { +        UNIMPLEMENTED(); +    } + +    void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { +        switch (exception) { +        case Dynarmic::A32::Exception::UndefinedInstruction: +        case Dynarmic::A32::Exception::UnpredictableInstruction: +            break; +        case Dynarmic::A32::Exception::Breakpoint: +            break; +        } +        LOG_CRITICAL(HW_GPU, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", +                     static_cast<std::size_t>(exception), pc, MemoryReadCode(pc)); +        UNIMPLEMENTED(); +    } + +    void CallSVC(u32 swi) override { +        Kernel::CallSVC(parent.system, swi); +    } + +    void AddTicks(u64 ticks) override { +        // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a +        // rough approximation of the amount of executed ticks in the system, it may be thrown off +        // if not all cores are doing a similar amount of work. Instead of doing this, we should +        // device a way so that timing is consistent across all cores without increasing the ticks 4 +        // times. +        u64 amortized_ticks = (ticks - num_interpreted_instructions) / Core::NUM_CPU_CORES; +        // Always execute at least one tick. +        amortized_ticks = std::max<u64>(amortized_ticks, 1); + +        parent.system.CoreTiming().AddTicks(amortized_ticks); +        num_interpreted_instructions = 0; +    } +    u64 GetTicksRemaining() override { +        return std::max(parent.system.CoreTiming().GetDowncount(), {}); +    } + +    ARM_Dynarmic_32& parent; +    std::size_t num_interpreted_instructions{}; +    u64 tpidrro_el0{}; +    u64 tpidr_el0{}; +}; + +std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& page_table, +                                                             std::size_t address_space_bits) const { +    Dynarmic::A32::UserConfig config; +    config.callbacks = cb.get(); +    // TODO(bunnei): Implement page table for 32-bit +    // config.page_table = &page_table.pointers; +    config.coprocessors[15] = std::make_shared<DynarmicCP15>((u32*)&CP15_regs[0]); +    config.define_unpredictable_behaviour = true; +    return std::make_unique<Dynarmic::A32::Jit>(config); +} + +MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_32, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64)); + +void ARM_Dynarmic_32::Run() { +    MICROPROFILE_SCOPE(ARM_Jit_Dynarmic_32); +    jit->Run(); +} + +void ARM_Dynarmic_32::Step() { +    cb->InterpreterFallback(jit->Regs()[15], 1); +} + +ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor, +                                 std::size_t core_index) +    : ARM_Interface{system}, +      cb(std::make_unique<DynarmicCallbacks32>(*this)), core_index{core_index}, +      exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} + +ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; + +void ARM_Dynarmic_32::SetPC(u64 pc) { +    jit->Regs()[15] = static_cast<u32>(pc); +} + +u64 ARM_Dynarmic_32::GetPC() const { +    return jit->Regs()[15]; +} + +u64 ARM_Dynarmic_32::GetReg(int index) const { +    return jit->Regs()[index]; +} + +void ARM_Dynarmic_32::SetReg(int index, u64 value) { +    jit->Regs()[index] = static_cast<u32>(value); +} + +u128 ARM_Dynarmic_32::GetVectorReg(int index) const { +    return {}; +} + +void ARM_Dynarmic_32::SetVectorReg(int index, u128 value) {} + +u32 ARM_Dynarmic_32::GetPSTATE() const { +    return jit->Cpsr(); +} + +void ARM_Dynarmic_32::SetPSTATE(u32 cpsr) { +    jit->SetCpsr(cpsr); +} + +u64 ARM_Dynarmic_32::GetTlsAddress() const { +    return CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)]; +} + +void ARM_Dynarmic_32::SetTlsAddress(VAddr address) { +    CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)] = static_cast<u32>(address); +} + +u64 ARM_Dynarmic_32::GetTPIDR_EL0() const { +    return cb->tpidr_el0; +} + +void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) { +    cb->tpidr_el0 = value; +} + +void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) { +    Dynarmic::A32::Context context; +    jit->SaveContext(context); +    ctx.cpu_registers = context.Regs(); +    ctx.cpsr = context.Cpsr(); +} + +void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) { +    Dynarmic::A32::Context context; +    context.Regs() = ctx.cpu_registers; +    context.SetCpsr(ctx.cpsr); +    jit->LoadContext(context); +} + +void ARM_Dynarmic_32::PrepareReschedule() { +    jit->HaltExecution(); +} + +void ARM_Dynarmic_32::ClearInstructionCache() { +    jit->ClearCache(); +} + +void ARM_Dynarmic_32::ClearExclusiveState() {} + +void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table, +                                       std::size_t new_address_space_size_in_bits) { +    auto key = std::make_pair(&page_table, new_address_space_size_in_bits); +    auto iter = jit_cache.find(key); +    if (iter != jit_cache.end()) { +        jit = iter->second; +        return; +    } +    jit = MakeJit(page_table, new_address_space_size_in_bits); +    jit_cache.emplace(key, jit); +} + +} // namespace Core diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h new file mode 100644 index 000000000..143e46e4d --- /dev/null +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h @@ -0,0 +1,77 @@ +// Copyright 2020 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <unordered_map> + +#include <dynarmic/A32/a32.h> +#include <dynarmic/A64/a64.h> +#include <dynarmic/A64/exclusive_monitor.h> +#include "common/common_types.h" +#include "common/hash.h" +#include "core/arm/arm_interface.h" +#include "core/arm/exclusive_monitor.h" + +namespace Memory { +class Memory; +} + +namespace Core { + +class DynarmicCallbacks32; +class DynarmicExclusiveMonitor; +class System; + +class ARM_Dynarmic_32 final : public ARM_Interface { +public: +    ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index); +    ~ARM_Dynarmic_32() override; + +    void SetPC(u64 pc) override; +    u64 GetPC() const override; +    u64 GetReg(int index) const override; +    void SetReg(int index, u64 value) override; +    u128 GetVectorReg(int index) const override; +    void SetVectorReg(int index, u128 value) override; +    u32 GetPSTATE() const override; +    void SetPSTATE(u32 pstate) override; +    void Run() override; +    void Step() override; +    VAddr GetTlsAddress() const override; +    void SetTlsAddress(VAddr address) override; +    void SetTPIDR_EL0(u64 value) override; +    u64 GetTPIDR_EL0() const override; + +    void SaveContext(ThreadContext32& ctx) override; +    void SaveContext(ThreadContext64& ctx) override {} +    void LoadContext(const ThreadContext32& ctx) override; +    void LoadContext(const ThreadContext64& ctx) override {} + +    void PrepareReschedule() override; +    void ClearExclusiveState() override; + +    void ClearInstructionCache() override; +    void PageTableChanged(Common::PageTable& new_page_table, +                          std::size_t new_address_space_size_in_bits) override; + +private: +    std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable& page_table, +                                                std::size_t address_space_bits) const; + +    using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; +    using JitCacheType = +        std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A32::Jit>, Common::PairHash>; + +    friend class DynarmicCallbacks32; +    std::unique_ptr<DynarmicCallbacks32> cb; +    JitCacheType jit_cache; +    std::shared_ptr<Dynarmic::A32::Jit> jit; +    std::size_t core_index; +    DynarmicExclusiveMonitor& exclusive_monitor; +    std::array<u32, 84> CP15_regs{}; +}; + +} // namespace Core diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 7c9d59ab8..a53a58ba0 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -8,7 +8,7 @@  #include <dynarmic/A64/config.h>  #include "common/logging/log.h"  #include "common/microprofile.h" -#include "core/arm/dynarmic/arm_dynarmic.h" +#include "core/arm/dynarmic/arm_dynarmic_64.h"  #include "core/core.h"  #include "core/core_manager.h"  #include "core/core_timing.h" @@ -25,9 +25,9 @@ namespace Core {  using Vector = Dynarmic::A64::Vector; -class ARM_Dynarmic_Callbacks : public Dynarmic::A64::UserCallbacks { +class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {  public: -    explicit ARM_Dynarmic_Callbacks(ARM_Dynarmic& parent) : parent(parent) {} +    explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent) : parent(parent) {}      u8 MemoryRead8(u64 vaddr) override {          return parent.system.Memory().Read8(vaddr); @@ -68,7 +68,7 @@ public:          LOG_INFO(Core_ARM, "Unicorn fallback @ 0x{:X} for {} instructions (instr = {:08X})", pc,                   num_instructions, MemoryReadCode(pc)); -        ARM_Interface::ThreadContext ctx; +        ARM_Interface::ThreadContext64 ctx;          parent.SaveContext(ctx);          parent.inner_unicorn.LoadContext(ctx);          parent.inner_unicorn.ExecuteInstructions(num_instructions); @@ -90,7 +90,7 @@ public:                  parent.jit->HaltExecution();                  parent.SetPC(pc);                  Kernel::Thread* const thread = parent.system.CurrentScheduler().GetCurrentThread(); -                parent.SaveContext(thread->GetContext()); +                parent.SaveContext(thread->GetContext64());                  GDBStub::Break();                  GDBStub::SendTrap(thread, 5);                  return; @@ -126,14 +126,14 @@ public:          return Timing::CpuCyclesToClockCycles(parent.system.CoreTiming().GetTicks());      } -    ARM_Dynarmic& parent; +    ARM_Dynarmic_64& parent;      std::size_t num_interpreted_instructions = 0;      u64 tpidrro_el0 = 0;      u64 tpidr_el0 = 0;  }; -std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& page_table, -                                                          std::size_t address_space_bits) const { +std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& page_table, +                                                             std::size_t address_space_bits) const {      Dynarmic::A64::UserConfig config;      // Callbacks @@ -162,76 +162,76 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& pag      return std::make_shared<Dynarmic::A64::Jit>(config);  } -MICROPROFILE_DEFINE(ARM_Jit_Dynarmic, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64)); +MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_64, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64)); -void ARM_Dynarmic::Run() { -    MICROPROFILE_SCOPE(ARM_Jit_Dynarmic); +void ARM_Dynarmic_64::Run() { +    MICROPROFILE_SCOPE(ARM_Jit_Dynarmic_64);      jit->Run();  } -void ARM_Dynarmic::Step() { +void ARM_Dynarmic_64::Step() {      cb->InterpreterFallback(jit->GetPC(), 1);  } -ARM_Dynarmic::ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor, -                           std::size_t core_index) +ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, ExclusiveMonitor& exclusive_monitor, +                                 std::size_t core_index)      : ARM_Interface{system}, -      cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{system}, +      cb(std::make_unique<DynarmicCallbacks64>(*this)), inner_unicorn{system},        core_index{core_index}, exclusive_monitor{                                    dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} -ARM_Dynarmic::~ARM_Dynarmic() = default; +ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; -void ARM_Dynarmic::SetPC(u64 pc) { +void ARM_Dynarmic_64::SetPC(u64 pc) {      jit->SetPC(pc);  } -u64 ARM_Dynarmic::GetPC() const { +u64 ARM_Dynarmic_64::GetPC() const {      return jit->GetPC();  } -u64 ARM_Dynarmic::GetReg(int index) const { +u64 ARM_Dynarmic_64::GetReg(int index) const {      return jit->GetRegister(index);  } -void ARM_Dynarmic::SetReg(int index, u64 value) { +void ARM_Dynarmic_64::SetReg(int index, u64 value) {      jit->SetRegister(index, value);  } -u128 ARM_Dynarmic::GetVectorReg(int index) const { +u128 ARM_Dynarmic_64::GetVectorReg(int index) const {      return jit->GetVector(index);  } -void ARM_Dynarmic::SetVectorReg(int index, u128 value) { +void ARM_Dynarmic_64::SetVectorReg(int index, u128 value) {      jit->SetVector(index, value);  } -u32 ARM_Dynarmic::GetPSTATE() const { +u32 ARM_Dynarmic_64::GetPSTATE() const {      return jit->GetPstate();  } -void ARM_Dynarmic::SetPSTATE(u32 pstate) { +void ARM_Dynarmic_64::SetPSTATE(u32 pstate) {      jit->SetPstate(pstate);  } -u64 ARM_Dynarmic::GetTlsAddress() const { +u64 ARM_Dynarmic_64::GetTlsAddress() const {      return cb->tpidrro_el0;  } -void ARM_Dynarmic::SetTlsAddress(VAddr address) { +void ARM_Dynarmic_64::SetTlsAddress(VAddr address) {      cb->tpidrro_el0 = address;  } -u64 ARM_Dynarmic::GetTPIDR_EL0() const { +u64 ARM_Dynarmic_64::GetTPIDR_EL0() const {      return cb->tpidr_el0;  } -void ARM_Dynarmic::SetTPIDR_EL0(u64 value) { +void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) {      cb->tpidr_el0 = value;  } -void ARM_Dynarmic::SaveContext(ThreadContext& ctx) { +void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {      ctx.cpu_registers = jit->GetRegisters();      ctx.sp = jit->GetSP();      ctx.pc = jit->GetPC(); @@ -242,7 +242,7 @@ void ARM_Dynarmic::SaveContext(ThreadContext& ctx) {      ctx.tpidr = cb->tpidr_el0;  } -void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) { +void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {      jit->SetRegisters(ctx.cpu_registers);      jit->SetSP(ctx.sp);      jit->SetPC(ctx.pc); @@ -253,20 +253,20 @@ void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) {      SetTPIDR_EL0(ctx.tpidr);  } -void ARM_Dynarmic::PrepareReschedule() { +void ARM_Dynarmic_64::PrepareReschedule() {      jit->HaltExecution();  } -void ARM_Dynarmic::ClearInstructionCache() { +void ARM_Dynarmic_64::ClearInstructionCache() {      jit->ClearCache();  } -void ARM_Dynarmic::ClearExclusiveState() { +void ARM_Dynarmic_64::ClearExclusiveState() {      jit->ClearExclusiveState();  } -void ARM_Dynarmic::PageTableChanged(Common::PageTable& page_table, -                                    std::size_t new_address_space_size_in_bits) { +void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table, +                                       std::size_t new_address_space_size_in_bits) {      auto key = std::make_pair(&page_table, new_address_space_size_in_bits);      auto iter = jit_cache.find(key);      if (iter != jit_cache.end()) { @@ -277,8 +277,8 @@ void ARM_Dynarmic::PageTableChanged(Common::PageTable& page_table,      jit_cache.emplace(key, jit);  } -DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count) -    : monitor(core_count), memory{memory_} {} +DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count) +    : monitor(core_count), memory{memory} {}  DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default; diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index ffbb69d76..e71240a96 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h @@ -21,18 +21,14 @@ class Memory;  namespace Core { -class ARM_Dynarmic_Callbacks; +class DynarmicCallbacks64;  class DynarmicExclusiveMonitor;  class System; -using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; -using JitCacheType = -    std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A64::Jit>, Common::PairHash>; - -class ARM_Dynarmic final : public ARM_Interface { +class ARM_Dynarmic_64 final : public ARM_Interface {  public: -    ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index); -    ~ARM_Dynarmic() override; +    ARM_Dynarmic_64(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index); +    ~ARM_Dynarmic_64() override;      void SetPC(u64 pc) override;      u64 GetPC() const override; @@ -49,8 +45,10 @@ public:      void SetTPIDR_EL0(u64 value) override;      u64 GetTPIDR_EL0() const override; -    void SaveContext(ThreadContext& ctx) override; -    void LoadContext(const ThreadContext& ctx) override; +    void SaveContext(ThreadContext32& ctx) override {} +    void SaveContext(ThreadContext64& ctx) override; +    void LoadContext(const ThreadContext32& ctx) override {} +    void LoadContext(const ThreadContext64& ctx) override;      void PrepareReschedule() override;      void ClearExclusiveState() override; @@ -63,8 +61,12 @@ private:      std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table,                                                  std::size_t address_space_bits) const; -    friend class ARM_Dynarmic_Callbacks; -    std::unique_ptr<ARM_Dynarmic_Callbacks> cb; +    using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; +    using JitCacheType = +        std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A64::Jit>, Common::PairHash>; + +    friend class DynarmicCallbacks64; +    std::unique_ptr<DynarmicCallbacks64> cb;      JitCacheType jit_cache;      std::shared_ptr<Dynarmic::A64::Jit> jit;      ARM_Unicorn inner_unicorn; @@ -75,7 +77,7 @@ private:  class DynarmicExclusiveMonitor final : public ExclusiveMonitor {  public: -    explicit DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count); +    explicit DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count);      ~DynarmicExclusiveMonitor() override;      void SetExclusive(std::size_t core_index, VAddr addr) override; @@ -88,7 +90,7 @@ public:      bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) override;  private: -    friend class ARM_Dynarmic; +    friend class ARM_Dynarmic_64;      Dynarmic::A64::ExclusiveMonitor monitor;      Memory::Memory& memory;  }; diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp new file mode 100644 index 000000000..3fdcdebde --- /dev/null +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp @@ -0,0 +1,80 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/arm/dynarmic/arm_dynarmic_cp15.h" + +using Callback = Dynarmic::A32::Coprocessor::Callback; +using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord; +using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords; + +std::optional<Callback> DynarmicCP15::CompileInternalOperation(bool two, unsigned opc1, +                                                               CoprocReg CRd, CoprocReg CRn, +                                                               CoprocReg CRm, unsigned opc2) { +    return {}; +} + +CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn, +                                                         CoprocReg CRm, unsigned opc2) { +    // TODO(merry): Privileged CP15 registers + +    if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C5 && opc2 == 4) { +        // This is a dummy write, we ignore the value written here. +        return &CP15[static_cast<std::size_t>(CP15Register::CP15_FLUSH_PREFETCH_BUFFER)]; +    } + +    if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C10) { +        switch (opc2) { +        case 4: +            // This is a dummy write, we ignore the value written here. +            return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_SYNC_BARRIER)]; +        case 5: +            // This is a dummy write, we ignore the value written here. +            return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_MEMORY_BARRIER)]; +        default: +            return {}; +        } +    } + +    if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0 && opc2 == 2) { +        return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)]; +    } + +    return {}; +} + +CallbackOrAccessTwoWords DynarmicCP15::CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) { +    return {}; +} + +CallbackOrAccessOneWord DynarmicCP15::CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn, +                                                        CoprocReg CRm, unsigned opc2) { +    // TODO(merry): Privileged CP15 registers + +    if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0) { +        switch (opc2) { +        case 2: +            return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)]; +        case 3: +            return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)]; +        default: +            return {}; +        } +    } + +    return {}; +} + +CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) { +    return {}; +} + +std::optional<Callback> DynarmicCP15::CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd, +                                                       std::optional<u8> option) { +    return {}; +} + +std::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd, +                                                        std::optional<u8> option) { +    return {}; +} diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h new file mode 100644 index 000000000..07bcde5f9 --- /dev/null +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h @@ -0,0 +1,152 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <optional> + +#include <dynarmic/A32/coprocessor.h> +#include "common/common_types.h" + +enum class CP15Register { +    // c0 - Information registers +    CP15_MAIN_ID, +    CP15_CACHE_TYPE, +    CP15_TCM_STATUS, +    CP15_TLB_TYPE, +    CP15_CPU_ID, +    CP15_PROCESSOR_FEATURE_0, +    CP15_PROCESSOR_FEATURE_1, +    CP15_DEBUG_FEATURE_0, +    CP15_AUXILIARY_FEATURE_0, +    CP15_MEMORY_MODEL_FEATURE_0, +    CP15_MEMORY_MODEL_FEATURE_1, +    CP15_MEMORY_MODEL_FEATURE_2, +    CP15_MEMORY_MODEL_FEATURE_3, +    CP15_ISA_FEATURE_0, +    CP15_ISA_FEATURE_1, +    CP15_ISA_FEATURE_2, +    CP15_ISA_FEATURE_3, +    CP15_ISA_FEATURE_4, + +    // c1 - Control registers +    CP15_CONTROL, +    CP15_AUXILIARY_CONTROL, +    CP15_COPROCESSOR_ACCESS_CONTROL, + +    // c2 - Translation table registers +    CP15_TRANSLATION_BASE_TABLE_0, +    CP15_TRANSLATION_BASE_TABLE_1, +    CP15_TRANSLATION_BASE_CONTROL, +    CP15_DOMAIN_ACCESS_CONTROL, +    CP15_RESERVED, + +    // c5 - Fault status registers +    CP15_FAULT_STATUS, +    CP15_INSTR_FAULT_STATUS, +    CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS, +    CP15_INST_FSR, + +    // c6 - Fault Address registers +    CP15_FAULT_ADDRESS, +    CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS, +    CP15_WFAR, +    CP15_IFAR, + +    // c7 - Cache operation registers +    CP15_WAIT_FOR_INTERRUPT, +    CP15_PHYS_ADDRESS, +    CP15_INVALIDATE_INSTR_CACHE, +    CP15_INVALIDATE_INSTR_CACHE_USING_MVA, +    CP15_INVALIDATE_INSTR_CACHE_USING_INDEX, +    CP15_FLUSH_PREFETCH_BUFFER, +    CP15_FLUSH_BRANCH_TARGET_CACHE, +    CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY, +    CP15_INVALIDATE_DATA_CACHE, +    CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA, +    CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX, +    CP15_INVALIDATE_DATA_AND_INSTR_CACHE, +    CP15_CLEAN_DATA_CACHE, +    CP15_CLEAN_DATA_CACHE_LINE_USING_MVA, +    CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX, +    CP15_DATA_SYNC_BARRIER, +    CP15_DATA_MEMORY_BARRIER, +    CP15_CLEAN_AND_INVALIDATE_DATA_CACHE, +    CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA, +    CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX, + +    // c8 - TLB operations +    CP15_INVALIDATE_ITLB, +    CP15_INVALIDATE_ITLB_SINGLE_ENTRY, +    CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH, +    CP15_INVALIDATE_ITLB_ENTRY_ON_MVA, +    CP15_INVALIDATE_DTLB, +    CP15_INVALIDATE_DTLB_SINGLE_ENTRY, +    CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH, +    CP15_INVALIDATE_DTLB_ENTRY_ON_MVA, +    CP15_INVALIDATE_UTLB, +    CP15_INVALIDATE_UTLB_SINGLE_ENTRY, +    CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH, +    CP15_INVALIDATE_UTLB_ENTRY_ON_MVA, + +    // c9 - Data cache lockdown register +    CP15_DATA_CACHE_LOCKDOWN, + +    // c10 - TLB/Memory map registers +    CP15_TLB_LOCKDOWN, +    CP15_PRIMARY_REGION_REMAP, +    CP15_NORMAL_REGION_REMAP, + +    // c13 - Thread related registers +    CP15_PID, +    CP15_CONTEXT_ID, +    CP15_THREAD_UPRW, // Thread ID register - User/Privileged Read/Write +    CP15_THREAD_URO,  // Thread ID register - User Read Only (Privileged R/W) +    CP15_THREAD_PRW,  // Thread ID register - Privileged R/W only. + +    // c15 - Performance and TLB lockdown registers +    CP15_PERFORMANCE_MONITOR_CONTROL, +    CP15_CYCLE_COUNTER, +    CP15_COUNT_0, +    CP15_COUNT_1, +    CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY, +    CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY, +    CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS, +    CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS, +    CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE, +    CP15_TLB_DEBUG_CONTROL, + +    // Skyeye defined +    CP15_TLB_FAULT_ADDR, +    CP15_TLB_FAULT_STATUS, + +    // Not an actual register. +    // All registers should be defined above this. +    CP15_REGISTER_COUNT, +}; + +class DynarmicCP15 final : public Dynarmic::A32::Coprocessor { +public: +    using CoprocReg = Dynarmic::A32::CoprocReg; + +    explicit DynarmicCP15(u32* cp15) : CP15(cp15){}; + +    std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd, +                                                     CoprocReg CRn, CoprocReg CRm, +                                                     unsigned opc2) override; +    CallbackOrAccessOneWord CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn, +                                               CoprocReg CRm, unsigned opc2) override; +    CallbackOrAccessTwoWords CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) override; +    CallbackOrAccessOneWord CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn, CoprocReg CRm, +                                              unsigned opc2) override; +    CallbackOrAccessTwoWords CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) override; +    std::optional<Callback> CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd, +                                             std::optional<u8> option) override; +    std::optional<Callback> CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd, +                                              std::optional<u8> option) override; + +private: +    u32* CP15{}; +}; diff --git a/src/core/arm/exclusive_monitor.cpp b/src/core/arm/exclusive_monitor.cpp index 94570e520..b32401e0b 100644 --- a/src/core/arm/exclusive_monitor.cpp +++ b/src/core/arm/exclusive_monitor.cpp @@ -3,7 +3,7 @@  // Refer to the license.txt file included.  #ifdef ARCHITECTURE_x86_64 -#include "core/arm/dynarmic/arm_dynarmic.h" +#include "core/arm/dynarmic/arm_dynarmic_64.h"  #endif  #include "core/arm/exclusive_monitor.h"  #include "core/memory.h" diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp index f99ad5802..8a9800a96 100644 --- a/src/core/arm/unicorn/arm_unicorn.cpp +++ b/src/core/arm/unicorn/arm_unicorn.cpp @@ -53,7 +53,7 @@ static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int si                                 void* user_data) {      auto* const system = static_cast<System*>(user_data); -    ARM_Interface::ThreadContext ctx{}; +    ARM_Interface::ThreadContext64 ctx{};      system->CurrentArmInterface().SaveContext(ctx);      ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x{:X}, pc=0x{:X}, lr=0x{:X}", addr,                 ctx.pc, ctx.cpu_registers[30]); @@ -179,7 +179,7 @@ void ARM_Unicorn::ExecuteInstructions(std::size_t num_instructions) {          }          Kernel::Thread* const thread = system.CurrentScheduler().GetCurrentThread(); -        SaveContext(thread->GetContext()); +        SaveContext(thread->GetContext64());          if (last_bkpt_hit || GDBStub::IsMemoryBreak() || GDBStub::GetCpuStepFlag()) {              last_bkpt_hit = false;              GDBStub::Break(); @@ -188,7 +188,7 @@ void ARM_Unicorn::ExecuteInstructions(std::size_t num_instructions) {      }  } -void ARM_Unicorn::SaveContext(ThreadContext& ctx) { +void ARM_Unicorn::SaveContext(ThreadContext64& ctx) {      int uregs[32];      void* tregs[32]; @@ -215,7 +215,7 @@ void ARM_Unicorn::SaveContext(ThreadContext& ctx) {      CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32));  } -void ARM_Unicorn::LoadContext(const ThreadContext& ctx) { +void ARM_Unicorn::LoadContext(const ThreadContext64& ctx) {      int uregs[32];      void* tregs[32]; diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h index 3c5b155f9..f30d13cb6 100644 --- a/src/core/arm/unicorn/arm_unicorn.h +++ b/src/core/arm/unicorn/arm_unicorn.h @@ -30,8 +30,6 @@ public:      void SetTlsAddress(VAddr address) override;      void SetTPIDR_EL0(u64 value) override;      u64 GetTPIDR_EL0() const override; -    void SaveContext(ThreadContext& ctx) override; -    void LoadContext(const ThreadContext& ctx) override;      void PrepareReschedule() override;      void ClearExclusiveState() override;      void ExecuteInstructions(std::size_t num_instructions); @@ -41,6 +39,11 @@ public:      void PageTableChanged(Common::PageTable&, std::size_t) override {}      void RecordBreak(GDBStub::BreakpointAddress bkpt); +    void SaveContext(ThreadContext32& ctx) override {} +    void SaveContext(ThreadContext64& ctx) override; +    void LoadContext(const ThreadContext32& ctx) override {} +    void LoadContext(const ThreadContext64& ctx) override; +  private:      static void InterruptHook(uc_engine* uc, u32 int_no, void* user_data); diff --git a/src/core/core_manager.cpp b/src/core/core_manager.cpp index 8eacf92dd..b6b797c80 100644 --- a/src/core/core_manager.cpp +++ b/src/core/core_manager.cpp @@ -6,9 +6,6 @@  #include <mutex>  #include "common/logging/log.h" -#ifdef ARCHITECTURE_x86_64 -#include "core/arm/dynarmic/arm_dynarmic.h" -#endif  #include "core/arm/exclusive_monitor.h"  #include "core/arm/unicorn/arm_unicorn.h"  #include "core/core.h" diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 67e95999d..e8d8871a7 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -217,7 +217,7 @@ static u64 RegRead(std::size_t id, Kernel::Thread* thread = nullptr) {          return 0;      } -    const auto& thread_context = thread->GetContext(); +    const auto& thread_context = thread->GetContext64();      if (id < SP_REGISTER) {          return thread_context.cpu_registers[id]; @@ -239,7 +239,7 @@ static void RegWrite(std::size_t id, u64 val, Kernel::Thread* thread = nullptr)          return;      } -    auto& thread_context = thread->GetContext(); +    auto& thread_context = thread->GetContext64();      if (id < SP_REGISTER) {          thread_context.cpu_registers[id] = val; @@ -259,7 +259,7 @@ static u128 FpuRead(std::size_t id, Kernel::Thread* thread = nullptr) {          return u128{0};      } -    auto& thread_context = thread->GetContext(); +    auto& thread_context = thread->GetContext64();      if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {          return thread_context.vector_registers[id - UC_ARM64_REG_Q0]; @@ -275,7 +275,7 @@ static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr)          return;      } -    auto& thread_context = thread->GetContext(); +    auto& thread_context = thread->GetContext64();      if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {          thread_context.vector_registers[id - UC_ARM64_REG_Q0] = val; @@ -916,7 +916,7 @@ static void WriteRegister() {      // Update ARM context, skipping scheduler - no running threads at this point      Core::System::GetInstance()          .ArmInterface(current_core) -        .LoadContext(current_thread->GetContext()); +        .LoadContext(current_thread->GetContext64());      SendReply("OK");  } @@ -947,7 +947,7 @@ static void WriteRegisters() {      // Update ARM context, skipping scheduler - no running threads at this point      Core::System::GetInstance()          .ArmInterface(current_core) -        .LoadContext(current_thread->GetContext()); +        .LoadContext(current_thread->GetContext64());      SendReply("OK");  } @@ -1019,7 +1019,7 @@ static void Step() {          // Update ARM context, skipping scheduler - no running threads at this point          Core::System::GetInstance()              .ArmInterface(current_core) -            .LoadContext(current_thread->GetContext()); +            .LoadContext(current_thread->GetContext64());      }      step_loop = true;      halt_loop = true; diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 9232f4d7e..e47f1deed 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -186,6 +186,10 @@ struct KernelCore::Impl {              return;          } +        for (auto& core : cores) { +            core.SetIs64Bit(process->Is64BitProcess()); +        } +          system.Memory().SetCurrentPageTable(*process);      } diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index 9303dd273..aa2787467 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -5,7 +5,8 @@  #include "common/logging/log.h"  #include "core/arm/arm_interface.h"  #ifdef ARCHITECTURE_x86_64 -#include "core/arm/dynarmic/arm_dynarmic.h" +#include "core/arm/dynarmic/arm_dynarmic_32.h" +#include "core/arm/dynarmic/arm_dynarmic_64.h"  #endif  #include "core/arm/exclusive_monitor.h"  #include "core/arm/unicorn/arm_unicorn.h" @@ -20,13 +21,17 @@ PhysicalCore::PhysicalCore(Core::System& system, std::size_t id,                             Core::ExclusiveMonitor& exclusive_monitor)      : core_index{id} {  #ifdef ARCHITECTURE_x86_64 -    arm_interface = std::make_unique<Core::ARM_Dynarmic>(system, exclusive_monitor, core_index); +    arm_interface_32 = +        std::make_unique<Core::ARM_Dynarmic_32>(system, exclusive_monitor, core_index); +    arm_interface_64 = +        std::make_unique<Core::ARM_Dynarmic_64>(system, exclusive_monitor, core_index); +  #else      arm_interface = std::make_shared<Core::ARM_Unicorn>(system);      LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");  #endif -    scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface, core_index); +    scheduler = std::make_unique<Kernel::Scheduler>(system, core_index);  }  PhysicalCore::~PhysicalCore() = default; @@ -48,4 +53,12 @@ void PhysicalCore::Shutdown() {      scheduler->Shutdown();  } +void PhysicalCore::SetIs64Bit(bool is_64_bit) { +    if (is_64_bit) { +        arm_interface = arm_interface_64.get(); +    } else { +        arm_interface = arm_interface_32.get(); +    } +} +  } // namespace Kernel diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index 4c32c0f1b..3269166be 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h @@ -68,10 +68,14 @@ public:          return *scheduler;      } +    void SetIs64Bit(bool is_64_bit); +  private:      std::size_t core_index; -    std::unique_ptr<Core::ARM_Interface> arm_interface; +    std::unique_ptr<Core::ARM_Interface> arm_interface_32; +    std::unique_ptr<Core::ARM_Interface> arm_interface_64;      std::unique_ptr<Kernel::Scheduler> scheduler; +    Core::ARM_Interface* arm_interface{};  };  } // namespace Kernel diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 2fcb7326c..edc414d69 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -42,7 +42,8 @@ void SetupMainThread(Process& owner_process, KernelCore& kernel, u32 priority) {      // Register 1 must be a handle to the main thread      const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap(); -    thread->GetContext().cpu_registers[1] = thread_handle; +    thread->GetContext32().cpu_registers[1] = thread_handle; +    thread->GetContext64().cpu_registers[1] = thread_handle;      // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires      thread->ResumeFromWait(); diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index c65f82fb7..1140c72a3 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -383,8 +383,8 @@ void GlobalScheduler::Unlock() {      // TODO(Blinkhawk): Setup the interrupts and change context on current core.  } -Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) -    : system(system), cpu_core(cpu_core), core_id(core_id) {} +Scheduler::Scheduler(Core::System& system, std::size_t core_id) +    : system{system}, core_id{core_id} {}  Scheduler::~Scheduler() = default; @@ -422,9 +422,10 @@ void Scheduler::UnloadThread() {      // Save context for previous thread      if (previous_thread) { -        cpu_core.SaveContext(previous_thread->GetContext()); +        system.ArmInterface(core_id).SaveContext(previous_thread->GetContext32()); +        system.ArmInterface(core_id).SaveContext(previous_thread->GetContext64());          // Save the TPIDR_EL0 system register in case it was modified. -        previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0()); +        previous_thread->SetTPIDR_EL0(system.ArmInterface(core_id).GetTPIDR_EL0());          if (previous_thread->GetStatus() == ThreadStatus::Running) {              // This is only the case when a reschedule is triggered without the current thread @@ -451,9 +452,10 @@ void Scheduler::SwitchContext() {      // Save context for previous thread      if (previous_thread) { -        cpu_core.SaveContext(previous_thread->GetContext()); +        system.ArmInterface(core_id).SaveContext(previous_thread->GetContext32()); +        system.ArmInterface(core_id).SaveContext(previous_thread->GetContext64());          // Save the TPIDR_EL0 system register in case it was modified. -        previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0()); +        previous_thread->SetTPIDR_EL0(system.ArmInterface(core_id).GetTPIDR_EL0());          if (previous_thread->GetStatus() == ThreadStatus::Running) {              // This is only the case when a reschedule is triggered without the current thread @@ -481,9 +483,10 @@ void Scheduler::SwitchContext() {              system.Kernel().MakeCurrentProcess(thread_owner_process);          } -        cpu_core.LoadContext(new_thread->GetContext()); -        cpu_core.SetTlsAddress(new_thread->GetTLSAddress()); -        cpu_core.SetTPIDR_EL0(new_thread->GetTPIDR_EL0()); +        system.ArmInterface(core_id).LoadContext(new_thread->GetContext32()); +        system.ArmInterface(core_id).LoadContext(new_thread->GetContext64()); +        system.ArmInterface(core_id).SetTlsAddress(new_thread->GetTLSAddress()); +        system.ArmInterface(core_id).SetTPIDR_EL0(new_thread->GetTPIDR_EL0());      } else {          current_thread = nullptr;          // Note: We do not reset the current process and current page table when idling because diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 1c93a838c..07df33f9c 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h @@ -181,7 +181,7 @@ private:  class Scheduler final {  public: -    explicit Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id); +    explicit Scheduler(Core::System& system, std::size_t core_id);      ~Scheduler();      /// Returns whether there are any threads that are ready to run. @@ -235,7 +235,6 @@ private:      std::shared_ptr<Thread> selected_thread = nullptr;      Core::System& system; -    Core::ARM_Interface& cpu_core;      u64 last_context_switch_time = 0;      u64 idle_selection_count = 0;      const std::size_t core_id; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index fd91779a3..4ffc113c2 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -187,6 +187,13 @@ static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_s      return RESULT_SUCCESS;  } +static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_size) { +    VAddr temp_heap_addr{}; +    const ResultCode result{SetHeapSize(system, &temp_heap_addr, heap_size)}; +    *heap_addr = static_cast<u32>(temp_heap_addr); +    return result; +} +  static ResultCode SetMemoryPermission(Core::System& system, VAddr addr, u64 size, u32 prot) {      LOG_TRACE(Kernel_SVC, "called, addr=0x{:X}, size=0x{:X}, prot=0x{:X}", addr, size, prot); @@ -371,6 +378,12 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,      return RESULT_SUCCESS;  } +static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle, +                                       u32 port_name_address) { + +    return ConnectToNamedPort(system, out_handle, port_name_address); +} +  /// Makes a blocking IPC call to an OS service.  static ResultCode SendSyncRequest(Core::System& system, Handle handle) {      const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); @@ -390,6 +403,10 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {      return session->SendSyncRequest(SharedFrom(thread), system.Memory());  } +static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { +    return SendSyncRequest(system, handle); +} +  /// Get the ID for the specified thread.  static ResultCode GetThreadId(Core::System& system, u64* thread_id, Handle thread_handle) {      LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle); @@ -405,6 +422,17 @@ static ResultCode GetThreadId(Core::System& system, u64* thread_id, Handle threa      return RESULT_SUCCESS;  } +static ResultCode GetThreadId32(Core::System& system, u32* thread_id_low, u32* thread_id_high, +                                Handle thread_handle) { +    u64 thread_id{}; +    const ResultCode result{GetThreadId(system, &thread_id, thread_handle)}; + +    *thread_id_low = static_cast<u32>(thread_id >> 32); +    *thread_id_high = static_cast<u32>(thread_id & std::numeric_limits<u32>::max()); + +    return result; +} +  /// Gets the ID of the specified process or a specified thread's owning process.  static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) {      LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle); @@ -479,6 +507,12 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr      return result;  } +static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address, +                                        s32 handle_count, u32 timeout_high, Handle* index) { +    const s64 nano_seconds{(static_cast<s64>(timeout_high) << 32) | static_cast<s64>(timeout_low)}; +    return WaitSynchronization(system, index, handles_address, handle_count, nano_seconds); +} +  /// Resumes a thread waiting on WaitSynchronization  static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) {      LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle); @@ -917,6 +951,18 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha      }  } +static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_high, u32 sub_id_low, +                            u32 info_id, u32 handle, u32 sub_id_high) { +    const u64 sub_id{static_cast<u64>(sub_id_low | (static_cast<u64>(sub_id_high) << 32))}; +    u64 res_value{}; + +    const ResultCode result{GetInfo(system, &res_value, info_id, handle, sub_id)}; +    *result_high = static_cast<u32>(res_value >> 32); +    *result_low = static_cast<u32>(res_value & std::numeric_limits<u32>::max()); + +    return result; +} +  /// Maps memory at a desired address  static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {      LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); @@ -1058,7 +1104,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, H          return ERR_BUSY;      } -    Core::ARM_Interface::ThreadContext ctx = thread->GetContext(); +    Core::ARM_Interface::ThreadContext64 ctx = thread->GetContext64();      // Mask away mode bits, interrupt bits, IL bit, and other reserved bits.      ctx.pstate &= 0xFF0FFE20; @@ -1088,6 +1134,10 @@ static ResultCode GetThreadPriority(Core::System& system, u32* priority, Handle      return RESULT_SUCCESS;  } +static ResultCode GetThreadPriority32(Core::System& system, u32* priority, Handle handle) { +    return GetThreadPriority(system, priority, handle); +} +  /// Sets the priority for the specified thread  static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) {      LOG_TRACE(Kernel_SVC, "called"); @@ -1259,6 +1309,11 @@ static ResultCode QueryMemory(Core::System& system, VAddr memory_info_address,                                query_address);  } +static ResultCode QueryMemory32(Core::System& system, u32 memory_info_address, +                                u32 page_info_address, u32 query_address) { +    return QueryMemory(system, memory_info_address, page_info_address, query_address); +} +  static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,                                         u64 src_address, u64 size) {      LOG_DEBUG(Kernel_SVC, @@ -1675,6 +1730,10 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_      }  } +static void SignalProcessWideKey32(Core::System& system, u32 condition_variable_addr, s32 target) { +    SignalProcessWideKey(system, condition_variable_addr, target); +} +  // Wait for an address (via Address Arbiter)  static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type, s32 value,                                   s64 timeout) { @@ -1760,6 +1819,10 @@ static ResultCode CloseHandle(Core::System& system, Handle handle) {      return handle_table.Close(handle);  } +static ResultCode CloseHandle32(Core::System& system, Handle handle) { +    return CloseHandle(system, handle); +} +  /// Clears the signaled state of an event or process.  static ResultCode ResetSignal(Core::System& system, Handle handle) {      LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle); @@ -2317,69 +2380,196 @@ struct FunctionDef {  };  } // namespace -static const FunctionDef SVC_Table[] = { +static const FunctionDef SVC_Table_32[] = {      {0x00, nullptr, "Unknown"}, -    {0x01, SvcWrap<SetHeapSize>, "SetHeapSize"}, -    {0x02, SvcWrap<SetMemoryPermission>, "SetMemoryPermission"}, -    {0x03, SvcWrap<SetMemoryAttribute>, "SetMemoryAttribute"}, -    {0x04, SvcWrap<MapMemory>, "MapMemory"}, -    {0x05, SvcWrap<UnmapMemory>, "UnmapMemory"}, -    {0x06, SvcWrap<QueryMemory>, "QueryMemory"}, -    {0x07, SvcWrap<ExitProcess>, "ExitProcess"}, -    {0x08, SvcWrap<CreateThread>, "CreateThread"}, -    {0x09, SvcWrap<StartThread>, "StartThread"}, -    {0x0A, SvcWrap<ExitThread>, "ExitThread"}, -    {0x0B, SvcWrap<SleepThread>, "SleepThread"}, -    {0x0C, SvcWrap<GetThreadPriority>, "GetThreadPriority"}, -    {0x0D, SvcWrap<SetThreadPriority>, "SetThreadPriority"}, -    {0x0E, SvcWrap<GetThreadCoreMask>, "GetThreadCoreMask"}, -    {0x0F, SvcWrap<SetThreadCoreMask>, "SetThreadCoreMask"}, -    {0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"}, -    {0x11, SvcWrap<SignalEvent>, "SignalEvent"}, -    {0x12, SvcWrap<ClearEvent>, "ClearEvent"}, -    {0x13, SvcWrap<MapSharedMemory>, "MapSharedMemory"}, -    {0x14, SvcWrap<UnmapSharedMemory>, "UnmapSharedMemory"}, -    {0x15, SvcWrap<CreateTransferMemory>, "CreateTransferMemory"}, -    {0x16, SvcWrap<CloseHandle>, "CloseHandle"}, -    {0x17, SvcWrap<ResetSignal>, "ResetSignal"}, -    {0x18, SvcWrap<WaitSynchronization>, "WaitSynchronization"}, -    {0x19, SvcWrap<CancelSynchronization>, "CancelSynchronization"}, -    {0x1A, SvcWrap<ArbitrateLock>, "ArbitrateLock"}, -    {0x1B, SvcWrap<ArbitrateUnlock>, "ArbitrateUnlock"}, -    {0x1C, SvcWrap<WaitProcessWideKeyAtomic>, "WaitProcessWideKeyAtomic"}, -    {0x1D, SvcWrap<SignalProcessWideKey>, "SignalProcessWideKey"}, -    {0x1E, SvcWrap<GetSystemTick>, "GetSystemTick"}, -    {0x1F, SvcWrap<ConnectToNamedPort>, "ConnectToNamedPort"}, +    {0x01, SvcWrap32<SetHeapSize32>, "SetHeapSize32"}, +    {0x02, nullptr, "Unknown"}, +    {0x03, nullptr, "SetMemoryAttribute32"}, +    {0x04, nullptr, "MapMemory32"}, +    {0x05, nullptr, "UnmapMemory32"}, +    {0x06, SvcWrap32<QueryMemory32>, "QueryMemory32"}, +    {0x07, nullptr, "ExitProcess32"}, +    {0x08, nullptr, "CreateThread32"}, +    {0x09, nullptr, "StartThread32"}, +    {0x0a, nullptr, "ExitThread32"}, +    {0x0b, nullptr, "SleepThread32"}, +    {0x0c, SvcWrap32<GetThreadPriority32>, "GetThreadPriority32"}, +    {0x0d, nullptr, "SetThreadPriority32"}, +    {0x0e, nullptr, "GetThreadCoreMask32"}, +    {0x0f, nullptr, "SetThreadCoreMask32"}, +    {0x10, nullptr, "GetCurrentProcessorNumber32"}, +    {0x11, nullptr, "SignalEvent32"}, +    {0x12, nullptr, "ClearEvent32"}, +    {0x13, nullptr, "MapSharedMemory32"}, +    {0x14, nullptr, "UnmapSharedMemory32"}, +    {0x15, nullptr, "CreateTransferMemory32"}, +    {0x16, SvcWrap32<CloseHandle32>, "CloseHandle32"}, +    {0x17, nullptr, "ResetSignal32"}, +    {0x18, SvcWrap32<WaitSynchronization32>, "WaitSynchronization32"}, +    {0x19, nullptr, "CancelSynchronization32"}, +    {0x1a, nullptr, "ArbitrateLock32"}, +    {0x1b, nullptr, "ArbitrateUnlock32"}, +    {0x1c, nullptr, "WaitProcessWideKeyAtomic32"}, +    {0x1d, SvcWrap32<SignalProcessWideKey32>, "SignalProcessWideKey32"}, +    {0x1e, nullptr, "GetSystemTick32"}, +    {0x1f, SvcWrap32<ConnectToNamedPort32>, "ConnectToNamedPort32"}, +    {0x20, nullptr, "Unknown"}, +    {0x21, SvcWrap32<SendSyncRequest32>, "SendSyncRequest32"}, +    {0x22, nullptr, "SendSyncRequestWithUserBuffer32"}, +    {0x23, nullptr, "Unknown"}, +    {0x24, nullptr, "GetProcessId32"}, +    {0x25, SvcWrap32<GetThreadId32>, "GetThreadId32"}, +    {0x26, nullptr, "Break32"}, +    {0x27, nullptr, "OutputDebugString32"}, +    {0x28, nullptr, "Unknown"}, +    {0x29, SvcWrap32<GetInfo32>, "GetInfo32"}, +    {0x2a, nullptr, "Unknown"}, +    {0x2b, nullptr, "Unknown"}, +    {0x2c, nullptr, "MapPhysicalMemory32"}, +    {0x2d, nullptr, "UnmapPhysicalMemory32"}, +    {0x2e, nullptr, "Unknown"}, +    {0x2f, nullptr, "Unknown"}, +    {0x30, nullptr, "Unknown"}, +    {0x31, nullptr, "Unknown"}, +    {0x32, nullptr, "SetThreadActivity32"}, +    {0x33, nullptr, "GetThreadContext32"}, +    {0x34, nullptr, "WaitForAddress32"}, +    {0x35, nullptr, "SignalToAddress32"}, +    {0x36, nullptr, "Unknown"}, +    {0x37, nullptr, "Unknown"}, +    {0x38, nullptr, "Unknown"}, +    {0x39, nullptr, "Unknown"}, +    {0x3a, nullptr, "Unknown"}, +    {0x3b, nullptr, "Unknown"}, +    {0x3c, nullptr, "Unknown"}, +    {0x3d, nullptr, "Unknown"}, +    {0x3e, nullptr, "Unknown"}, +    {0x3f, nullptr, "Unknown"}, +    {0x40, nullptr, "CreateSession32"}, +    {0x41, nullptr, "AcceptSession32"}, +    {0x42, nullptr, "Unknown"}, +    {0x43, nullptr, "ReplyAndReceive32"}, +    {0x44, nullptr, "Unknown"}, +    {0x45, nullptr, "CreateEvent32"}, +    {0x46, nullptr, "Unknown"}, +    {0x47, nullptr, "Unknown"}, +    {0x48, nullptr, "Unknown"}, +    {0x49, nullptr, "Unknown"}, +    {0x4a, nullptr, "Unknown"}, +    {0x4b, nullptr, "Unknown"}, +    {0x4c, nullptr, "Unknown"}, +    {0x4d, nullptr, "Unknown"}, +    {0x4e, nullptr, "Unknown"}, +    {0x4f, nullptr, "Unknown"}, +    {0x50, nullptr, "Unknown"}, +    {0x51, nullptr, "Unknown"}, +    {0x52, nullptr, "Unknown"}, +    {0x53, nullptr, "Unknown"}, +    {0x54, nullptr, "Unknown"}, +    {0x55, nullptr, "Unknown"}, +    {0x56, nullptr, "Unknown"}, +    {0x57, nullptr, "Unknown"}, +    {0x58, nullptr, "Unknown"}, +    {0x59, nullptr, "Unknown"}, +    {0x5a, nullptr, "Unknown"}, +    {0x5b, nullptr, "Unknown"}, +    {0x5c, nullptr, "Unknown"}, +    {0x5d, nullptr, "Unknown"}, +    {0x5e, nullptr, "Unknown"}, +    {0x5F, nullptr, "FlushProcessDataCache32"}, +    {0x60, nullptr, "Unknown"}, +    {0x61, nullptr, "Unknown"}, +    {0x62, nullptr, "Unknown"}, +    {0x63, nullptr, "Unknown"}, +    {0x64, nullptr, "Unknown"}, +    {0x65, nullptr, "GetProcessList32"}, +    {0x66, nullptr, "Unknown"}, +    {0x67, nullptr, "Unknown"}, +    {0x68, nullptr, "Unknown"}, +    {0x69, nullptr, "Unknown"}, +    {0x6A, nullptr, "Unknown"}, +    {0x6B, nullptr, "Unknown"}, +    {0x6C, nullptr, "Unknown"}, +    {0x6D, nullptr, "Unknown"}, +    {0x6E, nullptr, "Unknown"}, +    {0x6f, nullptr, "GetSystemInfo32"}, +    {0x70, nullptr, "CreatePort32"}, +    {0x71, nullptr, "ManageNamedPort32"}, +    {0x72, nullptr, "ConnectToPort32"}, +    {0x73, nullptr, "SetProcessMemoryPermission32"}, +    {0x74, nullptr, "Unknown"}, +    {0x75, nullptr, "Unknown"}, +    {0x76, nullptr, "Unknown"}, +    {0x77, nullptr, "MapProcessCodeMemory32"}, +    {0x78, nullptr, "UnmapProcessCodeMemory32"}, +    {0x79, nullptr, "Unknown"}, +    {0x7A, nullptr, "Unknown"}, +    {0x7B, nullptr, "TerminateProcess32"}, +}; + +static const FunctionDef SVC_Table_64[] = { +    {0x00, nullptr, "Unknown"}, +    {0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"}, +    {0x02, SvcWrap64<SetMemoryPermission>, "SetMemoryPermission"}, +    {0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"}, +    {0x04, SvcWrap64<MapMemory>, "MapMemory"}, +    {0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"}, +    {0x06, SvcWrap64<QueryMemory>, "QueryMemory"}, +    {0x07, SvcWrap64<ExitProcess>, "ExitProcess"}, +    {0x08, SvcWrap64<CreateThread>, "CreateThread"}, +    {0x09, SvcWrap64<StartThread>, "StartThread"}, +    {0x0A, SvcWrap64<ExitThread>, "ExitThread"}, +    {0x0B, SvcWrap64<SleepThread>, "SleepThread"}, +    {0x0C, SvcWrap64<GetThreadPriority>, "GetThreadPriority"}, +    {0x0D, SvcWrap64<SetThreadPriority>, "SetThreadPriority"}, +    {0x0E, SvcWrap64<GetThreadCoreMask>, "GetThreadCoreMask"}, +    {0x0F, SvcWrap64<SetThreadCoreMask>, "SetThreadCoreMask"}, +    {0x10, SvcWrap64<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"}, +    {0x11, SvcWrap64<SignalEvent>, "SignalEvent"}, +    {0x12, SvcWrap64<ClearEvent>, "ClearEvent"}, +    {0x13, SvcWrap64<MapSharedMemory>, "MapSharedMemory"}, +    {0x14, SvcWrap64<UnmapSharedMemory>, "UnmapSharedMemory"}, +    {0x15, SvcWrap64<CreateTransferMemory>, "CreateTransferMemory"}, +    {0x16, SvcWrap64<CloseHandle>, "CloseHandle"}, +    {0x17, SvcWrap64<ResetSignal>, "ResetSignal"}, +    {0x18, SvcWrap64<WaitSynchronization>, "WaitSynchronization"}, +    {0x19, SvcWrap64<CancelSynchronization>, "CancelSynchronization"}, +    {0x1A, SvcWrap64<ArbitrateLock>, "ArbitrateLock"}, +    {0x1B, SvcWrap64<ArbitrateUnlock>, "ArbitrateUnlock"}, +    {0x1C, SvcWrap64<WaitProcessWideKeyAtomic>, "WaitProcessWideKeyAtomic"}, +    {0x1D, SvcWrap64<SignalProcessWideKey>, "SignalProcessWideKey"}, +    {0x1E, SvcWrap64<GetSystemTick>, "GetSystemTick"}, +    {0x1F, SvcWrap64<ConnectToNamedPort>, "ConnectToNamedPort"},      {0x20, nullptr, "SendSyncRequestLight"}, -    {0x21, SvcWrap<SendSyncRequest>, "SendSyncRequest"}, +    {0x21, SvcWrap64<SendSyncRequest>, "SendSyncRequest"},      {0x22, nullptr, "SendSyncRequestWithUserBuffer"},      {0x23, nullptr, "SendAsyncRequestWithUserBuffer"}, -    {0x24, SvcWrap<GetProcessId>, "GetProcessId"}, -    {0x25, SvcWrap<GetThreadId>, "GetThreadId"}, -    {0x26, SvcWrap<Break>, "Break"}, -    {0x27, SvcWrap<OutputDebugString>, "OutputDebugString"}, +    {0x24, SvcWrap64<GetProcessId>, "GetProcessId"}, +    {0x25, SvcWrap64<GetThreadId>, "GetThreadId"}, +    {0x26, SvcWrap64<Break>, "Break"}, +    {0x27, SvcWrap64<OutputDebugString>, "OutputDebugString"},      {0x28, nullptr, "ReturnFromException"}, -    {0x29, SvcWrap<GetInfo>, "GetInfo"}, +    {0x29, SvcWrap64<GetInfo>, "GetInfo"},      {0x2A, nullptr, "FlushEntireDataCache"},      {0x2B, nullptr, "FlushDataCache"}, -    {0x2C, SvcWrap<MapPhysicalMemory>, "MapPhysicalMemory"}, -    {0x2D, SvcWrap<UnmapPhysicalMemory>, "UnmapPhysicalMemory"}, +    {0x2C, SvcWrap64<MapPhysicalMemory>, "MapPhysicalMemory"}, +    {0x2D, SvcWrap64<UnmapPhysicalMemory>, "UnmapPhysicalMemory"},      {0x2E, nullptr, "GetFutureThreadInfo"},      {0x2F, nullptr, "GetLastThreadInfo"}, -    {0x30, SvcWrap<GetResourceLimitLimitValue>, "GetResourceLimitLimitValue"}, -    {0x31, SvcWrap<GetResourceLimitCurrentValue>, "GetResourceLimitCurrentValue"}, -    {0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"}, -    {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"}, -    {0x34, SvcWrap<WaitForAddress>, "WaitForAddress"}, -    {0x35, SvcWrap<SignalToAddress>, "SignalToAddress"}, +    {0x30, SvcWrap64<GetResourceLimitLimitValue>, "GetResourceLimitLimitValue"}, +    {0x31, SvcWrap64<GetResourceLimitCurrentValue>, "GetResourceLimitCurrentValue"}, +    {0x32, SvcWrap64<SetThreadActivity>, "SetThreadActivity"}, +    {0x33, SvcWrap64<GetThreadContext>, "GetThreadContext"}, +    {0x34, SvcWrap64<WaitForAddress>, "WaitForAddress"}, +    {0x35, SvcWrap64<SignalToAddress>, "SignalToAddress"},      {0x36, nullptr, "SynchronizePreemptionState"},      {0x37, nullptr, "Unknown"},      {0x38, nullptr, "Unknown"},      {0x39, nullptr, "Unknown"},      {0x3A, nullptr, "Unknown"},      {0x3B, nullptr, "Unknown"}, -    {0x3C, SvcWrap<KernelDebug>, "KernelDebug"}, -    {0x3D, SvcWrap<ChangeKernelTraceState>, "ChangeKernelTraceState"}, +    {0x3C, SvcWrap64<KernelDebug>, "KernelDebug"}, +    {0x3D, SvcWrap64<ChangeKernelTraceState>, "ChangeKernelTraceState"},      {0x3E, nullptr, "Unknown"},      {0x3F, nullptr, "Unknown"},      {0x40, nullptr, "CreateSession"}, @@ -2387,7 +2577,7 @@ static const FunctionDef SVC_Table[] = {      {0x42, nullptr, "ReplyAndReceiveLight"},      {0x43, nullptr, "ReplyAndReceive"},      {0x44, nullptr, "ReplyAndReceiveWithUserBuffer"}, -    {0x45, SvcWrap<CreateEvent>, "CreateEvent"}, +    {0x45, SvcWrap64<CreateEvent>, "CreateEvent"},      {0x46, nullptr, "Unknown"},      {0x47, nullptr, "Unknown"},      {0x48, nullptr, "MapPhysicalMemoryUnsafe"}, @@ -2398,9 +2588,9 @@ static const FunctionDef SVC_Table[] = {      {0x4D, nullptr, "SleepSystem"},      {0x4E, nullptr, "ReadWriteRegister"},      {0x4F, nullptr, "SetProcessActivity"}, -    {0x50, SvcWrap<CreateSharedMemory>, "CreateSharedMemory"}, -    {0x51, SvcWrap<MapTransferMemory>, "MapTransferMemory"}, -    {0x52, SvcWrap<UnmapTransferMemory>, "UnmapTransferMemory"}, +    {0x50, SvcWrap64<CreateSharedMemory>, "CreateSharedMemory"}, +    {0x51, SvcWrap64<MapTransferMemory>, "MapTransferMemory"}, +    {0x52, SvcWrap64<UnmapTransferMemory>, "UnmapTransferMemory"},      {0x53, nullptr, "CreateInterruptEvent"},      {0x54, nullptr, "QueryPhysicalAddress"},      {0x55, nullptr, "QueryIoMapping"}, @@ -2419,8 +2609,8 @@ static const FunctionDef SVC_Table[] = {      {0x62, nullptr, "TerminateDebugProcess"},      {0x63, nullptr, "GetDebugEvent"},      {0x64, nullptr, "ContinueDebugEvent"}, -    {0x65, SvcWrap<GetProcessList>, "GetProcessList"}, -    {0x66, SvcWrap<GetThreadList>, "GetThreadList"}, +    {0x65, SvcWrap64<GetProcessList>, "GetProcessList"}, +    {0x66, SvcWrap64<GetThreadList>, "GetThreadList"},      {0x67, nullptr, "GetDebugThreadContext"},      {0x68, nullptr, "SetDebugThreadContext"},      {0x69, nullptr, "QueryDebugProcessMemory"}, @@ -2436,24 +2626,32 @@ static const FunctionDef SVC_Table[] = {      {0x73, nullptr, "SetProcessMemoryPermission"},      {0x74, nullptr, "MapProcessMemory"},      {0x75, nullptr, "UnmapProcessMemory"}, -    {0x76, SvcWrap<QueryProcessMemory>, "QueryProcessMemory"}, -    {0x77, SvcWrap<MapProcessCodeMemory>, "MapProcessCodeMemory"}, -    {0x78, SvcWrap<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"}, +    {0x76, SvcWrap64<QueryProcessMemory>, "QueryProcessMemory"}, +    {0x77, SvcWrap64<MapProcessCodeMemory>, "MapProcessCodeMemory"}, +    {0x78, SvcWrap64<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"},      {0x79, nullptr, "CreateProcess"},      {0x7A, nullptr, "StartProcess"},      {0x7B, nullptr, "TerminateProcess"}, -    {0x7C, SvcWrap<GetProcessInfo>, "GetProcessInfo"}, -    {0x7D, SvcWrap<CreateResourceLimit>, "CreateResourceLimit"}, -    {0x7E, SvcWrap<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"}, +    {0x7C, SvcWrap64<GetProcessInfo>, "GetProcessInfo"}, +    {0x7D, SvcWrap64<CreateResourceLimit>, "CreateResourceLimit"}, +    {0x7E, SvcWrap64<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"},      {0x7F, nullptr, "CallSecureMonitor"},  }; -static const FunctionDef* GetSVCInfo(u32 func_num) { -    if (func_num >= std::size(SVC_Table)) { +static const FunctionDef* GetSVCInfo32(u32 func_num) { +    if (func_num >= std::size(SVC_Table_32)) { +        LOG_ERROR(Kernel_SVC, "Unknown svc=0x{:02X}", func_num); +        return nullptr; +    } +    return &SVC_Table_32[func_num]; +} + +static const FunctionDef* GetSVCInfo64(u32 func_num) { +    if (func_num >= std::size(SVC_Table_64)) {          LOG_ERROR(Kernel_SVC, "Unknown svc=0x{:02X}", func_num);          return nullptr;      } -    return &SVC_Table[func_num]; +    return &SVC_Table_64[func_num];  }  MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); @@ -2464,7 +2662,8 @@ void CallSVC(Core::System& system, u32 immediate) {      // Lock the global kernel mutex when we enter the kernel HLE.      std::lock_guard lock{HLE::g_hle_lock}; -    const FunctionDef* info = GetSVCInfo(immediate); +    const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate) +                                                                        : GetSVCInfo32(immediate);      if (info) {          if (info->func) {              info->func(system); diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 29a2cfa9d..7d735e3fa 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -15,6 +15,10 @@ static inline u64 Param(const Core::System& system, int n) {      return system.CurrentArmInterface().GetReg(n);  } +static inline u32 Param32(const Core::System& system, int n) { +    return static_cast<u32>(system.CurrentArmInterface().GetReg(n)); +} +  /**   * HLE a function return from the current ARM userland process   * @param system System context @@ -24,40 +28,44 @@ static inline void FuncReturn(Core::System& system, u64 result) {      system.CurrentArmInterface().SetReg(0, result);  } +static inline void FuncReturn32(Core::System& system, u32 result) { +    system.CurrentArmInterface().SetReg(0, (u64)result); +} +  ////////////////////////////////////////////////////////////////////////////////////////////////////  // Function wrappers that return type ResultCode  template <ResultCode func(Core::System&, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, Param(system, 0)).raw);  }  template <ResultCode func(Core::System&, u64, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, Param(system, 0), Param(system, 1)).raw);  }  template <ResultCode func(Core::System&, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);  }  template <ResultCode func(Core::System&, u32, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(          system,          func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw);  }  template <ResultCode func(Core::System&, u32, u64, u64, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),                              Param(system, 2), Param(system, 3))                             .raw);  }  template <ResultCode func(Core::System&, u32*)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u32 param = 0;      const u32 retval = func(system, ¶m).raw;      system.CurrentArmInterface().SetReg(1, param); @@ -65,7 +73,7 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u32*, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u32 param_1 = 0;      const u32 retval = func(system, ¶m_1, static_cast<u32>(Param(system, 1))).raw;      system.CurrentArmInterface().SetReg(1, param_1); @@ -73,7 +81,7 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u32*, u32*)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u32 param_1 = 0;      u32 param_2 = 0;      const u32 retval = func(system, ¶m_1, ¶m_2).raw; @@ -86,7 +94,7 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u32*, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u32 param_1 = 0;      const u32 retval = func(system, ¶m_1, Param(system, 1)).raw;      system.CurrentArmInterface().SetReg(1, param_1); @@ -94,7 +102,7 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u32*, u64, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u32 param_1 = 0;      const u32 retval =          func(system, ¶m_1, Param(system, 1), static_cast<u32>(Param(system, 2))).raw; @@ -104,7 +112,7 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u64*, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u64 param_1 = 0;      const u32 retval = func(system, ¶m_1, static_cast<u32>(Param(system, 1))).raw; @@ -113,12 +121,12 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u64, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1))).raw);  }  template <ResultCode func(Core::System&, u64*, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u64 param_1 = 0;      const u32 retval = func(system, ¶m_1, Param(system, 1)).raw; @@ -127,7 +135,7 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u64*, u32, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u64 param_1 = 0;      const u32 retval = func(system, ¶m_1, static_cast<u32>(Param(system, 1)),                              static_cast<u32>(Param(system, 2))) @@ -138,19 +146,19 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u32, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw);  }  template <ResultCode func(Core::System&, u32, u32, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)),                              static_cast<u32>(Param(system, 1)), Param(system, 2))                             .raw);  }  template <ResultCode func(Core::System&, u32, u32*, u64*)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u32 param_1 = 0;      u64 param_2 = 0;      const ResultCode retval = func(system, static_cast<u32>(Param(system, 2)), ¶m_1, ¶m_2); @@ -161,54 +169,54 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u64, u64, u32, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, Param(system, 0), Param(system, 1),                              static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3)))                             .raw);  }  template <ResultCode func(Core::System&, u64, u64, u32, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, Param(system, 0), Param(system, 1),                              static_cast<u32>(Param(system, 2)), Param(system, 3))                             .raw);  }  template <ResultCode func(Core::System&, u32, u64, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),                              static_cast<u32>(Param(system, 2)))                             .raw);  }  template <ResultCode func(Core::System&, u64, u64, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, Param(system, 0), Param(system, 1), Param(system, 2)).raw);  }  template <ResultCode func(Core::System&, u64, u64, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(          system,          func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw);  }  template <ResultCode func(Core::System&, u32, u64, u64, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),                              Param(system, 2), static_cast<u32>(Param(system, 3)))                             .raw);  }  template <ResultCode func(Core::System&, u32, u64, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(          system,          func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2)).raw);  }  template <ResultCode func(Core::System&, u32*, u64, u64, s64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u32 param_1 = 0;      const u32 retval = func(system, ¶m_1, Param(system, 1), static_cast<u32>(Param(system, 2)),                              static_cast<s64>(Param(system, 3))) @@ -219,14 +227,14 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u64, u64, u32, s64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, Param(system, 0), Param(system, 1),                              static_cast<u32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))                             .raw);  }  template <ResultCode func(Core::System&, u64*, u64, u64, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u64 param_1 = 0;      const u32 retval =          func(system, ¶m_1, Param(system, 1), Param(system, 2), Param(system, 3)).raw; @@ -236,7 +244,7 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u32*, u64, u64, u64, u32, s32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u32 param_1 = 0;      const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2), Param(system, 3),                              static_cast<u32>(Param(system, 4)), static_cast<s32>(Param(system, 5))) @@ -247,7 +255,7 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u32*, u64, u64, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u32 param_1 = 0;      const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2),                              static_cast<u32>(Param(system, 3))) @@ -258,7 +266,7 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, Handle*, u64, u32, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      u32 param_1 = 0;      const u32 retval = func(system, ¶m_1, Param(system, 1), static_cast<u32>(Param(system, 2)),                              static_cast<u32>(Param(system, 3))) @@ -269,14 +277,14 @@ void SvcWrap(Core::System& system) {  }  template <ResultCode func(Core::System&, u64, u32, s32, s64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)),                              static_cast<s32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))                             .raw);  }  template <ResultCode func(Core::System&, u64, u32, s32, s32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)),                              static_cast<s32>(Param(system, 2)), static_cast<s32>(Param(system, 3)))                             .raw); @@ -286,7 +294,7 @@ void SvcWrap(Core::System& system) {  // Function wrappers that return type u32  template <u32 func(Core::System&)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system));  } @@ -294,7 +302,7 @@ void SvcWrap(Core::System& system) {  // Function wrappers that return type u64  template <u64 func(Core::System&)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system));  } @@ -302,44 +310,110 @@ void SvcWrap(Core::System& system) {  /// Function wrappers that return type void  template <void func(Core::System&)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      func(system);  }  template <void func(Core::System&, u32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      func(system, static_cast<u32>(Param(system, 0)));  }  template <void func(Core::System&, u32, u64, u64, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2),           Param(system, 3));  }  template <void func(Core::System&, s64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      func(system, static_cast<s64>(Param(system, 0)));  }  template <void func(Core::System&, u64, s32)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      func(system, Param(system, 0), static_cast<s32>(Param(system, 1)));  }  template <void func(Core::System&, u64, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      func(system, Param(system, 0), Param(system, 1));  }  template <void func(Core::System&, u64, u64, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      func(system, Param(system, 0), Param(system, 1), Param(system, 2));  }  template <void func(Core::System&, u32, u64, u64)> -void SvcWrap(Core::System& system) { +void SvcWrap64(Core::System& system) {      func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2));  } +// Used by QueryMemory32 +template <ResultCode func(Core::System&, u32, u32, u32)> +void SvcWrap32(Core::System& system) { +    FuncReturn32(system, +                 func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2)).raw); +} + +// Used by GetInfo32 +template <ResultCode func(Core::System&, u32*, u32*, u32, u32, u32, u32)> +void SvcWrap32(Core::System& system) { +    u32 param_1 = 0; +    u32 param_2 = 0; + +    const u32 retval = func(system, ¶m_1, ¶m_2, Param32(system, 0), Param32(system, 1), +                            Param32(system, 2), Param32(system, 3)) +                           .raw; + +    system.CurrentArmInterface().SetReg(1, param_1); +    system.CurrentArmInterface().SetReg(2, param_2); +    FuncReturn(system, retval); +} + +// Used by GetThreadPriority32, ConnectToNamedPort32 +template <ResultCode func(Core::System&, u32*, u32)> +void SvcWrap32(Core::System& system) { +    u32 param_1 = 0; +    const u32 retval = func(system, ¶m_1, Param32(system, 1)).raw; +    system.CurrentArmInterface().SetReg(1, param_1); +    FuncReturn(system, retval); +} + +// Used by GetThreadId32 +template <ResultCode func(Core::System&, u32*, u32*, u32)> +void SvcWrap32(Core::System& system) { +    u32 param_1 = 0; +    u32 param_2 = 0; + +    const u32 retval = func(system, ¶m_1, ¶m_2, Param32(system, 1)).raw; +    system.CurrentArmInterface().SetReg(1, param_1); +    system.CurrentArmInterface().SetReg(2, param_2); +    FuncReturn(system, retval); +} + +// Used by SignalProcessWideKey32 +template <void func(Core::System&, u32, s32)> +void SvcWrap32(Core::System& system) { +    func(system, static_cast<u32>(Param(system, 0)), static_cast<s32>(Param(system, 1))); +} + +// Used by SendSyncRequest32 +template <ResultCode func(Core::System&, u32)> +void SvcWrap32(Core::System& system) { +    FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw); +} + +// Used by WaitSynchronization32 +template <ResultCode func(Core::System&, u32, u32, s32, u32, Handle*)> +void SvcWrap32(Core::System& system) { +    u32 param_1 = 0; +    const u32 retval = func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2), +                            Param32(system, 3), ¶m_1) +                           .raw; +    system.CurrentArmInterface().SetReg(1, param_1); +    FuncReturn(system, retval); +} +  } // namespace Kernel diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index bf850e0b2..83e956036 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -133,15 +133,16 @@ void Thread::CancelWait() {      ResumeFromWait();  } -/** - * Resets a thread context, making it ready to be scheduled and run by the CPU - * @param context Thread context to reset - * @param stack_top Address of the top of the stack - * @param entry_point Address of entry point for execution - * @param arg User argument for thread - */ -static void ResetThreadContext(Core::ARM_Interface::ThreadContext& context, VAddr stack_top, -                               VAddr entry_point, u64 arg) { +static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context, u32 stack_top, +                                 u32 entry_point, u32 arg) { +    context = {}; +    context.cpu_registers[0] = arg; +    context.cpu_registers[15] = entry_point; +    context.cpu_registers[13] = stack_top; +} + +static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, VAddr stack_top, +                                 VAddr entry_point, u64 arg) {      context = {};      context.cpu_registers[0] = arg;      context.pc = entry_point; @@ -198,9 +199,9 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(KernelCore& kernel, std::strin      thread->owner_process->RegisterThread(thread.get()); -    // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used -    // to initialize the context -    ResetThreadContext(thread->context, stack_top, entry_point, arg); +    ResetThreadContext32(thread->context_32, static_cast<u32>(stack_top), +                         static_cast<u32>(entry_point), static_cast<u32>(arg)); +    ResetThreadContext64(thread->context_64, stack_top, entry_point, arg);      return MakeResult<std::shared_ptr<Thread>>(std::move(thread));  } @@ -213,11 +214,13 @@ void Thread::SetPriority(u32 priority) {  }  void Thread::SetWaitSynchronizationResult(ResultCode result) { -    context.cpu_registers[0] = result.raw; +    context_32.cpu_registers[0] = result.raw; +    context_64.cpu_registers[0] = result.raw;  }  void Thread::SetWaitSynchronizationOutput(s32 output) { -    context.cpu_registers[1] = output; +    context_32.cpu_registers[1] = output; +    context_64.cpu_registers[1] = output;  }  s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr<SynchronizationObject> object) const { diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 129e7858a..23fdef8a4 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -102,7 +102,8 @@ public:      using MutexWaitingThreads = std::vector<std::shared_ptr<Thread>>; -    using ThreadContext = Core::ARM_Interface::ThreadContext; +    using ThreadContext32 = Core::ARM_Interface::ThreadContext32; +    using ThreadContext64 = Core::ARM_Interface::ThreadContext64;      using ThreadSynchronizationObjects = std::vector<std::shared_ptr<SynchronizationObject>>; @@ -273,12 +274,20 @@ public:          return status == ThreadStatus::WaitSynch;      } -    ThreadContext& GetContext() { -        return context; +    ThreadContext32& GetContext32() { +        return context_32;      } -    const ThreadContext& GetContext() const { -        return context; +    const ThreadContext32& GetContext32() const { +        return context_32; +    } + +    ThreadContext64& GetContext64() { +        return context_64; +    } + +    const ThreadContext64& GetContext64() const { +        return context_64;      }      ThreadStatus GetStatus() const { @@ -466,7 +475,8 @@ private:      void AdjustSchedulingOnPriority(u32 old_priority);      void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core); -    Core::ARM_Interface::ThreadContext context{}; +    ThreadContext32 context_32{}; +    ThreadContext64 context_64{};      u64 thread_id = 0; diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index d19c3623c..53559e8b1 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -129,12 +129,6 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect      }      metadata.Print(); -    const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()}; -    if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit || -        arch_bits == FileSys::ProgramAddressSpaceType::Is32BitNoMap) { -        return {ResultStatus::Error32BitISA, {}}; -    } -      if (process.LoadFromMetadata(metadata).IsError()) {          return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};      } diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index f95eee3b1..85ac81ef7 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp @@ -111,7 +111,7 @@ json GetProcessorStateDataAuto(Core::System& system) {      const auto& vm_manager{process->VMManager()};      auto& arm{system.CurrentArmInterface()}; -    Core::ARM_Interface::ThreadContext context{}; +    Core::ARM_Interface::ThreadContext64 context{};      arm.SaveContext(context);      return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32", diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 3f1a94627..c1ea25fb8 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -116,7 +116,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons      constexpr std::size_t BaseRegister = 29;      auto& memory = Core::System::GetInstance().Memory(); -    u64 base_pointer = thread.GetContext().cpu_registers[BaseRegister]; +    u64 base_pointer = thread.GetContext64().cpu_registers[BaseRegister];      while (base_pointer != 0) {          const u64 lr = memory.Read64(base_pointer + sizeof(u64)); @@ -240,7 +240,7 @@ QString WaitTreeThread::GetText() const {          break;      } -    const auto& context = thread.GetContext(); +    const auto& context = thread.GetContext64();      const QString pc_info = tr(" PC = 0x%1 LR = 0x%2")                                  .arg(context.pc, 8, 16, QLatin1Char{'0'})                                  .arg(context.cpu_registers[30], 8, 16, QLatin1Char{'0'}); | 
