os: add FlushDataCache

This commit is contained in:
Michael Scire 2021-10-10 00:33:52 -07:00
parent a595c232b9
commit bc96ebb74c
7 changed files with 150 additions and 19 deletions

View file

@ -37,7 +37,7 @@ namespace ams::ncm {
size_t m_peak_total_alloc_size; size_t m_peak_total_alloc_size;
size_t m_peak_alloc_size; size_t m_peak_alloc_size;
public: 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); } mem::StandardAllocator *GetAllocator() { return std::addressof(m_allocator); }
size_t GetPeakTotalAllocationSize() const { return m_peak_total_alloc_size; } size_t GetPeakTotalAllocationSize() const { return m_peak_total_alloc_size; }

View file

@ -53,3 +53,4 @@
#include <stratosphere/os/os_io_region.hpp> #include <stratosphere/os/os_io_region.hpp>
#include <stratosphere/os/os_multiple_wait.hpp> #include <stratosphere/os/os_multiple_wait.hpp>
#include <stratosphere/os/os_argument.hpp> #include <stratosphere/os/os_argument.hpp>
#include <stratosphere/os/os_cache.hpp>

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::os {
void FlushDataCache(const void *addr, size_t size);
void FlushEntireDataCache();
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
#ifdef ATMOSPHERE_OS_HORIZON
#include "os_cache_impl.os.horizon.hpp"
#else
#error "Unknown OS for ThreadManagerImpl"
#endif

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
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<uintptr_t>(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<uintptr_t>(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<uintptr_t>(addr), size);
R_ASSERT(result);
AMS_UNUSED(result);
#endif
}
inline void FlushEntireDataCacheImpl() {
svc::FlushEntireDataCache();
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#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();
}
}

View file

