diff options
| author | Mai <mathew1800@gmail.com> | 2022-12-11 21:09:31 +0000 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-11 21:09:31 +0000 | 
| commit | d5684dbe7d7a562a79e267350ef9a45f23dfb817 (patch) | |
| tree | b0d46890c04d8eada6e95f7a25a79f89ff8f6beb | |
| parent | 623429a27ec943f3c1ba758aaf741589b0493ddb (diff) | |
| parent | ed3719244111af380fbba9e13286192c00708dea (diff) | |
Merge pull request #9415 from liamwhite/dc
memory: correct semantics of data cache management operations
| -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      bit_util.h      cityhash.cpp      cityhash.h -    cache_management.cpp -    cache_management.h      common_funcs.h      common_precompiled_headers.h      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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <cstdint> -#include <cstring> - -#include "common/cache_management.h" - -namespace Common { - -#if defined(ARCHITECTURE_x86_64) - -// Most cache operations are no-ops on x86 - -void DataCacheLineCleanByVAToPoU(void* start, size_t size) {} -void DataCacheLineCleanAndInvalidateByVAToPoC(void* start, size_t size) {} -void DataCacheLineCleanByVAToPoC(void* start, size_t size) {} -void DataCacheZeroByVA(void* start, size_t size) { -    std::memset(start, 0, size); -} - -#elif defined(ARCHITECTURE_arm64) - -// BS/DminLine is log2(cache size in words), we want size in bytes -#define EXTRACT_DMINLINE(ctr_el0) (1 << ((((ctr_el0) >> 16) & 0xf) + 2)) -#define EXTRACT_BS(dczid_el0) (1 << (((dczid_el0)&0xf) + 2)) - -#define DEFINE_DC_OP(op_name, function_name)                                                       \ -    void function_name(void* start, size_t size) {                                                 \ -        size_t ctr_el0;                                                                            \ -        asm volatile("mrs %[ctr_el0], ctr_el0\n\t" : [ctr_el0] "=r"(ctr_el0));                     \ -        size_t cacheline_size = EXTRACT_DMINLINE(ctr_el0);                                         \ -        uintptr_t va_start = reinterpret_cast<uintptr_t>(start);                                   \ -        uintptr_t va_end = va_start + size;                                                        \ -        for (uintptr_t va = va_start; va < va_end; va += cacheline_size) {                         \ -            asm volatile("dc " #op_name ", %[va]\n\t" : : [va] "r"(va) : "memory");                \ -        }                                                                                          \ -    } - -#define DEFINE_DC_OP_DCZID(op_name, function_name)                                                 \ -    void function_name(void* start, size_t size) {                                                 \ -        size_t dczid_el0;                                                                          \ -        asm volatile("mrs %[dczid_el0], dczid_el0\n\t" : [dczid_el0] "=r"(dczid_el0));             \ -        size_t cacheline_size = EXTRACT_BS(dczid_el0);                                             \ -        uintptr_t va_start = reinterpret_cast<uintptr_t>(start);                                   \ -        uintptr_t va_end = va_start + size;                                                        \ -        for (uintptr_t va = va_start; va < va_end; va += cacheline_size) {                         \ -            asm volatile("dc " #op_name ", %[va]\n\t" : : [va] "r"(va) : "memory");                \ -        }                                                                                          \ -    } - -DEFINE_DC_OP(cvau, DataCacheLineCleanByVAToPoU); -DEFINE_DC_OP(civac, DataCacheLineCleanAndInvalidateByVAToPoC); -DEFINE_DC_OP(cvac, DataCacheLineCleanByVAToPoC); -DEFINE_DC_OP_DCZID(zva, DataCacheZeroByVA); - -#endif - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <cstddef> - -namespace Common { - -// Data cache instructions enabled at EL0 by SCTLR_EL1.UCI. -// VA = virtual address -// PoC = point of coherency -// PoU = point of unification - -// dc cvau -void DataCacheLineCleanByVAToPoU(void* start, size_t size); - -// dc civac -void DataCacheLineCleanAndInvalidateByVAToPoC(void* start, size_t size); - -// dc cvac -void DataCacheLineCleanByVAToPoC(void* start, size_t size); - -// dc zva -void DataCacheZeroByVA(void* start, size_t size); - -} // 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 @@  #include "common/assert.h"  #include "common/atomic_ops.h" -#include "common/cache_management.h"  #include "common/common_types.h"  #include "common/logging/log.h"  #include "common/page_table.h" @@ -340,10 +339,9 @@ struct Memory::Impl {                      LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}", current_vaddr);                      throw InvalidMemoryException();                  }, -                [&](const std::size_t block_size, u8* const host_ptr) { cb(block_size, host_ptr); }, +                [&](const std::size_t block_size, u8* const host_ptr) {},                  [&](const VAddr current_vaddr, const std::size_t block_size, u8* const host_ptr) { -                    system.GPU().FlushRegion(current_vaddr, block_size); -                    cb(block_size, host_ptr); +                    cb(current_vaddr, block_size);                  },                  [](const std::size_t block_size) {});          } catch (InvalidMemoryException&) { @@ -354,27 +352,30 @@ struct Memory::Impl {      }      Result InvalidateDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { -        auto perform = [&](const std::size_t block_size, u8* const host_ptr) { -            // Do nothing; this operation (dc ivac) cannot be supported -            // from EL0 +        auto on_rasterizer = [&](const VAddr current_vaddr, const std::size_t block_size) { +            // dc ivac: Invalidate to point of coherency +            // GPU flush -> CPU invalidate +            system.GPU().FlushRegion(current_vaddr, block_size);          }; -        return PerformCacheOperation(process, dest_addr, size, perform); +        return PerformCacheOperation(process, dest_addr, size, on_rasterizer);      }      Result StoreDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { -        auto perform = [&](const std::size_t block_size, u8* const host_ptr) { +        auto on_rasterizer = [&](const VAddr current_vaddr, const std::size_t block_size) {              // dc cvac: Store to point of coherency -            Common::DataCacheLineCleanByVAToPoC(host_ptr, block_size); +            // CPU flush -> GPU invalidate +            system.GPU().InvalidateRegion(current_vaddr, block_size);          }; -        return PerformCacheOperation(process, dest_addr, size, perform); +        return PerformCacheOperation(process, dest_addr, size, on_rasterizer);      }      Result FlushDataCache(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { -        auto perform = [&](const std::size_t block_size, u8* const host_ptr) { +        auto on_rasterizer = [&](const VAddr current_vaddr, const std::size_t block_size) {              // dc civac: Store to point of coherency, and invalidate from cache -            Common::DataCacheLineCleanAndInvalidateByVAToPoC(host_ptr, block_size); +            // CPU flush -> GPU invalidate +            system.GPU().InvalidateRegion(current_vaddr, block_size);          }; -        return PerformCacheOperation(process, dest_addr, size, perform); +        return PerformCacheOperation(process, dest_addr, size, on_rasterizer);      }      void MarkRegionDebug(VAddr vaddr, u64 size, bool debug) { | 
