1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "gtest/gtest.h"
18
19 #include <sys/mman.h>
20 #include <sys/syscall.h>
21
TEST(Syscall,SchedSetAffinity)22 TEST(Syscall, SchedSetAffinity) {
23 int mask = 1;
24 ASSERT_EQ(syscall(SYS_sched_setaffinity, 0, 4, &mask), 0);
25 }
26
TEST(Syscall,CacheFlush)27 TEST(Syscall, CacheFlush) {
28 // This test work as simple JIT engine with code patching.
29 // Workflow is like this:
30 // - create code
31 // - flush cache
32 // - runs code
33 // - modify code
34 // - flush cache
35 // - run code
36 static const int kCacheFlushSyscall = 0xf0002;
37 static const uint32_t code_template[] = {
38 0xe3000001, // movw r0, #0x1
39 0xe12fff1e, // bx lr
40 };
41 uint8_t* start = reinterpret_cast<uint8_t*>(mmap(0,
42 sizeof(code_template),
43 PROT_READ | PROT_WRITE | PROT_EXEC,
44 MAP_PRIVATE | MAP_ANONYMOUS,
45 -1,
46 0));
47 ASSERT_NE(start, MAP_FAILED);
48 memcpy(start, code_template, sizeof(code_template));
49 uint8_t* end = start + sizeof(code_template);
50 ASSERT_EQ(syscall(kCacheFlushSyscall, start, end, 0), 0);
51 using TestFunc = int (*)(void);
52 TestFunc func = reinterpret_cast<TestFunc>(start);
53 ASSERT_EQ(func(), 0x1);
54 *reinterpret_cast<uint32_t*>(start) = 0xe3000011; // movw r0, #0x11
55 ASSERT_EQ(syscall(kCacheFlushSyscall, start, end, 0), 0);
56 ASSERT_EQ(func(), 0x11);
57 munmap(start, sizeof(code_template));
58 }
59
TEST(Syscall,OAbiDisabled)60 TEST(Syscall, OAbiDisabled) {
61 int pipefd[2];
62 ASSERT_EQ(pipe(pipefd), 0);
63 char buf[4] = "Tst";
64 register uint32_t r0 asm("r0") = pipefd[1];
65 register uint32_t r1 asm("r1") = reinterpret_cast<uint32_t>(buf);
66 register uint32_t r2 asm("r2") = sizeof(buf);
67 register uint32_t r7 asm("r7") = SYS_write;
68 // Call "write" syscall using EABI, but instrument it to be interpreted as "read" if executed
69 // on system with OABI syscall calling convention or CONFIG_OABI_COMPAT mode enabled.
70 //
71 // On kernels with CONFIG_OABI_COMPAT immediate from "swi" instruction would be used, attempt to
72 // use "read" syscall (based on .imm value of "swi"instruction) would happen - and test would
73 // fail.
74 //
75 // On kernels without CONFIG_OABI_COMPAT value from r7 would be used and test would succeed.
76 asm("swi %1" : "=r"(r0) : "i"(SYS_read), "r"(r0), "r"(r1), "r"(r2), "r"(r7));
77 uint32_t result = r0;
78 ASSERT_EQ(result, sizeof(buf));
79 close(pipefd[0]);
80 close(pipefd[1]);
81 }
82