diff options
| -rw-r--r-- | src/common/settings.h | 1 | ||||
| -rw-r--r-- | src/core/arm/arm_interface.cpp | 8 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 21 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 21 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_cpu_debug.cpp | 4 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_cpu_debug.ui | 13 | ||||
| -rw-r--r-- | src/yuzu_cmd/config.cpp | 1 | ||||
| -rw-r--r-- | src/yuzu_cmd/default_ini.h | 4 | 
9 files changed, 69 insertions, 6 deletions
| diff --git a/src/common/settings.h b/src/common/settings.h index c0620066c..29b730cff 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -400,6 +400,7 @@ struct Values {      Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"};      Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"};      Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"}; +    Setting<bool> cpuopt_ignore_memory_aborts{true, "cpuopt_ignore_memory_aborts"};      SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"};      SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"}; diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp index 29ba562dc..2df7b0ee8 100644 --- a/src/core/arm/arm_interface.cpp +++ b/src/core/arm/arm_interface.cpp @@ -145,11 +145,15 @@ void ARM_Interface::Run() {          // Notify the debugger and go to sleep if a breakpoint was hit,          // or if the thread is unable to continue for any reason.          if (Has(hr, breakpoint) || Has(hr, no_execute)) { -            RewindBreakpointInstruction(); +            if (!Has(hr, no_execute)) { +                RewindBreakpointInstruction(); +            }              if (system.DebuggerEnabled()) {                  system.GetDebugger().NotifyThreadStopped(current_thread); +            } else { +                LogBacktrace();              } -            current_thread->RequestSuspend(Kernel::SuspendType::Debug); +            current_thread->RequestSuspend(SuspendType::Debug);              break;          } diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 227e06ea1..947747d36 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -29,7 +29,9 @@ class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {  public:      explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)          : parent{parent_}, -          memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()} {} +          memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()}, +          check_memory_access{debugger_enabled || +                              !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}      u8 MemoryRead8(u32 vaddr) override {          CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); @@ -154,6 +156,17 @@ public:      }      bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { +        if (!check_memory_access) { +            return true; +        } + +        if (!memory.IsValidVirtualAddressRange(addr, size)) { +            LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}", +                         addr); +            parent.jit.load()->HaltExecution(ARM_Interface::no_execute); +            return false; +        } +          if (!debugger_enabled) {              return true;          } @@ -181,7 +194,8 @@ public:      ARM_Dynarmic_32& parent;      Core::Memory::Memory& memory;      std::size_t num_interpreted_instructions{}; -    bool debugger_enabled{}; +    const bool debugger_enabled{}; +    const bool check_memory_access{};      static constexpr u64 minimum_run_cycles = 10000U;  }; @@ -264,6 +278,9 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*          if (!Settings::values.cpuopt_recompile_exclusives) {              config.recompile_on_exclusive_fastmem_failure = false;          } +        if (!Settings::values.cpuopt_ignore_memory_aborts) { +            config.check_halt_on_memory_access = true; +        }      } else {          // Unsafe optimizations          if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index cb53d64ba..3df943df7 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -29,7 +29,9 @@ class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {  public:      explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)          : parent{parent_}, -          memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()} {} +          memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()}, +          check_memory_access{debugger_enabled || +                              !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}      u8 MemoryRead8(u64 vaddr) override {          CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); @@ -198,6 +200,17 @@ public:      }      bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { +        if (!check_memory_access) { +            return true; +        } + +        if (!memory.IsValidVirtualAddressRange(addr, size)) { +            LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}", +                         addr); +            parent.jit.load()->HaltExecution(ARM_Interface::no_execute); +            return false; +        } +          if (!debugger_enabled) {              return true;          } @@ -226,7 +239,8 @@ public:      Core::Memory::Memory& memory;      u64 tpidrro_el0 = 0;      u64 tpidr_el0 = 0; -    bool debugger_enabled{}; +    const bool debugger_enabled{}; +    const bool check_memory_access{};      static constexpr u64 minimum_run_cycles = 10000U;  }; @@ -323,6 +337,9 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*          if (!Settings::values.cpuopt_recompile_exclusives) {              config.recompile_on_exclusive_fastmem_failure = false;          } +        if (!Settings::values.cpuopt_ignore_memory_aborts) { +            config.check_halt_on_memory_access = true; +        }      } else {          // Unsafe optimizations          if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index c11d1c8b3..722fc708e 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -679,6 +679,7 @@ void Config::ReadCpuValues() {          ReadBasicSetting(Settings::values.cpuopt_fastmem);          ReadBasicSetting(Settings::values.cpuopt_fastmem_exclusives);          ReadBasicSetting(Settings::values.cpuopt_recompile_exclusives); +        ReadBasicSetting(Settings::values.cpuopt_ignore_memory_aborts);      }      qt_config->endGroup(); @@ -1291,6 +1292,7 @@ void Config::SaveCpuValues() {          WriteBasicSetting(Settings::values.cpuopt_fastmem);          WriteBasicSetting(Settings::values.cpuopt_fastmem_exclusives);          WriteBasicSetting(Settings::values.cpuopt_recompile_exclusives); +        WriteBasicSetting(Settings::values.cpuopt_ignore_memory_aborts);      }      qt_config->endGroup(); diff --git a/src/yuzu/configuration/configure_cpu_debug.cpp b/src/yuzu/configuration/configure_cpu_debug.cpp index 3c302ec16..8cfef0cc1 100644 --- a/src/yuzu/configuration/configure_cpu_debug.cpp +++ b/src/yuzu/configuration/configure_cpu_debug.cpp @@ -45,6 +45,9 @@ void ConfigureCpuDebug::SetConfiguration() {      ui->cpuopt_recompile_exclusives->setEnabled(runtime_lock);      ui->cpuopt_recompile_exclusives->setChecked(          Settings::values.cpuopt_recompile_exclusives.GetValue()); +    ui->cpuopt_ignore_memory_aborts->setEnabled(runtime_lock); +    ui->cpuopt_ignore_memory_aborts->setChecked( +        Settings::values.cpuopt_ignore_memory_aborts.GetValue());  }  void ConfigureCpuDebug::ApplyConfiguration() { @@ -59,6 +62,7 @@ void ConfigureCpuDebug::ApplyConfiguration() {      Settings::values.cpuopt_fastmem = ui->cpuopt_fastmem->isChecked();      Settings::values.cpuopt_fastmem_exclusives = ui->cpuopt_fastmem_exclusives->isChecked();      Settings::values.cpuopt_recompile_exclusives = ui->cpuopt_recompile_exclusives->isChecked(); +    Settings::values.cpuopt_ignore_memory_aborts = ui->cpuopt_ignore_memory_aborts->isChecked();  }  void ConfigureCpuDebug::changeEvent(QEvent* event) { diff --git a/src/yuzu/configuration/configure_cpu_debug.ui b/src/yuzu/configuration/configure_cpu_debug.ui index 2bc268810..3010f7fad 100644 --- a/src/yuzu/configuration/configure_cpu_debug.ui +++ b/src/yuzu/configuration/configure_cpu_debug.ui @@ -175,6 +175,19 @@            </property>           </widget>          </item> +        <item> +         <widget class="QCheckBox" name="cpuopt_ignore_memory_aborts"> +          <property name="toolTip"> +           <string> +            <div style="white-space: nowrap">This optimization speeds up memory accesses by allowing invalid memory accesses to succeed.</div> +            <div style="white-space: nowrap">Enabling it reduces the overhead of all memory accesses and has no impact on programs that don't access invalid memory.</div> +           </string> +          </property> +          <property name="text"> +           <string>Enable fallbacks for invalid memory accesses</string> +          </property> +         </widget> +        </item>         </layout>        </widget>       </item> diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 2c78e776c..de9b220da 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -286,6 +286,7 @@ void Config::ReadValues() {      ReadSetting("Cpu", Settings::values.cpuopt_fastmem);      ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives);      ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives); +    ReadSetting("Cpu", Settings::values.cpuopt_ignore_memory_aborts);      ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma);      ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error);      ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr); diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 5bbc3f532..6fcf04e1b 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -208,6 +208,10 @@ cpuopt_fastmem_exclusives =  # 0: Disabled, 1 (default): Enabled  cpuopt_recompile_exclusives = +# Enable optimization to ignore invalid memory accesses (faster guest memory access) +# 0: Disabled, 1 (default): Enabled +cpuopt_ignore_memory_aborts = +  # Enable unfuse FMA (improve performance on CPUs without FMA)  # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.  # 0: Disabled, 1 (default): Enabled | 
