| [158] | 1 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 2 | // File     : sys_handler.c | 
|---|
 | 3 | // Date     : 01/04/2012 | 
|---|
 | 4 | // Author   : alain greiner and joel porquet | 
|---|
 | 5 | // Copyright (c) UPMC-LIP6 | 
|---|
 | 6 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [203] | 7 | // The sys_handler.c and sys_handler.h files are part of the GIET-VM nano-kernel. | 
|---|
| [158] | 8 | // It define the syscall_vector[] (at the end of this file), as well as the  | 
|---|
 | 9 | // associated syscall handlers that are not related to peripherals. | 
|---|
 | 10 | // The syscall handlers for peripherals are defined in the drivers.c file. | 
|---|
 | 11 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 12 |  | 
|---|
 | 13 | #include <sys_handler.h> | 
|---|
 | 14 | #include <drivers.h> | 
|---|
 | 15 | #include <ctx_handler.h> | 
|---|
 | 16 | #include <common.h> | 
|---|
 | 17 | #include <giet_config.h> | 
|---|
 | 18 | #include <mapping_info.h> | 
|---|
 | 19 |  | 
|---|
 | 20 | //////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 21 | //    Initialize the syscall vector with syscall handlers | 
|---|
| [158] | 22 | //////////////////////////////////////////////////////////////////////////// | 
|---|
| [253] | 23 | const void * _syscall_vector[32] =  | 
|---|
 | 24 | { | 
|---|
| [228] | 25 |     &_procid,              /* 0x00 */ | 
|---|
 | 26 |     &_proctime,            /* 0x01 */ | 
|---|
 | 27 |     &_tty_write,           /* 0x02 */ | 
|---|
 | 28 |     &_tty_read,            /* 0x03 */ | 
|---|
 | 29 |     &_timer_start,         /* 0x04 */ | 
|---|
 | 30 |     &_timer_stop,          /* 0x05 */ | 
|---|
 | 31 |     &_gcd_write,           /* 0x06 */ | 
|---|
 | 32 |     &_gcd_read,            /* 0x07 */ | 
|---|
| [232] | 33 |     &_heap_info,           /* 0x08 */ | 
|---|
| [238] | 34 |     &_local_task_id,       /* 0x09 */ | 
|---|
 | 35 |     &_global_task_id,      /* 0x0A */  | 
|---|
| [253] | 36 |     &_fb_cma_init,         /* 0x0B */ | 
|---|
 | 37 |     &_fb_cma_write,        /* 0x0C */ | 
|---|
 | 38 |     &_fb_cma_stop,         /* 0x0D */ | 
|---|
| [228] | 39 |     &_exit,                /* 0x0E */ | 
|---|
 | 40 |     &_procs_number,        /* 0x0F */ | 
|---|
 | 41 |     &_fb_sync_write,       /* 0x10 */ | 
|---|
 | 42 |     &_fb_sync_read,        /* 0x11 */ | 
|---|
| [253] | 43 |     &_fb_dma_write,        /* 0x12 */ | 
|---|
 | 44 |     &_fb_dma_read,         /* 0x13 */ | 
|---|
 | 45 |     &_fb_dma_completed,    /* 0x14 */ | 
|---|
| [228] | 46 |     &_ioc_write,           /* 0x15 */ | 
|---|
 | 47 |     &_ioc_read,            /* 0x16 */ | 
|---|
 | 48 |     &_ioc_completed,       /* 0x17 */ | 
|---|
| [237] | 49 |     &_ioc_get_block_size,  /* 0x18 */ | 
|---|
| [253] | 50 |     &_ctx_switch,          /* 0x19 */ | 
|---|
| [228] | 51 |     &_vobj_get_vbase,      /* 0x1A */ | 
|---|
| [253] | 52 |     &_nic_cma_rx_init,     /* 0x1B */ | 
|---|
 | 53 |     &_nic_cma_tx_init,     /* 0x1C */ | 
|---|
 | 54 |     &_nic_cma_stop,        /* 0x1D */ | 
|---|
 | 55 |     &_nic_sync_read,       /* 0x1E */ | 
|---|
 | 56 |     &_nic_sync_write,      /* 0x1F */ | 
|---|
| [158] | 57 | }; | 
|---|
 | 58 |  | 
