From 11e9dcfe11dce005aae607bc36fa833af16945a5 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sun, 10 Oct 2021 00:33:52 -0700 Subject: [PATCH] os: add FlushDataCache --- .../ncm/ncm_content_manager_impl.hpp | 2 +- libstratosphere/include/stratosphere/os.hpp | 1 + .../include/stratosphere/os/os_cache.hpp | 24 +++++++++ .../source/os/impl/os_cache_impl.hpp | 23 ++++++++ .../os/impl/os_cache_impl.os.horizon.hpp | 54 +++++++++++++++++++ libstratosphere/source/os/os_cache.cpp | 29 ++++++++++ 6 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 libstratosphere/include/stratosphere/os/os_cache.hpp create mode 100644 libstratosphere/source/os/impl/os_cache_impl.hpp create mode 100644 libstratosphere/source/os/impl/os_cache_impl.os.horizon.hpp create mode 100644 libstratosphere/source/os/os_cache.cpp diff --git a/libstratosphere/include/stratosphere/ncm/ncm_content_manager_impl.hpp b/libstratosphere/include/stratosphere/ncm/ncm_content_manager_impl.hpp index ed5f69e1..01026705 100644 --- a/libstratosphere/include/stratosphere/ncm/ncm_content_manager_impl.hpp +++ b/libstratosphere/include/stratosphere/ncm/ncm_content_manager_impl.hpp @@ -37,7 +37,7 @@ namespace ams::ncm { size_t m_peak_total_alloc_size; size_t m_peak_alloc_size; public: - explicit ContentMetaMemoryResource(void *heap, size_t heap_size) : m_allocator(heap, heap_size), m_peak_alloc_size(0), m_peak_total_alloc_size(0) { /* ... */ } + explicit ContentMetaMemoryResource(void *heap, size_t heap_size) : m_allocator(heap, heap_size), m_peak_total_alloc_size(0), m_peak_alloc_size(0) { /* ... */ } mem::StandardAllocator *GetAllocator() { return std::addressof(m_allocator); } size_t GetPeakTotalAllocationSize() const { return m_peak_total_alloc_size; } diff --git a/libstratosphere/include/stratosphere/os.hpp b/libstratosphere/include/stratosphere/os.hpp index c1e05ba4..42ab77ea 100644 --- a/libstratosphere/include/stratosphere/os.hpp +++ b/libstratosphere/include/stratosphere/os.hpp @@ -53,3 +53,4 @@ #include #include #include +#include diff --git a/libstratosphere/include/stratosphere/os/os_cache.hpp b/libstratosphere/include/stratosphere/os/os_cache.hpp new file mode 100644 index 00000000..67e4b046 --- /dev/null +++ b/libstratosphere/include/stratosphere/os/os_cache.hpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::os { + + void FlushDataCache(const void *addr, size_t size); + void FlushEntireDataCache(); + +} diff --git a/libstratosphere/source/os/impl/os_cache_impl.hpp b/libstratosphere/source/os/impl/os_cache_impl.hpp new file mode 100644 index 00000000..7b2830a3 --- /dev/null +++ b/libstratosphere/source/os/impl/os_cache_impl.hpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +#ifdef ATMOSPHERE_OS_HORIZON + #include "os_cache_impl.os.horizon.hpp" +#else + #error "Unknown OS for ThreadManagerImpl" +#endif diff --git a/libstratosphere/source/os/impl/os_cache_impl.os.horizon.hpp b/libstratosphere/source/os/impl/os_cache_impl.os.horizon.hpp new file mode 100644 index 00000000..46562b20 --- /dev/null +++ b/libstratosphere/source/os/impl/os_cache_impl.os.horizon.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::os::impl { + + inline void FlushDataCacheImpl(const void *addr, size_t size) { + #if defined(ATMOSPHERE_ARCH_ARM64) + { + /* Declare helper variables. */ + uintptr_t cache_type_register = 0; + uintptr_t cache_line_size = 0; + const uintptr_t end_addr = reinterpret_cast(addr) + size; + + /* Get the cache type register. */ + __asm__ __volatile__("mrs %[cache_type_register], ctr_el0" : [cache_type_register]"=r"(cache_type_register)); + + /* Calculate cache line size. */ + cache_line_size = 4 << ((cache_type_register >> 16) & 0xF); + + /* Iterate, flushing cache lines. */ + for (uintptr_t cur = reinterpret_cast(addr) & ~(cache_line_size - 1); cur < end_addr; cur += cache_line_size) { + __asm__ __volatile__ ("dc civac, %[cur]" :: [cur]"r"(cur)); + } + + /* Insert a memory barrier, now that memory has been flushed. */ + __asm__ __volatile__("dsb sy" ::: "memory"); + } + #else + const auto result = svc::FlushProcessDataCache(svc::PseudoHandle::CurrentProcess, reinterpret_cast(addr), size); + R_ASSERT(result); + AMS_UNUSED(result); + #endif + } + + inline void FlushEntireDataCacheImpl() { + svc::FlushEntireDataCache(); + } + +} \ No newline at end of file diff --git a/libstratosphere/source/os/os_cache.cpp b/libstratosphere/source/os/os_cache.cpp new file mode 100644 index 00000000..65a27c22 --- /dev/null +++ b/libstratosphere/source/os/os_cache.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "impl/os_cache_impl.hpp" + +namespace ams::os { + + void FlushDataCache(const void *addr, size_t size) { + return impl::FlushDataCacheImpl(addr, size); + } + + void FlushEntireDataCache() { + return impl::FlushEntireDataCacheImpl(); + } + +}