@ -372,7 +372,7 @@ namespace ams::spl::impl {
std::memcpy(layout->in_block, src, sizeof(layout->in_block)); std::memcpy(layout->in_block, src, sizeof(layout->in_block));
armDCacheFlush(layout, sizeof(*layout)); os::FlushDataCache(layout, sizeof(*layout));
{ {
std::scoped_lock lk(g_async_op_lock); std::scoped_lock lk(g_async_op_lock);
smc::AsyncOperationKey op_key; smc::AsyncOperationKey op_key;
@ -390,7 +390,7 @@ namespace ams::spl::impl {
return res; return res;
} }
} }
armDCacheFlush(layout, sizeof(*layout)); os::FlushDataCache(layout, sizeof(*layout));
std::memcpy(dst, layout->out_block, sizeof(layout->out_block)); std::memcpy(dst, layout->out_block, sizeof(layout->out_block));
return smc::Result::Success; return smc::Result::Success;
@ -407,7 +407,7 @@ namespace ams::spl::impl {
R_UNLESS(src_size <= sizeof(DecryptAndStoreDeviceUniqueKeyLayout), spl::ResultInvalidSize()); R_UNLESS(src_size <= sizeof(DecryptAndStoreDeviceUniqueKeyLayout), spl::ResultInvalidSize());
std::memcpy(layout, src, src_size); std::memcpy(layout, src, src_size);
armDCacheFlush(layout, sizeof(*layout)); os::FlushDataCache(layout, sizeof(*layout));
smc::Result smc_res; smc::Result smc_res;
if (hos::GetVersion() >= hos::Version_5_0_0) { if (hos::GetVersion() >= hos::Version_5_0_0) {
smc_res = smc::DecryptDeviceUniqueData(layout->data, src_size, access_key, key_source, static_cast<smc::DeviceUniqueDataMode>(option)); smc_res = smc::DecryptDeviceUniqueData(layout->data, src_size, access_key, key_source, static_cast<smc::DeviceUniqueDataMode>(option));
@ -438,7 +438,7 @@ namespace ams::spl::impl {
std::memcpy(layout->mod + mod_ofs, mod, mod_size); std::memcpy(layout->mod + mod_ofs, mod, mod_size);
/* Do exp mod operation. */ /* Do exp mod operation. */
armDCacheFlush(layout, sizeof(*layout)); os::FlushDataCache(layout, sizeof(*layout));
{ {
std::scoped_lock lk(g_async_op_lock); std::scoped_lock lk(g_async_op_lock);
smc::AsyncOperationKey op_key; smc::AsyncOperationKey op_key;
@ -452,7 +452,7 @@ namespace ams::spl::impl {
return smc::ConvertResult(res); return smc::ConvertResult(res);
} }
} }
armDCacheFlush(g_work_buffer, sizeof(out_size)); os::FlushDataCache(g_work_buffer, sizeof(out_size));
std::memcpy(out, g_work_buffer, out_size); std::memcpy(out, g_work_buffer, out_size);
return ResultSuccess(); return ResultSuccess();
@ -478,7 +478,7 @@ namespace ams::spl::impl {
std::memcpy(layout->mod + mod_ofs, mod, mod_size); std::memcpy(layout->mod + mod_ofs, mod, mod_size);
/* Do exp mod operation. */ /* Do exp mod operation. */
armDCacheFlush(layout, sizeof(*layout)); os::FlushDataCache(layout, sizeof(*layout));
{ {
std::scoped_lock lk(g_async_op_lock); std::scoped_lock lk(g_async_op_lock);
smc::AsyncOperationKey op_key; smc::AsyncOperationKey op_key;
@ -492,7 +492,7 @@ namespace ams::spl::impl {
return smc::ConvertResult(res); return smc::ConvertResult(res);
} }
} }
armDCacheFlush(g_work_buffer, sizeof(*out_access_key)); os::FlushDataCache(g_work_buffer, sizeof(*out_access_key));
std::memcpy(out_access_key, g_work_buffer, sizeof(*out_access_key)); std::memcpy(out_access_key, g_work_buffer, sizeof(*out_access_key));
return ResultSuccess(); return ResultSuccess();
@ -566,7 +566,7 @@ namespace ams::spl::impl {
std::memcpy(layout->mod + mod_ofs, mod, mod_size); std::memcpy(layout->mod + mod_ofs, mod, mod_size);
/* Do exp mod operation. */ /* Do exp mod operation. */
armDCacheFlush(layout, sizeof(*layout)); os::FlushDataCache(layout, sizeof(*layout));
{ {
std::scoped_lock lk(g_async_op_lock); std::scoped_lock lk(g_async_op_lock);
smc::AsyncOperationKey op_key; smc::AsyncOperationKey op_key;
@ -580,7 +580,7 @@ namespace ams::spl::impl {
return smc::ConvertResult(res); return smc::ConvertResult(res);
} }
} }
armDCacheFlush(g_work_buffer, sizeof(out_size)); os::FlushDataCache(g_work_buffer, sizeof(out_size));
std::memcpy(out, g_work_buffer, out_size); std::memcpy(out, g_work_buffer, out_size);
return ResultSuccess(); return ResultSuccess();
@ -701,9 +701,9 @@ namespace ams::spl::impl {
crypt_ctx->out.address = dst_se_addr; crypt_ctx->out.address = dst_se_addr;
crypt_ctx->out.size = dst_size; crypt_ctx->out.size = dst_size;
armDCacheFlush(crypt_ctx, sizeof(*crypt_ctx)); os::FlushDataCache(crypt_ctx, sizeof(*crypt_ctx));
armDCacheFlush(const_cast<void *>(src), src_size); os::FlushDataCache(const_cast<void *>(src), src_size);
armDCacheFlush(dst, dst_size); os::FlushDataCache(dst, dst_size);
{ {
std::scoped_lock lk(g_async_op_lock); std::scoped_lock lk(g_async_op_lock);
smc::AsyncOperationKey op_key; smc::AsyncOperationKey op_key;
@ -720,7 +720,7 @@ namespace ams::spl::impl {
return smc::ConvertResult(res); return smc::ConvertResult(res);
} }
} }
armDCacheFlush(dst, dst_size); os::FlushDataCache(dst, dst_size);
return ResultSuccess(); return ResultSuccess();
} }
@ -783,7 +783,7 @@ namespace ams::spl::impl {
R_UNLESS(src_size <= sizeof(DecryptDeviceUniqueDataLayout), spl::ResultInvalidSize()); R_UNLESS(src_size <= sizeof(DecryptDeviceUniqueDataLayout), spl::ResultInvalidSize());
std::memcpy(layout->data, src, src_size); std::memcpy(layout->data, src, src_size);
armDCacheFlush(layout, sizeof(*layout)); os::FlushDataCache(layout, sizeof(*layout));
smc::Result smc_res; smc::Result smc_res;
size_t copy_size = 0; size_t copy_size = 0;
@ -795,7 +795,7 @@ namespace ams::spl::impl {
copy_size = std::min(dst_size, copy_size); copy_size = std::min(dst_size, copy_size);
} }
armDCacheFlush(layout, sizeof(*layout)); os::FlushDataCache(layout, sizeof(*layout));
if (smc_res == smc::Result::Success) { if (smc_res == smc::Result::Success) {
std::memcpy(dst, layout->data, copy_size); std::memcpy(dst, layout->data, copy_size);
} }
@ -827,7 +827,7 @@ namespace ams::spl::impl {
std::memcpy(layout, src, src_size); std::memcpy(layout, src, src_size);
armDCacheFlush(layout, sizeof(*layout)); os::FlushDataCache(layout, sizeof(*layout));
return smc::ConvertResult(smc::LoadEsDeviceKey(layout->data, src_size, access_key, key_source, option)); return smc::ConvertResult(smc::LoadEsDeviceKey(layout->data, src_size, access_key, key_source, option));
} }
} }
@ -915,12 +915,12 @@ namespace ams::spl::impl {
layout->access_key_enc = access_key_enc; layout->access_key_enc = access_key_enc;
layout->source_enc = source_enc; layout->source_enc = source_enc;
armDCacheFlush(layout, sizeof(*layout)); os::FlushDataCache(layout, sizeof(*layout));
smc::Result smc_res = smc::ReencryptDeviceUniqueData(layout->data, src_size, layout->access_key_dec, layout->source_dec, layout->access_key_enc, layout->source_enc, option); smc::Result smc_res = smc::ReencryptDeviceUniqueData(layout->data, src_size, layout->access_key_dec, layout->source_dec, layout->access_key_enc, layout->source_enc, option);
if (smc_res == smc::Result::Success) { if (smc_res == smc::Result::Success) {
size_t copy_size = std::min(dst_size, src_size); size_t copy_size = std::min(dst_size, src_size);
armDCacheFlush(layout, copy_size); os::FlushDataCache(layout, copy_size);
std::memcpy(dst, layout->data, copy_size); std::memcpy(dst, layout->data, copy_size);
} }