core: add option to break on unmapped access
This commit is contained in:
parent
dcc663e1bf
commit
6072b22a0b
|
@ -399,6 +399,7 @@ struct Values {
|
||||||
Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"};
|
Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"};
|
||||||
Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"};
|
Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"};
|
||||||
Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_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_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"};
|
||||||
SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"};
|
SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"};
|
||||||
|
|
|
@ -145,11 +145,15 @@ void ARM_Interface::Run() {
|
||||||
// Notify the debugger and go to sleep if a breakpoint was hit,
|
// Notify the debugger and go to sleep if a breakpoint was hit,
|
||||||
// or if the thread is unable to continue for any reason.
|
// or if the thread is unable to continue for any reason.
|
||||||
if (Has(hr, breakpoint) || Has(hr, no_execute)) {
|
if (Has(hr, breakpoint) || Has(hr, no_execute)) {
|
||||||
|
if (!Has(hr, no_execute)) {
|
||||||
RewindBreakpointInstruction();
|
RewindBreakpointInstruction();
|
||||||
|
}
|
||||||
if (system.DebuggerEnabled()) {
|
if (system.DebuggerEnabled()) {
|
||||||
system.GetDebugger().NotifyThreadStopped(current_thread);
|
system.GetDebugger().NotifyThreadStopped(current_thread);
|
||||||
|
} else {
|
||||||
|
LogBacktrace();
|
||||||
}
|
}
|
||||||
current_thread->RequestSuspend(Kernel::SuspendType::Debug);
|
current_thread->RequestSuspend(SuspendType::Debug);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,9 @@ class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
|
||||||
public:
|
public:
|
||||||
explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
|
explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
|
||||||
: parent{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 {
|
u8 MemoryRead8(u32 vaddr) override {
|
||||||
CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
|
CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
|
||||||
|
@ -154,6 +156,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) {
|
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) {
|
if (!debugger_enabled) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -181,7 +194,8 @@ public:
|
||||||
ARM_Dynarmic_32& parent;
|
ARM_Dynarmic_32& parent;
|
||||||
Core::Memory::Memory& memory;
|
Core::Memory::Memory& memory;
|
||||||
std::size_t num_interpreted_instructions{};
|
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;
|
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) {
|
if (!Settings::values.cpuopt_recompile_exclusives) {
|
||||||
config.recompile_on_exclusive_fastmem_failure = false;
|
config.recompile_on_exclusive_fastmem_failure = false;
|
||||||
}
|
}
|
||||||
|
if (!Settings::values.cpuopt_ignore_memory_aborts) {
|
||||||
|
config.check_halt_on_memory_access = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Unsafe optimizations
|
// Unsafe optimizations
|
||||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
|
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
|
||||||
|
|
|
@ -29,7 +29,9 @@ class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
|
||||||
public:
|
public:
|
||||||
explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)
|
explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)
|
||||||
: parent{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 {
|
u8 MemoryRead8(u64 vaddr) override {
|
||||||
CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
|
CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
|
||||||
|
@ -198,6 +200,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) {
|
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) {
|
if (!debugger_enabled) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -226,7 +239,8 @@ public:
|
||||||
Core::Memory::Memory& memory;
|
Core::Memory::Memory& memory;
|
||||||
u64 tpidrro_el0 = 0;
|
u64 tpidrro_el0 = 0;
|
||||||
u64 tpidr_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;
|
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) {
|
if (!Settings::values.cpuopt_recompile_exclusives) {
|
||||||
config.recompile_on_exclusive_fastmem_failure = false;
|
config.recompile_on_exclusive_fastmem_failure = false;
|
||||||
}
|
}
|
||||||
|
if (!Settings::values.cpuopt_ignore_memory_aborts) {
|
||||||
|
config.check_halt_on_memory_access = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Unsafe optimizations
|
// Unsafe optimizations
|
||||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
|
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
|
||||||
|
|
|
@ -658,6 +658,7 @@ void Config::ReadCpuValues() {
|
||||||
ReadBasicSetting(Settings::values.cpuopt_fastmem);
|
ReadBasicSetting(Settings::values.cpuopt_fastmem);
|
||||||
ReadBasicSetting(Settings::values.cpuopt_fastmem_exclusives);
|
ReadBasicSetting(Settings::values.cpuopt_fastmem_exclusives);
|
||||||
ReadBasicSetting(Settings::values.cpuopt_recompile_exclusives);
|
ReadBasicSetting(Settings::values.cpuopt_recompile_exclusives);
|
||||||
|
ReadBasicSetting(Settings::values.cpuopt_ignore_memory_aborts);
|
||||||
}
|
}
|
||||||
|
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
|
@ -1257,6 +1258,7 @@ void Config::SaveCpuValues() {
|
||||||
WriteBasicSetting(Settings::values.cpuopt_fastmem);
|
WriteBasicSetting(Settings::values.cpuopt_fastmem);
|
||||||
WriteBasicSetting(Settings::values.cpuopt_fastmem_exclusives);
|
WriteBasicSetting(Settings::values.cpuopt_fastmem_exclusives);
|
||||||
WriteBasicSetting(Settings::values.cpuopt_recompile_exclusives);
|
WriteBasicSetting(Settings::values.cpuopt_recompile_exclusives);
|
||||||
|
WriteBasicSetting(Settings::values.cpuopt_ignore_memory_aborts);
|
||||||
}
|
}
|
||||||
|
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
|
|
|
@ -45,6 +45,9 @@ void ConfigureCpuDebug::SetConfiguration() {
|
||||||
ui->cpuopt_recompile_exclusives->setEnabled(runtime_lock);
|
ui->cpuopt_recompile_exclusives->setEnabled(runtime_lock);
|
||||||
ui->cpuopt_recompile_exclusives->setChecked(
|
ui->cpuopt_recompile_exclusives->setChecked(
|
||||||
Settings::values.cpuopt_recompile_exclusives.GetValue());
|
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() {
|
void ConfigureCpuDebug::ApplyConfiguration() {
|
||||||
|
@ -59,6 +62,7 @@ void ConfigureCpuDebug::ApplyConfiguration() {
|
||||||
Settings::values.cpuopt_fastmem = ui->cpuopt_fastmem->isChecked();
|
Settings::values.cpuopt_fastmem = ui->cpuopt_fastmem->isChecked();
|
||||||
Settings::values.cpuopt_fastmem_exclusives = ui->cpuopt_fastmem_exclusives->isChecked();
|
Settings::values.cpuopt_fastmem_exclusives = ui->cpuopt_fastmem_exclusives->isChecked();
|
||||||
Settings::values.cpuopt_recompile_exclusives = ui->cpuopt_recompile_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) {
|
void ConfigureCpuDebug::changeEvent(QEvent* event) {
|
||||||
|
|
|
@ -175,6 +175,19 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -286,6 +286,7 @@ void Config::ReadValues() {
|
||||||
ReadSetting("Cpu", Settings::values.cpuopt_fastmem);
|
ReadSetting("Cpu", Settings::values.cpuopt_fastmem);
|
||||||
ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives);
|
ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives);
|
||||||
ReadSetting("Cpu", Settings::values.cpuopt_recompile_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_unfuse_fma);
|
||||||
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error);
|
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error);
|
||||||
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr);
|
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr);
|
||||||
|
|
|
@ -208,6 +208,10 @@ cpuopt_fastmem_exclusives =
|
||||||
# 0: Disabled, 1 (default): Enabled
|
# 0: Disabled, 1 (default): Enabled
|
||||||
cpuopt_recompile_exclusives =
|
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)
|
# 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.
|
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||||
# 0: Disabled, 1 (default): Enabled
|
# 0: Disabled, 1 (default): Enabled
|
||||||
|
|
Reference in New Issue