Pull cache flush out of Haystack

Merge of http://go/wvgerrit/20924

This CL pulls the cache flush code out of the haystack code and into
the adapter level.  This is so it will be built with processor
specific compiler flags instead of as part of the precompiled binary.

level3/mips/libwvlevel3.a  Level3 Library 4465 Sep 10 2016 21:44:37
level3/arm/libwvlevel3.a  Level3 Library 4445 Sep 10 2016 21:30:01
level3/x86/libwvlevel3.a  Level3 Library 4464 Sep 10 2016 21:49:53

b/30550782 Battery Problems

Change-Id: I8967da498a43cabe82e78345162705dc2fcdb859
This commit is contained in:
Fred Gylys-Colwell
2016-09-10 12:04:03 -07:00
parent 3f040e0a9d
commit 84d7185e5f
5 changed files with 64 additions and 4 deletions

View File

@@ -13,6 +13,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#if __mips__
#include <sys/syscall.h>
#include <asm/cachectl.h>
#endif
#include <iostream>
#include <map>
@@ -235,6 +242,61 @@ struct FunctionPointers {
L1_LoadKeys_V9_or_V10_t LoadKeys_V9_or_V10;
};
// The Cache Flush function is very processor dependent, but is needed by the
// haystack code. The haystack code is delivered as a static prebuilt library.
// For that reason, we pass a function pointer for cache_flush into the
// haystack. The function is combiled outside of the haystack and may use
// target (processor) specific compiler flags.
void clear_cache_function(void *page, size_t len) {
// Note on cross platform support. If __has_builtin is not defined as a
// preprocessor function, we cannot use
// "#if defined(__has_builtin) && __has_builtin(..)".
// So, instead, we will define USED_BUILTIN_CLEAR_CACHE if both conditions
// are true, and use "#ifndef USED_BUILTIN_CLEAR_CACHE" instead of #else.
#ifdef __has_builtin
#if __has_builtin(__builtin___clear_cache)
#pragma message "clear_cache_function is using __builtin___clear_cache."
#define USED_BUILTIN_CLEAR_CACHE
char *begin = static_cast<char *>(page);
char *end = begin + len;
__builtin___clear_cache(begin, end);
#endif
#endif
#ifndef USED_BUILTIN_CLEAR_CACHE
#if __arm__
#pragma message "clear_cache_function is using arm asm."
// ARM Cache Flush System Call:
char *begin = static_cast<char *>(page);
char *end = begin + len;
const int syscall = 0xf0002;
__asm __volatile (
"push {r0, r1, r2, r7}\n"
"mov r0, %0\n"
"mov r1, %1\n"
"mov r7, %2\n"
"mov r2, #0x0\n"
"svc 0x00000000\n"
"pop {r0, r1, r2, r7}\n"
:
: "r" (begin), "r" (end), "r" (syscall)
: "r0", "r1", "r7"
);
#elif __mips__
#pragma message "clear_cache_function is using mips asm."
int result = syscall(__NR_cacheflush, page, len, ICACHE);
if (result) {
fprintf(stderr, "cacheflush failed!: errno=%d %s\n", errno,
strerror(errno));
exit(-1); // TODO(fredgc): figure out more graceful error handling.
}
#else
#pragma message "clear_cache_function is not doing anything."
// TODO(fredgc): silence warning about unused variables.
#endif
#endif
}
struct LevelSession {
FunctionPointers* fcn;
OEMCrypto_SESSION session;
@@ -269,7 +331,7 @@ class Adapter {
OEMCryptoResult Initialize() {
LoadLevel3();
OEMCryptoResult result = Level3_Initialize();
OEMCryptoResult result = Level3_Initialize(clear_cache_function);
if (force_level3()) {
LOGW("Test code. User requested falling back to L3");
return result;
@@ -416,7 +478,6 @@ class Adapter {
}
void LoadLevel3() {
level3_.Initialize = Level3_Initialize;
level3_.Terminate = Level3_Terminate;
level3_.OpenSession = Level3_OpenSession;
level3_.CloseSession = Level3_CloseSession;

View File

@@ -64,7 +64,7 @@ namespace wvoec3 {
extern "C" {
bool Level3_PreInitialize(const char* path);
OEMCryptoResult Level3_Initialize(void);
OEMCryptoResult Level3_Initialize(void (*ClearCache)(void *, size_t));
OEMCryptoResult Level3_Terminate(void);
OEMCryptoResult Level3_OpenSession(OEMCrypto_SESSION *session);
OEMCryptoResult Level3_CloseSession(OEMCrypto_SESSION session);
@@ -80,7 +80,6 @@ OEMCryptoResult Level3_GenerateSignature(OEMCrypto_SESSION session,
size_t message_length,
uint8_t* signature,
size_t* signature_length);
OEMCryptoResult Level3_LoadKeys(OEMCrypto_SESSION session,
const uint8_t* message,
size_t message_length,