1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file.
4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(__arm__)  // nacl_irt_icache is supported only on ARM.
6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <errno.h>
8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <sys/mman.h>
9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "components/nacl/loader/nonsfi/irt_interfaces.h"
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST(NaClIrtIcacheTest, ClearCache) {
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  int (*irt_clear_cache)(void*, size_t) =
15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      nacl::nonsfi::kIrtIcache.clear_cache;
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Create code for a function to return 0x01.
17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  static const uint32_t code_template[] = {
18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    0xe3000001,  // movw r0, #0x1
19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    0xe12fff1e,  // bx lr
20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  };
21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void* start =
22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      mmap(NULL, sizeof(code_template), PROT_READ | PROT_WRITE | PROT_EXEC,
23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_NE(MAP_FAILED, start);
25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  memcpy(start, code_template, sizeof(code_template));
26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  size_t size = sizeof(code_template);
27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(0, irt_clear_cache(start, size));
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  typedef int (*TestFunc)(void);
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TestFunc func = reinterpret_cast<TestFunc>(start);
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(0x1, func());
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Modify the function to return 0x11.
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  *reinterpret_cast<uint32_t*>(start) = 0xe3000011;  // movw r0, #0x11
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // In most cases 0x1 is still returned because the cached code is executed
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // although the CPU is not obliged to do so.
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Uncomment the following line to see if the cached code is executed.
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // EXPECT_EQ(0x1, func());
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(0, irt_clear_cache(start, size));
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Now it is ensured that 0x11 is returned because I-cache was invalidated
39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // and updated with the new code.
40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(0x11, func());
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(0, munmap(start, sizeof(code_template)));
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST(NaClIrtIcacheTest, ClearCacheInvalidArg) {
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  int (*irt_clear_cache)(void*, size_t) =
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      nacl::nonsfi::kIrtIcache.clear_cache;
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const size_t mem_size = 256;
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void* start =
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      mmap(NULL, mem_size, PROT_READ | PROT_WRITE | PROT_EXEC,
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(0, irt_clear_cache(start, mem_size));
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(EINVAL, irt_clear_cache(start, 0));
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(EINVAL, irt_clear_cache(NULL, mem_size));
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_EQ(0, munmap(start, mem_size));
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif
58