core: arm: Implement InvalidateCacheRange for CPU cache invalidation.
This commit is contained in:
parent
c0870315fd
commit
63fd1bb503
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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};
|
||||||
|
|
Reference in New Issue