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
virtual void ClearInstructionCache() = 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.
///
/**
* Clear instruction cache range
* @param addr Start address of the cache range to clear
* @param size Size of the cache range to clear, starting at addr
*/
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,
std::size_t new_address_space_size_in_bits) = 0;

View File

@ -286,6 +286,13 @@ void ARM_Dynarmic_32::ClearInstructionCache() {
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() {
jit->ClearExclusiveState();
}

View File

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

View File

@ -322,6 +322,13 @@ void ARM_Dynarmic_64::ClearInstructionCache() {
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() {
jit->ClearExclusiveState();
}

View File

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

View File

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

View File

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

View File

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

View File

@ -156,6 +156,8 @@ public:
void InvalidateAllInstructionCaches();
void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
/// Adds a port to the named port table
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;
}
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 OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None
? OperationType::ChangePermissionsAndRefresh

View File

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

View File

@ -527,9 +527,6 @@ public:
header.segment_headers[RO_INDEX].memory_size,
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};
rb.Push(RESULT_SUCCESS);
rb.Push(*map_result);
@ -590,8 +587,6 @@ public:
const auto result{UnmapNro(iter->second)};
system.InvalidateCpuInstructionCaches();
nro.erase(iter);
IPC::ResponseBuilder rb{ctx, 2};