| [1] | 1 | /* | 
|---|
 | 2 |  * kernel_init.c - kernel parallel initialization | 
|---|
 | 3 |  *  | 
|---|
 | 4 |  * Authors :  Alain Greiner  (2016) | 
|---|
 | 5 |  * | 
|---|
 | 6 |  * Copyright (c) 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 <almos_config.h> | 
|---|
 | 25 | #include <errno.h> | 
|---|
 | 26 | #include <hal_types.h> | 
|---|
 | 27 | #include <hal_special.h> | 
|---|
 | 28 | #include <hal_context.h> | 
|---|
 | 29 | #include <remote_barrier.h> | 
|---|
 | 30 | #include <core.h> | 
|---|
 | 31 | #include <list.h> | 
|---|
 | 32 | #include <thread.h> | 
|---|
 | 33 | #include <scheduler.h> | 
|---|
 | 34 | #include <kmem.h> | 
|---|
 | 35 | #include <cluster.h> | 
|---|
 | 36 | #include <devfs.h> | 
|---|
 | 37 | #include <sysfs.h> | 
|---|
 | 38 | #include <string.h> | 
|---|
 | 39 | #include <memcpy.h> | 
|---|
 | 40 | #include <ppm.h> | 
|---|
 | 41 | #include <page.h> | 
|---|
| [5] | 42 | #include <chdev.h> | 
|---|
| [1] | 43 | #include <boot_info.h> | 
|---|
 | 44 | #include <dqdt.h> | 
|---|
 | 45 | #include <dev_icu.h> | 
|---|
 | 46 | #include <dev_mmc.h> | 
|---|
| [5] | 47 | #include <dev_dma.h> | 
|---|
 | 48 | #include <dev_iob.h> | 
|---|
| [1] | 49 | #include <dev_ioc.h> | 
|---|
| [5] | 50 | #include <dev_txt.h> | 
|---|
| [1] | 51 | #include <dev_pic.h> | 
|---|
 | 52 | #include <printk.h> | 
|---|
 | 53 | #include <vfs.h> | 
|---|
| [5] | 54 | #include <soclib_tty.h> | 
|---|
| [1] | 55 |  | 
|---|
 | 56 |  | 
|---|
| [5] | 57 | #define KERNEL_INIT_SYNCHRO  0xA5A5B5B5 | 
|---|
| [1] | 58 |  | 
|---|
 | 59 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 60 | // All these global variables are replicated in all clusters. | 
|---|
 | 61 | // They are initialised by the kernel_init() function. | 
|---|
 | 62 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 63 |  | 
|---|
| [5] | 64 | // This variable defines the local boot_info structure | 
|---|
 | 65 | __attribute__((section(".kinfo"))) | 
|---|
 | 66 | boot_info_t          boot_info          CACHELINE_ALIGNED; | 
|---|
 | 67 |  | 
|---|
| [1] | 68 | // This variable defines the local cluster manager  | 
|---|
| [5] | 69 | __attribute__((section(".kdata"))) | 
|---|
| [1] | 70 | cluster_t            cluster_manager    CACHELINE_ALIGNED;  | 
|---|
 | 71 |  | 
|---|
| [5] | 72 | // These variables define the kernel process0 descriptor and associated thread | 
|---|
 | 73 | __attribute__((section(".kdata"))) | 
|---|
| [1] | 74 | process_t            process_zero       CACHELINE_ALIGNED;             | 
|---|
 | 75 | thread_t             thread_zero        CACHELINE_ALIGNED; | 
|---|
 | 76 |  | 
|---|
 | 77 | // This variable contains the extended pointers on the device descriptors | 
|---|
| [5] | 78 | __attribute__((section(".kdata"))) | 
|---|
 | 79 | chdev_directory_t    chdev_dir          CACHELINE_ALIGNED; | 
|---|
| [1] | 80 |  | 
|---|
| [5] | 81 | // This variable contains the input IRQ indexes for the PIC device | 
|---|
 | 82 | __attribute__((section(".kdata"))) | 
|---|
 | 83 | chdev_pic_input_t    chdev_pic_input    CACHELINE_ALIGNED; | 
|---|
| [1] | 84 |  | 
|---|
| [5] | 85 | // This variable contains the input IRQ indexes for the ICU device | 
|---|
 | 86 | __attribute__((section(".kdata"))) | 
|---|
 | 87 | chdev_icu_input_t    chdev_icu_input    CACHELINE_ALIGNED; | 
|---|
| [1] | 88 |  | 
|---|
| [5] | 89 | // This variable synchronizes the local cores during kernel_init() | 
|---|
 | 90 | __attribute__((section(".kdata"))) | 
|---|
 | 91 | volatile uint32_t    local_sync_init    CACHELINE_ALIGNED;   | 
|---|
 | 92 |  | 
|---|
| [1] | 93 | // This variable defines the local cluster identifier | 
|---|
| [5] | 94 | __attribute__((section(".kdata"))) | 
|---|
 | 95 | cxy_t                local_cxy          CACHELINE_ALIGNED; | 
|---|
| [1] | 96 |  | 
|---|
| [5] | 97 | // This variable is the lock protecting the kernel TXT terminal (used by printk) | 
|---|
 | 98 | __attribute__((section(".kdata"))) | 
|---|
 | 99 | remote_spinlock_t    txt0_lock          CACHELINE_ALIGNED; | 
|---|
| [1] | 100 |  | 
|---|
 | 101 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [5] | 102 | // This function displays the ALMOS_MKH banner. | 
|---|
| [1] | 103 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [5] | 104 | static void print_banner( uint32_t nclusters , uint32_t ncores ) | 
|---|
| [1] | 105 | {  | 
|---|
| [5] | 106 |     printk("\n" | 
|---|
 | 107 |            "                    _        __    __     _____     ______         __    __    _   __   _     _   \n" | 
|---|
 | 108 |            "          /\\       | |      |  \\  /  |   / ___ \\   / _____|       |  \\  /  |  | | / /  | |   | |  \n" | 
|---|
 | 109 |            "         /  \\      | |      |   \\/   |  | /   \\ | | /             |   \\/   |  | |/ /   | |   | |  \n" | 
|---|
 | 110 |            "        / /\\ \\     | |      | |\\  /| |  | |   | | | |_____   ___  | |\\  /| |  |   /    | |___| |  \n" | 
|---|
 | 111 |            "       / /__\\ \\    | |      | | \\/ | |  | |   | | \\_____  \\ |___| | | \\/ | |  |   \\    |  ___  |  \n" | 
|---|
 | 112 |            "      / ______ \\   | |      | |    | |  | |   | |       | |       | |    | |  | |\\ \\   | |   | |  \n" | 
|---|
 | 113 |            "     / /      \\ \\  | |____  | |    | |  | \\___/ |  _____/ |       | |    | |  | | \\ \\  | |   | |  \n" | 
|---|
 | 114 |            "    /_/        \\_\\ |______| |_|    |_|   \\_____/  |______/        |_|    |_|  |_|  \\_\\ |_|   |_|  \n" | 
|---|
 | 115 |            "\n\n\t\t Advanced Locality Management Operating System / Multi Kernel Hybrid\n" | 
|---|
 | 116 |            "\n\n\t\t\t Version 0.0   :   %d clusters   /   %d cores per cluster\n\n", nclusters , ncores );  | 
|---|
 | 117 | } | 
|---|
| [1] | 118 |  | 
|---|
 | 119 |  | 
|---|
| [5] | 120 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 121 | // This static function allocates memory and initializes the TXT0 chdev descriptor, | 
|---|
 | 122 | // associated to the kernel terminal, shared by all kernel instances for debug messages. | 
|---|
 | 123 | // It should be called by a thread running in the I/O cluster, because the TXT0 chdev | 
|---|
 | 124 | // is created in the I/O cluster. | 
|---|
 | 125 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 126 | // @ info    : pointer on the local boot-info structure. | 
|---|
 | 127 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 128 | static void txt0_device_init( boot_info_t * info ) | 
|---|
 | 129 | { | 
|---|
 | 130 |     boot_device_t * dev_tbl;         // pointer on array of devices in boot_info | 
|---|
 | 131 |         uint32_t        dev_nr;          // actual number of devices in this cluster | 
|---|
 | 132 |         xptr_t          base;            // remote pointer on segment base | 
|---|
 | 133 |         uint32_t        size;            // channel size (bytes) | 
|---|
 | 134 |     uint32_t        type;            // peripheral type | 
|---|
 | 135 |     uint32_t        func;            // device functionnal index | 
|---|
 | 136 |     uint32_t        impl;            // device implementation index | 
|---|
 | 137 |         uint32_t        i;               // device index in dev_tbl | 
|---|
 | 138 |         uint32_t        x;               // X cluster coordinate | 
|---|
 | 139 |         uint32_t        y;               // Y cluster coordinate | 
|---|
 | 140 |         chdev_t       * chdev;           // local pointer on created chdev | 
|---|
| [1] | 141 |  | 
|---|
| [5] | 142 |     // get number of peripherals and base of devices array from boot_info | 
|---|
 | 143 |         dev_nr      = info->ext_dev_nr; | 
|---|
 | 144 |     dev_tbl     = info->ext_dev; | 
|---|
| [1] | 145 |  | 
|---|
| [5] | 146 |     // loop on external peripherals to find TXT | 
|---|
 | 147 |         for( i = 0 ; i < dev_nr ; i++ ) | 
|---|
 | 148 |         { | 
|---|
 | 149 |         size        = dev_tbl[i].size; | 
|---|
 | 150 |         base        = dev_tbl[i].base; | 
|---|
 | 151 |         type        = dev_tbl[i].type; | 
|---|
 | 152 |         func        = FUNC_FROM_TYPE( type ); | 
|---|
 | 153 |         impl        = IMPL_FROM_TYPE( type ); | 
|---|
 | 154 |  | 
|---|
 | 155 |         if (func == DEV_FUNC_TXT )  | 
|---|
 | 156 |         { | 
|---|
 | 157 |             // allocate and initialize a local chdev for TXT0 | 
|---|
 | 158 |             chdev = chdev_create( func, | 
|---|
 | 159 |                                   impl, | 
|---|
 | 160 |                                   0,        // channel | 
|---|
 | 161 |                                   0,        // direction | 
|---|
 | 162 |                                   base ); | 
|---|
 | 163 |  | 
|---|
 | 164 |             // Complete TXT specific initialisation | 
|---|
 | 165 |             if( impl == IMPL_TXT_TTY ) | 
|---|
 | 166 |             { | 
|---|
 | 167 |                 chdev->cmd = &soclib_tty_cmd; | 
|---|
 | 168 |                 chdev->isr = &soclib_tty_isr; | 
|---|
 | 169 |                 soclib_tty_init( chdev ); | 
|---|
 | 170 |             } | 
|---|
 | 171 |  | 
|---|
 | 172 |             // initialize the replicated chdev_dir[x][y] structures | 
|---|
 | 173 |             for( x = 0 ; x < info->x_size ; x++ ) | 
|---|
 | 174 |             { | 
|---|
 | 175 |                 for( y = 0 ; y < info->y_size ; y++ ) | 
|---|
 | 176 |                 { | 
|---|
 | 177 |                     cxy_t  cxy = (x<<info->y_width) + y; | 
|---|
 | 178 |                     hal_remote_swd( XPTR( cxy , &chdev_dir.txt[0] ) , XPTR( local_cxy , chdev ) ); | 
|---|
 | 179 |                 } | 
|---|
 | 180 |             } | 
|---|
 | 181 |  | 
|---|
 | 182 |                     kinit_dmsg("\n[INFO] %s : core[%x][0] created TXT0 chdev / paddr = %l at cycle %d\n", | 
|---|
 | 183 |                        __FUNCTION__ , local_cxy , chdev_func_str( func ), chdev_xp , hal_time_stamp() ); | 
|---|
 | 184 |         } | 
|---|
 | 185 |  | 
|---|
 | 186 |         } // end loop on devices | 
|---|
 | 187 |  | 
|---|
 | 188 | }  // end txt0_device_init() | 
|---|
 | 189 |  | 
|---|
| [1] | 190 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [5] | 191 | // This static function allocates memory for the chdev (channel_device) descriptors | 
|---|
 | 192 | // associated to the internal peripherals contained in the local cluster. These internal | 
|---|
 | 193 | // devices (ICU, MMC, DMA) chdev descriptors are placed in the local cluster. | 
|---|
| [1] | 194 | // It initialises these device descriptors as specified by the boot_info_t structure, | 
|---|
 | 195 | // including the dynamic linking with the driver for the specified implementation. | 
|---|
 | 196 | // Finally, all copies of the devices directory are initialised. | 
|---|
 | 197 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 198 | // @ info    : pointer on the local boot-info structure. | 
|---|
 | 199 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [5] | 200 | static void internal_devices_init( boot_info_t * info ) | 
|---|
| [1] | 201 | { | 
|---|
 | 202 |     boot_device_t * dev_tbl;         // pointer on array of devices in boot_info | 
|---|
 | 203 |         uint32_t        dev_nr;          // actual number of devices in this cluster | 
|---|
 | 204 |         xptr_t          base;            // remote pointer on segment base | 
|---|
 | 205 |         uint32_t        size;            // channel size (bytes) | 
|---|
 | 206 |     uint32_t        type;            // peripheral type | 
|---|
 | 207 |     uint32_t        func;            // device functionnal index | 
|---|
 | 208 |     uint32_t        impl;            // device implementation index | 
|---|
 | 209 |         uint32_t        i;               // device index in dev_tbl | 
|---|
 | 210 |         uint32_t        x;               // X cluster coordinate | 
|---|
 | 211 |         uint32_t        y;               // Y cluster coordinate | 
|---|
| [5] | 212 |         uint32_t        channels_nr;     // number of channels in device | 
|---|
 | 213 |         uint32_t        channel;         // channel index | 
|---|
| [1] | 214 |         uint32_t        p0;              // device parameter 0 | 
|---|
 | 215 |         uint32_t        p1;              // device parameter 1 | 
|---|
 | 216 |         uint32_t        p2;              // device parameter 2 | 
|---|
 | 217 |         uint32_t        p3;              // device parameter 3 | 
|---|
 | 218 |  | 
|---|
| [5] | 219 |         chdev_t       * chdev;           // local pointer on one channel_device descriptor | 
|---|
 | 220 |     xptr_t          chdev_xp;        // extended pointer on channel_device descriptor | 
|---|
| [1] | 221 |  | 
|---|
| [5] | 222 |     // get number of internal devices and base of devices array from boot_info | 
|---|
 | 223 |         dev_nr      = info->int_dev_nr; | 
|---|
 | 224 |     dev_tbl     = info->int_dev; | 
|---|
 | 225 |  | 
|---|
 | 226 |     // loop on all internal devices in cluster | 
|---|
| [1] | 227 |         for( i = 0 ; i < dev_nr ; i++ ) | 
|---|
 | 228 |         { | 
|---|
| [5] | 229 |         size        = dev_tbl[i].size; | 
|---|
 | 230 |         base        = dev_tbl[i].base; | 
|---|
 | 231 |         type        = dev_tbl[i].type; | 
|---|
 | 232 |         channels_nr = dev_tbl[i].channels; | 
|---|
 | 233 |         p0          = dev_tbl[i].param0; | 
|---|
 | 234 |         p1          = dev_tbl[i].param1; | 
|---|
 | 235 |         p2          = dev_tbl[i].param2; | 
|---|
 | 236 |         p3          = dev_tbl[i].param3; | 
|---|
| [1] | 237 |  | 
|---|
 | 238 |         func     = FUNC_FROM_TYPE( type ); | 
|---|
 | 239 |         impl     = IMPL_FROM_TYPE( type ); | 
|---|
 | 240 |  | 
|---|
| [5] | 241 |         // do nothing for RAM, that does not require a chdev descriptor. | 
|---|
 | 242 |         if( func == DEV_FUNC_RAM ) continue; | 
|---|
| [1] | 243 |  | 
|---|
| [5] | 244 |         // check internal device functional type | 
|---|
 | 245 |         if( (func != DEV_FUNC_MMC) && | 
|---|
 | 246 |             (func != DEV_FUNC_ICU) && | 
|---|
 | 247 |             (func != DEV_FUNC_DMA) )  | 
|---|
 | 248 |         { | 
|---|
 | 249 |             assert( false , __FUNCTION__ , "illegal internal peripheral type" ); | 
|---|
 | 250 |         } | 
|---|
| [1] | 251 |  | 
|---|
| [5] | 252 |         // loop on channels  | 
|---|
 | 253 |         for( channel = 0 ; channel < channels_nr ; channel++ ) | 
|---|
 | 254 |         { | 
|---|
 | 255 |             // create one chdev in local cluster | 
|---|
 | 256 |             chdev = chdev_create( func , | 
|---|
 | 257 |                                   impl, | 
|---|
 | 258 |                                   channel,       | 
|---|
 | 259 |                                   false,           // TX | 
|---|
 | 260 |                                   base ); | 
|---|
| [1] | 261 |  | 
|---|
| [5] | 262 |             assert( (chdev != NULL) , __FUNCTION__ , "cannot allocate internal chdev" ); | 
|---|
| [1] | 263 |              | 
|---|
| [5] | 264 |             // get extended pointer on channel descriptor  | 
|---|
 | 265 |             chdev_xp = XPTR( local_cxy , chdev ); | 
|---|
| [1] | 266 |  | 
|---|
 | 267 |             // TODO ??? AG | 
|---|
 | 268 |                     // devfs_register( dev ); | 
|---|
 | 269 |  | 
|---|
 | 270 |             // make device type specific initialisation | 
|---|
 | 271 |             // the number of parameters depends on the device type | 
|---|
| [5] | 272 |             // TODO : remove these parameters that  must be provided by the driver | 
|---|
 | 273 |             if     ( func == DEV_FUNC_ICU ) dev_icu_init( chdev , p0 , p1 , p2 );      | 
|---|
 | 274 |             else if( func == DEV_FUNC_MMC ) dev_mmc_init( chdev ); | 
|---|
 | 275 |             else                            dev_dma_init( chdev ); | 
|---|
| [1] | 276 |  | 
|---|
| [5] | 277 |             // initialize the replicated chdev_dir[x][y] structures | 
|---|
 | 278 |             // containing extended pointers on all devices descriptors  | 
|---|
 | 279 |             xptr_t * entry;     | 
|---|
| [1] | 280 |  | 
|---|
| [5] | 281 |             if     ( func == DEV_FUNC_ICU ) entry  = &chdev_dir.icu[local_cxy]; | 
|---|
 | 282 |             else if( func == DEV_FUNC_MMC ) entry  = &chdev_dir.mmc[local_cxy]; | 
|---|
 | 283 |             else                            entry  = &chdev_dir.dma[channel]; | 
|---|
| [1] | 284 |    | 
|---|
| [5] | 285 |             if( func != DEV_FUNC_DMA )  // ICU and MMC devices are remotely accessible | 
|---|
| [1] | 286 |             { | 
|---|
| [5] | 287 |                 for( x = 0 ; x < info->x_size ; x++ ) | 
|---|
| [1] | 288 |                 { | 
|---|
| [5] | 289 |                     for( y = 0 ; y < info->y_size ; y++ ) | 
|---|
| [1] | 290 |                     { | 
|---|
| [5] | 291 |                         cxy_t  cxy = (x<<info->y_width) + y; | 
|---|
 | 292 |                         hal_remote_swd( XPTR( cxy , entry ) , chdev_xp ); | 
|---|
| [1] | 293 |                     } | 
|---|
 | 294 |                 } | 
|---|
 | 295 |             } | 
|---|
| [5] | 296 |             else                      // DMA devices are NOT remotely accessible | 
|---|
 | 297 |             { | 
|---|
 | 298 |                 *entry = chdev_xp; | 
|---|
 | 299 |             } | 
|---|
| [1] | 300 |  | 
|---|
| [5] | 301 |             kinit_dmsg("\n[INFO] %s :core[%x][0] created chdev %s / channel %d" | 
|---|
 | 302 |                        " / paddr = %l at cycle %d\n", | 
|---|
 | 303 |                        __FUNCTION__ , local_cxy , chdev_func_str( func ) ,  | 
|---|
 | 304 |                        channel , chdev_xp , hal_time_stamp() ); | 
|---|
 | 305 |  | 
|---|
| [1] | 306 |         } // end loop on channels | 
|---|
 | 307 |  | 
|---|
| [5] | 308 |         // initialize the entries of the local chdev_icu_input structure | 
|---|
 | 309 |         // defining how internal peripherals are connected to ICU  | 
|---|
 | 310 |         if( func == DEV_FUNC_ICU )   | 
|---|
 | 311 |         { | 
|---|
 | 312 |             uint32_t   id; | 
|---|
 | 313 |             uint8_t    valid; | 
|---|
 | 314 |             uint32_t   dev_type; | 
|---|
 | 315 |             uint8_t    channel; | 
|---|
| [1] | 316 |  | 
|---|
| [5] | 317 |             // loop on ICU inputs | 
|---|
 | 318 |             for( id = 0 ; id < CONFIG_MAX_HWIS_PER_ICU ; id++ ) | 
|---|
 | 319 |             { | 
|---|
 | 320 |                 valid    = dev_tbl[i].irq[id].valid; | 
|---|
 | 321 |                 dev_type = dev_tbl[i].irq[id].dev_type; | 
|---|
 | 322 |                 channel  = dev_tbl[i].irq[id].channel; | 
|---|
 | 323 |  | 
|---|
 | 324 |                 if( valid ) // only valid local IRQs are registered | 
|---|
 | 325 |                 { | 
|---|
 | 326 |                     uint32_t * index;   // local pointer on the entry to be set | 
|---|
 | 327 |                     uint16_t   dev_func = FUNC_FROM_TYPE( dev_type ); | 
|---|
 | 328 |                     if( dev_func == DEV_FUNC_MMC )   | 
|---|
 | 329 |                         index = &chdev_icu_input.mmc; | 
|---|
 | 330 |                     else if( dev_func == DEV_FUNC_DMA )   | 
|---|
 | 331 |                         index = &chdev_icu_input.dma[channel];  | 
|---|
 | 332 |                     else | 
|---|
 | 333 |                     { | 
|---|
 | 334 |                         assert( false , __FUNCTION__ , "illegal source device for ICU input" ); | 
|---|
 | 335 |                     }                    | 
|---|
 | 336 |  | 
|---|
 | 337 |                     // set entry in local structure | 
|---|
 | 338 |                     *index = id; | 
|---|
 | 339 |                 } | 
|---|
 | 340 |  | 
|---|
 | 341 |             }  // end loop on ICU inputs | 
|---|
 | 342 |         }  // end if ICU | 
|---|
 | 343 |         } // end loop on peripherals | 
|---|
 | 344 | }  // end internal_devices_init() | 
|---|
 | 345 |  | 
|---|
 | 346 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 347 | // This static function allocates memory for the chdev descriptors associated  | 
|---|
 | 348 | // to the external (shared) peripherals contained in the local cluster. These external | 
|---|
 | 349 | // devices (IOB, IOC, TXT, NIC, etc ) are distributed on all clusters.  | 
|---|
 | 350 | // It initialises these device descriptors as specified by the boot_info_t structure, | 
|---|
 | 351 | // including the dynamic linking with the driver for the specified implementation. | 
|---|
 | 352 | // Finally, all copies of the devices directory are initialised. | 
|---|
 | 353 | // | 
|---|
 | 354 | // The number of channel_devices depends on the device functionnal type. | 
|---|
 | 355 | // There is three nested loops to scan the full set of external channel_devices: | 
|---|
 | 356 | // - loop on external devices. | 
|---|
 | 357 | // - loop on channels for multi-channels devices. | 
|---|
 | 358 | // - loop on directions (RX/TX) for NIC device. | 
|---|
 | 359 | // The set of channel_devices is indexed by the chdev_gid global index, that is used | 
|---|
 | 360 | // to select the cluster containing a given chdev[func,channel,direction]. | 
|---|
 | 361 | // All clusters scan the full set of chdevs, but only the cluster matching | 
|---|
 | 362 | // (chdev_gid % (x_size*y_size)) create the corresponding chdev.  | 
|---|
 | 363 | // | 
|---|
 | 364 | // TODO check that cluster IO contains a PIC [AG] | 
|---|
 | 365 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 366 | // @ info    : pointer on the local boot-info structure. | 
|---|
 | 367 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 368 | static void external_devices_init( boot_info_t * info ) | 
|---|
 | 369 | { | 
|---|
 | 370 |     boot_device_t * dev_tbl;         // pointer on array of devices in boot_info | 
|---|
 | 371 |         uint32_t        dev_nr;          // actual number of devices in this cluster | 
|---|
 | 372 |         xptr_t          base;            // remote pointer on segment base | 
|---|
 | 373 |         uint32_t        size;            // channel size (bytes) | 
|---|
 | 374 |     uint32_t        type;            // peripheral type | 
|---|
 | 375 |     uint32_t        func;            // device functionnal index | 
|---|
 | 376 |     uint32_t        impl;            // device implementation index | 
|---|
 | 377 |         uint32_t        i;               // device index in dev_tbl | 
|---|
 | 378 |         uint32_t        x;               // X cluster coordinate | 
|---|
 | 379 |         uint32_t        y;               // Y cluster coordinate | 
|---|
 | 380 |         uint32_t        channels_nr;     // number of channels | 
|---|
 | 381 |         uint32_t        channel;         // channel index | 
|---|
 | 382 |         uint32_t        directions_nr;   // number of directions  | 
|---|
 | 383 |         uint32_t        direction;       // direction index | 
|---|
 | 384 |         uint32_t        p0;              // device parameter 0 | 
|---|
 | 385 |         uint32_t        p1;              // device parameter 1 | 
|---|
 | 386 |         uint32_t        p2;              // device parameter 2 | 
|---|
 | 387 |         uint32_t        p3;              // device parameter 3 | 
|---|
 | 388 |     uint32_t        first_channel;   // used in loop on channels | 
|---|
 | 389 |  | 
|---|
 | 390 |         chdev_t       * chdev;           // local pointer on one channel_device descriptor | 
|---|
 | 391 |     xptr_t          chdev_xp;        // extended pointer on channel_device descriptor | 
|---|
 | 392 |     uint32_t        chdev_gid = 0;   // global index of channel_device descriptor | 
|---|
 | 393 |  | 
|---|
 | 394 |     // get number of peripherals and base of devices array from boot_info | 
|---|
 | 395 |         dev_nr      = info->ext_dev_nr; | 
|---|
 | 396 |     dev_tbl     = info->ext_dev; | 
|---|
 | 397 |  | 
|---|
 | 398 |     // loop on external peripherals | 
|---|
 | 399 |         for( i = 0 ; i < dev_nr ; i++ ) | 
|---|
 | 400 |         { | 
|---|
 | 401 |         size        = dev_tbl[i].size; | 
|---|
 | 402 |         base        = dev_tbl[i].base; | 
|---|
 | 403 |         type        = dev_tbl[i].type; | 
|---|
 | 404 |         channels_nr = dev_tbl[i].channels; | 
|---|
 | 405 |         p0          = dev_tbl[i].param0; | 
|---|
 | 406 |         p1          = dev_tbl[i].param1; | 
|---|
 | 407 |         p2          = dev_tbl[i].param2; | 
|---|
 | 408 |         p3          = dev_tbl[i].param3; | 
|---|
 | 409 |  | 
|---|
 | 410 |         func     = FUNC_FROM_TYPE( type ); | 
|---|
 | 411 |         impl     = IMPL_FROM_TYPE( type ); | 
|---|
 | 412 |  | 
|---|
 | 413 |         // There is one chdev per direction for NIC | 
|---|
 | 414 |         if (func == DEV_FUNC_NIC) directions_nr = 2; | 
|---|
 | 415 |         else                      directions_nr = 1; | 
|---|
 | 416 |  | 
|---|
 | 417 |         // The TXT0 chdev has already been created | 
|---|
 | 418 |         if (func == DEV_FUNC_TXT) first_channel = 1; | 
|---|
 | 419 |         else                      first_channel = 0; | 
|---|
 | 420 |  | 
|---|
 | 421 |         // do nothing for ROM, that does not require a device descriptor. | 
|---|
 | 422 |         if( func == DEV_FUNC_ROM ) continue; | 
|---|
 | 423 |  | 
|---|
 | 424 |         // check external device functionnal type | 
|---|
 | 425 |         if( (func != DEV_FUNC_IOB) && | 
|---|
 | 426 |             (func != DEV_FUNC_PIC) && | 
|---|
 | 427 |             (func != DEV_FUNC_IOC) && | 
|---|
 | 428 |             (func != DEV_FUNC_TXT) && | 
|---|
 | 429 |             (func != DEV_FUNC_NIC) && | 
|---|
 | 430 |             (func != DEV_FUNC_FBF) )  | 
|---|
| [1] | 431 |         { | 
|---|
| [5] | 432 |             assert( false , __FUNCTION__ , "undefined external peripheral type" ); | 
|---|
 | 433 |         } | 
|---|
 | 434 |  | 
|---|
 | 435 |         // loops on channels  | 
|---|
 | 436 |         for( channel = first_channel ; channel < channels_nr ; channel++ ) | 
|---|
 | 437 |         {  | 
|---|
 | 438 |             // loop on directions | 
|---|
 | 439 |             for( direction = 0 ; direction < directions_nr ; direction++ ) | 
|---|
| [1] | 440 |             { | 
|---|
| [5] | 441 |                 // get target cluster for chdev[func,channel,direction] | 
|---|
 | 442 |                 uint32_t offset     = chdev_gid % ( info->x_size * info->y_size ); | 
|---|
 | 443 |                 uint32_t cx         = offset / info->y_size; | 
|---|
 | 444 |                 uint32_t cy         = offset % info->y_size; | 
|---|
 | 445 |                 uint32_t target_cxy = (cx<<info->y_width) + cy; | 
|---|
| [1] | 446 |  | 
|---|
| [5] | 447 |                 // allocate and initialize a local chdev | 
|---|
 | 448 |                 // if local cluster matches target cluster | 
|---|
 | 449 |                 if( target_cxy == local_cxy ) | 
|---|
| [1] | 450 |                 { | 
|---|
| [5] | 451 |                     chdev = chdev_create( func, | 
|---|
 | 452 |                                           impl, | 
|---|
 | 453 |                                           channel, | 
|---|
 | 454 |                                           direction, | 
|---|
 | 455 |                                           base ); | 
|---|
 | 456 |  | 
|---|
 | 457 |                     assert( (chdev != NULL), __FUNCTION__ ,  | 
|---|
 | 458 |                             "cannot allocate external device" ); | 
|---|
 | 459 |  | 
|---|
 | 460 |                     // get extended pointer on chdev | 
|---|
 | 461 |                     chdev_xp = XPTR( local_cxy , chdev ); | 
|---|
 | 462 |  | 
|---|
 | 463 |                     // make device type specific initialisation | 
|---|
 | 464 |                     // the number of parameters depends on the device type | 
|---|
 | 465 |                     // TODO : remove the parameters that  must be provided by the drivers | 
|---|
 | 466 |                     if     ( func == DEV_FUNC_IOB ) dev_iob_init( chdev ); | 
|---|
 | 467 |                     else if( func == DEV_FUNC_IOC ) dev_ioc_init( chdev ); | 
|---|
 | 468 |                     else if( func == DEV_FUNC_TXT ) dev_txt_init( chdev ); | 
|---|
 | 469 |                     else if( func == DEV_FUNC_NIC ) dev_nic_init( chdev ); | 
|---|
 | 470 |                     else if( func == DEV_FUNC_PIC ) dev_pic_init( chdev , p0 ); | 
|---|
 | 471 |                     else if( func == DEV_FUNC_FBF ) dev_fbf_init( chdev , p0 , p1 ); | 
|---|
 | 472 |                     else | 
|---|
 | 473 |                     { | 
|---|
 | 474 |                         assert( false , __FUNCTION__ , "undefined device type" ); | 
|---|
 | 475 |                     } | 
|---|
 | 476 |  | 
|---|
 | 477 |                     // all external (shared) devices are remotely accessible  | 
|---|
 | 478 |                     // initialize the replicated chdev_dir[x][y] structures | 
|---|
 | 479 |                     // defining the extended pointers on chdev descriptors  | 
|---|
 | 480 |                     xptr_t * entry;     | 
|---|
 | 481 |                  | 
|---|
 | 482 |                     if( func == DEV_FUNC_IOB ) entry  = &chdev_dir.iob; | 
|---|
 | 483 |                     if( func == DEV_FUNC_PIC ) entry  = &chdev_dir.pic; | 
|---|
 | 484 |                     if( func == DEV_FUNC_TXT ) entry  = &chdev_dir.txt[channel]; | 
|---|
 | 485 |                     if( func == DEV_FUNC_IOC ) entry  = &chdev_dir.ioc[channel]; | 
|---|
 | 486 |                     if( func == DEV_FUNC_FBF ) entry  = &chdev_dir.fbf[channel]; | 
|---|
 | 487 |                     if( func == DEV_FUNC_NIC ) entry  = &chdev_dir.nic_tx[channel]; | 
|---|
 | 488 |    | 
|---|
| [1] | 489 |                     for( x = 0 ; x < info->x_size ; x++ ) | 
|---|
 | 490 |                     { | 
|---|
 | 491 |                         for( y = 0 ; y < info->y_size ; y++ ) | 
|---|
 | 492 |                         { | 
|---|
 | 493 |                             cxy_t  cxy = (x<<info->y_width) + y; | 
|---|
| [5] | 494 |                             hal_remote_swd( XPTR( cxy , entry ) , chdev_xp ); | 
|---|
 | 495 |                         } | 
|---|
| [1] | 496 |                     } | 
|---|
 | 497 |  | 
|---|
| [5] | 498 |                             kinit_dmsg("\n[INFO] %s : core[%x][0] created chdev %s / channel = %d" | 
|---|
 | 499 |                                " / paddr = %l at cycle %d\n", | 
|---|
 | 500 |                                __FUNCTION__ , local_cxy , chdev_func_str( func ), | 
|---|
 | 501 |                                channel , chdev_xp , hal_time_stamp() ); | 
|---|
 | 502 |  | 
|---|
 | 503 |                 }  // end if match | 
|---|
 | 504 |  | 
|---|
 | 505 |                 // increment chdev global index (matching or not)             | 
|---|
 | 506 |                 chdev_gid++; | 
|---|
 | 507 |  | 
|---|
 | 508 |             } // end loop on directions | 
|---|
 | 509 |  | 
|---|
 | 510 |         }  // end loop on channels | 
|---|
 | 511 |  | 
|---|
 | 512 |         // initialize the entries of the local chdev_pic_input structure | 
|---|
 | 513 |         // defining how external peripherals are connected to PIC  | 
|---|
 | 514 |         if( func == DEV_FUNC_PIC )   | 
|---|
| [1] | 515 |         { | 
|---|
| [5] | 516 |             uint32_t   id; | 
|---|
 | 517 |             uint8_t    valid; | 
|---|
 | 518 |             uint32_t   dev_type; | 
|---|
 | 519 |             uint8_t    channel; | 
|---|
 | 520 |             uint8_t    is_rx; | 
|---|
 | 521 |  | 
|---|
 | 522 |             // loop on PIC inputs | 
|---|
 | 523 |             for( id = 0 ; id < CONFIG_MAX_IRQS_PER_PIC ; id++ ) | 
|---|
| [1] | 524 |             { | 
|---|
| [5] | 525 |                 valid     = dev_tbl[i].irq[id].valid; | 
|---|
 | 526 |                 dev_type  = dev_tbl[i].irq[id].dev_type; | 
|---|
 | 527 |                 channel   = dev_tbl[i].irq[id].channel; | 
|---|
 | 528 |                 is_rx     = dev_tbl[i].irq[id].is_rx; | 
|---|
| [1] | 529 |  | 
|---|
| [5] | 530 |                 if( valid )  // only valid inputs are registered | 
|---|
| [1] | 531 |                 { | 
|---|
| [5] | 532 |                     uint32_t * index;  // local pointer on one entry | 
|---|
| [1] | 533 |                     uint16_t dev_func = FUNC_FROM_TYPE( dev_type ); | 
|---|
| [5] | 534 |  | 
|---|
 | 535 |                     if( dev_func == DEV_FUNC_TXT ) | 
|---|
| [1] | 536 |                     { | 
|---|
| [5] | 537 |                         index = &chdev_pic_input.txt[channel]; | 
|---|
| [1] | 538 |                     } | 
|---|
| [5] | 539 |                     else if( dev_func == DEV_FUNC_IOC ) | 
|---|
 | 540 |                     { | 
|---|
 | 541 |                         index = &chdev_pic_input.ioc[channel];  | 
|---|
 | 542 |                     } | 
|---|
 | 543 |                     else if( (dev_func == DEV_FUNC_NIC) && (is_rx == 0) ) | 
|---|
 | 544 |                     { | 
|---|
 | 545 |                         index = &chdev_pic_input.nic_tx[channel];  | 
|---|
 | 546 |                     } | 
|---|
 | 547 |                     else if( (dev_func == DEV_FUNC_NIC) && (is_rx != 0) ) | 
|---|
 | 548 |                     { | 
|---|
 | 549 |                         index = &chdev_pic_input.nic_rx[channel];  | 
|---|
 | 550 |                     } | 
|---|
 | 551 |                     else | 
|---|
 | 552 |                     { | 
|---|
 | 553 |                         assert( false , __FUNCTION__ , "illegal source device for PIC input" ); | 
|---|
 | 554 |                     }                    | 
|---|
 | 555 |  | 
|---|
 | 556 |                     // set entry in local structure | 
|---|
 | 557 |                     *index = id;  | 
|---|
| [1] | 558 |                 } | 
|---|
| [5] | 559 |             } // end loop on PIC inputs | 
|---|
 | 560 |         } // end PIC | 
|---|
 | 561 |         } // end loop on devices | 
|---|
 | 562 | }  // end external_devices_init() | 
|---|
| [1] | 563 |  | 
|---|
 | 564 |  | 
|---|
 | 565 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 566 | // This function is the entry point for the kernel initialisation. | 
|---|
 | 567 | // It is executed by all cores in all clusters, but only core[0] in each cluster | 
|---|
| [5] | 568 | // initialize the cluster manager, ant the local peripherals.  | 
|---|
 | 569 | // To comply with the multi-kernels paradigm, it access only local cluster memory, using | 
|---|
 | 570 | // only informations contained in the local boot_info_t structure, set by the bootloader. | 
|---|
| [1] | 571 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 572 | // @ info    : pointer on the local boot-info structure. | 
|---|
 | 573 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 574 | void kernel_init( boot_info_t * info ) | 
|---|
 | 575 | { | 
|---|
 | 576 |     uint32_t     core_lid;      // running core local index | 
|---|
 | 577 |     cxy_t        core_cxy;      // running core cluster identifier | 
|---|
 | 578 |     gid_t        core_gid;      // running core hardware identifier  | 
|---|
 | 579 |     cluster_t  * cluster;       // pointer on local cluster manager | 
|---|
 | 580 |     core_t     * core;          // pointer on running core descriptor | 
|---|
 | 581 |     thread_t   * thread_idle;   // pointer on thread_idle   | 
|---|
 | 582 |  | 
|---|
 | 583 |         uint32_t     i; | 
|---|
 | 584 |     bool_t       found; | 
|---|
 | 585 |     error_t      error; | 
|---|
 | 586 |  | 
|---|
 | 587 |     // initialise global cluster identifier | 
|---|
 | 588 |     local_cxy = info->cxy; | 
|---|
 | 589 |  | 
|---|
 | 590 |     // each core get its global index from hardware register | 
|---|
 | 591 |     core_gid = hal_get_gid();  | 
|---|
 | 592 |  | 
|---|
 | 593 |     // Each core makes an associative search in boot_info | 
|---|
| [5] | 594 |     // to get its (cxy,lid) composite index from its gid | 
|---|
| [1] | 595 |     found    = false; | 
|---|
 | 596 |     core_cxy = 0; | 
|---|
 | 597 |     core_lid = 0; | 
|---|
 | 598 |     for( i = 0 ; i < info->cores_nr ; i++ ) | 
|---|
 | 599 |     { | 
|---|
 | 600 |         if( core_gid == info->core[i].gid ) | 
|---|
 | 601 |         { | 
|---|
 | 602 |             core_lid = info->core[i].lid; | 
|---|
 | 603 |             core_cxy = info->core[i].cxy; | 
|---|
 | 604 |             found = true; | 
|---|
 | 605 |             break; | 
|---|
 | 606 |         } | 
|---|
 | 607 |     } | 
|---|
 | 608 |           | 
|---|
| [5] | 609 |     // suicide if not found | 
|---|
 | 610 |     if( (found == false) || (core_cxy != local_cxy) ) hal_core_sleep(); | 
|---|
| [1] | 611 |  | 
|---|
| [5] | 612 |     ////////////////////////////////////////////////////////////// | 
|---|
 | 613 |     // In first step, only CP0 initialises local resources | 
|---|
 | 614 |     ////////////////////////////////////////////////////////////// | 
|---|
| [1] | 615 |  | 
|---|
 | 616 |     if( core_lid == 0 )     | 
|---|
 | 617 |     { | 
|---|
 | 618 |         // initialize local cluster manager (cores and memory allocators) | 
|---|
 | 619 |         error = cluster_init( info ); | 
|---|
| [5] | 620 |   | 
|---|
 | 621 |         // suicide if failure | 
|---|
 | 622 |         if( error ) hal_core_sleep(); | 
|---|
| [1] | 623 |  | 
|---|
| [5] | 624 |         // get pointer on local cluster manager and on core descriptor | 
|---|
 | 625 |         cluster = LOCAL_CLUSTER; | 
|---|
 | 626 |             core    = &cluster->core_tbl[core_lid]; | 
|---|
 | 627 |  | 
|---|
| [1] | 628 |         // initialize process_zero descriptor | 
|---|
 | 629 |                 process_zero_init( info ); | 
|---|
 | 630 |  | 
|---|
| [5] | 631 |         // CP0 initialize its private thread_zero descriptor | 
|---|
| [1] | 632 |             memset( &thread_zero , 0 , sizeof(thread_t) ); | 
|---|
 | 633 |             thread_zero.type     = THREAD_KERNEL; | 
|---|
 | 634 |             thread_zero.process  = &process_zero; | 
|---|
 | 635 |             hal_set_current_thread( &thread_zero ); | 
|---|
 | 636 |  | 
|---|
| [5] | 637 |         // CP0 in I/O cluster initialize the kernel TXT0 chdev descriptor. | 
|---|
 | 638 |         // this TXTO device is shared by the all kernel instances for debug messages: | 
|---|
 | 639 |         // the printk() function call the dev_txt_sync_write() function that call | 
|---|
 | 640 |         // directly the relevant TXT driver, without desheduling. | 
|---|
 | 641 |         if( core_cxy == info->io_cxy ) txt0_device_init( info ); | 
|---|
| [1] | 642 |  | 
|---|
| [5] | 643 |         // synchronise all CP0s before using TXT0 | 
|---|
 | 644 |         remote_barrier( XPTR( info->io_cxy , &cluster->barrier ) ,  | 
|---|
 | 645 |                         (cluster->x_size * cluster->y_size) ); | 
|---|
 | 646 |  | 
|---|
 | 647 |         // All CP0 initialise internal peripheral chdev descriptors. | 
|---|
 | 648 |         // Each CP0[cxy] scan the set of its internal (private) peripherals, | 
|---|
 | 649 |         // and allocate memory for the corresponding chdev descriptors. | 
|---|
 | 650 |         internal_devices_init( info ); | 
|---|
 | 651 |          | 
|---|
 | 652 |         // All CP0 contribute to initialise external peripheral chdev descriptors. | 
|---|
 | 653 |         // Each CP0[cxy] scan the set of external (shared) peripherals (but the TXT0), | 
|---|
 | 654 |         // and allocates memory for the chdev descriptors that must be placed | 
|---|
 | 655 |         // on the (cxy) cluster according to its global index.   | 
|---|
 | 656 |         external_devices_init( info ); | 
|---|
 | 657 |  | 
|---|
| [1] | 658 |         // TODO initialize devFS and sysFS | 
|---|
 | 659 |                 // devfs_root_init(); | 
|---|
 | 660 |                 // sysfs_root_init(); | 
|---|
 | 661 |  | 
|---|
 | 662 |         // TODO ??? [AG] | 
|---|
 | 663 |                 // clusters_sysfs_register(); | 
|---|
 | 664 |  | 
|---|
| [5] | 665 |         // TODO initialize virtual file system | 
|---|
| [1] | 666 |         // vfs_init(); | 
|---|
 | 667 |  | 
|---|
 | 668 |         // TODO ??? [AG] | 
|---|
 | 669 |                 // sysconf_init(); | 
|---|
 | 670 |  | 
|---|
 | 671 |         // activate other cores in same cluster | 
|---|
| [5] | 672 |                 local_sync_init = KERNEL_INIT_SYNCHRO; | 
|---|
| [1] | 673 |                 hal_wbflush(); | 
|---|
 | 674 |     } | 
|---|
 | 675 |     else   // other cores                                   | 
|---|
 | 676 |     { | 
|---|
 | 677 |         // other cores wait synchro from core[0] | 
|---|
| [5] | 678 |                 while( local_sync_init != KERNEL_INIT_SYNCHRO ) | 
|---|
| [1] | 679 |         { | 
|---|
 | 680 |                    uint32_t retval = hal_time_stamp() + 1000; | 
|---|
 | 681 |                    while( hal_time_stamp() < retval )  asm volatile ("nop"); | 
|---|
 | 682 |         } | 
|---|
 | 683 |  | 
|---|
| [5] | 684 |         // get pointer on local cluster manager and on core descriptor | 
|---|
 | 685 |         cluster = LOCAL_CLUSTER; | 
|---|
 | 686 |             core    = &cluster->core_tbl[core_lid]; | 
|---|
 | 687 |  | 
|---|
 | 688 |         // core initialise its private thread_zero descriptor  | 
|---|
| [1] | 689 |             memset( &thread_zero , 0 , sizeof(thread_t) ); | 
|---|
 | 690 |             thread_zero.type     = THREAD_KERNEL; | 
|---|
 | 691 |             thread_zero.process  = &process_zero; | 
|---|
 | 692 |             hal_set_current_thread( &thread_zero ); | 
|---|
 | 693 |     } | 
|---|
 | 694 |  | 
|---|
 | 695 |         // each core creates its private idle thread descriptor  | 
|---|
 | 696 |         error = thread_kernel_create( &thread_idle, | 
|---|
 | 697 |                                   THREAD_IDLE,  | 
|---|
 | 698 |                                   &thread_idle_func,  | 
|---|
 | 699 |                                   NULL, | 
|---|
 | 700 |                                   core_lid ); | 
|---|
 | 701 |  | 
|---|
| [5] | 702 |     assert( (error == 0) , __FUNCTION__ , "cannot create idle thread" ); | 
|---|
 | 703 |  | 
|---|
| [1] | 704 |     // each core register thread_idle in scheduler  | 
|---|
 | 705 |     core->scheduler.idle = thread_idle; | 
|---|
 | 706 |  | 
|---|
 | 707 |     // each core register thread pointer in core hardware register | 
|---|
 | 708 |     hal_set_current_thread( thread_idle ); | 
|---|
 | 709 |  | 
|---|
| [5] | 710 |     kinit_dmsg("\n[INFO] %s : thread idle created for core[%x][%d] at cycle %d\n", | 
|---|
 | 711 |                __FUNCTION__ , core_cxy , core_lid , hal_time_stamp()); | 
|---|
| [1] | 712 |  | 
|---|
 | 713 |     // global syncho for all core[0] in all clusters | 
|---|
 | 714 |     if( core_lid == 0 ) | 
|---|
 | 715 |     { | 
|---|
 | 716 |         remote_barrier( XPTR( info->io_cxy , &cluster->barrier ) ,  | 
|---|
 | 717 |                         (cluster->x_size * cluster->y_size) ); | 
|---|
 | 718 |     } | 
|---|
 | 719 |  | 
|---|
 | 720 |     // local synchro for all cores in local cluster | 
|---|
 | 721 |     remote_barrier( XPTR( local_cxy , &cluster->barrier ) ,  | 
|---|
 | 722 |                     cluster->cores_nr ); | 
|---|
 | 723 |  | 
|---|
| [5] | 724 |     if( (core_lid ==  0) && (local_cxy == info->io_cxy) )  | 
|---|
| [1] | 725 |     { | 
|---|
| [5] | 726 |         print_banner( (info->x_size * info->y_size) , info->cores_nr ); | 
|---|
| [1] | 727 |     } | 
|---|
 | 728 |  | 
|---|
| [5] | 729 |     // load idle thread context on calling core | 
|---|
| [1] | 730 |         hal_cpu_context_load( thread_idle ); | 
|---|
 | 731 |  | 
|---|
 | 732 | } // end kernel_init() | 
|---|
 | 733 |  | 
|---|
 | 734 |  | 
|---|
 | 735 |  | 
|---|