diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/common/cache_management.cpp | 59 | ||||
| -rw-r--r-- | src/common/cache_management.h | 27 | ||||
| -rw-r--r-- | src/core/memory.cpp | 29 |
4 files changed, 15 insertions, 102 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 6bdffcb7a..25b22a281 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -34,8 +34,6 @@ add_library(common STATIC | |||
| 34 | bit_util.h | 34 | bit_util.h |
| 35 | cityhash.cpp | 35 | cityhash.cpp |
| 36 | cityhash.h | 36 | cityhash.h |
| 37 | cache_management.cpp | ||
| 38 | cache_management.h | ||
| 39 | common_funcs.h | 37 | common_funcs.h |
| 40 | common_precompiled_headers.h | 38 | common_precompiled_headers.h |
| 41 | common_types.h | 39 | common_types.h |
diff --git a/src/common/cache_management.cpp b/src/common/cache_management.cpp deleted file mode 100644 index ed353828a..000000000 --- a/src/common/cache_management.cpp +++ /dev/null | |||
| @@ -1,59 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <cstdint> | ||
| 5 | #include <cstring> | ||
| 6 | |||
| 7 | #include "common/cache_management.h" | ||
| 8 | |||
| 9 | namespace Common { | ||
| 10 | |||
| 11 | #if defined(ARCHITECTURE_x86_64) | ||
| 12 | |||
| 13 | // Most cache operations are no-ops on x86 | ||
| 14 | |||
| 15 | void DataCacheLineCleanByVAToPoU(void* start, size_t size) {} | ||
| 16 | void DataCacheLineCleanAndInvalidateByVAToPoC(void* start, size_t size) {} | ||
| 17 | void DataCacheLineCleanByVAToPoC(void* start, size_t size) {} | ||
| 18 | void DataCacheZeroByVA(void* start, size_t size) { | ||
| 19 | std::memset(start, 0, size); | ||
| 20 | } | ||
| 21 | |||
| 22 | #elif defined(ARCHITECTURE_arm64) | ||
| 23 | |||
| 24 | // BS/DminLine is log2(cache size in words), we want size in bytes | ||
| 25 | #define EXTRACT_DMINLINE(ctr_el0) (1 << ((((ctr_el0) >> 16) & 0xf) + 2)) | ||
| 26 | #define EXTRACT_BS(dczid_el0) (1 << (((dczid_el0)&0xf) + 2)) | ||
| 27 | |||
| 28 | #define DEFINE_DC_OP(op_name, function_name) \ | ||
| 29 | void function_name(void* start, size_t size) { \ | ||
| 30 | size_t ctr_el0; \ | ||
| 31 | asm volatile("mrs %[ctr_el0], ctr_el0\n\t" : [ctr_el0] "=r"(ctr_el0)); \ | ||
| 32 | size_t cacheline_size = EXTRACT_DMINLINE(ctr_el0); \ | ||
| 33 | uintptr_t va_start = reinterpret_cast<uintptr_t>(start); \ | ||
| 34 | uintptr_t va_end = va_start + size; \ | ||
| 35 | for (uintptr_t va = va_start; va < va_end; va += cacheline_size) { \ | ||
| 36 | asm volatile("dc " #op_name ", %[va]\n\t" : : [va] "r"(va) : "memory"); \ | ||
| 37 | } \ | ||
| 38 | } | ||
| 39 | |||
| 40 | #define DEFINE_DC_OP_DCZID(op_name, function_name) \ | ||
| 41 | void function_name(void* start, size_t size) { \ | ||
| 42 | size_t dczid_el0; \ | ||
| 43 | asm volatile("mrs %[dczid_el0], dczid_el0\n\t" : [dczid_el0] "=r"(dczid_el0)); \ | ||
| 44 | size_t cacheline_size = EXTRACT_BS(dczid_el0); \ | ||
| 45 | uintptr_t va_start = reinterpret_cast<uintptr_t>(start); \ | ||
| 46 | uintptr_t va_end = va_start + size; \ | ||
| 47 | for (uintptr_t va = va_start; va < va_end; va += cacheline_size) { \ | ||
| 48 | asm volatile("dc " #op_name ", %[va]\n\t" : : [va] "r"(va) : "memory"); \ | ||
| 49 | } \ | ||
| 50 | } | ||
| 51 | |||
| 52 | DEFINE_DC_OP(cvau, DataCacheLineCleanByVAToPoU); | ||
| 53 | DEFINE_DC_OP(civac, DataCacheLineCleanAndInvalidateByVAToPoC); | ||
| 54 | DEFINE_DC_OP(cvac, DataCacheLineCleanByVAToPoC); | ||
| 55 | DEFINE_DC_OP_DCZID(zva, DataCacheZeroByVA); | ||
| 56 | |||
| 57 | #endif | ||
| 58 | |||
| 59 | } // namespace Common | ||
diff --git a/src/common/cache_management.h b/src/common/cache_management.h deleted file mode 100644 index 038323e95..000000000 --- a/src/common/cache_management.h +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <cstddef> | ||
| 7 | |||
| 8 | namespace Common { | ||
| 9 | |||
| 10 | // Data cache instructions enabled at EL0 by SCTLR_EL1.UCI. | ||
| 11 | // VA = virtual address | ||
| 12 | // PoC = point of coherency | ||
| 13 | // PoU = point of unification | ||
| 14 | |||
| 15 | // dc cvau | ||
| 16 | void DataCacheLineCleanByVAToPoU(void* start, size_t size); | ||
| 17 | |||
| 18 | // dc civac | ||
| 19 | void DataCacheLineCleanAndInvalidateByVAToPoC(void* start, size_t size); | ||
| 20 | |||
| 21 | // dc cvac | ||
| 22 | void DataCacheLineCleanByVAToPoC(void* start, size_t size); | ||
| 23 | |||
| 24 | // dc zva | ||
| 25 | void DataCacheZeroByVA(void* start, size_t size); | ||
| 26 | |||
| 27 | } // namespace Common | ||
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index b3f50223b..26be74df4 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/atomic_ops.h" | 8 | #include "common/atomic_ops.h" |
| 9 | #include "common/cache_management.h" | ||
| 10 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 11 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 12 | #include "common/page_table.h" | 11 | #include "common/page_table.h" |
| @@ -340,10 +339,9 @@ struct Memory::Impl { | |||
| 340 | LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}", current_vaddr); | 339 | LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}", current_vaddr); |
| 341 | throw InvalidMemoryException(); | 340 | throw InvalidMemoryException(); |
| 342 | }, | 341 | }, |
| 343 | [&](const std::size_t block_size, u8* const host_ptr) { cb(block_size, host_ptr); }, | 342 | [&](const std::size_t block_size, u8* const host_ptr) {}, |
| 344 | [&](const VAddr current_vaddr, const std::size_t block_size, u8* const host_ptr) { | 343 | [&](const VAddr current_vaddr, const std::size_t block_size, u8* const host_ptr) { |
| 345 | system.GPU().FlushRegion(current_vaddr, block_size); | 344 | cb(current_vaddr, block_size); |
| 346 | cb(block_size, host_ptr); | ||
| 347 | }, | 345 | }, |
| 348 | [](const std::size_t block_size) {}); | 346 | [](const std::size_t block_size) {}); |
| 349 | } catch (InvalidMemoryException&) { | 347 | } catch (InvalidMemoryException&) { |
| @@ -354,27 +352,30 @@ struct Memory::Impl { | |||
| 354 | } | 352 | } |
| 355 | 353 | ||
| 356 | Result InvalidateDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { | 354 | Result InvalidateDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { |
| 357 | auto perform = [&](const std::size_t block_size, u8* const host_ptr) { | 355 | auto on_rasterizer = [&](const VAddr current_vaddr, const std::size_t block_size) { |
| 358 | // Do nothing; this operation (dc ivac) cannot be supported | 356 | // dc ivac: Invalidate to point of coherency |
| 359 | // from EL0 | 357 | // GPU flush -> CPU invalidate |
| 358 | system.GPU().FlushRegion(current_vaddr, block_size); | ||
| 360 | }; | 359 | }; |
| 361 | return PerformCacheOperation(process, dest_addr, size, perform); | 360 | return PerformCacheOperation(process, dest_addr, size, on_rasterizer); |
| 362 | } | 361 | } |
| 363 | 362 | ||
| 364 | Result StoreDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { | 363 | Result StoreDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { |
| 365 | auto perform = [&](const std::size_t block_size, u8* const host_ptr) { | 364 | auto on_rasterizer = [&](const VAddr current_vaddr, const std::size_t block_size) { |
| 366 | // dc cvac: Store to point of coherency | 365 | // dc cvac: Store to point of coherency |
| 367 | Common::DataCacheLineCleanByVAToPoC(host_ptr, block_size); | 366 | // CPU flush -> GPU invalidate |
| 367 | system.GPU().InvalidateRegion(current_vaddr, block_size); | ||
| 368 | }; | 368 | }; |
| 369 | return PerformCacheOperation(process, dest_addr, size, perform); | 369 | return PerformCacheOperation(process, dest_addr, size, on_rasterizer); |
| 370 | } | 370 | } |
| 371 | 371 | ||
| 372 | Result FlushDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { | 372 | Result FlushDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { |
| 373 | auto perform = [&](const std::size_t block_size, u8* const host_ptr) { | 373 | auto on_rasterizer = [&](const VAddr current_vaddr, const std::size_t block_size) { |
| 374 | // dc civac: Store to point of coherency, and invalidate from cache | 374 | // dc civac: Store to point of coherency, and invalidate from cache |
| 375 | Common::DataCacheLineCleanAndInvalidateByVAToPoC(host_ptr, block_size); | 375 | // CPU flush -> GPU invalidate |
| 376 | system.GPU().InvalidateRegion(current_vaddr, block_size); | ||
| 376 | }; | 377 | }; |
| 377 | return PerformCacheOperation(process, dest_addr, size, perform); | 378 | return PerformCacheOperation(process, dest_addr, size, on_rasterizer); |
| 378 | } | 379 | } |
| 379 | 380 | ||
| 380 | void MarkRegionDebug(VAddr vaddr, u64 size, bool debug) { | 381 | void MarkRegionDebug(VAddr vaddr, u64 size, bool debug) { |