DolphinQt: Properly lock CPU before accessing emulated memory

This fixes a problem I was having where using frame advance with the
debugger open would frequently cause panic alerts about invalid addresses
due to the CPU thread changing MSR.DR while the host thread was trying
to access memory.

To aid in tracking down all the places where we weren't properly locking
the CPU, I've created a new type (in Core.h) that you have to pass as a
reference or pointer to functions that require running as the CPU thread.
This commit is contained in:
JosJuice committed 2023-02-12 11:27:50 +01:00
1 parent efed037c4a
commit 7cecb28bdf
79 files changed
+1796 -1184

No files matched your search

+19 -15
View File
@@ -375,11 +375,11 @@ bool CBoot::FindMapFile(std::string* existing_map_file, std::string* writable_ma
return false;
}
bool CBoot::LoadMapFromFilename()
bool CBoot::LoadMapFromFilename(const Core::CPUThreadGuard& guard)
{
std::string strMapFilename;
bool found = FindMapFile(&strMapFilename, nullptr);
if (found && g_symbolDB.LoadMap(strMapFilename))
if (found && g_symbolDB.LoadMap(guard, strMapFilename))
{
UpdateDebugger_MapLoaded();
return true;
@@ -486,7 +486,8 @@ static void CopyDefaultExceptionHandlers(Core::System& system)
}
// Third boot step after BootManager and Core. See Call schedule in BootManager.cpp
bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
std::unique_ptr<BootParameters> boot)
{
SConfig& config = SConfig::GetInstance();
@@ -502,8 +503,10 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
struct BootTitle
{
BootTitle(Core::System& system_, const std::vector<DiscIO::Riivolution::Patch>& patches)
: system(system_), config(SConfig::GetInstance()), riivolution_patches(patches)
BootTitle(Core::System& system_, const Core::CPUThreadGuard& guard_,
const std::vector<DiscIO::Riivolution::Patch>& patches)
: system(system_), guard(guard_), config(SConfig::GetInstance()),
riivolution_patches(patches)
{
}
bool operator()(BootParameters::Disc& disc) const
@@ -515,10 +518,10 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
if (!volume)
return false;
if (!EmulatedBS2(system, config.bWii, *volume, riivolution_patches))
if (!EmulatedBS2(system, guard, config.bWii, *volume, riivolution_patches))
return false;
SConfig::OnNewTitleLoad();
SConfig::OnNewTitleLoad(guard);
return true;
}
@@ -551,7 +554,7 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
}
else
{
SetupGCMemory(system);
SetupGCMemory(system, guard);
}
if (!executable.reader->LoadIntoMemory())
@@ -560,11 +563,11 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
return false;
}
SConfig::OnNewTitleLoad();
SConfig::OnNewTitleLoad(guard);
ppc_state.pc = executable.reader->GetEntryPoint();
if (executable.reader->LoadSymbols())
if (executable.reader->LoadSymbols(guard))
{
UpdateDebugger_MapLoaded();
HLE::PatchFunctions(system);
@@ -578,7 +581,7 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
if (!Boot_WiiWAD(system, wad))
return false;
SConfig::OnNewTitleLoad();
SConfig::OnNewTitleLoad(guard);
return true;
}
@@ -588,7 +591,7 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
if (!BootNANDTitle(system, nand_title.id))
return false;
SConfig::OnNewTitleLoad();
SConfig::OnNewTitleLoad(guard);
return true;
}
@@ -613,7 +616,7 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
SetDisc(DiscIO::CreateDisc(ipl.disc->path), ipl.disc->auto_disc_change_paths);
}
SConfig::OnNewTitleLoad();
SConfig::OnNewTitleLoad(guard);
return true;
}
@@ -625,14 +628,15 @@ bool CBoot::BootUp(Core::System& system, std::unique_ptr<BootParameters> boot)
private:
Core::System& system;
const Core::CPUThreadGuard& guard;
const SConfig& config;
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches;
};
if (!std::visit(BootTitle(system, boot->riivolution_patches), boot->parameters))
if (!std::visit(BootTitle(system, guard, boot->riivolution_patches), boot->parameters))
return false;
DiscIO::Riivolution::ApplyGeneralMemoryPatches(boot->riivolution_patches);
DiscIO::Riivolution::ApplyGeneralMemoryPatches(guard, boot->riivolution_patches);
return true;
}
+15 -9
View File
@@ -21,8 +21,9 @@
namespace Core
{
class CPUThreadGuard;
class System;
}
} // namespace Core
namespace File
{
@@ -153,7 +154,8 @@ struct BootParameters
class CBoot
{
public:
static bool BootUp(Core::System& system, std::unique_ptr<BootParameters> boot);
static bool BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
std::unique_ptr<BootParameters> boot);
// Tries to find a map file for the current game by looking first in the
// local user directory, then in the shared user directory.
@@ -166,7 +168,7 @@ public:
//
// Returns true if a map file exists, false if none could be found.
static bool FindMapFile(std::string* existing_map_file, std::string* writable_map_file);
static bool LoadMapFromFilename();
static bool LoadMapFromFilename(const Core::CPUThreadGuard& guard);
private:
static bool DVDRead(const DiscIO::VolumeDisc& disc, u64 dvd_offset, u32 output_address,
@@ -182,17 +184,21 @@ private:
static void SetupMSR(PowerPC::PowerPCState& ppc_state);
static void SetupHID(PowerPC::PowerPCState& ppc_state, bool is_wii);
static void SetupBAT(Core::System& system, bool is_wii);
static bool RunApploader(Core::System& system, bool is_wii, const DiscIO::VolumeDisc& volume,
static bool RunApploader(Core::System& system, const Core::CPUThreadGuard& guard, bool is_wii,
const DiscIO::VolumeDisc& volume,
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
static bool EmulatedBS2_GC(Core::System& system, const DiscIO::VolumeDisc& volume,
static bool EmulatedBS2_GC(Core::System& system, const Core::CPUThreadGuard& guard,
const DiscIO::VolumeDisc& volume,
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
static bool EmulatedBS2_Wii(Core::System& system, const DiscIO::VolumeDisc& volume,
static bool EmulatedBS2_Wii(Core::System& system, const Core::CPUThreadGuard& guard,
const DiscIO::VolumeDisc& volume,
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
static bool EmulatedBS2(Core::System& system, bool is_wii, const DiscIO::VolumeDisc& volume,
static bool EmulatedBS2(Core::System& system, const Core::CPUThreadGuard& guard, bool is_wii,
const DiscIO::VolumeDisc& volume,
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches);
static bool Load_BS2(Core::System& system, const std::string& boot_rom_filename);
static void SetupGCMemory(Core::System& system);
static void SetupGCMemory(Core::System& system, const Core::CPUThreadGuard& guard);
static bool SetupWiiMemory(Core::System& system, IOS::HLE::IOSC::ConsoleType console_type);
};
@@ -208,7 +214,7 @@ public:
virtual bool IsValid() const = 0;
virtual bool IsWii() const = 0;
virtual bool LoadIntoMemory(bool only_in_mem1 = false) const = 0;
virtual bool LoadSymbols() const = 0;
virtual bool LoadSymbols(const Core::CPUThreadGuard& guard) const = 0;
protected:
std::vector<u8> m_bytes;
+33 -27
View File
@@ -44,14 +44,14 @@
namespace
{
void PresetTimeBaseTicks()
void PresetTimeBaseTicks(const Core::CPUThreadGuard& guard)
{
const u64 emulated_time =
ExpansionInterface::CEXIIPL::GetEmulatedTime(ExpansionInterface::CEXIIPL::GC_EPOCH);
const u64 time_base_ticks = emulated_time * 40500000ULL;
PowerPC::HostWrite_U64(time_base_ticks, 0x800030D8);
PowerPC::HostWrite_U64(guard, time_base_ticks, 0x800030D8);
}
} // Anonymous namespace
@@ -131,7 +131,8 @@ void CBoot::SetupBAT(Core::System& system, bool is_wii)
PowerPC::IBATUpdated();
}
bool CBoot::RunApploader(Core::System& system, bool is_wii, const DiscIO::VolumeDisc& volume,
bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard, bool is_wii,
const DiscIO::VolumeDisc& volume,
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
{
const DiscIO::Partition partition = volume.GetGamePartition();
@@ -166,8 +167,8 @@ bool CBoot::RunApploader(Core::System& system, bool is_wii, const DiscIO::Volume
// iAppLoaderInit
DEBUG_LOG_FMT(BOOT, "Call iAppLoaderInit");
PowerPC::HostWrite_U32(0x4E800020, 0x81300000); // Write BLR
HLE::Patch(system, 0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader
PowerPC::HostWrite_U32(guard, 0x4E800020, 0x81300000); // Write BLR
HLE::Patch(system, 0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader
ppc_state.gpr[3] = 0x81300000;
RunFunction(system, iAppLoaderInit);
@@ -196,7 +197,8 @@ bool CBoot::RunApploader(Core::System& system, bool is_wii, const DiscIO::Volume
ram_address, length);
DVDRead(volume, dvd_offset, ram_address, length, partition);
DiscIO::Riivolution::ApplyApploaderMemoryPatches(riivolution_patches, ram_address, length);
DiscIO::Riivolution::ApplyApploaderMemoryPatches(guard, riivolution_patches, ram_address,
length);
ppc_state.gpr[3] = 0x81300004;
ppc_state.gpr[4] = 0x81300008;
@@ -216,36 +218,37 @@ bool CBoot::RunApploader(Core::System& system, bool is_wii, const DiscIO::Volume
return true;
}
void CBoot::SetupGCMemory(Core::System& system)
void CBoot::SetupGCMemory(Core::System& system, const Core::CPUThreadGuard& guard)
{
auto& memory = system.GetMemory();
// Booted from bootrom. 0xE5207C22 = booted from jtag
PowerPC::HostWrite_U32(0x0D15EA5E, 0x80000020);
PowerPC::HostWrite_U32(guard, 0x0D15EA5E, 0x80000020);
// Physical Memory Size (24MB on retail)
PowerPC::HostWrite_U32(memory.GetRamSizeReal(), 0x80000028);
PowerPC::HostWrite_U32(guard, memory.GetRamSizeReal(), 0x80000028);
// Console type - DevKit (retail ID == 0x00000003) see YAGCD 4.2.1.1.2
// TODO: determine why some games fail when using a retail ID.
// (Seem to take different EXI paths, see Ikaruga for example)
const u32 console_type = static_cast<u32>(Core::ConsoleType::LatestDevkit);
PowerPC::HostWrite_U32(console_type, 0x8000002C);
PowerPC::HostWrite_U32(guard, console_type, 0x8000002C);
// Fake the VI Init of the IPL (YAGCD 4.2.1.4)
PowerPC::HostWrite_U32(DiscIO::IsNTSC(SConfig::GetInstance().m_region) ? 0 : 1, 0x800000CC);
PowerPC::HostWrite_U32(guard, DiscIO::IsNTSC(SConfig::GetInstance().m_region) ? 0 : 1,
0x800000CC);
PowerPC::HostWrite_U32(0x01000000, 0x800000d0); // ARAM Size. 16MB main + 4/16/32MB external
// (retail consoles have no external ARAM)
// ARAM Size. 16MB main + 4/16/32MB external. (retail consoles have no external ARAM)
PowerPC::HostWrite_U32(guard, 0x01000000, 0x800000d0);
PowerPC::HostWrite_U32(0x09a7ec80, 0x800000F8); // Bus Clock Speed
PowerPC::HostWrite_U32(0x1cf7c580, 0x800000FC); // CPU Clock Speed
PowerPC::HostWrite_U32(guard, 0x09a7ec80, 0x800000F8); // Bus Clock Speed
PowerPC::HostWrite_U32(guard, 0x1cf7c580, 0x800000FC); // CPU Clock Speed
PowerPC::HostWrite_U32(0x4c000064, 0x80000300); // Write default DSI Handler: rfi
PowerPC::HostWrite_U32(0x4c000064, 0x80000800); // Write default FPU Handler: rfi
PowerPC::HostWrite_U32(0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
PowerPC::HostWrite_U32(guard, 0x4c000064, 0x80000300); // Write default DSI Handler: rfi
PowerPC::HostWrite_U32(guard, 0x4c000064, 0x80000800); // Write default FPU Handler: rfi
PowerPC::HostWrite_U32(guard, 0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
PresetTimeBaseTicks();
PresetTimeBaseTicks(guard);
// HIO checks this
// PowerPC::HostWrite_U16(0x8200, 0x000030e6); // Console type
@@ -255,7 +258,8 @@ void CBoot::SetupGCMemory(Core::System& system)
// GameCube Bootstrap 2 HLE:
// copy the apploader to 0x81200000
// execute the apploader, function by function, using the above utility.
bool CBoot::EmulatedBS2_GC(Core::System& system, const DiscIO::VolumeDisc& volume,
bool CBoot::EmulatedBS2_GC(Core::System& system, const Core::CPUThreadGuard& guard,
const DiscIO::VolumeDisc& volume,
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
{
INFO_LOG_FMT(BOOT, "Faking GC BS2...");
@@ -266,7 +270,7 @@ bool CBoot::EmulatedBS2_GC(Core::System& system, const DiscIO::VolumeDisc& volum
SetupHID(ppc_state, /*is_wii*/ false);
SetupBAT(system, /*is_wii*/ false);
SetupGCMemory(system);
SetupGCMemory(system, guard);
// Datel titles don't initialize the postMatrices, but they have dual-texture coordinate
// transformation enabled. We initialize all of xfmem to 0, which results in everything using
@@ -309,7 +313,7 @@ bool CBoot::EmulatedBS2_GC(Core::System& system, const DiscIO::VolumeDisc& volum
// Global pointer to Small Data Area Base (Luigi's Mansion's apploader uses it)
ppc_state.gpr[13] = ntsc ? 0x81465320 : 0x814b4fc0;
return RunApploader(system, /*is_wii*/ false, volume, riivolution_patches);
return RunApploader(system, guard, /*is_wii*/ false, volume, riivolution_patches);
}
static DiscIO::Region CodeRegion(char c)
@@ -507,7 +511,8 @@ static void WriteEmptyPlayRecord()
// Wii Bootstrap 2 HLE:
// copy the apploader to 0x81200000
// execute the apploader
bool CBoot::EmulatedBS2_Wii(Core::System& system, const DiscIO::VolumeDisc& volume,
bool CBoot::EmulatedBS2_Wii(Core::System& system, const Core::CPUThreadGuard& guard,
const DiscIO::VolumeDisc& volume,
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
{
INFO_LOG_FMT(BOOT, "Faking Wii BS2...");
@@ -578,7 +583,7 @@ bool CBoot::EmulatedBS2_Wii(Core::System& system, const DiscIO::VolumeDisc& volu
ppc_state.gpr[1] = 0x816ffff0; // StackPointer
if (!RunApploader(system, /*is_wii*/ true, volume, riivolution_patches))
if (!RunApploader(system, guard, /*is_wii*/ true, volume, riivolution_patches))
return false;
// The Apploader probably just overwrote values needed for RAM Override. Run this again!
@@ -593,9 +598,10 @@ bool CBoot::EmulatedBS2_Wii(Core::System& system, const DiscIO::VolumeDisc& volu
// Returns true if apploader has run successfully. If is_wii is true, the disc
// that volume refers to must currently be inserted into the emulated disc drive.
bool CBoot::EmulatedBS2(Core::System& system, bool is_wii, const DiscIO::VolumeDisc& volume,
bool CBoot::EmulatedBS2(Core::System& system, const Core::CPUThreadGuard& guard, bool is_wii,
const DiscIO::VolumeDisc& volume,
const std::vector<DiscIO::Riivolution::Patch>& riivolution_patches)
{
return is_wii ? EmulatedBS2_Wii(system, volume, riivolution_patches) :
EmulatedBS2_GC(system, volume, riivolution_patches);
return is_wii ? EmulatedBS2_Wii(system, guard, volume, riivolution_patches) :
EmulatedBS2_GC(system, guard, volume, riivolution_patches);
}
+1 -1
View File
@@ -27,7 +27,7 @@ public:
bool IsAncast() const { return m_is_ancast; };
u32 GetEntryPoint() const override { return m_dolheader.entryPoint; }
bool LoadIntoMemory(bool only_in_mem1 = false) const override;
bool LoadSymbols() const override { return false; }
bool LoadSymbols(const Core::CPUThreadGuard& guard) const override { return false; }
private:
enum
+2 -2
View File
@@ -181,7 +181,7 @@ SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const
return -1;
}
bool ElfReader::LoadSymbols() const
bool ElfReader::LoadSymbols(const Core::CPUThreadGuard& guard) const
{
bool hasSymbols = false;
SectionID sec = GetSectionByName(".symtab");
@@ -219,7 +219,7 @@ bool ElfReader::LoadSymbols() const
default:
continue;
}
g_symbolDB.AddKnownSymbol(value, size, name, symtype);
g_symbolDB.AddKnownSymbol(guard, value, size, name, symtype);
hasSymbols = true;
}
}
+1 -1
View File
@@ -36,7 +36,7 @@ public:
u32 GetEntryPoint() const override { return entryPoint; }
u32 GetFlags() const { return (u32)(header->e_flags); }
bool LoadIntoMemory(bool only_in_mem1 = false) const override;
bool LoadSymbols() const override;
bool LoadSymbols(const Core::CPUThreadGuard& guard) const override;
// TODO: actually check for validity.
bool IsValid() const override { return true; }
bool IsWii() const override;