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

Last change on this file since 690 was 690, checked in by alain, 9 months 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.