Fix vertex upload regression
[chai.git] / shim.c
1 /* Raw shim communication appears here.
2  * If/when the shim is replaced by something less hacky,
3  * only this file will change.
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <sys/ioctl.h>
9 #include <sys/mman.h>
10 #include <fcntl.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <unistd.h>
14
15 #include "shim.h"
16
17 #define m_ioctl(fd, data, no) \
18         data.header.id = no; \
19         if(ioctl(fd, _IOC(_IOC_READ | _IOC_WRITE, 0x82, 0, sizeof(data)), &data)) { \
20                 printf("Bad ioctl %d (%s)\n", no, strerror(errno)); \
21                 exit(1); \
22         }
23
24 int open_kernel_module()
25 {
26         int fd = open("/dev/mali0", O_RDWR | O_CLOEXEC);
27
28         if(fd == -1) {
29                 printf("Failed to open /dev/mali0\n");
30                 return 1;
31         }
32
33         /* Declare the ABI version (handshake 1/3) */
34
35         struct uku_version_check_args check = {
36                 .major = /* BASE_UK_VERSION_MAJOR */ 0x8,
37                 .minor = /* BASE_UK_VERSION_MINOR */ 0x0,
38         };
39
40         m_ioctl(fd, check, UKP_FUNC_ID_CHECK_VERSION);
41
42         /* Map the Memmap Tracking Handle (handshake 2/3) */
43
44         uint8_t *mtp = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_SHARED, fd,
45                                 BASE_MEM_MAP_TRACKING_HANDLE);
46
47         if(mtp == MAP_FAILED) {
48                 printf("MP map failed (%s)\n", strerror(errno));
49                 return -1;
50         }
51
52         /* Declare special flags (handshake 3/3) */
53
54         struct kbase_uk_set_flags flags = {
55                 .create_flags = BASE_CONTEXT_CREATE_FLAG_NONE
56         };
57
58         m_ioctl(fd, flags, KBASE_FUNC_SET_FLAGS);
59
60         return fd;
61 }
62
63 uint64_t alloc_gpu_pages(int fd, int pages, int e_flags)
64 {
65         struct kbase_uk_mem_alloc alloc = {
66                 .va_pages = pages,
67                 .commit_pages = pages,
68                 .extent = 0,
69                 .flags = e_flags
70         };
71
72         printf("Allocing %d pages flag %X to %d\n", pages, e_flags, fd);
73
74         m_ioctl(fd, alloc, KBASE_FUNC_MEM_ALLOC);
75
76         // return alloc.gpu_va;
77
78         /* Only necessary when we report old versions */
79
80         if(e_flags & BASE_MEM_SAME_VA)  {
81                 return (uint32_t) mmap(NULL, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, MAP_SHARED, fd, alloc.gpu_va);
82         } else {
83                 return alloc.gpu_va;
84         }
85 }
86
87 uint64_t alloc_gpu_heap(int fd, int pages)
88 {
89         struct kbase_uk_mem_alloc alloc = {
90                 .va_pages = pages,
91                 .commit_pages = 1,
92                 .extent = 0x80,
93                 .flags = 0x26F
94         };
95
96         m_ioctl(fd, alloc, KBASE_FUNC_MEM_ALLOC);
97
98         return alloc.gpu_va;
99 }
100
101 void free_gpu(int fd, uint64_t addr)
102 {
103         struct kbase_uk_mem_free gfree = { .gpu_addr = addr };
104         m_ioctl(fd, gfree, KBASE_FUNC_MEM_FREE);
105 }
106
107 void sync_gpu(int fd, uint8_t* cpu, uint64_t gpu, size_t bytes)
108 {
109         struct basep_syncset base_sset = {
110                 .mem_handle = { .basep = { .handle = gpu & PAGE_MASK } },
111                 .user_addr = (u32) cpu,
112                 .size = (gpu & ~PAGE_MASK) + bytes,
113                 .type = BASE_SYNCSET_OP_MSYNC
114         };
115
116         struct kbase_uk_sync_now sync = {
117                 .sset = { .basep_sset = base_sset}
118         };
119
120         m_ioctl(fd, sync, KBASE_FUNC_SYNC);
121 }
122
123 static void submit_job_internal(int fd, struct base_jd_atom_v2 *atoms, size_t count)
124 {
125         struct kbase_uk_job_submit submit = {
126                 .addr = { .value = atoms },
127                 .nr_atoms = count,
128                 .stride = sizeof(struct base_jd_atom_v2)
129         };
130         
131         m_ioctl(fd, submit, KBASE_FUNC_JOB_SUBMIT);
132 }
133
134 #define ATOM_QUEUE_MAX 16
135
136 struct base_jd_atom_v2 atom_queue[ATOM_QUEUE_MAX];
137 int atom_queue_size = 0;
138
139 void flush_job_queue(int fd)
140 {
141         if(atom_queue_size) {
142                 submit_job_internal(fd, atom_queue, atom_queue_size);
143                 atom_queue_size = 0;
144         }
145 }
146
147 void submit_job(int fd, struct base_jd_atom_v2 atom)
148 {
149         memcpy(&atom_queue[atom_queue_size++], &atom, sizeof(atom));
150
151         if(atom_queue_size == ATOM_QUEUE_MAX)
152                 flush_job_queue(fd);
153 }
154
155 /* Not strictly an ioctl but still shim related */
156
157 uint8_t* mmap_gpu(int fd, uint64_t addr, int page_count)
158 {
159         uint8_t* buffer = mmap(NULL, page_count << PAGE_SHIFT,
160                                 PROT_READ | PROT_WRITE, MAP_SHARED,
161                                 fd, addr);
162
163         if(buffer == MAP_FAILED) {
164                 printf("Buffer map failed (%s)\n", strerror(errno));
165                 exit(1);
166         }
167
168         return buffer;
169 }
170
171 /* Seems to fail but called anyway by the blob */
172
173 void stream_create(int fd, char *stream)
174 {
175         struct kbase_uk_stream_create s;
176         strcpy(s.name, stream);
177         m_ioctl(fd, s, KBASE_FUNC_STREAM_CREATE);
178 }
179
180
181 void query_gpu_props(int fd)
182 {
183         struct kbase_uk_gpuprops v;
184         m_ioctl(fd, v, KBASE_FUNC_GPU_PROPS_REG_DUMP);
185 }