Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | /* |
2 | * This confidential and proprietary software may be used only as | |
3 | * authorised by a licensing agreement from ARM Limited | |
4 | * (C) COPYRIGHT 2008-2013 ARM Limited | |
5 | * ALL RIGHTS RESERVED | |
6 | * The entire notice above must be reproduced on all authorised | |
7 | * copies and copies may only be made to the extent permitted | |
8 | * by a licensing agreement from ARM Limited. | |
9 | */ | |
10 | #include <linux/fs.h> /* file system operations */ | |
11 | #include <asm/uaccess.h> /* user space access */ | |
12 | ||
13 | #include "mali_ukk.h" | |
14 | #include "mali_osk.h" | |
15 | #include "mali_kernel_common.h" | |
16 | #include "mali_session.h" | |
17 | #include "mali_ukk_wrappers.h" | |
18 | ||
19 | int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user * uargs) | |
20 | { | |
21 | _mali_uk_mem_write_safe_s kargs; | |
22 | _mali_osk_errcode_t err; | |
23 | ||
24 | MALI_CHECK_NON_NULL(uargs, -EINVAL); | |
25 | MALI_CHECK_NON_NULL(session_data, -EINVAL); | |
26 | ||
27 | if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_mem_write_safe_s))) { | |
28 | return -EFAULT; | |
29 | } | |
30 | ||
31 | kargs.ctx = session_data; | |
32 | ||
33 | /* Check if we can access the buffers */ | |
34 | if (!access_ok(VERIFY_WRITE, kargs.dest, kargs.size) | |
35 | || !access_ok(VERIFY_READ, kargs.src, kargs.size)) { | |
36 | return -EINVAL; | |
37 | } | |
38 | ||
39 | /* Check if size wraps */ | |
40 | if ((kargs.size + kargs.dest) <= kargs.dest | |
41 | || (kargs.size + kargs.src) <= kargs.src) { | |
42 | return -EINVAL; | |
43 | } | |
44 | ||
45 | err = _mali_ukk_mem_write_safe(&kargs); | |
46 | if (_MALI_OSK_ERR_OK != err) { | |
47 | return map_errcode(err); | |
48 | } | |
49 | ||
50 | if (0 != put_user(kargs.size, &uargs->size)) { | |
51 | return -EFAULT; | |
52 | } | |
53 | ||
54 | return 0; | |
55 | } | |
56 | ||
57 | int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument) | |
58 | { | |
59 | _mali_uk_map_external_mem_s uk_args; | |
60 | _mali_osk_errcode_t err_code; | |
61 | ||
62 | /* validate input */ | |
63 | /* the session_data pointer was validated by caller */ | |
64 | MALI_CHECK_NON_NULL( argument, -EINVAL); | |
65 | ||
66 | /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ | |
67 | if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_map_external_mem_s)) ) { | |
68 | return -EFAULT; | |
69 | } | |
70 | ||
71 | uk_args.ctx = session_data; | |
72 | err_code = _mali_ukk_map_external_mem( &uk_args ); | |
73 | ||
74 | if (0 != put_user(uk_args.cookie, &argument->cookie)) { | |
75 | if (_MALI_OSK_ERR_OK == err_code) { | |
76 | /* Rollback */ | |
77 | _mali_uk_unmap_external_mem_s uk_args_unmap; | |
78 | ||
79 | uk_args_unmap.ctx = session_data; | |
80 | uk_args_unmap.cookie = uk_args.cookie; | |
81 | err_code = _mali_ukk_unmap_external_mem( &uk_args_unmap ); | |
82 | if (_MALI_OSK_ERR_OK != err_code) { | |
83 | MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_unmap_external_mem, as a result of failing put_user(), failed\n")); | |
84 | } | |
85 | } | |
86 | return -EFAULT; | |
87 | } | |
88 | ||
89 | /* Return the error that _mali_ukk_free_big_block produced */ | |
90 | return map_errcode(err_code); | |
91 | } | |
92 | ||
93 | int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument) | |
94 | { | |
95 | _mali_uk_unmap_external_mem_s uk_args; | |
96 | _mali_osk_errcode_t err_code; | |
97 | ||
98 | /* validate input */ | |
99 | /* the session_data pointer was validated by caller */ | |
100 | MALI_CHECK_NON_NULL( argument, -EINVAL); | |
101 | ||
102 | /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ | |
103 | if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_unmap_external_mem_s)) ) { | |
104 | return -EFAULT; | |
105 | } | |
106 | ||
107 | uk_args.ctx = session_data; | |
108 | err_code = _mali_ukk_unmap_external_mem( &uk_args ); | |
109 | ||
110 | /* Return the error that _mali_ukk_free_big_block produced */ | |
111 | return map_errcode(err_code); | |
112 | } | |
113 | ||
114 | #if defined(CONFIG_MALI400_UMP) | |
115 | int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument) | |
116 | { | |
117 | _mali_uk_release_ump_mem_s uk_args; | |
118 | _mali_osk_errcode_t err_code; | |
119 | ||
120 | /* validate input */ | |
121 | /* the session_data pointer was validated by caller */ | |
122 | MALI_CHECK_NON_NULL( argument, -EINVAL); | |
123 | ||
124 | /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ | |
125 | if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_release_ump_mem_s)) ) { | |
126 | return -EFAULT; | |
127 | } | |
128 | ||
129 | uk_args.ctx = session_data; | |
130 | err_code = _mali_ukk_release_ump_mem( &uk_args ); | |
131 | ||
132 | /* Return the error that _mali_ukk_free_big_block produced */ | |
133 | return map_errcode(err_code); | |
134 | } | |
135 | ||
136 | int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument) | |
137 | { | |
138 | _mali_uk_attach_ump_mem_s uk_args; | |
139 | _mali_osk_errcode_t err_code; | |
140 | ||
141 | /* validate input */ | |
142 | /* the session_data pointer was validated by caller */ | |
143 | MALI_CHECK_NON_NULL( argument, -EINVAL); | |
144 | ||
145 | /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ | |
146 | if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_attach_ump_mem_s)) ) { | |
147 | return -EFAULT; | |
148 | } | |
149 | ||
150 | uk_args.ctx = session_data; | |
151 | err_code = _mali_ukk_attach_ump_mem( &uk_args ); | |
152 | ||
153 | if (0 != put_user(uk_args.cookie, &argument->cookie)) { | |
154 | if (_MALI_OSK_ERR_OK == err_code) { | |
155 | /* Rollback */ | |
156 | _mali_uk_release_ump_mem_s uk_args_unmap; | |
157 | ||
158 | uk_args_unmap.ctx = session_data; | |
159 | uk_args_unmap.cookie = uk_args.cookie; | |
160 | err_code = _mali_ukk_release_ump_mem( &uk_args_unmap ); | |
161 | if (_MALI_OSK_ERR_OK != err_code) { | |
162 | MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_attach_mem, as a result of failing put_user(), failed\n")); | |
163 | } | |
164 | } | |
165 | return -EFAULT; | |
166 | } | |
167 | ||
168 | /* Return the error that _mali_ukk_map_external_ump_mem produced */ | |
169 | return map_errcode(err_code); | |
170 | } | |
171 | #endif /* CONFIG_MALI400_UMP */ | |
172 | ||
173 | int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs) | |
174 | { | |
175 | _mali_uk_query_mmu_page_table_dump_size_s kargs; | |
176 | _mali_osk_errcode_t err; | |
177 | ||
178 | MALI_CHECK_NON_NULL(uargs, -EINVAL); | |
179 | MALI_CHECK_NON_NULL(session_data, -EINVAL); | |
180 | ||
181 | kargs.ctx = session_data; | |
182 | ||
183 | err = _mali_ukk_query_mmu_page_table_dump_size(&kargs); | |
184 | if (_MALI_OSK_ERR_OK != err) return map_errcode(err); | |
185 | ||
186 | if (0 != put_user(kargs.size, &uargs->size)) return -EFAULT; | |
187 | ||
188 | return 0; | |
189 | } | |
190 | ||
191 | int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs) | |
192 | { | |
193 | _mali_uk_dump_mmu_page_table_s kargs; | |
194 | _mali_osk_errcode_t err; | |
195 | void *buffer; | |
196 | int rc = -EFAULT; | |
197 | ||
198 | /* validate input */ | |
199 | MALI_CHECK_NON_NULL(uargs, -EINVAL); | |
200 | /* the session_data pointer was validated by caller */ | |
201 | ||
202 | kargs.buffer = NULL; | |
203 | ||
204 | /* get location of user buffer */ | |
205 | if (0 != get_user(buffer, &uargs->buffer)) goto err_exit; | |
206 | /* get size of mmu page table info buffer from user space */ | |
207 | if ( 0 != get_user(kargs.size, &uargs->size) ) goto err_exit; | |
208 | /* verify we can access the whole of the user buffer */ | |
209 | if (!access_ok(VERIFY_WRITE, buffer, kargs.size)) goto err_exit; | |
210 | ||
211 | /* allocate temporary buffer (kernel side) to store mmu page table info */ | |
212 | MALI_CHECK(kargs.size > 0, -ENOMEM); | |
213 | kargs.buffer = _mali_osk_valloc(kargs.size); | |
214 | if (NULL == kargs.buffer) { | |
215 | rc = -ENOMEM; | |
216 | goto err_exit; | |
217 | } | |
218 | ||
219 | kargs.ctx = session_data; | |
220 | err = _mali_ukk_dump_mmu_page_table(&kargs); | |
221 | if (_MALI_OSK_ERR_OK != err) { | |
222 | rc = map_errcode(err); | |
223 | goto err_exit; | |
224 | } | |
225 | ||
226 | /* copy mmu page table info back to user space and update pointers */ | |
227 | if (0 != copy_to_user(uargs->buffer, kargs.buffer, kargs.size) ) goto err_exit; | |
228 | if (0 != put_user((kargs.register_writes - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->register_writes)) goto err_exit; | |
229 | if (0 != put_user((kargs.page_table_dump - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->page_table_dump)) goto err_exit; | |
230 | if (0 != put_user(kargs.register_writes_size, &uargs->register_writes_size)) goto err_exit; | |
231 | if (0 != put_user(kargs.page_table_dump_size, &uargs->page_table_dump_size)) goto err_exit; | |
232 | rc = 0; | |
233 | ||
234 | err_exit: | |
235 | if (kargs.buffer) _mali_osk_vfree(kargs.buffer); | |
236 | return rc; | |
237 | } |