112 lines
4.2 KiB
C++
112 lines
4.2 KiB
C++
/***
|
|
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: Cache.cpp
|
|
Date: 2022-3-21
|
|
Author: Reece
|
|
***/
|
|
#include <Source/RuntimeInternal.hpp>
|
|
#include "Memory.hpp"
|
|
#include "Cache.hpp"
|
|
#include <Source/HWInfo/HWInfo.hpp>
|
|
|
|
#define LINUX_SUPPORTS_CACHE_CTL 0
|
|
|
|
#if defined(AURORA_IS_LINUX_DERIVED)
|
|
#include <sys/mman.h>
|
|
#if LINUX_SUPPORTS_CACHE_CTL
|
|
#include <sys/cachectl.h>
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(AURORA_IS_XNU_DERIVED)
|
|
void sys_icache_invalidate(void *start, size_t len);
|
|
#endif
|
|
|
|
|
|
namespace Aurora::Memory::Cache
|
|
{
|
|
AUKN_SYM void OptimizeAddressRangeOnCore(const AuList<AuPair<AuUInt, AuUInt>> &addressRanges)
|
|
{
|
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
|
AuList<WIN32_MEMORY_RANGE_ENTRY> arry;
|
|
|
|
if (!AuTryResize(arry, addressRanges.size()))
|
|
{
|
|
return;
|
|
}
|
|
AuUInt index {};
|
|
#endif
|
|
|
|
for (const auto &addressRange : addressRanges)
|
|
{
|
|
auto base = AuPageRound(addressRange.first, AuUInt(AuHwInfo::gPageSize));
|
|
auto length = AuPageRoundUp(addressRange.second + (addressRange.first - base), AuUInt(AuHwInfo::gPageSize));
|
|
|
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
|
arry[index++] = {
|
|
AuReinterpretCast<LPVOID>(base),
|
|
length
|
|
};
|
|
#endif
|
|
|
|
#if defined(AURORA_IS_POSIX_DERIVED)
|
|
// The posix_madvise() interface conforms to IEEE Std 1003.1-2001 ("POSIX.1").
|
|
// The madvise() system call first appeared in 4.4BSD.
|
|
// https://www.freebsd.org/cgi/man.cgi?query=madvise&apropos=0&sektion=2&manpath=FreeBSD+9.0-RELEASE&arch=default&format=html
|
|
// https://man7.org/linux/man-pages/man2/madvise.2.html
|
|
|
|
if (madvise(AuReinterpretCast<void *>(base), length, MADV_WILLNEED) != 0)
|
|
{
|
|
SysPushErrorHAL("Couldn't advice memory range 0x{:x} {}", base, length);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
|
if (!PrefetchVirtualMemory(GetCurrentProcess(), arry.size(), arry.data(), 0))
|
|
{
|
|
SysPushErrorHAL("Couldn't pin memory range into cache");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
AUKN_SYM void ClearInstructionCache(const AuPair<AuUInt, AuUInt> &addressRange)
|
|
{
|
|
auto base = AuPageRound(addressRange.first, AuUInt(AuHwInfo::gPageSize));
|
|
auto length = AuPageRoundUp(addressRange.second + (addressRange.first - base), AuUInt(AuHwInfo::gPageSize));
|
|
|
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
|
FlushInstructionCache(GetCurrentProcess(), AuReinterpretCast<LPCVOID>(base), length);
|
|
#elif defined(AURORA_IS_XNU_DERIVED)
|
|
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sys_icache_invalidate.3.html
|
|
sys_icache_invalidate(AuReinterpretCast<const void *>(base), length);
|
|
#elif defined(AURORA_IS_LINUX_DERIVED) && defined(LINUX_SUPPORTS_CACHE_CTL) && LINUX_SUPPORTS_CACHE_CTL
|
|
// https://man7.org/linux/man-pages/man2/cacheflush.2.html
|
|
cacheflush(AuReinterpretCast<const void *>(base), length, ICACHE);
|
|
#elif (defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64)) && (defined(AURORA_COMPILER_CLANG) || AURORA_COMPILER_GCC)
|
|
|
|
const size_t cacheLine = 64; // TODO: pull from Aurora::HWInfo
|
|
|
|
asm volatile("sfence\n\t"
|
|
:
|
|
:
|
|
: "memory");
|
|
|
|
for (AuUInt i = 0; i < length; i += cacheLine)
|
|
{
|
|
asm volatile("clflush (%0)\n\t"
|
|
:
|
|
: "r"(AuReinterpretCast<const char *>(base) + i)
|
|
: "memory");
|
|
}
|
|
|
|
#elif defined(AURORA_COMPILER_GCC)
|
|
__builtin___clear_cache(AuReinterpretCast<const char *>(base), AuReinterpretCast<const char *>(base) + length);
|
|
#elif defined(AURORA_COMPILER_CLANG) && defined(AURORA_ARCH_ARM)
|
|
// https://github.com/llvm/llvm-project/blob/d480f968ad8b56d3ee4a6b6df5532d485b0ad01e/clang/include/clang/Basic/BuiltinsARM.def#L25
|
|
// Does not exist anywhere else
|
|
__clear_cache(AuReinterpretCast<const char *>(base), AuReinterpretCast<const char *>(base) + length);
|
|
#endif
|
|
}
|
|
} |