source: trunk/kernel/syscalls/sys_get.c@ 690

Last change on this file since 690 was 690, checked in by alain, 6 years ago

Introduce the sys_get.c file in replacement of
sys_get_*.c files.

File size: 15.7 KB
Line 
1/*
2 * sys_get.c - Kernel function implementing all non_standard "get_xxx()" syscalls.
3 *
4 * Author Alain Greiner (2016,2017,2018,2019,2020)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_kernel_types.h>
25#include <hal_uspace.h>
26#include <hal_vmm.h>
27#include <hal_special.h>
28#include <errno.h>
29#include <core.h>
30#include <thread.h>
31#include <process.h>
32#include <vmm.h>
33#include <printk.h>
34
35#include <syscalls.h>
36
37/////////////////////////////////////////////////////////////////////////////////
38// This function returns a printable string for the sys_get command type.
39/////////////////////////////////////////////////////////////////////////////////
40
41#if DEBUG_SYS_GET
42static char* get_cmd_type_str( uint32_t type )
43{
44 if ( type == GET_PROCESSES ) return "PROCESSES";
45 else if( type == GET_CONFIG ) return "CONFIG";
46 else if( type == GET_CORE_ID ) return "CORE_ID";
47 else if( type == GET_NB_CORES ) return "NB_CORES";
48 else if( type == GET_BEST_CORE ) return "BEST_CORE";
49 else if( type == GET_CYCLE ) return "CYCLE";
50 else if( type == GET_THREAD_INFO ) return "THREAD_INFO";
51 else return "undefined";
52}
53#endif
54
55//////////////////////////
56int sys_get ( reg_t arg0,
57 reg_t arg1,
58 reg_t arg2,
59 reg_t arg3 )
60{
61 vseg_t * vseg;
62 int ret;
63
64 thread_t * this = CURRENT_THREAD;
65 process_t * process = this->process;
66
67 uint32_t type = arg0;
68
69#if DEBUG_SYS_GET || DEBUG_SYSCALLS_ERROR || CONFIG_INSTRUMENTATION_SYSCALLS
70uint64_t tm_start = hal_get_cycles();
71#endif
72
73#if DEBUG_SYS_GET
74if( DEBUG_SYS_GET < (uint32_t)tm_start )
75printk("\n[%s] thread[%x,%x] enter / %s / a1 %x / a2 %x / a3 %x / cycle %d\n",
76__FUNCTION__, process->pid, this->trdid, get_cmd_type_str( type ),
77arg1, arg2, arg3, (uint32_t)tm_start );
78#endif
79
80 switch( type )
81 {
82 ///////////////
83 case GET_CYCLE:
84 {
85 char * u_buf = (char *)(intptr_t)arg1;
86
87 // check buffer in user space
88 if( vmm_get_vseg( process , (intptr_t)arg1 , &vseg ) )
89 {
90
91#if DEBUG_SYSCALLS_ERROR
92if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
93printk("\n[ERROR] in %s for CYCLE : thread[%x,%x] / user buffer unmapped %x\n",
94__FUNCTION__ , process->pid , this->trdid , (intptr_t)arg1 );
95#endif
96 this->errno = EINVAL;
97 ret = -1;
98 break;
99 }
100
101 // call relevant core function
102 uint64_t k_cycle = hal_get_cycles();
103
104 // copy to user space
105 hal_copy_to_uspace( u_buf,
106 XPTR( local_cxy , &k_cycle ),
107 sizeof(uint64_t) );
108 ret = 0;
109 break;
110 }
111 ///////////////////
112 case GET_PROCESSES:
113 {
114 uint32_t cxy = ((uint32_t)arg1 >> 16);
115 uint32_t owned = ((uint32_t)arg1 & 0xFFFF);
116 char * u_buf = (char *)(intptr_t)arg2;
117 uint32_t size = (uint32_t)arg3;
118
119 char k_buf[CONFIG_PROCESS_DISPLAY_BUF_SIZE]; // kernel buffer (one line)
120
121 uint32_t length; // number of bytes copied in k_buf (without NUL)
122 uint32_t offset = 0; // number of bytes already copied to u_buf
123 xptr_t iter_xp;
124
125 // check buffer in user space
126 if( vmm_get_vseg( process , (intptr_t)u_buf , &vseg ) )
127 {
128
129#if DEBUG_SYSCALLS_ERROR
130if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
131printk("\n[ERROR] in %s for PROCESSES : thread[%x,%x] / user buffer unmapped %x\n",
132__FUNCTION__ , process->pid , this->trdid , (intptr_t)arg2 );
133#endif
134 this->errno = EINVAL;
135 ret = -1;
136 break;
137 }
138
139#if DEBUG_SYS_GET
140if( DEBUG_SYS_GET < (uint32_t)tm_start )
141printk("\n[%s] for PROCESSES : thread[%x,%x] cxy %x / owned %d\n",
142__FUNCTION__, process->pid, this->trdid, cxy, owned );
143#endif
144
145 // build extended pointers on root and lock of process list in cluster cxy
146 xptr_t root_xp = XPTR( cxy , &LOCAL_CLUSTER->pmgr.local_root );
147 xptr_t lock_xp = XPTR( cxy , &LOCAL_CLUSTER->pmgr.local_lock );
148
149 // take lock on process list
150 remote_queuelock_acquire( lock_xp );
151
152 // loop on all processes in cluster cxy
153 XLIST_FOREACH( root_xp , iter_xp )
154 {
155 // get process pointers
156 xptr_t process_xp = XLIST_ELEMENT( iter_xp , process_t , local_list );
157 process_t * process_ptr = GET_PTR( process_xp );
158 cxy_t process_cxy = GET_CXY( process_xp );
159
160 // get process PID
161 pid_t pid = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) );
162
163#if DEBUG_SYS_GET
164if( DEBUG_SYS_GET < (uint32_t)tm_start )
165printk("\n[%s] for PROCESSES : thread[%x,%x] in FOREACH / pid %x\n",
166__FUNCTION__, process->pid, this->trdid, pid );
167#endif
168
169 // when owned is set, display only owned user processes
170 if( (owned == 0) ||
171 ((CXY_FROM_PID( pid ) == cxy) && (LPID_FROM_PID( pid ) != 0)) )
172 {
173 // build string for one line (one process descriptor)
174 length = process_build_string( process_xp,
175 k_buf,
176 CONFIG_PROCESS_DISPLAY_BUF_SIZE );
177
178 // copy this string to u_buf (with the '\n' , but without the NUL)
179 hal_copy_to_uspace( u_buf + offset,
180 XPTR( local_cxy , k_buf ),
181 length );
182 // update offset
183 offset += length;
184 }
185
186 // check user buffer overflow
187 if( (offset + CONFIG_PROCESS_DISPLAY_BUF_SIZE) >= size )
188 {
189 // build a warning message
190 length = snprintk( k_buf , CONFIG_PROCESS_DISPLAY_BUF_SIZE ,
191 " ... user buffer too for all process in cluster %x", cxy );
192
193 // copy this string to u_buf
194 hal_copy_to_uspace( u_buf + offset,
195 XPTR( local_cxy , k_buf ),
196 length );
197 // exit FOREACH loop
198 break;
199 }
200 else // add the NUL character in u_buf
201 {
202 char byte = 0;
203
204 // copy this NUL character to u_buf
205 hal_copy_to_uspace( u_buf + offset,
206 XPTR( local_cxy , &byte ),
207 1 );
208 }
209 } // end FOREACH
210
211 // release lock on process list
212 remote_queuelock_release( lock_xp );
213
214 ret = 0;
215 break;
216 }
217 ////////////////
218 case GET_CONFIG:
219 {
220 hard_config_t * u_config = (hard_config_t *)arg1;
221
222 hard_config_t k_config; // local kernel structure
223
224 // check u_config mapped in user space
225 if( vmm_get_vseg( process , (intptr_t)u_config , &vseg ) )
226 {
227
228#if DEBUG_SYSCALLS_ERROR
229if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
230printk("\n[ERROR] in %s for CONFIG : thread[%x,%x] / user pointer %x unmapped\n",
231__FUNCTION__ , process->pid , this->trdid , (intptr_t)u_config );
232#endif
233 this->errno = EINVAL;
234 ret = -1;
235 break;
236 }
237
238 // copy config parameters from cluster descriptor to kernel structure
239 k_config.x_size = LOCAL_CLUSTER->x_size;
240 k_config.y_size = LOCAL_CLUSTER->y_size;
241 k_config.ncores = LOCAL_CLUSTER->cores_nr;
242 k_config.txt_channels = LOCAL_CLUSTER->nb_txt_channels;
243 k_config.nic_channels = LOCAL_CLUSTER->nb_nic_channels;
244 k_config.ioc_channels = LOCAL_CLUSTER->nb_ioc_channels;
245 k_config.fbf_channels = LOCAL_CLUSTER->nb_fbf_channels;
246
247 // copy k_config structure to user space
248 hal_copy_to_uspace( u_config ,
249 XPTR(local_cxy, &k_config ),
250 sizeof(hard_config_t) );
251 ret = 0;
252 break;
253 }
254 /////////////////
255 case GET_CORE_ID:
256 {
257 uint32_t * u_cxy = (uint32_t *)arg1;
258 uint32_t * u_lid = (uint32_t *)arg2;
259
260 // check cxy buffer in user space
261 if( vmm_get_vseg( process , (intptr_t)u_cxy , &vseg ) )
262 {
263
264#if DEBUG_SYSCALLS_ERROR
265if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
266printk("\n[ERROR] in %s for CORE_ID : thread[%x,%x] / cxy buffer unmapped %x\n",
267__FUNCTION__ , process->pid , this->trdid , (intptr_t)u_cxy );
268#endif
269 this->errno = EINVAL;
270 ret = -1;
271 break;
272 }
273
274 // check lid buffer in user space
275 if( vmm_get_vseg( process , (intptr_t)u_lid , &vseg ) )
276 {
277
278#if DEBUG_SYSCALLS_ERROR
279if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
280printk("\n[ERROR] in %s for CORE_ID : thread[%x,%x] / lid buffer unmapped %x\n",
281__FUNCTION__ , process->pid , this->trdid , (intptr_t)u_lid );
282#endif
283 this->errno = EINVAL;
284 ret = -1;
285 break;
286 }
287
288 // get lid from core decriptor
289 lid_t lid = this->core->lid;
290
291 // copy cxy to user space
292 hal_copy_to_uspace( u_cxy,
293 XPTR( local_cxy , &local_cxy ),
294 sizeof(uint32_t) );
295
296 hal_copy_to_uspace( u_lid,
297 XPTR( local_cxy , &lid ),
298 sizeof(uint32_t) );
299 ret = 0;
300 break;
301 }
302 //////////////////
303 case GET_NB_CORES:
304 {
305 uint32_t cores;
306 cxy_t cxy = arg1;
307 uint32_t * u_cores = (uint32_t *)arg2;
308
309 // check ncores buffer in user space
310 if( vmm_get_vseg( process , (intptr_t)u_cores , &vseg ) )
311 {
312
313#if DEBUG_SYSCALLS_ERROR
314if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
315printk("\n[ERROR] in %s for NB_CORES : thread[%x,%x] / user buffer unmapped %x\n",
316__FUNCTION__ , process->pid , this->trdid , (intptr_t)u_cores );
317#endif
318 this->errno = EFAULT;
319 ret = -1;
320 break;
321 }
322
323 // get number of cores in cluster
324 if( cluster_is_active( cxy ) )
325 {
326 cores = hal_remote_l32( XPTR( cxy , &LOCAL_CLUSTER->cores_nr ) );
327 }
328 else // target cluster undefined
329 {
330 cores = 0;
331 }
332
333 // copy to user space
334 hal_copy_to_uspace( u_cores,
335 XPTR( local_cxy , &cores ),
336 sizeof(uint32_t) );
337 ret = 0;
338 break;
339 }
340 ///////////////////
341 case GET_BEST_CORE:
342 {
343 uint32_t base_cxy = ((uint32_t)arg1 >> 16);
344 uint32_t level = ((uint32_t)arg1 & 0xFFFF);
345 uint32_t * cxy = (uint32_t *)(intptr_t)arg2;
346 uint32_t * lid = (uint32_t *)(intptr_t)arg3;
347
348 uint32_t k_cxy;
349 uint32_t k_lid;
350
351 // check <cxy> buffer in user space
352 if( vmm_get_vseg( process , (intptr_t)cxy , &vseg ) )
353 {
354
355#if DEBUG_SYSCALLS_ERROR
356if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
357printk("\n[ERROR] in %s for BEST_CORE : thread[%x,%x] / user buffer cxy unmapped %x\n",
358__FUNCTION__ , process->pid , this->trdid , cxy );
359#endif
360 this->errno = EINVAL;
361 ret = -1;
362 break;
363 }
364
365 // check <lid> buffer in user space
366 if( vmm_get_vseg( process , (intptr_t)lid , &vseg ) )
367 {
368
369#if DEBUG_SYSCALLS_ERROR
370if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
371printk("\n[ERROR] in %s for BEST_CORE : thread[%x,%x] / user buffer lid unmapped %x\n",
372__FUNCTION__ , process->pid , this->trdid , lid );
373#endif
374 this->errno = EINVAL;
375 ret = -1;
376 break;
377 }
378
379 // check level argument
380 if( level > 5 )
381 {
382
383#if DEBUG_SYSCALLS_ERROR
384if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
385printk("\n[ERROR] in %s for BEST_CORE : thread[%x,%x] / level argument %d too large\n",
386__FUNCTION__ , process->pid , this->trdid , level );
387#endif
388 this->errno = EINVAL;
389 ret = -1;
390 break;
391 }
392
393 // get extended pointer on the macro-cluster DQDT root node
394 xptr_t root_xp = dqdt_get_root( base_cxy , level );
395
396 if( root_xp == XPTR_NULL ) // macro-cluster undefined
397 {
398
399#if DEBUG_SYSCALLS_ERROR
400if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
401printk("\n[ERROR] in %s for BEST_CORE ; thread[%x,%x] DQDT undefined\n",
402__FUNCTION__, process->pid, this->trdid );
403#endif
404 this->errno = EINVAL;
405 ret = -1;
406 break;
407 }
408
409 // get best core in best cluster
410 k_cxy = (uint32_t)dqdt_get_cluster_for_thread( root_xp );
411 k_lid = (uint32_t)cluster_select_local_core( k_cxy );
412
413 // copy to user space
414 hal_copy_to_uspace( cxy,
415 XPTR( local_cxy , &k_cxy ),
416 sizeof(uint32_t) );
417
418 hal_copy_to_uspace( lid,
419 XPTR( local_cxy , &k_lid ),
420 sizeof(uint32_t) );
421 ret = 0;
422 break;
423 }
424 /////////////////////
425 case GET_THREAD_INFO:
426 {
427 thread_info_t * u_info = (thread_info_t *)arg1;
428
429 // check buffer in user space
430 if( vmm_get_vseg( process , (intptr_t)u_info , &vseg ) )
431 {
432
433#if DEBUG_SYSCALLS_ERROR
434if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
435printk("\n[ERROR] in %s for THREAD_INFO : thread[%x,%x] / user buffer unmapped %x\n",
436__FUNCTION__ , process->pid , this->trdid , (intptr_t)u_info );
437#endif
438 this->errno = EINVAL;
439 ret = -1;
440 break;
441 }
442
443 // copy this thread_info_t structure to user space
444 hal_copy_to_uspace( u_info,
445 XPTR( local_cxy , &this->info),
446 sizeof(thread_info_t) );
447 ret = 0;
448 break;
449 }
450 default:
451 {
452 ret = -1;
453 }
454 } // end switch cmd
455
456 hal_fence();
457
458#if (DEBUG_SYS_GET || CONFIG_INSTRUMENTATION_SYSCALLS)
459uint64_t tm_end = hal_get_cycles();
460#endif
461
462#if DEBUG_SYS_GET
463if( DEBUG_SYS_GET < tm_end )
464printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
465__FUNCTION__ , process->pid, this->trdid, (uint32_t)tm_end );
466#endif
467
468#if CONFIG_INSTRUMENTATION_SYSCALLS
469hal_atomic_add( &syscalls_cumul_cost[SYS_GET] , tm_end - tm_start );
470hal_atomic_add( &syscalls_occurences[SYS_GET] , 1 );
471#endif
472
473 return ret;
474
475} // end sys_get()
Note: See TracBrowser for help on using the repository browser.