|---|
 | 59 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 60 | // function executed in case of undefined syscall | 
|---|
 | 61 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 62 | void _sys_ukn() { | 
|---|
 | 63 |     unsigned int epc; | 
|---|
 | 64 |     asm volatile("mfc0 %0, $14" : "=r" (epc)); | 
|---|
| [158] | 65 |  | 
|---|
 | 66 |     _puts("\n\n!!! Undefined System Call !!!\n"); | 
|---|
 | 67 |     _puts("\nEPC = "); | 
|---|
| [228] | 68 |     _putx(epc); | 
|---|
| [158] | 69 |     _exit(); | 
|---|
 | 70 | } | 
|---|
| [228] | 71 |  | 
|---|
| [158] | 72 | //////////////////////////////////////////////////////////////////////////// | 
|---|
 | 73 | // _exit() | 
|---|
 | 74 | // Task suicide... after printing a death message. | 
|---|
 | 75 | //////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 76 | void _exit() { | 
|---|
 | 77 |     unsigned int date = _proctime(); | 
|---|
| [158] | 78 |     unsigned int proc_id = _procid(); | 
|---|
| [238] | 79 |     unsigned int task_id = _get_context_slot(CTX_LTID_ID); | 
|---|
| [189] | 80 |  | 
|---|
| [228] | 81 |     // print death message | 
|---|
| [189] | 82 |     _get_lock(&_tty_put_lock); | 
|---|
| [199] | 83 |     _puts("\n[GIET] Exit task "); | 
|---|
| [228] | 84 |     _putd(task_id); | 
|---|
| [158] | 85 |     _puts(" on processor "); | 
|---|
| [228] | 86 |     _putd(proc_id); | 
|---|
| [167] | 87 |     _puts(" at cycle "); | 
|---|
| [228] | 88 |     _putd(date); | 
|---|
| [165] | 89 |     _puts("\n\n"); | 
|---|
| [189] | 90 |     _release_lock(&_tty_put_lock); | 
|---|
| [228] | 91 |  | 
|---|
| [199] | 92 |     // goes to sleeping state | 
|---|
| [238] | 93 |     _set_context_slot(CTX_RUN_ID, 0); | 
|---|
| [228] | 94 |  | 
|---|
| [199] | 95 |     // deschedule | 
|---|
| [231] | 96 |     _context_switch(); | 
|---|
| [158] | 97 | }  | 
|---|
| [228] | 98 |  | 
|---|
| [158] | 99 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 100 | // _procid() | 
|---|
 | 101 | // Access CP0 and returns current processor's identifier. | 
|---|
 | 102 | // Max number or processors is 1024. | 
|---|
 | 103 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 104 | unsigned int _procid()  | 
|---|
 | 105 | { | 
|---|
| [158] | 106 |     unsigned int ret; | 
|---|
| [228] | 107 |     asm volatile("mfc0 %0, $15, 1" : "=r" (ret)); | 
|---|
| [165] | 108 |     return (ret & 0xFFF); | 
|---|
| [158] | 109 | } | 
|---|
| [228] | 110 |  | 
|---|
| [158] | 111 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 112 | // _proctime() | 
|---|
 | 113 | // Access CP0 and returns current processor's elapsed clock cycles since boot. | 
|---|
 | 114 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 115 | unsigned int _proctime()  | 
|---|
 | 116 | { | 
|---|
| [158] | 117 |     unsigned int ret; | 
|---|
| [228] | 118 |     asm volatile("mfc0 %0, $9" : "=r" (ret)); | 
|---|
| [158] | 119 |     return ret; | 
|---|
 | 120 | } | 
|---|
| [228] | 121 |  | 
|---|
| [158] | 122 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 123 | // _procnumber() | 
|---|
 | 124 | // returns in buffer argument the number of processors in the cluster | 
|---|
 | 125 | // specified by the cluster_id argument. | 
|---|
 | 126 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 127 | unsigned int _procs_number(unsigned int  cluster_id,  | 
|---|
 | 128 |                            unsigned int* buffer)  | 
