diff --git a/Source/Core/Core/HW/Memmap.cpp b/Source/Core/Core/HW/Memmap.cpp index e6d8fd56a5..6065506caa 100644 --- a/Source/Core/Core/HW/Memmap.cpp +++ b/Source/Core/Core/HW/Memmap.cpp @@ -183,8 +183,10 @@ bool MemoryManager::InitFastmemArena() // the emulated system. This lets the JIT emulate PPC load/store instructions by translating a PPC // address to a host address as follows and then using a regular load/store instruction: // - // RMEM = ppcState.msr.DR ? m_logical_base : m_physical_base - // host_address = RMEM + u32(ppc_address_base + ppc_address_offset) + // logical_base = m_ppc_state.pagetable_update_pending ? + // m_logical_base_without_page_table : m_logical_base_with_page_table; + // RMEM = m_ppc_state.msr.DR ? m_logical_base : logical_base; + // host_address = RMEM + u32(ppc_address_base + ppc_address_offset); // // If the resulting host address is backed by real memory, the memory access will simply work. // If not, a segfault handler will backpatch the JIT code to instead call functions in MMU.cpp. @@ -199,19 +201,22 @@ bool MemoryManager::InitFastmemArena() // 4 GiB range by at most 2 GiB in either direction. So, make sure we have 2 GiB of guard pages // on each side of each 4 GiB range. // - // We need two 4 GiB ranges, one for PPC addresses with address translation disabled - // (m_physical_base) and one for PPC addresses with address translation enabled (m_logical_base), - // so our memory map ends up looking like this: + // We need three 4 GiB ranges, one for PPC addresses with address translation disabled + // (m_physical_base) and two for PPC addresses with address translation enabled + // (m_logical_base_without_page_table and m_logical_base_with_page_table), so our memory map ends + // up looking like this: // // 2 GiB guard // 4 GiB view for disabled address translation // 2 GiB guard - // 4 GiB view for enabled address translation + // 4 GiB view for enabled address translation without page table + // 2 GiB guard + // 4 GiB view for enabled address translation with page table // 2 GiB guard constexpr size_t ppc_view_size = 0x1'0000'0000; constexpr size_t guard_size = 0x8000'0000; - constexpr size_t memory_size = ppc_view_size * 2 + guard_size * 3; + constexpr size_t memory_size = ppc_view_size * 3 + guard_size * 4; m_fastmem_arena = m_arena.ReserveMemoryRegion(memory_size); if (!m_fastmem_arena) @@ -221,7 +226,8 @@ bool MemoryManager::InitFastmemArena() } m_physical_base = m_fastmem_arena + guard_size; - m_logical_base = m_fastmem_arena + ppc_view_size + guard_size * 2; + m_logical_base_without_page_table = m_fastmem_arena + ppc_view_size + guard_size * 2; + m_logical_base_with_page_table = m_fastmem_arena + ppc_view_size * 2 + guard_size * 3; for (const PhysicalMemoryRegion& region : m_physical_regions) { @@ -247,11 +253,17 @@ bool MemoryManager::InitFastmemArena() void MemoryManager::UpdateDBATMappings(const PowerPC::BatTable& dbat_table) { - for (const auto& [logical_address, entry] : m_dbat_mapped_entries) + for (const auto& [logical_address, entry] : m_dbat_mapped_entries_without_page_table) { m_arena.UnmapFromMemoryRegion(entry.mapped_pointer, entry.mapped_size); } - m_dbat_mapped_entries.clear(); + m_dbat_mapped_entries_without_page_table.clear(); + + for (const auto& [logical_address, entry] : m_dbat_mapped_entries_with_page_table) + { + m_arena.UnmapFromMemoryRegion(entry.mapped_pointer, entry.mapped_size); + } + m_dbat_mapped_entries_with_page_table.clear(); RemoveAllPageTableMappings(); @@ -298,18 +310,30 @@ void MemoryManager::UpdateDBATMappings(const PowerPC::BatTable& dbat_table) if (m_is_fastmem_arena_initialized) { u32 position = physical_region.shm_position + intersection_start - mapping_address; - u8* base = m_logical_base + mapped_logical_address; - void* mapped_pointer = m_arena.MapInMemoryRegion(position, mapped_size, base, true); - if (!mapped_pointer) + u8* base_1 = m_logical_base_without_page_table + mapped_logical_address; + void* mapped_pointer_1 = m_arena.MapInMemoryRegion(position, mapped_size, base_1, true); + if (!mapped_pointer_1) { PanicAlertFmt("Memory::UpdateDBATMappings(): Failed to map memory region at 0x{:08X} " - "(size 0x{:08X}) into logical fastmem region at 0x{:08X}.", + "(size 0x{:08X}) into logical fastmem region 1 at 0x{:08X}.", intersection_start, mapped_size, logical_address); continue; } - m_dbat_mapped_entries.emplace(logical_address, - LogicalMemoryView{mapped_pointer, mapped_size}); + m_dbat_mapped_entries_without_page_table.emplace( + logical_address, LogicalMemoryView{mapped_pointer_1, mapped_size}); + + u8* base_2 = m_logical_base_with_page_table + mapped_logical_address; + void* mapped_pointer_2 = m_arena.MapInMemoryRegion(position, mapped_size, base_2, true); + if (!mapped_pointer_2) + { + PanicAlertFmt("Memory::UpdateDBATMappings(): Failed to map memory region at 0x{:08X} " + "(size 0x{:08X}) into logical fastmem region 2 at 0x{:08X}.", + intersection_start, mapped_size, logical_address); + continue; + } + m_dbat_mapped_entries_with_page_table.emplace( + logical_address, LogicalMemoryView{mapped_pointer_2, mapped_size}); } u32 bat_index = mapped_logical_address / PowerPC::BAT_PAGE_SIZE; @@ -401,7 +425,8 @@ void MemoryManager::AddHostPageTableMapping(u32 logical_address, u32 translated_ // Found an overlapping region; map it. const u32 position = physical_region.shm_position + intersection_start - mapping_address; - u8* const base = m_logical_base + logical_address + intersection_start - translated_address; + u8* const base = + m_logical_base_with_page_table + logical_address + intersection_start - translated_address; const u32 mapped_size = intersection_end - intersection_start; const auto it = m_page_table_mapped_entries.find(logical_address); @@ -573,11 +598,17 @@ void MemoryManager::ShutdownFastmemArena() m_arena.UnmapFromMemoryRegion(base, region.size); } - for (const auto& [logical_address, entry] : m_dbat_mapped_entries) + for (const auto& [logical_address, entry] : m_dbat_mapped_entries_without_page_table) { m_arena.UnmapFromMemoryRegion(entry.mapped_pointer, entry.mapped_size); } - m_dbat_mapped_entries.clear(); + m_dbat_mapped_entries_without_page_table.clear(); + + for (const auto& [logical_address, entry] : m_dbat_mapped_entries_with_page_table) + { + m_arena.UnmapFromMemoryRegion(entry.mapped_pointer, entry.mapped_size); + } + m_dbat_mapped_entries_with_page_table.clear(); for (const auto& [logical_address, entry] : m_page_table_mapped_entries) { @@ -593,7 +624,8 @@ void MemoryManager::ShutdownFastmemArena() m_fastmem_arena = nullptr; m_fastmem_arena_size = 0; m_physical_base = nullptr; - m_logical_base = nullptr; + m_logical_base_without_page_table = nullptr; + m_logical_base_with_page_table = nullptr; m_is_fastmem_arena_initialized = false; } diff --git a/Source/Core/Core/HW/Memmap.h b/Source/Core/Core/HW/Memmap.h index baa910cc70..dda664d3c3 100644 --- a/Source/Core/Core/HW/Memmap.h +++ b/Source/Core/Core/HW/Memmap.h @@ -81,7 +81,8 @@ public: bool IsAddressInFastmemArea(const u8* address) const; u8* GetPhysicalBase() const { return m_physical_base; } - u8* GetLogicalBase() const { return m_logical_base; } + u8* GetLogicalBaseWithoutPageTable() const { return m_logical_base_without_page_table; } + u8* GetLogicalBaseWithPageTable() const { return m_logical_base_with_page_table; } u8* GetPhysicalPageMappingsBase() const { return m_physical_page_mappings_base; } u8* GetLogicalPageMappingsBase() const { return m_logical_page_mappings_base; } @@ -181,10 +182,11 @@ private: u8* m_fastmem_arena = nullptr; size_t m_fastmem_arena_size = 0; u8* m_physical_base = nullptr; - u8* m_logical_base = nullptr; + u8* m_logical_base_without_page_table = nullptr; + u8* m_logical_base_with_page_table = nullptr; - // This page table is used for a "soft MMU" implementation when - // setting up the full memory map in process memory isn't possible. + // This page table is used for a "soft MMU" implementation when setting up the full + // memory map in process memory isn't possible. Only BAT mappings are included. u8* m_physical_page_mappings_base = nullptr; u8* m_logical_page_mappings_base = nullptr; @@ -252,9 +254,13 @@ private: // [0x7E000000, 0x80000000) - FakeVMEM // [0xE0000000, 0xE0040000) - 256KB locked L1 // - // The 4GB starting at m_logical_base represents access from the CPU - // with address translation turned on. This mapping is computed based - // on the BAT registers. + // The 4GB starting at m_logical_base_without_page_table represents access + // from the CPU with address translation turned on. This mapping is computed + // based on the BAT registers. + // + // The 4GB starting at m_logical_base_with_page_table is the same as + // m_logical_base_without_page_table, except mappings are computed based on + // the page table in addition to the BAT registers. // // Each of these 4GB regions is surrounded by 2GB of empty space so overflows // in address computation in the JIT don't access unrelated memory. @@ -270,7 +276,8 @@ private: std::array m_physical_regions{}; // The key is the logical address - std::map m_dbat_mapped_entries; + std::map m_dbat_mapped_entries_without_page_table; + std::map m_dbat_mapped_entries_with_page_table; std::map m_page_table_mapped_entries; std::array m_physical_page_mappings{}; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 0b976eb1c8..a5d1dc29ae 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -145,16 +145,26 @@ bool Jit64::HandleFault(uintptr_t access_address, SContext* ctx) if (memory.IsAddressInFastmemArea(reinterpret_cast(access_address))) { - auto& ppc_state = m_system.GetPPCState(); const uintptr_t memory_base = reinterpret_cast( - ppc_state.msr.DR ? memory.GetLogicalBase() : memory.GetPhysicalBase()); + m_ppc_state.msr.DR ? + (m_ppc_state.pagetable_update_pending ? memory.GetLogicalBaseWithoutPageTable() : + memory.GetLogicalBaseWithPageTable()) : + memory.GetPhysicalBase()); if (access_address < memory_base || access_address >= memory_base + 0x1'0000'0000) { WARN_LOG_FMT(DYNA_REC, "Jit64 address calculation overflowed! Please report if this happens a lot. " "PC {:#018x}, access address {:#018x}, memory base {:#018x}, MSR.DR {}", - ctx->CTX_PC, access_address, memory_base, ppc_state.msr.DR); + ctx->CTX_PC, access_address, memory_base, m_ppc_state.msr.DR); + } + + if (m_ppc_state.msr.DR && m_ppc_state.pagetable_update_pending) + { + // Switch from logical base without page table to logical base with page table, + // then rerun the code that faulted. + m_system.GetMMU().PageTableUpdated(); + return true; } return BackPatch(ctx); @@ -373,7 +383,7 @@ void Jit64::FallBackToInterpreter(UGeckoInstruction inst) // We must also update constant propagation m_constant_propagation.ClearGPRs(js.op->regsOut); - if (js.op->opinfo->flags & FL_SET_MSR) + if (js.op->opinfo->flags & (FL_SET_MSR | FL_TLBIE)) EmitUpdateMembase(); if (js.op->canEndBlock) @@ -520,11 +530,12 @@ void Jit64::MSRUpdated(const OpArg& msr, X64Reg scratch_reg) if (msr.IsImm()) { MOV(64, R(RMEM), - ImmPtr(UReg_MSR(msr.Imm32()).DR ? memory.GetLogicalBase() : memory.GetPhysicalBase())); + ImmPtr(UReg_MSR(msr.Imm32()).DR ? memory.GetLogicalBaseWithPageTable() : + memory.GetPhysicalBase())); } else { - MOV(64, R(RMEM), ImmPtr(memory.GetLogicalBase())); + MOV(64, R(RMEM), ImmPtr(memory.GetLogicalBaseWithPageTable())); MOV(64, R(scratch_reg), ImmPtr(memory.GetPhysicalBase())); TEST(32, msr, Imm32(dr_bit)); CMOVcc(64, RMEM, R(scratch_reg), CC_Z); diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 5b61528fae..4e67389c7c 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -139,20 +139,33 @@ bool JitArm64::HandleFault(uintptr_t access_address, SContext* ctx) if (memory.IsAddressInFastmemArea(reinterpret_cast(access_address))) { const uintptr_t memory_base = reinterpret_cast( - m_ppc_state.msr.DR ? memory.GetLogicalBase() : memory.GetPhysicalBase()); + m_ppc_state.msr.DR ? + (m_ppc_state.pagetable_update_pending ? memory.GetLogicalBaseWithoutPageTable() : + memory.GetLogicalBaseWithPageTable()) : + memory.GetPhysicalBase()); if (access_address < memory_base || access_address >= memory_base + 0x1'0000'0000) { - ERROR_LOG_FMT(DYNA_REC, - "JitArm64 address calculation overflowed. This should never happen! " - "PC {:#018x}, access address {:#018x}, memory base {:#018x}, MSR.DR {}, " - "mem_ptr {}, pbase {}, lbase {}", - ctx->CTX_PC, access_address, memory_base, m_ppc_state.msr.DR, - fmt::ptr(m_ppc_state.mem_ptr), fmt::ptr(memory.GetPhysicalBase()), - fmt::ptr(memory.GetLogicalBase())); + ASSERT_MSG(DYNA_REC, false, + "JitArm64 address calculation overflowed!\n\n" + "PC {:#018x}, access address {:#018x}, memory base {:#018x}, MSR.DR {}, " + "pagetable update pending {}, mem_ptr {}, pbase {}, lbase1 {}, lbase2 {}", + ctx->CTX_PC, access_address, memory_base, m_ppc_state.msr.DR, + m_ppc_state.pagetable_update_pending, fmt::ptr(m_ppc_state.mem_ptr), + fmt::ptr(memory.GetPhysicalBase()), + fmt::ptr(memory.GetLogicalBaseWithoutPageTable()), + fmt::ptr(memory.GetLogicalBaseWithPageTable())); + } + else if (m_ppc_state.msr.DR && m_ppc_state.pagetable_update_pending) + { + // Switch from logical base without page table to logical base with page table, + // then rerun the code that faulted. + m_system.GetMMU().PageTableUpdated(); + success = true; } else { + // Backpatch the code that faulted. success = HandleFastmemFault(ctx); } } @@ -282,7 +295,7 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst) // We must also update constant propagation m_constant_propagation.ClearGPRs(js.op->regsOut); - if (js.op->opinfo->flags & FL_SET_MSR) + if (js.op->opinfo->flags & (FL_SET_MSR | FL_TLBIE)) EmitUpdateMembase(); if (js.op->canEndBlock) @@ -429,10 +442,10 @@ void JitArm64::MSRUpdated(u32 msr) { // Update mem_ptr auto& memory = m_system.GetMemory(); - MOVP2R(MEM_REG, - UReg_MSR(msr).DR ? - (jo.fastmem ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase()) : - (jo.fastmem ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase())); + MOVP2R(MEM_REG, UReg_MSR(msr).DR ? (jo.fastmem ? memory.GetLogicalBaseWithPageTable() : + memory.GetLogicalPageMappingsBase()) : + (jo.fastmem ? memory.GetPhysicalBase() : + memory.GetPhysicalPageMappingsBase())); STR(IndexType::Unsigned, MEM_REG, PPC_REG, PPCSTATE_OFF(mem_ptr)); // Update feature_flags @@ -476,7 +489,8 @@ void JitArm64::MSRUpdated(ARM64Reg msr) // Update mem_ptr auto& memory = m_system.GetMemory(); - MOVP2R(MEM_REG, jo.fastmem ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase()); + MOVP2R(MEM_REG, + jo.fastmem ? memory.GetLogicalBaseWithPageTable() : memory.GetLogicalPageMappingsBase()); MOVP2R(XA, jo.fastmem ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase()); TST(msr, LogicalImm(1ULL << UReg_MSR{}.DR.StartBit(), GPRSize::B32)); CSEL(MEM_REG, MEM_REG, XA, CCFlags::CC_NEQ); diff --git a/Source/Core/Core/PowerPC/JitInterface.cpp b/Source/Core/Core/PowerPC/JitInterface.cpp index f229be35f2..d72253a11f 100644 --- a/Source/Core/Core/PowerPC/JitInterface.cpp +++ b/Source/Core/Core/PowerPC/JitInterface.cpp @@ -102,8 +102,10 @@ void JitInterface::UpdateMembase() #endif if (ppc_state.msr.DR) { - ppc_state.mem_ptr = - fastmem_arena ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase(); + ppc_state.mem_ptr = fastmem_arena ? (ppc_state.pagetable_update_pending ? + memory.GetLogicalBaseWithoutPageTable() : + memory.GetLogicalBaseWithPageTable()) : + memory.GetLogicalPageMappingsBase(); } else { diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index 940e93c7ea..4bba6993aa 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -1375,10 +1375,8 @@ void MMU::InvalidateTLBEntry(u32 address) m_ppc_state.tlb[PowerPC::DATA_TLB_INDEX][entry_index].Invalidate(); m_ppc_state.tlb[PowerPC::INST_TLB_INDEX][entry_index].Invalidate(); - if (m_ppc_state.msr.DR) - PageTableUpdated(); - else - m_ppc_state.pagetable_update_pending = true; + m_ppc_state.pagetable_update_pending = true; + m_system.GetJitInterface().UpdateMembase(); } void MMU::ClearPageTable() diff --git a/Source/Core/Core/PowerPC/PPCTables.cpp b/Source/Core/Core/PowerPC/PPCTables.cpp index 5e17d459eb..c4db2dc2d6 100644 --- a/Source/Core/Core/PowerPC/PPCTables.cpp +++ b/Source/Core/Core/PowerPC/PPCTables.cpp @@ -385,7 +385,7 @@ constexpr std::array s_table31{{ {310, "eciwx", OpType::System, 1, FL_IN_A0B | FL_OUT_D | FL_LOADSTORE}, {438, "ecowx", OpType::System, 1, FL_IN_A0B | FL_IN_S | FL_LOADSTORE}, {854, "eieio", OpType::System, 1, 0}, - {306, "tlbie", OpType::System, 1, FL_IN_B | FL_PROGRAMEXCEPTION}, + {306, "tlbie", OpType::System, 1, FL_IN_B | FL_PROGRAMEXCEPTION | FL_TLBIE}, {566, "tlbsync", OpType::System, 1, FL_PROGRAMEXCEPTION}, }}; diff --git a/Source/Core/Core/PowerPC/PPCTables.h b/Source/Core/Core/PowerPC/PPCTables.h index 847eaf40c2..3834702204 100644 --- a/Source/Core/Core/PowerPC/PPCTables.h +++ b/Source/Core/Core/PowerPC/PPCTables.h @@ -68,6 +68,7 @@ enum InstructionFlags : u64 FL_SET_CRx = FL_SET_CR0 | FL_SET_CR1 | FL_SET_CRn | FL_SET_ALL_CR, FL_READ_CRx = FL_READ_CRn | FL_READ_CR_BI | FL_READ_ALL_CR, FL_SET_MSR = (1ull << 39), + FL_TLBIE = (1ull << 40), }; enum class OpType diff --git a/Source/UnitTests/Core/PowerPC/PageTableHostMappingTest.cpp b/Source/UnitTests/Core/PowerPC/PageTableHostMappingTest.cpp index 2cfb4b8c8f..2ed3bbfb02 100644 --- a/Source/UnitTests/Core/PowerPC/PageTableHostMappingTest.cpp +++ b/Source/UnitTests/Core/PowerPC/PageTableHostMappingTest.cpp @@ -64,7 +64,7 @@ public: { std::string logical_address; auto& memory = Core::System::GetInstance().GetMemory(); - auto logical_base = reinterpret_cast(memory.GetLogicalBase()); + auto logical_base = reinterpret_cast(memory.GetLogicalBaseWithPageTable()); if (access_address >= logical_base && access_address < logical_base + 0x1'0000'0000) logical_address = fmt::format(" (PPC {:#010x})", access_address - logical_base); @@ -80,7 +80,8 @@ public: // After we return from the signal handler, the memory access will happen again. // Let it succeed this time so the signal handler won't get called over and over. auto& memory = Core::System::GetInstance().GetMemory(); - const uintptr_t logical_base = reinterpret_cast(memory.GetLogicalBase()); + const uintptr_t logical_base = + reinterpret_cast(memory.GetLogicalBaseWithPageTable()); const u32 logical_address = static_cast(access_address - logical_base); const u32 mask = s_minimum_mapping_size - 1; for (u32 i = logical_address & mask; i < s_minimum_mapping_size; i += PowerPC::HW_PAGE_SIZE) @@ -102,27 +103,6 @@ private: StubBlockCache m_block_cache; }; -// This is used as a performance optimization. If several page table updates are performed while -// DR is disabled, MMU.cpp will only have to rescan the page table one time once DR is enabled again -// instead of after each page table update. -class DisableDR final -{ -public: - DisableDR() - { - auto& system = Core::System::GetInstance(); - system.GetPPCState().msr.DR = 0; - system.GetPowerPC().MSRUpdated(); - } - - ~DisableDR() - { - auto& system = Core::System::GetInstance(); - system.GetPPCState().msr.DR = 1; - system.GetPowerPC().MSRUpdated(); - } -}; - class PageTableHostMappingTest : public ::testing::Test { public: @@ -240,9 +220,13 @@ public: SCOPED_TRACE( fmt::format("ExpectMapped({:#010x}, {:#010x})", logical_address, physical_address)); - auto& memory = Core::System::GetInstance().GetMemory(); + auto& system = Core::System::GetInstance(); + if (system.GetPPCState().pagetable_update_pending) + system.GetMMU().PageTableUpdated(); + + auto& memory = system.GetMemory(); u8* physical_base = memory.GetPhysicalBase(); - u8* logical_base = memory.GetLogicalBase(); + u8* logical_base = memory.GetLogicalBaseWithPageTable(); auto* physical_ptr = reinterpret_cast(physical_base + physical_address); auto* logical_ptr = reinterpret_cast(logical_base + logical_address); @@ -267,9 +251,13 @@ public: SCOPED_TRACE( fmt::format("ExpectReadOnlyMapped({:#010x}, {:#010x})", logical_address, physical_address)); - auto& memory = Core::System::GetInstance().GetMemory(); + auto& system = Core::System::GetInstance(); + if (system.GetPPCState().pagetable_update_pending) + system.GetMMU().PageTableUpdated(); + + auto& memory = system.GetMemory(); u8* physical_base = memory.GetPhysicalBase(); - u8* logical_base = memory.GetLogicalBase(); + u8* logical_base = memory.GetLogicalBaseWithPageTable(); auto* physical_ptr = reinterpret_cast(physical_base + physical_address); auto* logical_ptr = reinterpret_cast(logical_base + logical_address); @@ -293,8 +281,12 @@ public: { SCOPED_TRACE(fmt::format("ExpectNotMapped({:#010x})", logical_address)); - auto& memory = Core::System::GetInstance().GetMemory(); - u8* logical_base = memory.GetLogicalBase(); + auto& system = Core::System::GetInstance(); + if (system.GetPPCState().pagetable_update_pending) + system.GetMMU().PageTableUpdated(); + + auto& memory = system.GetMemory(); + u8* logical_base = memory.GetLogicalBaseWithPageTable(); auto* logical_ptr = reinterpret_cast(logical_base + logical_address); s_detection_address = logical_ptr; @@ -382,7 +374,6 @@ public: static void AddHostSizedMapping(u32 logical_address, u32 physical_address, u32 index) { - DisableDR disable_dr; for (u32 i = 0; i < s_minimum_mapping_size; i += PowerPC::HW_PAGE_SIZE) AddMapping(logical_address + i, physical_address + i, index); } @@ -396,7 +387,6 @@ public: static void RemoveHostSizedMapping(u32 logical_address, u32 physical_address, u32 index) { - DisableDR disable_dr; for (u32 i = 0; i < s_minimum_mapping_size; i += PowerPC::HW_PAGE_SIZE) RemoveMapping(logical_address + i, physical_address + i, index); } @@ -438,23 +428,17 @@ TEST_F(PageTableHostMappingTest, Basic) TEST_F(PageTableHostMappingTest, LargeHostPageMismatchedAddresses) { - { - DisableDR disable_dr; - AddMapping(0x10110000, 0x00111000, 0); - for (u32 i = PowerPC::HW_PAGE_SIZE; i < s_minimum_mapping_size; i += PowerPC::HW_PAGE_SIZE) - AddMapping(0x10110000 + i, 0x00110000 + i, 0); - } + AddMapping(0x10110000, 0x00111000, 0); + for (u32 i = PowerPC::HW_PAGE_SIZE; i < s_minimum_mapping_size; i += PowerPC::HW_PAGE_SIZE) + AddMapping(0x10110000 + i, 0x00110000 + i, 0); ExpectMappedOnlyIf4KHostPages(0x10110000, 0x00111000); } TEST_F(PageTableHostMappingTest, LargeHostPageMisalignedAddresses) { - { - DisableDR disable_dr; - for (u32 i = 0; i < s_minimum_mapping_size * 2; i += PowerPC::HW_PAGE_SIZE) - AddMapping(0x10120000 + i, 0x00121000 + i, 0); - } + for (u32 i = 0; i < s_minimum_mapping_size * 2; i += PowerPC::HW_PAGE_SIZE) + AddMapping(0x10120000 + i, 0x00121000 + i, 0); ExpectMappedOnlyIf4KHostPages(0x10120000, 0x00121000); ExpectMappedOnlyIf4KHostPages(0x10120000 + s_minimum_mapping_size, @@ -463,14 +447,11 @@ TEST_F(PageTableHostMappingTest, LargeHostPageMisalignedAddresses) TEST_F(PageTableHostMappingTest, ChangeSR) { + for (u32 i = 0; i < s_minimum_mapping_size; i += PowerPC::HW_PAGE_SIZE) { - DisableDR disable_dr; - for (u32 i = 0; i < s_minimum_mapping_size; i += PowerPC::HW_PAGE_SIZE) - { - auto [pte1, pte2] = CreateMapping(0x20130000 + i, 0x00130000 + i); - pte1.VSID = 0xabc; - SetPTE(pte1, pte2, 0x20130000 + i, 0); - } + auto [pte1, pte2] = CreateMapping(0x20130000 + i, 0x00130000 + i); + pte1.VSID = 0xabc; + SetPTE(pte1, pte2, 0x20130000 + i, 0); } ExpectNotMapped(0x20130000); @@ -635,14 +616,11 @@ TEST_F(PageTableHostMappingTest, WIMG) { for (u32 i = 0; i < 16; ++i) { + for (u32 j = 0; j < s_minimum_mapping_size; j += PowerPC::HW_PAGE_SIZE) { - DisableDR disable_dr; - for (u32 j = 0; j < s_minimum_mapping_size; j += PowerPC::HW_PAGE_SIZE) - { - auto [pte1, pte2] = CreateMapping(0x101e0000 + j, 0x001e0000 + j); - pte2.WIMG = i; - SetPTE(pte1, pte2, 0x101e0000 + j, 0); - } + auto [pte1, pte2] = CreateMapping(0x101e0000 + j, 0x001e0000 + j); + pte2.WIMG = i; + SetPTE(pte1, pte2, 0x101e0000 + j, 0); } if ((i & 0b1100) != 0) @@ -657,7 +635,6 @@ TEST_F(PageTableHostMappingTest, RC) auto& mmu = Core::System::GetInstance().GetMMU(); const auto set_up_mapping = [] { - DisableDR disable_dr; for (u32 i = 0; i < s_minimum_mapping_size; i += PowerPC::HW_PAGE_SIZE) { auto [pte1, pte2] = CreateMapping(0x101f0000 + i, 0x001f0000 + i);