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