From cbfc3c7193ec18edf0ada3608a01402d12ff2ac3 Mon Sep 17 00:00:00 2001 From: Robert Shih Date: Thu, 13 Aug 2020 01:15:46 -0700 Subject: [PATCH] wvoec3: add membarriers to complete cache flush Merge of http://go/wvgerrit/104543 Bug: 159465432 Test: oemcrypto_test Change-Id: Idcf345088c1d40836b5e100d2f758147986a4b04 --- .../level3/include/clear_cache_function.h | 62 ++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/libwvdrmengine/level3/include/clear_cache_function.h b/libwvdrmengine/level3/include/clear_cache_function.h index 691490c5..2c6d1b97 100644 --- a/libwvdrmengine/level3/include/clear_cache_function.h +++ b/libwvdrmengine/level3/include/clear_cache_function.h @@ -1,13 +1,65 @@ +#include #include #include -#if __mips__ +#include #include -#include +#include + +#if __mips__ +# include #endif +#include "log.h" + namespace wvoec3 { +bool supports_membarier_syscall() { + // Check kernel version supports membarrier(2); version 4.16 is required. + static constexpr int kRequiredMajor = 4; + static constexpr int kRequiredMinor = 16; + struct utsname uts; + int major = 0, minor = 0; + if (uname(&uts) != 0 || strcmp(uts.sysname, "Linux") != 0 || + sscanf(uts.release, "%d.%d", &major, &minor) != 2) { + LOGE("Failed to get kernel version"); + return false; + } + if (major < kRequiredMajor || + (major == kRequiredMajor && minor < kRequiredMinor)) { + LOGE("Kernel version %d, %d < required %d, %d", major, minor, + kRequiredMajor, kRequiredMinor); + return false; + } + return true; +} + +#if defined(__NR_membarrier) + +// membarrier function is used to complete flush of CPU instruction pipelines. +// Reference: +// * membarrier(2) +// * art::jit::JitMemoryRegion::CommitCode +int membarrier_function(int command) { + static bool supports_membarier = supports_membarier_syscall(); + if (supports_membarier) { + return syscall(__NR_membarrier, command, 0); + } + errno = ENOSYS; + return -1; +} + +#else // __NR_membarrier +# pragma message \ + "(info): __NR_membarrier unavailable; membarrier_function will be no-op." + +int membarrier_function(int) { + errno = ENOSYS; + return -1; +} + +#endif // __NR_membarrier + // The Cache Flush function is very processor dependent, and is used by the // Level3 code using platform-specific flags. // Linked in separately from the rest of the build, since this code isn't @@ -58,6 +110,12 @@ void clear_cache_function(void *page, size_t len) { // TODO(fredgc): silence warning about unused variables. #endif #endif + +#if defined(__arm__) || defined(__aarch64__) +# pragma message "(info): inserting membarrier_function calls." + membarrier_function(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE); + membarrier_function(MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE); +#endif // defined(__arm__) || defined(__aarch64__) } } // namespace wvoec3 \ No newline at end of file