core: arm: Implement InvalidateCacheRange for CPU cache invalidation.

This commit is contained in:
bunnei 2020-11-13 23:20:32 -08:00
parent c0870315fd
commit 63fd1bb503
12 changed files with 56 additions and 16 deletions

View File

@ -70,12 +70,19 @@ public:
/// Clear all instruction cache /// Clear all instruction cache
virtual void ClearInstructionCache() = 0; virtual void ClearInstructionCache() = 0;
/// Notifies CPU emulation that the current page table has changed. /**
/// * Clear instruction cache range
/// @param new_page_table The new page table. * @param addr Start address of the cache range to clear
/// @param new_address_space_size_in_bits The new usable size of the address space in bits. * @param size Size of the cache range to clear, starting at addr
/// This can be either 32, 36, or 39 on official software. */
/// virtual void InvalidateCacheRange(VAddr addr, std::size_t size) = 0;
/**
* Notifies CPU emulation that the current page table has changed.
* @param new_page_table The new page table.
* @param new_address_space_size_in_bits The new usable size of the address space in bits.
* This can be either 32, 36, or 39 on official software.
*/
virtual void PageTableChanged(Common::PageTable& new_page_table, virtual void PageTableChanged(Common::PageTable& new_page_table,
std::size_t new_address_space_size_in_bits) = 0; std::size_t new_address_space_size_in_bits) = 0;

View File

@ -286,6 +286,13 @@ void ARM_Dynarmic_32::ClearInstructionCache() {
jit->ClearCache(); jit->ClearCache();
} }
void ARM_Dynarmic_32::InvalidateCacheRange(VAddr addr, std::size_t size) {
if (!jit) {
return;
}
jit->InvalidateCacheRange(static_cast<u32>(addr), size);
}
void ARM_Dynarmic_32::ClearExclusiveState() { void ARM_Dynarmic_32::ClearExclusiveState() {
jit->ClearExclusiveState(); jit->ClearExclusiveState();
} }

View File

@ -59,6 +59,7 @@ public:
void ClearExclusiveState() override; void ClearExclusiveState() override;
void ClearInstructionCache() override; void ClearInstructionCache() override;
void InvalidateCacheRange(VAddr addr, std::size_t size) override;
void PageTableChanged(Common::PageTable& new_page_table, void PageTableChanged(Common::PageTable& new_page_table,
std::size_t new_address_space_size_in_bits) override; std::size_t new_address_space_size_in_bits) override;

View File

@ -322,6 +322,13 @@ void ARM_Dynarmic_64::ClearInstructionCache() {
jit->ClearCache(); jit->ClearCache();
} }
void ARM_Dynarmic_64::InvalidateCacheRange(VAddr addr, std::size_t size) {
if (!jit) {
return;
}
jit->InvalidateCacheRange(addr, size);
}
void ARM_Dynarmic_64::ClearExclusiveState() { void ARM_Dynarmic_64::ClearExclusiveState() {
jit->ClearExclusiveState(); jit->ClearExclusiveState();
} }

View File

@ -56,6 +56,7 @@ public:
void ClearExclusiveState() override; void ClearExclusiveState() override;
void ClearInstructionCache() override; void ClearInstructionCache() override;
void InvalidateCacheRange(VAddr addr, std::size_t size) override;
void PageTableChanged(Common::PageTable& new_page_table, void PageTableChanged(Common::PageTable& new_page_table,
std::size_t new_address_space_size_in_bits) override; std::size_t new_address_space_size_in_bits) override;

View File

@ -457,6 +457,10 @@ void System::InvalidateCpuInstructionCaches() {
impl->kernel.InvalidateAllInstructionCaches(); impl->kernel.InvalidateAllInstructionCaches();
} }
void System::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
impl->kernel.InvalidateCpuInstructionCacheRange(addr, size);
}
void System::Shutdown() { void System::Shutdown() {
impl->Shutdown(); impl->Shutdown();
} }

View File

@ -166,6 +166,8 @@ public:
*/ */
void InvalidateCpuInstructionCaches(); void InvalidateCpuInstructionCaches();
void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
/// Shutdown the emulated system. /// Shutdown the emulated system.
void Shutdown(); void Shutdown();

View File

@ -497,12 +497,17 @@ const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const {
} }
void KernelCore::InvalidateAllInstructionCaches() { void KernelCore::InvalidateAllInstructionCaches() {
if (!IsMulticore()) {
for (auto& physical_core : impl->cores) { for (auto& physical_core : impl->cores) {
physical_core.ArmInterface().ClearInstructionCache(); physical_core.ArmInterface().ClearInstructionCache();
} }
} else { }
UNIMPLEMENTED();
void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
for (auto& physical_core : impl->cores) {
if (!physical_core.IsInitialized()) {
continue;
}
physical_core.ArmInterface().InvalidateCacheRange(addr, size);
} }
} }

View File

@ -156,6 +156,8 @@ public:
void InvalidateAllInstructionCaches(); void InvalidateAllInstructionCaches();
void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
/// Adds a port to the named port table /// Adds a port to the named port table
void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port); void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port);

View File

@ -670,6 +670,11 @@ ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, Memo
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
if ((prev_perm & MemoryPermission::Execute) != (perm & MemoryPermission::Execute)) {
// Memory execution state is changing, invalidate CPU cache range
system.InvalidateCpuInstructionCacheRange(addr, size);
}
const std::size_t num_pages{size / PageSize}; const std::size_t num_pages{size / PageSize};
const OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None const OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None
? OperationType::ChangePermissionsAndRefresh ? OperationType::ChangePermissionsAndRefresh

View File

@ -58,6 +58,10 @@ public:
// Shutdown this physical core. // Shutdown this physical core.
void Shutdown(); void Shutdown();
bool IsInitialized() const {
return arm_interface != nullptr;
}
Core::ARM_Interface& ArmInterface() { Core::ARM_Interface& ArmInterface() {
return *arm_interface; return *arm_interface;
} }

View File

@ -527,9 +527,6 @@ public:
header.segment_headers[RO_INDEX].memory_size, header.segment_headers[RO_INDEX].memory_size,
header.segment_headers[DATA_INDEX].memory_size, nro_address}); header.segment_headers[DATA_INDEX].memory_size, nro_address});
// Invalidate JIT caches for the newly mapped process code
system.InvalidateCpuInstructionCaches();
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push(*map_result); rb.Push(*map_result);
@ -590,8 +587,6 @@ public:
const auto result{UnmapNro(iter->second)}; const auto result{UnmapNro(iter->second)};
system.InvalidateCpuInstructionCaches();
nro.erase(iter); nro.erase(iter);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};