|---|
 | 129 | { | 
|---|
| [228] | 130 |     mapping_header_t * header  = (mapping_header_t *) &seg_mapping_base; | 
|---|
 | 131 |     mapping_cluster_t * cluster = _get_cluster_base(header); | 
|---|
| [158] | 132 |  | 
|---|
| [228] | 133 |     if (cluster_id < header->clusters) { | 
|---|
| [158] | 134 |         *buffer = cluster[cluster_id].procs; | 
|---|
 | 135 |         return 0; | 
|---|
 | 136 |     } | 
|---|
| [228] | 137 |     else { | 
|---|
 | 138 |         return 1; | 
|---|
| [158] | 139 |     } | 
|---|
 | 140 | } | 
|---|
| [161] | 141 |  | 
|---|
| [238] | 142 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
 | 143 | // _local_task_id() | 
|---|
 | 144 | // Returns current task local index. | 
|---|
 | 145 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
 | 146 | unsigned int _local_task_id() | 
|---|
 | 147 | { | 
|---|
 | 148 |     return _get_context_slot(CTX_LTID_ID); | 
|---|
 | 149 | } | 
|---|
| [158] | 150 |  | 
|---|
| [238] | 151 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
 | 152 | // _global_task_id() | 
|---|
 | 153 | // Returns current task global index. | 
|---|
 | 154 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
 | 155 | unsigned int _global_task_id() | 
|---|
 | 156 | { | 
|---|
 | 157 |     return _get_context_slot(CTX_GTID_ID); | 
|---|
 | 158 | } | 
|---|
 | 159 |  | 
|---|
 | 160 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
 | 161 | // _get_vobj() | 
|---|
 | 162 | // This function writes in res_vobj a pointer on a vobj  | 
|---|
 | 163 | // identified by the (vspace_name / vobj_name ) couple. | 
|---|
 | 164 | // The vobj_type argument is here only for the purpose of checking . | 
|---|
 | 165 | // returns 0: success, else: failed. | 
|---|
 | 166 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
 | 167 | int _get_vobj( char*             vspace_name,  | 
|---|
 | 168 |                char*             vobj_name,  | 
|---|
 | 169 |                unsigned int      vobj_type,  | 
|---|
 | 170 |                mapping_vobj_t**  res_vobj )  | 
|---|
 | 171 | { | 
|---|
| [228] | 172 |     mapping_header_t * header = (mapping_header_t *) &seg_mapping_base; | 
|---|
 | 173 |     mapping_vspace_t * vspace = _get_vspace_base(header); | 
|---|
| [238] | 174 |     mapping_vobj_t * vobj     = _get_vobj_base(header); | 
|---|
| [158] | 175 |  | 
|---|
| [228] | 176 |     unsigned int vspace_id; | 
|---|
 | 177 |     unsigned int vobj_id; | 
|---|
 | 178 |  | 
|---|
| [158] | 179 |     // scan vspaces  | 
|---|
| [238] | 180 |     for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++)  | 
|---|
 | 181 |     { | 
|---|
 | 182 |         if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0)  | 
|---|
 | 183 |         { | 
|---|
| [160] | 184 |             // scan vobjs | 
|---|
| [228] | 185 |             for (vobj_id = vspace[vspace_id].vobj_offset;  | 
|---|
| [165] | 186 |                  vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs);  | 
|---|
| [238] | 187 |                  vobj_id++)  | 
|---|
 | 188 |             { | 
|---|
 | 189 |                 if (_strncmp(vobj[vobj_id].name, vobj_name, 31) == 0)  | 
|---|
 | 190 |                 { | 
|---|
 | 191 |                     if (vobj[vobj_id].type != vobj_type)  | 
|---|
 | 192 |                     { | 
|---|
| [228] | 193 |                         _get_lock(&_tty_put_lock); | 
|---|
 | 194 |                         _puts("*** Error in _get_obj: wrong type\n"); | 
|---|
 | 195 |                         _release_lock(&_tty_put_lock); | 
|---|
| [230] | 196 |                         return -1; // wrong type | 
|---|
| [228] | 197 |                     } | 
|---|
| [215] | 198 |                     *res_vobj = &vobj[vobj_id]; | 
|---|
| [158] | 199 |                     return 0; | 
|---|
 | 200 |                 } | 
|---|
 | 201 |             }  | 
|---|
 | 202 |         } | 
|---|
| [163] | 203 |     }  | 
|---|
| [228] | 204 |     _get_lock(&_tty_put_lock); | 
|---|
 | 205 |     _puts("*** Error in _get_obj: object not found\n"); | 
