sv_magic -> scratchpad
[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         /* Declare special flags (handshake 2/3) */
43
44         struct kbase_uk_set_flags flags = {
45                 .create_flags = BASE_CONTEXT_CREATE_FLAG_NONE
46         };
47
48         m_ioctl(fd, flags, KBASE_FUNC_SET_FLAGS);
49
50         /* Map the Memmap Tracking Handle (handshake 3/3) */
51
52         uint8_t *mtp = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, fd,
53                                 BASE_MEM_MAP_TRACKING_HANDLE);
54
55         if(mtp == MAP_FAILED) {
56                 printf("MP map failed (%s)\n", strerror(errno));
57                 return -1;
58         }
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 void free_gpu(int fd, uint64_t addr)
88 {
89         struct kbase_uk_mem_free gfree = { .gpu_addr = addr };
90         m_ioctl(fd, gfree, KBASE_FUNC_MEM_FREE);
91 }
92
93 void sync_gpu(int fd, uint8_t* cpu, uint64_t gpu, size_t bytes)
94 {
95         struct basep_syncset base_sset = {
96                 .mem_handle = { .basep = { .handle = gpu & PAGE_MASK } },
97                 .user_addr = (u32) cpu,
98                 .size = (gpu & ~PAGE_MASK) + bytes,
99                 .type = BASE_SYNCSET_OP_MSYNC
100         };
101
102         struct kbase_uk_sync_now sync = {
103                 .sset = { .basep_sset = base_sset}
104         };
105
106         m_ioctl(fd, sync, KBASE_FUNC_SYNC);
107 }
108
109 static void submit_job_internal(int fd, struct base_jd_atom_v2 *atoms, size_t count)
110 {
111         struct kbase_uk_job_submit submit = {
112                 .addr = { .value = atoms },
113                 .nr_atoms = count,
114                 .stride = sizeof(struct base_jd_atom_v2)
115         };
116         
117         m_ioctl(fd, submit, KBASE_FUNC_JOB_SUBMIT);
118 }
119
120 #define ATOM_QUEUE_MAX 16
121
122 struct base_jd_atom_v2 atom_queue[ATOM_QUEUE_MAX];
123 int atom_queue_size = 0;
124
125 void flush_job_queue(int fd)
126 {
127         if(atom_queue_size) {
128                 submit_job_internal(fd, atom_queue, atom_queue_size);
129                 atom_queue_size = 0;
130         }
131 }
132
133 void submit_job(int fd, struct base_jd_atom_v2 atom)
134 {
135         memcpy(&atom_queue[atom_queue_size++], &atom, sizeof(atom));
136
137         if(atom_queue_size == ATOM_QUEUE_MAX)
138                 flush_job_queue(fd);
139 }
140
141 /* Not strictly an ioctl but still shim related */
142
143 uint8_t* mmap_gpu(int fd, uint64_t addr, int page_count)
144 {
145         uint8_t* buffer = mmap(NULL, page_count << PAGE_SHIFT,
146                                 PROT_READ | PROT_WRITE, MAP_SHARED,
147                                 fd, addr);
148
149         if(buffer == MAP_FAILED) {
150                 printf("Buffer map failed (%s)\n", strerror(errno));
151                 exit(1);
152         }
153
154         return buffer;
155 }
156
157 /* Seems to fail but called anyway by the blob */
158
159 void stream_create(int fd, char *stream)
160 {
161         struct kbase_uk_stream_create s;
162         strcpy(s.name, stream);
163         m_ioctl(fd, s, KBASE_FUNC_STREAM_CREATE);
164 }