|---|
 | 206 |     _release_lock(&_tty_put_lock); | 
|---|
| [215] | 207 |  | 
|---|
| [228] | 208 |     return -2; //not found  | 
|---|
| [158] | 209 | } | 
|---|
| [228] | 210 |  | 
|---|
| [215] | 211 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
 | 212 | // _vobj_get_vbase() | 
|---|
 | 213 | // This function writes in vobj_vaddr the virtual base address of a vobj  | 
|---|
 | 214 | // identified by the (vspace_name / vobj_name ) couple. | 
|---|
 | 215 | // The vobj_type argument is here only for the purpose of checking . | 
|---|
 | 216 | // returns 0: success, else: failed. | 
|---|
 | 217 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 218 | unsigned int _vobj_get_vbase( char*         vspace_name, | 
|---|
 | 219 |                               char*         vobj_name, | 
|---|
 | 220 |                               unsigned int  vobj_type, | 
|---|
 | 221 |                               unsigned int* vobj_vaddr )  | 
|---|
 | 222 | { | 
|---|
 | 223 |     mapping_vobj_t* res_vobj; | 
|---|
 | 224 |     unsigned int    ret; | 
|---|
 | 225 |     if ((ret = _get_vobj(vspace_name, vobj_name, vobj_type, &res_vobj)))  | 
|---|
 | 226 |     { | 
|---|
| [215] | 227 |         return ret; | 
|---|
 | 228 |     } | 
|---|
 | 229 |     *vobj_vaddr = res_vobj->vaddr; | 
|---|
 | 230 |     return 0; | 
|---|
 | 231 | } | 
|---|
 | 232 |  | 
|---|
 | 233 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
 | 234 | // _vobj_get_length() | 
|---|
 | 235 | // This function writes in vobj_length the virtual base address of a vobj  | 
|---|
 | 236 | // identified by the (vspace_name / vobj_name ) couple. | 
|---|
 | 237 | // The vobj_type argument is here only for the purpose of checking . | 
|---|
 | 238 | // returns 0: success, else: failed. | 
|---|
 | 239 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 240 | unsigned int _vobj_get_length( char*         vspace_name,  | 
|---|
 | 241 |                                char*         vobj_name, | 
|---|
 | 242 |                                unsigned int  vobj_type,  | 
|---|
 | 243 |                                unsigned int* vobj_length )  | 
|---|
 | 244 | { | 
|---|
| [228] | 245 |     mapping_vobj_t * res_vobj; | 
|---|
| [215] | 246 |     unsigned int ret; | 
|---|
| [238] | 247 |     if ((ret = _get_vobj(vspace_name, vobj_name, vobj_type, &res_vobj)))  | 
|---|
 | 248 |     { | 
|---|
| [215] | 249 |         return ret; | 
|---|
 | 250 |     } | 
|---|
 | 251 |     *vobj_length = res_vobj->length; | 
|---|
 | 252 |     return 0; | 
|---|
 | 253 | } | 
|---|
| [228] | 254 |  | 
|---|
 | 255 |  | 
|---|
 | 256 | //////////////////////////////////////////////////////////////// | 
|---|
 | 257 | // _context_switch() | 
|---|
 | 258 | // This functions masks interruptions before calling _ctx_switch | 
|---|
 | 259 | // (They are usually masked when we receive a isr_switch interrupt | 
|---|
| [238] | 260 | // because we execute ISRs with interrupt masked) | 
|---|
| [228] | 261 | //////////////////////////////////////////////////////////////// | 
|---|
| [238] | 262 | void _context_switch()  | 
|---|
 | 263 | { | 
|---|
| [231] | 264 |     _it_disable(); | 
|---|
| [228] | 265 |     _ctx_switch(); | 
|---|
 | 266 | } | 
|---|
 | 267 |  | 
|---|
 | 268 |  | 
|---|
 | 269 | // Local Variables: | 
|---|
 | 270 | // tab-width: 4 | 
|---|
 | 271 | // c-basic-offset: 4 | 
|---|
 | 272 | // c-file-offsets:((innamespace . 0)(inline-open . 0)) | 
|---|
 | 273 | // indent-tabs-mode: nil | 
|---|
 | 274 | // End: | 
|---|
 | 275 | // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 | 
|---|
 | 276 |  | 
|---|