| [1] | 1 | /* | 
|---|
 | 2 |  * kernel_init.c - kernel parallel initialization | 
|---|
| [127] | 3 |  * | 
|---|
| [23] | 4 |  * Authors :  Mohamed Lamine Karaoui (2015) | 
|---|
| [623] | 5 |  *            Alain Greiner  (2016,2017,2018,2019) | 
|---|
| [1] | 6 |  * | 
|---|
 | 7 |  * Copyright (c) Sorbonne Universites | 
|---|
 | 8 |  * | 
|---|
 | 9 |  * This file is part of ALMOS-MKH. | 
|---|
 | 10 |  * | 
|---|
 | 11 |  * ALMOS-MKH is free software; you can redistribute it and/or modify it | 
|---|
 | 12 |  * under the terms of the GNU General Public License as published by | 
|---|
 | 13 |  * the Free Software Foundation; version 2.0 of the License. | 
|---|
 | 14 |  * | 
|---|
 | 15 |  * ALMOS-MKH is distributed in the hope that it will be useful, but | 
|---|
 | 16 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
 | 17 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
 | 18 |  * General Public License for more details. | 
|---|
 | 19 |  * | 
|---|
 | 20 |  * You should have received a copy of the GNU General Public License | 
|---|
 | 21 |  * along with ALMOS-MKH; if not, write to the Free Software Foundation, | 
|---|
 | 22 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
 | 23 |  */ | 
|---|
 | 24 |  | 
|---|
| [14] | 25 | #include <kernel_config.h> | 
|---|
| [1] | 26 | #include <errno.h> | 
|---|
| [457] | 27 | #include <hal_kernel_types.h> | 
|---|
| [1] | 28 | #include <hal_special.h> | 
|---|
 | 29 | #include <hal_context.h> | 
|---|
| [279] | 30 | #include <hal_irqmask.h> | 
|---|
| [564] | 31 | #include <hal_macros.h> | 
|---|
| [296] | 32 | #include <hal_ppm.h> | 
|---|
| [14] | 33 | #include <barrier.h> | 
|---|
| [564] | 34 | #include <xbarrier.h> | 
|---|
| [407] | 35 | #include <remote_fifo.h> | 
|---|
| [1] | 36 | #include <core.h> | 
|---|
 | 37 | #include <list.h> | 
|---|
| [68] | 38 | #include <xlist.h> | 
|---|
| [204] | 39 | #include <xhtab.h> | 
|---|
| [1] | 40 | #include <thread.h> | 
|---|
 | 41 | #include <scheduler.h> | 
|---|
 | 42 | #include <kmem.h> | 
|---|
 | 43 | #include <cluster.h> | 
|---|
 | 44 | #include <string.h> | 
|---|
 | 45 | #include <memcpy.h> | 
|---|
 | 46 | #include <ppm.h> | 
|---|
 | 47 | #include <page.h> | 
|---|
| [5] | 48 | #include <chdev.h> | 
|---|
| [1] | 49 | #include <boot_info.h> | 
|---|
 | 50 | #include <dqdt.h> | 
|---|
 | 51 | #include <dev_mmc.h> | 
|---|
| [5] | 52 | #include <dev_dma.h> | 
|---|
 | 53 | #include <dev_iob.h> | 
|---|
| [1] | 54 | #include <dev_ioc.h> | 
|---|
| [5] | 55 | #include <dev_txt.h> | 
|---|
| [1] | 56 | #include <dev_pic.h> | 
|---|
 | 57 | #include <printk.h> | 
|---|
 | 58 | #include <vfs.h> | 
|---|
| [23] | 59 | #include <devfs.h> | 
|---|
| [68] | 60 | #include <mapper.h> | 
|---|
| [1] | 61 |  | 
|---|
 | 62 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [279] | 63 | // All the following global variables are replicated in all clusters. | 
|---|
| [1] | 64 | // They are initialised by the kernel_init() function. | 
|---|
| [14] | 65 | // | 
|---|
| [127] | 66 | // WARNING : The section names have been defined to control the base addresses of the | 
|---|
| [14] | 67 | // boot_info structure and the idle thread descriptors, through the kernel.ld script: | 
|---|
| [127] | 68 | // - the boot_info structure is built by the bootloader, and used by kernel_init. | 
|---|
 | 69 | //   it must be the first object in the kdata segment. | 
|---|
| [14] | 70 | // - the array of idle threads descriptors must be placed on the first page boundary after | 
|---|
 | 71 | //   the boot_info structure in the kdata segment. | 
|---|
| [1] | 72 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 73 |  | 
|---|
| [5] | 74 | // This variable defines the local boot_info structure | 
|---|
 | 75 | __attribute__((section(".kinfo"))) | 
|---|
| [14] | 76 | boot_info_t          boot_info; | 
|---|
| [5] | 77 |  | 
|---|
| [14] | 78 | // This variable defines the "idle" threads descriptors array | 
|---|
 | 79 | __attribute__((section(".kidle"))) | 
|---|
| [381] | 80 | char                 idle_threads[CONFIG_THREAD_DESC_SIZE * | 
|---|
| [14] | 81 |                                    CONFIG_MAX_LOCAL_CORES]   CONFIG_PPM_PAGE_ALIGNED; | 
|---|
 | 82 |  | 
|---|
| [127] | 83 | // This variable defines the local cluster manager | 
|---|
| [5] | 84 | __attribute__((section(".kdata"))) | 
|---|
| [19] | 85 | cluster_t            cluster_manager                         CONFIG_CACHE_LINE_ALIGNED; | 
|---|
| [1] | 86 |  | 
|---|
| [564] | 87 | // This variable defines the TXT_TX[0] chdev | 
|---|
| [188] | 88 | __attribute__((section(".kdata"))) | 
|---|
| [564] | 89 | chdev_t              txt0_tx_chdev                           CONFIG_CACHE_LINE_ALIGNED; | 
|---|
| [188] | 90 |  | 
|---|
| [564] | 91 | // This variable defines the TXT_RX[0] chdev | 
|---|
| [539] | 92 | __attribute__((section(".kdata"))) | 
|---|
| [564] | 93 | chdev_t              txt0_rx_chdev                           CONFIG_CACHE_LINE_ALIGNED; | 
|---|
| [539] | 94 |  | 
|---|
| [14] | 95 | // This variables define the kernel process0 descriptor | 
|---|
| [5] | 96 | __attribute__((section(".kdata"))) | 
|---|
| [19] | 97 | process_t            process_zero                            CONFIG_CACHE_LINE_ALIGNED; | 
|---|
| [1] | 98 |  | 
|---|
| [624] | 99 | // This variable defines a set of extended pointers on the distributed chdevs | 
|---|
| [5] | 100 | __attribute__((section(".kdata"))) | 
|---|
| [14] | 101 | chdev_directory_t    chdev_dir                               CONFIG_CACHE_LINE_ALIGNED; | 
|---|
| [1] | 102 |  | 
|---|
| [188] | 103 | // This variable contains the input IRQ indexes for the IOPIC controller | 
|---|
| [5] | 104 | __attribute__((section(".kdata"))) | 
|---|
| [246] | 105 | iopic_input_t        iopic_input                             CONFIG_CACHE_LINE_ALIGNED; | 
|---|
| [1] | 106 |  | 
|---|
| [188] | 107 | // This variable contains the input IRQ indexes for the LAPIC controller | 
|---|
| [5] | 108 | __attribute__((section(".kdata"))) | 
|---|
| [188] | 109 | lapic_input_t        lapic_input                             CONFIG_CACHE_LINE_ALIGNED; | 
|---|
| [1] | 110 |  | 
|---|
| [14] | 111 | // This variable defines the local cluster identifier | 
|---|
| [5] | 112 | __attribute__((section(".kdata"))) | 
|---|
| [14] | 113 | cxy_t                local_cxy                               CONFIG_CACHE_LINE_ALIGNED; | 
|---|
| [5] | 114 |  | 
|---|
| [623] | 115 | // This variable is used for core[0] cores synchronisation in kernel_init() | 
|---|
| [5] | 116 | __attribute__((section(".kdata"))) | 
|---|
| [564] | 117 | xbarrier_t           global_barrier                          CONFIG_CACHE_LINE_ALIGNED; | 
|---|
| [1] | 118 |  | 
|---|
| [127] | 119 | // This variable is used for local cores synchronisation in kernel_init() | 
|---|
| [14] | 120 | __attribute__((section(".kdata"))) | 
|---|
 | 121 | barrier_t            local_barrier                           CONFIG_CACHE_LINE_ALIGNED; | 
|---|
 | 122 |  | 
|---|
| [127] | 123 | // This variable defines the array of supported File System contexts | 
|---|
| [50] | 124 | __attribute__((section(".kdata"))) | 
|---|
 | 125 | vfs_ctx_t            fs_context[FS_TYPES_NR]                 CONFIG_CACHE_LINE_ALIGNED; | 
|---|
 | 126 |  | 
|---|
| [564] | 127 | // This array is used for debug, and describes the kernel locks usage, | 
|---|
 | 128 | // It must be kept consistent with the defines in kernel_config.h file. | 
|---|
| [624] | 129 | __attribute__((section(".kdata"))) | 
|---|
| [564] | 130 | char * lock_type_str[] = | 
|---|
 | 131 | { | 
|---|
 | 132 |     "unused_0",              //  0 | 
|---|
| [408] | 133 |  | 
|---|
| [564] | 134 |     "CLUSTER_KCM",           //  1 | 
|---|
| [632] | 135 |     "SCHED_STATE",           //  2 | 
|---|
 | 136 |     "VMM_STACK",             //  3 | 
|---|
 | 137 |     "VMM_MMAP",              //  4 | 
|---|
 | 138 |     "VFS_CTX",               //  5 | 
|---|
 | 139 |     "KCM_STATE",             //  6 | 
|---|
 | 140 |     "KHM_STATE",             //  7 | 
|---|
 | 141 |     "HTAB_STATE",            //  8 | 
|---|
| [564] | 142 |  | 
|---|
| [632] | 143 |     "PPM_FREE",              //  9 | 
|---|
| [564] | 144 |     "THREAD_JOIN",           // 10 | 
|---|
| [610] | 145 |     "XHTAB_STATE",           // 11 | 
|---|
| [564] | 146 |     "CHDEV_QUEUE",           // 12 | 
|---|
 | 147 |     "CHDEV_TXT0",            // 13 | 
|---|
 | 148 |     "CHDEV_TXTLIST",         // 14 | 
|---|
 | 149 |     "PAGE_STATE",            // 15 | 
|---|
 | 150 |     "MUTEX_STATE",           // 16 | 
|---|
 | 151 |     "CONDVAR_STATE",         // 17 | 
|---|
 | 152 |     "SEM_STATE",             // 18 | 
|---|
| [619] | 153 |     "PROCESS_CWD",           // 19 | 
|---|
 | 154 |     "BARRIER_STATE",         // 20 | 
|---|
| [564] | 155 |  | 
|---|
 | 156 |     "CLUSTER_PREFTBL",       // 21 | 
|---|
| [601] | 157 |  | 
|---|
| [564] | 158 |     "PPM_DIRTY",             // 22 | 
|---|
 | 159 |     "CLUSTER_LOCALS",        // 23 | 
|---|
 | 160 |     "CLUSTER_COPIES",        // 24 | 
|---|
 | 161 |     "PROCESS_CHILDREN",      // 25 | 
|---|
 | 162 |     "PROCESS_USERSYNC",      // 26 | 
|---|
 | 163 |     "PROCESS_FDARRAY",       // 27 | 
|---|
| [628] | 164 |     "PROCESS_DIR",           // 28 | 
|---|
| [640] | 165 |     "VMM_VSL",               // 29 | 
|---|
| [564] | 166 |  | 
|---|
| [611] | 167 |     "PROCESS_THTBL",         // 30 | 
|---|
| [564] | 168 |  | 
|---|
| [611] | 169 |     "MAPPER_STATE",          // 31 | 
|---|
 | 170 |     "VFS_SIZE",              // 32 | 
|---|
 | 171 |     "VFS_FILE",              // 33 | 
|---|
| [640] | 172 |     "VFS_MAIN",              // 34 | 
|---|
 | 173 |     "FATFS_FAT",             // 35 | 
|---|
| [564] | 174 | };         | 
|---|
 | 175 |  | 
|---|
| [601] | 176 | // debug variables to analyse the sys_read() and sys_write() syscalls timing | 
|---|
| [564] | 177 |  | 
|---|
| [438] | 178 | #if DEBUG_SYS_READ | 
|---|
| [407] | 179 | uint32_t   enter_sys_read; | 
|---|
 | 180 | uint32_t   exit_sys_read; | 
|---|
 | 181 |  | 
|---|
| [435] | 182 | uint32_t   enter_devfs_read; | 
|---|
 | 183 | uint32_t   exit_devfs_read; | 
|---|
| [407] | 184 |  | 
|---|
 | 185 | uint32_t   enter_txt_read; | 
|---|
 | 186 | uint32_t   exit_txt_read; | 
|---|
 | 187 |  | 
|---|
| [435] | 188 | uint32_t   enter_chdev_cmd_read; | 
|---|
 | 189 | uint32_t   exit_chdev_cmd_read; | 
|---|
| [407] | 190 |  | 
|---|
| [435] | 191 | uint32_t   enter_chdev_server_read; | 
|---|
 | 192 | uint32_t   exit_chdev_server_read; | 
|---|
| [407] | 193 |  | 
|---|
| [435] | 194 | uint32_t   enter_tty_cmd_read; | 
|---|
 | 195 | uint32_t   exit_tty_cmd_read; | 
|---|
| [407] | 196 |  | 
|---|
| [435] | 197 | uint32_t   enter_tty_isr_read; | 
|---|
 | 198 | uint32_t   exit_tty_isr_read; | 
|---|
| [407] | 199 | #endif | 
|---|
 | 200 |  | 
|---|
| [435] | 201 | // these debug variables are used to analyse the sys_write() syscall timing | 
|---|
 | 202 |  | 
|---|
| [438] | 203 | #if DEBUG_SYS_WRITE     | 
|---|
| [435] | 204 | uint32_t   enter_sys_write; | 
|---|
 | 205 | uint32_t   exit_sys_write; | 
|---|
 | 206 |  | 
|---|
 | 207 | uint32_t   enter_devfs_write; | 
|---|
 | 208 | uint32_t   exit_devfs_write; | 
|---|
 | 209 |  | 
|---|
 | 210 | uint32_t   enter_txt_write; | 
|---|
 | 211 | uint32_t   exit_txt_write; | 
|---|
 | 212 |  | 
|---|
 | 213 | uint32_t   enter_chdev_cmd_write; | 
|---|
 | 214 | uint32_t   exit_chdev_cmd_write; | 
|---|
 | 215 |  | 
|---|
 | 216 | uint32_t   enter_chdev_server_write; | 
|---|
 | 217 | uint32_t   exit_chdev_server_write; | 
|---|
 | 218 |  | 
|---|
 | 219 | uint32_t   enter_tty_cmd_write; | 
|---|
 | 220 | uint32_t   exit_tty_cmd_write; | 
|---|
 | 221 |  | 
|---|
 | 222 | uint32_t   enter_tty_isr_write; | 
|---|
 | 223 | uint32_t   exit_tty_isr_write; | 
|---|
 | 224 | #endif | 
|---|
 | 225 |  | 
|---|
| [564] | 226 | // intrumentation variables : cumulated costs per syscall type in cluster | 
|---|
| [624] | 227 |  | 
|---|
 | 228 | #if CONFIG_INSTRUMENTATION_SYSCALLS | 
|---|
 | 229 | __attribute__((section(".kdata"))) | 
|---|
| [564] | 230 | uint32_t   syscalls_cumul_cost[SYSCALLS_NR]; | 
|---|
 | 231 |  | 
|---|
| [624] | 232 | __attribute__((section(".kdata"))) | 
|---|
| [564] | 233 | uint32_t   syscalls_occurences[SYSCALLS_NR]; | 
|---|
| [624] | 234 | #endif | 
|---|
| [564] | 235 |  | 
|---|
| [1] | 236 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [5] | 237 | // This function displays the ALMOS_MKH banner. | 
|---|
| [1] | 238 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [5] | 239 | static void print_banner( uint32_t nclusters , uint32_t ncores ) | 
|---|
| [127] | 240 | { | 
|---|
| [5] | 241 |     printk("\n" | 
|---|
 | 242 |            "                    _        __    __     _____     ______         __    __    _   __   _     _   \n" | 
|---|
 | 243 |            "          /\\       | |      |  \\  /  |   / ___ \\   / _____|       |  \\  /  |  | | / /  | |   | |  \n" | 
|---|
 | 244 |            "         /  \\      | |      |   \\/   |  | /   \\ | | /             |   \\/   |  | |/ /   | |   | |  \n" | 
|---|
 | 245 |            "        / /\\ \\     | |      | |\\  /| |  | |   | | | |_____   ___  | |\\  /| |  |   /    | |___| |  \n" | 
|---|
 | 246 |            "       / /__\\ \\    | |      | | \\/ | |  | |   | | \\_____  \\ |___| | | \\/ | |  |   \\    |  ___  |  \n" | 
|---|
 | 247 |            "      / ______ \\   | |      | |    | |  | |   | |       | |       | |    | |  | |\\ \\   | |   | |  \n" | 
|---|
 | 248 |            "     / /      \\ \\  | |____  | |    | |  | \\___/ |  _____/ |       | |    | |  | | \\ \\  | |   | |  \n" | 
|---|
 | 249 |            "    /_/        \\_\\ |______| |_|    |_|   \\_____/  |______/        |_|    |_|  |_|  \\_\\ |_|   |_|  \n" | 
|---|
 | 250 |            "\n\n\t\t Advanced Locality Management Operating System / Multi Kernel Hybrid\n" | 
|---|
| [457] | 251 |            "\n\n\t\t %s / %d cluster(s) / %d core(s) per cluster\n\n", | 
|---|
| [635] | 252 |            CONFIG_VERSION , nclusters , ncores ); | 
|---|
| [5] | 253 | } | 
|---|
| [1] | 254 |  | 
|---|
 | 255 |  | 
|---|
| [5] | 256 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 257 | // This function initializes the TXT_TX[0] and TXT_RX[0] chdev descriptors, implementing | 
|---|
 | 258 | // the "kernel terminal", shared by all kernel instances for debug messages.  | 
|---|
 | 259 | // These chdev are implemented as global variables (replicated in all clusters), | 
|---|
 | 260 | // because this terminal is used before the kmem allocator initialisation, but only  | 
|---|
 | 261 | // the chdevs in cluster 0 are registered in the "chdev_dir" directory. | 
|---|
| [127] | 262 | // As this TXT0 chdev supports only the TXT_SYNC_WRITE command, we don't create | 
|---|
 | 263 | // a server thread, we don't allocate a WTI, and we don't initialize the waiting queue. | 
|---|
| [564] | 264 | // Note: The TXT_RX[0] chdev is created, but is not used by ALMOS-MKH (september 2018). | 
|---|
| [5] | 265 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 266 | // @ info    : pointer on the local boot-info structure. | 
|---|
 | 267 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 268 | static void __attribute__ ((noinline)) txt0_device_init( boot_info_t * info ) | 
|---|
| [5] | 269 | { | 
|---|
 | 270 |     boot_device_t * dev_tbl;         // pointer on array of devices in boot_info | 
|---|
| [127] | 271 |     uint32_t        dev_nr;          // actual number of devices in this cluster | 
|---|
 | 272 |     xptr_t          base;            // remote pointer on segment base | 
|---|
 | 273 |     uint32_t        func;            // device functional index | 
|---|
| [5] | 274 |     uint32_t        impl;            // device implementation index | 
|---|
| [127] | 275 |     uint32_t        i;               // device index in dev_tbl | 
|---|
 | 276 |     uint32_t        x;               // X cluster coordinate | 
|---|
 | 277 |     uint32_t        y;               // Y cluster coordinate | 
|---|
| [1] | 278 |  | 
|---|
| [5] | 279 |     // get number of peripherals and base of devices array from boot_info | 
|---|
| [127] | 280 |     dev_nr      = info->ext_dev_nr; | 
|---|
| [5] | 281 |     dev_tbl     = info->ext_dev; | 
|---|
| [1] | 282 |  | 
|---|
| [14] | 283 |     // loop on external peripherals to find TXT device | 
|---|
| [127] | 284 |     for( i = 0 ; i < dev_nr ; i++ ) | 
|---|
 | 285 |     { | 
|---|
| [5] | 286 |         base        = dev_tbl[i].base; | 
|---|
| [188] | 287 |         func        = FUNC_FROM_TYPE( dev_tbl[i].type ); | 
|---|
 | 288 |         impl        = IMPL_FROM_TYPE( dev_tbl[i].type ); | 
|---|
| [5] | 289 |  | 
|---|
| [127] | 290 |         if (func == DEV_FUNC_TXT ) | 
|---|
| [5] | 291 |         { | 
|---|
| [564] | 292 |             // initialize TXT_TX[0] chdev | 
|---|
 | 293 |             txt0_tx_chdev.func    = func; | 
|---|
 | 294 |             txt0_tx_chdev.impl    = impl; | 
|---|
 | 295 |             txt0_tx_chdev.channel = 0; | 
|---|
 | 296 |             txt0_tx_chdev.base    = base; | 
|---|
 | 297 |             txt0_tx_chdev.is_rx   = false; | 
|---|
 | 298 |             remote_busylock_init( XPTR( local_cxy , &txt0_tx_chdev.wait_lock ), | 
|---|
 | 299 |                                   LOCK_CHDEV_TXT0 ); | 
|---|
| [188] | 300 |              | 
|---|
| [564] | 301 |             // initialize TXT_RX[0] chdev | 
|---|
 | 302 |             txt0_rx_chdev.func    = func; | 
|---|
 | 303 |             txt0_rx_chdev.impl    = impl; | 
|---|
 | 304 |             txt0_rx_chdev.channel = 0; | 
|---|
 | 305 |             txt0_rx_chdev.base    = base; | 
|---|
 | 306 |             txt0_rx_chdev.is_rx   = true; | 
|---|
 | 307 |             remote_busylock_init( XPTR( local_cxy , &txt0_rx_chdev.wait_lock ), | 
|---|
 | 308 |                                   LOCK_CHDEV_TXT0 ); | 
|---|
 | 309 |              | 
|---|
 | 310 |             // make TXT specific initialisations  | 
|---|
 | 311 |             dev_txt_init( &txt0_tx_chdev );                  | 
|---|
 | 312 |             dev_txt_init( &txt0_rx_chdev ); | 
|---|
| [14] | 313 |  | 
|---|
| [564] | 314 |             // register TXT_TX[0] & TXT_RX[0] in chdev_dir[x][y] | 
|---|
 | 315 |             // for all valid clusters              | 
|---|
| [5] | 316 |             for( x = 0 ; x < info->x_size ; x++ ) | 
|---|
 | 317 |             { | 
|---|
| [564] | 318 |                 for( y = 0 ; y < info->y_size ; y++ ) | 
|---|
| [5] | 319 |                 { | 
|---|
| [564] | 320 |                     cxy_t cxy = HAL_CXY_FROM_XY( x , y ); | 
|---|
 | 321 |  | 
|---|
 | 322 |                     if( cluster_is_active( cxy ) ) | 
|---|
 | 323 |                     { | 
|---|
 | 324 |                         hal_remote_s64( XPTR( cxy , &chdev_dir.txt_tx[0] ) , | 
|---|
 | 325 |                                         XPTR( local_cxy , &txt0_tx_chdev ) ); | 
|---|
 | 326 |                         hal_remote_s64( XPTR( cxy , &chdev_dir.txt_rx[0] ) , | 
|---|
 | 327 |                                         XPTR( local_cxy , &txt0_rx_chdev ) ); | 
|---|
| [559] | 328 |                     } | 
|---|
| [5] | 329 |                 } | 
|---|
 | 330 |             } | 
|---|
| [564] | 331 |  | 
|---|
 | 332 |             hal_fence(); | 
|---|
| [5] | 333 |         } | 
|---|
| [188] | 334 |         } // end loop on devices | 
|---|
 | 335 | }  // end txt0_device_init() | 
|---|
| [5] | 336 |  | 
|---|
| [1] | 337 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [188] | 338 | // This function allocates memory and initializes the chdev descriptors for the internal | 
|---|
 | 339 | // peripherals contained in the local cluster, other than the LAPIC, as specified by  | 
|---|
 | 340 | // the boot_info, including the linking with the driver for the specified implementation. | 
|---|
 | 341 | // The relevant entries in all copies of the devices directory are initialised. | 
|---|
| [1] | 342 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 343 | // @ info    : pointer on the local boot-info structure. | 
|---|
 | 344 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 345 | static void __attribute__ ((noinline)) internal_devices_init( boot_info_t * info ) | 
|---|
| [1] | 346 | { | 
|---|
| [188] | 347 |     boot_device_t * dev_tbl;         // pointer on array of internaldevices in boot_info | 
|---|
 | 348 |         uint32_t        dev_nr;          // actual number of devices in this cluster | 
|---|
 | 349 |         xptr_t          base;            // remote pointer on segment base | 
|---|
 | 350 |     uint32_t        func;            // device functionnal index | 
|---|
 | 351 |     uint32_t        impl;            // device implementation index | 
|---|
 | 352 |         uint32_t        i;               // device index in dev_tbl | 
|---|
 | 353 |         uint32_t        x;               // X cluster coordinate | 
|---|
 | 354 |         uint32_t        y;               // Y cluster coordinate | 
|---|
 | 355 |         uint32_t        channels;        // number of channels | 
|---|
 | 356 |         uint32_t        channel;         // channel index | 
|---|
 | 357 |         chdev_t       * chdev_ptr;       // local pointer on created chdev | 
|---|
| [1] | 358 |  | 
|---|
| [188] | 359 |     // get number of internal peripherals and base from boot_info | 
|---|
 | 360 |         dev_nr  = info->int_dev_nr; | 
|---|
 | 361 |     dev_tbl = info->int_dev; | 
|---|
| [1] | 362 |  | 
|---|
| [188] | 363 |     // loop on internal peripherals | 
|---|
 | 364 |         for( i = 0 ; i < dev_nr ; i++ ) | 
|---|
 | 365 |         { | 
|---|
 | 366 |         base        = dev_tbl[i].base; | 
|---|
 | 367 |         channels    = dev_tbl[i].channels; | 
|---|
 | 368 |         func        = FUNC_FROM_TYPE( dev_tbl[i].type ); | 
|---|
 | 369 |         impl        = IMPL_FROM_TYPE( dev_tbl[i].type ); | 
|---|
| [204] | 370 |   | 
|---|
| [188] | 371 |         ////////////////////////// | 
|---|
 | 372 |         if( func == DEV_FUNC_MMC )   | 
|---|
| [5] | 373 |         { | 
|---|
| [1] | 374 |  | 
|---|
| [564] | 375 |             // check channels | 
|---|
 | 376 |             if( channels != 1 ) | 
|---|
| [580] | 377 |             { | 
|---|
 | 378 |                 printk("\n[PANIC] in %s : MMC device must be single channel\n", | 
|---|
 | 379 |                 __FUNCTION__ ); | 
|---|
 | 380 |                 hal_core_sleep(); | 
|---|
 | 381 |             } | 
|---|
| [564] | 382 |  | 
|---|
| [188] | 383 |             // create chdev in local cluster | 
|---|
 | 384 |             chdev_ptr = chdev_create( func, | 
|---|
 | 385 |                                       impl, | 
|---|
 | 386 |                                       0,          // channel | 
|---|
 | 387 |                                       false,      // direction | 
|---|
 | 388 |                                       base ); | 
|---|
| [14] | 389 |  | 
|---|
| [564] | 390 |             // check memory | 
|---|
 | 391 |             if( chdev_ptr == NULL ) | 
|---|
| [580] | 392 |             { | 
|---|
 | 393 |                 printk("\n[PANIC] in %s : cannot create MMC chdev\n", | 
|---|
 | 394 |                 __FUNCTION__ ); | 
|---|
 | 395 |                 hal_core_sleep(); | 
|---|
 | 396 |             } | 
|---|
| [188] | 397 |              | 
|---|
 | 398 |             // make MMC specific initialisation | 
|---|
 | 399 |             dev_mmc_init( chdev_ptr ); | 
|---|
| [1] | 400 |  | 
|---|
| [188] | 401 |             // set the MMC field in all chdev_dir[x][y] structures | 
|---|
 | 402 |             for( x = 0 ; x < info->x_size ; x++ ) | 
|---|
| [1] | 403 |             { | 
|---|
| [564] | 404 |                 for( y = 0 ; y < info->y_size ; y++ ) | 
|---|
| [188] | 405 |                 { | 
|---|
| [564] | 406 |                     cxy_t cxy = HAL_CXY_FROM_XY( x , y ); | 
|---|
 | 407 |  | 
|---|
 | 408 |                     if( cluster_is_active( cxy ) ) | 
|---|
 | 409 |                     { | 
|---|
 | 410 |                         hal_remote_s64( XPTR( cxy , &chdev_dir.mmc[local_cxy] ),  | 
|---|
| [559] | 411 |                                         XPTR( local_cxy , chdev_ptr ) ); | 
|---|
 | 412 |                     } | 
|---|
| [188] | 413 |                 } | 
|---|
| [1] | 414 |             } | 
|---|
| [188] | 415 |  | 
|---|
| [438] | 416 | #if( DEBUG_KERNEL_INIT & 0x1 ) | 
|---|
 | 417 | if( hal_time_stamp() > DEBUG_KERNEL_INIT ) | 
|---|
| [601] | 418 | printk("\n[%s] : created MMC in cluster %x / chdev = %x\n", | 
|---|
| [407] | 419 | __FUNCTION__ , local_cxy , chdev_ptr ); | 
|---|
| [389] | 420 | #endif | 
|---|
| [14] | 421 |         } | 
|---|
| [188] | 422 |         /////////////////////////////// | 
|---|
 | 423 |         else if( func == DEV_FUNC_DMA ) | 
|---|
| [127] | 424 |         { | 
|---|
| [188] | 425 |             // create one chdev per channel in local cluster | 
|---|
 | 426 |             for( channel = 0 ; channel < channels ; channel++ ) | 
|---|
 | 427 |             {    | 
|---|
 | 428 |                 // create chdev[channel] in local cluster | 
|---|
 | 429 |                 chdev_ptr = chdev_create( func, | 
|---|
 | 430 |                                           impl, | 
|---|
 | 431 |                                           channel, | 
|---|
 | 432 |                                           false,     // direction | 
|---|
 | 433 |                                           base ); | 
|---|
| [5] | 434 |  | 
|---|
| [564] | 435 |                 // check memory | 
|---|
 | 436 |                 if( chdev_ptr == NULL ) | 
|---|
| [580] | 437 |                 { | 
|---|
 | 438 |                     printk("\n[PANIC] in %s : cannot create DMA chdev\n", | 
|---|
 | 439 |                     __FUNCTION__ ); | 
|---|
 | 440 |                     hal_core_sleep(); | 
|---|
 | 441 |                 } | 
|---|
| [564] | 442 |              | 
|---|
| [188] | 443 |                 // make DMA specific initialisation | 
|---|
 | 444 |                 dev_dma_init( chdev_ptr );      | 
|---|
| [127] | 445 |  | 
|---|
| [188] | 446 |                 // initialize only the DMA[channel] field in the local chdev_dir[x][y] | 
|---|
 | 447 |                 // structure because the DMA device is not remotely accessible. | 
|---|
 | 448 |                 chdev_dir.dma[channel] = XPTR( local_cxy , chdev_ptr ); | 
|---|
| [5] | 449 |  | 
|---|
| [438] | 450 | #if( DEBUG_KERNEL_INIT & 0x1 ) | 
|---|
 | 451 | if( hal_time_stamp() > DEBUG_KERNEL_INIT ) | 
|---|
| [601] | 452 | printk("\n[%s] : created DMA[%d] in cluster %x / chdev = %x\n", | 
|---|
| [389] | 453 | __FUNCTION__ , channel , local_cxy , chdev_ptr ); | 
|---|
 | 454 | #endif | 
|---|
| [188] | 455 |             } | 
|---|
| [14] | 456 |         } | 
|---|
| [127] | 457 |     } | 
|---|
| [5] | 458 | }  // end internal_devices_init() | 
|---|
 | 459 |  | 
|---|
 | 460 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [188] | 461 | // This function allocates memory and initializes the chdev descriptors for the   | 
|---|
| [408] | 462 | // external (shared) peripherals other than the IOPIC, as specified by the boot_info. | 
|---|
 | 463 | // This includes the dynamic linking with the driver for the specified implementation. | 
|---|
| [188] | 464 | // These chdev descriptors are distributed on all clusters, using a modulo on a global  | 
|---|
| [408] | 465 | // index, identically computed in all clusters. | 
|---|
| [623] | 466 | // This function is executed in all clusters by the core[0] core, that computes a global index | 
|---|
 | 467 | // for all external chdevs. Each core[0] core creates only the chdevs that must be placed in  | 
|---|
| [408] | 468 | // the local cluster, because the global index matches the local index.  | 
|---|
| [188] | 469 | // The relevant entries in all copies of the devices directory are initialised. | 
|---|
| [5] | 470 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 471 | // @ info    : pointer on the local boot-info structure. | 
|---|
 | 472 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 473 | static void external_devices_init( boot_info_t * info ) | 
|---|
 | 474 | { | 
|---|
| [188] | 475 |     boot_device_t * dev_tbl;         // pointer on array of external devices in boot_info | 
|---|
 | 476 |         uint32_t        dev_nr;          // actual number of external devices  | 
|---|
 | 477 |         xptr_t          base;            // remote pointer on segment base | 
|---|
| [5] | 478 |     uint32_t        func;            // device functionnal index | 
|---|
 | 479 |     uint32_t        impl;            // device implementation index | 
|---|
| [188] | 480 |         uint32_t        i;               // device index in dev_tbl | 
|---|
 | 481 |         uint32_t        x;               // X cluster coordinate | 
|---|
 | 482 |         uint32_t        y;               // Y cluster coordinate | 
|---|
 | 483 |         uint32_t        channels;        // number of channels | 
|---|
 | 484 |         uint32_t        channel;         // channel index | 
|---|
 | 485 |         uint32_t        directions;      // number of directions (1 or 2) | 
|---|
 | 486 |         uint32_t        rx;              // direction index (0 or 1) | 
|---|
| [127] | 487 |     chdev_t       * chdev;           // local pointer on one channel_device descriptor | 
|---|
| [188] | 488 |     uint32_t        ext_chdev_gid;   // global index of external chdev | 
|---|
| [5] | 489 |  | 
|---|
 | 490 |     // get number of peripherals and base of devices array from boot_info | 
|---|
| [127] | 491 |     dev_nr      = info->ext_dev_nr; | 
|---|
| [5] | 492 |     dev_tbl     = info->ext_dev; | 
|---|
 | 493 |  | 
|---|
| [188] | 494 |     // initializes global index (PIC is already placed in cluster 0 | 
|---|
 | 495 |     ext_chdev_gid = 1; | 
|---|
 | 496 |  | 
|---|
| [5] | 497 |     // loop on external peripherals | 
|---|
| [127] | 498 |     for( i = 0 ; i < dev_nr ; i++ ) | 
|---|
 | 499 |     { | 
|---|
| [188] | 500 |         base     = dev_tbl[i].base; | 
|---|
 | 501 |         channels = dev_tbl[i].channels; | 
|---|
 | 502 |         func     = FUNC_FROM_TYPE( dev_tbl[i].type ); | 
|---|
 | 503 |         impl     = IMPL_FROM_TYPE( dev_tbl[i].type ); | 
|---|
| [5] | 504 |  | 
|---|
| [407] | 505 |         // There is one chdev per direction for NIC and for TXT | 
|---|
 | 506 |         if((func == DEV_FUNC_NIC) || (func == DEV_FUNC_TXT)) directions = 2; | 
|---|
 | 507 |         else                                                 directions = 1; | 
|---|
| [5] | 508 |  | 
|---|
| [407] | 509 |         // do nothing for ROM, that does not require a device descriptor. | 
|---|
| [5] | 510 |         if( func == DEV_FUNC_ROM ) continue; | 
|---|
 | 511 |  | 
|---|
| [188] | 512 |         // do nothing for PIC, that is already initialized | 
|---|
 | 513 |         if( func == DEV_FUNC_PIC ) continue; | 
|---|
| [5] | 514 |  | 
|---|
| [188] | 515 |         // check PIC device initialized | 
|---|
| [564] | 516 |         if( chdev_dir.pic == XPTR_NULL ) | 
|---|
| [580] | 517 |         { | 
|---|
 | 518 |             printk("\n[PANIC] in %s : PIC device must be initialized first\n", | 
|---|
 | 519 |             __FUNCTION__ ); | 
|---|
 | 520 |             hal_core_sleep(); | 
|---|
 | 521 |         } | 
|---|
| [188] | 522 |  | 
|---|
 | 523 |         // check external device functionnal type | 
|---|
| [564] | 524 |         if( (func != DEV_FUNC_IOB) && (func != DEV_FUNC_IOC) && (func != DEV_FUNC_TXT) && | 
|---|
 | 525 |             (func != DEV_FUNC_NIC) && (func != DEV_FUNC_FBF) ) | 
|---|
| [580] | 526 |         { | 
|---|
 | 527 |             printk("\n[PANIC] in %s : undefined peripheral type\n", | 
|---|
 | 528 |             __FUNCTION__ ); | 
|---|
 | 529 |             hal_core_sleep(); | 
|---|
 | 530 |         } | 
|---|
| [188] | 531 |  | 
|---|
| [127] | 532 |         // loops on channels | 
|---|
| [428] | 533 |         for( channel = 0 ; channel < channels ; channel++ ) | 
|---|
| [127] | 534 |         { | 
|---|
| [5] | 535 |             // loop on directions | 
|---|
| [188] | 536 |             for( rx = 0 ; rx < directions ; rx++ ) | 
|---|
| [1] | 537 |             { | 
|---|
| [564] | 538 |                 // skip TXT0 that has already been initialized | 
|---|
 | 539 |                 if( (func == DEV_FUNC_TXT) && (channel == 0) ) continue; | 
|---|
| [428] | 540 |  | 
|---|
| [564] | 541 |                 // all kernel instances compute the target cluster for all chdevs, | 
|---|
 | 542 |                 // computing the global index ext_chdev_gid[func,channel,direction] | 
|---|
 | 543 |                 cxy_t target_cxy; | 
|---|
 | 544 |                 while( 1 ) | 
|---|
| [536] | 545 |                 { | 
|---|
| [564] | 546 |                     uint32_t offset     = ext_chdev_gid % ( info->x_size * info->y_size ); | 
|---|
 | 547 |                     uint32_t x          = offset / info->y_size; | 
|---|
 | 548 |                     uint32_t y          = offset % info->y_size; | 
|---|
| [536] | 549 |  | 
|---|
| [564] | 550 |                     target_cxy = HAL_CXY_FROM_XY( x , y ); | 
|---|
 | 551 |  | 
|---|
 | 552 |                     // exit loop if target cluster is active | 
|---|
 | 553 |                     if( cluster_is_active( target_cxy ) ) break; | 
|---|
 | 554 |                  | 
|---|
 | 555 |                     // increment global index otherwise | 
|---|
 | 556 |                     ext_chdev_gid++; | 
|---|
| [550] | 557 |                 } | 
|---|
 | 558 |  | 
|---|
| [5] | 559 |                 // allocate and initialize a local chdev | 
|---|
| [407] | 560 |                 // when local cluster matches target cluster | 
|---|
| [5] | 561 |                 if( target_cxy == local_cxy ) | 
|---|
| [1] | 562 |                 { | 
|---|
| [5] | 563 |                     chdev = chdev_create( func, | 
|---|
 | 564 |                                           impl, | 
|---|
 | 565 |                                           channel, | 
|---|
| [188] | 566 |                                           rx,          // direction | 
|---|
| [5] | 567 |                                           base ); | 
|---|
 | 568 |  | 
|---|
| [564] | 569 |                     if( chdev == NULL ) | 
|---|
| [580] | 570 |                     { | 
|---|
 | 571 |                         printk("\n[PANIC] in %s : cannot allocate chdev\n", | 
|---|
 | 572 |                         __FUNCTION__ ); | 
|---|
 | 573 |                         hal_core_sleep(); | 
|---|
 | 574 |                     } | 
|---|
| [5] | 575 |  | 
|---|
 | 576 |                     // make device type specific initialisation | 
|---|
 | 577 |                     if     ( func == DEV_FUNC_IOB ) dev_iob_init( chdev ); | 
|---|
 | 578 |                     else if( func == DEV_FUNC_IOC ) dev_ioc_init( chdev ); | 
|---|
 | 579 |                     else if( func == DEV_FUNC_TXT ) dev_txt_init( chdev ); | 
|---|
 | 580 |                     else if( func == DEV_FUNC_NIC ) dev_nic_init( chdev ); | 
|---|
| [188] | 581 |                     else if( func == DEV_FUNC_FBF ) dev_fbf_init( chdev ); | 
|---|
| [5] | 582 |  | 
|---|
| [127] | 583 |                     // all external (shared) devices are remotely accessible | 
|---|
| [5] | 584 |                     // initialize the replicated chdev_dir[x][y] structures | 
|---|
| [127] | 585 |                     // defining the extended pointers on chdev descriptors | 
|---|
| [633] | 586 |                     xptr_t * entry = NULL; | 
|---|
| [127] | 587 |  | 
|---|
| [188] | 588 |                     if(func==DEV_FUNC_IOB             ) entry  = &chdev_dir.iob; | 
|---|
 | 589 |                     if(func==DEV_FUNC_IOC             ) entry  = &chdev_dir.ioc[channel]; | 
|---|
 | 590 |                     if(func==DEV_FUNC_FBF             ) entry  = &chdev_dir.fbf[channel]; | 
|---|
| [407] | 591 |                     if((func==DEV_FUNC_TXT) && (rx==0)) entry  = &chdev_dir.txt_tx[channel]; | 
|---|
 | 592 |                     if((func==DEV_FUNC_TXT) && (rx==1)) entry  = &chdev_dir.txt_rx[channel]; | 
|---|
| [188] | 593 |                     if((func==DEV_FUNC_NIC) && (rx==0)) entry  = &chdev_dir.nic_tx[channel]; | 
|---|
 | 594 |                     if((func==DEV_FUNC_NIC) && (rx==1)) entry  = &chdev_dir.nic_rx[channel]; | 
|---|
| [127] | 595 |  | 
|---|
| [1] | 596 |                     for( x = 0 ; x < info->x_size ; x++ ) | 
|---|
 | 597 |                     { | 
|---|
| [564] | 598 |                         for( y = 0 ; y < info->y_size ; y++ ) | 
|---|
| [1] | 599 |                         { | 
|---|
| [564] | 600 |                             cxy_t cxy = HAL_CXY_FROM_XY( x , y ); | 
|---|
 | 601 |  | 
|---|
| [633] | 602 |                             if( cluster_is_active( cxy ) && ( entry != NULL ) ) | 
|---|
| [564] | 603 |                             { | 
|---|
 | 604 |                                 hal_remote_s64( XPTR( cxy , entry ), | 
|---|
| [559] | 605 |                                                 XPTR( local_cxy , chdev ) ); | 
|---|
 | 606 |                             } | 
|---|
| [5] | 607 |                         } | 
|---|
| [1] | 608 |                     } | 
|---|
 | 609 |  | 
|---|
| [438] | 610 | #if( DEBUG_KERNEL_INIT & 0x1 ) | 
|---|
 | 611 | if( hal_time_stamp() > DEBUG_KERNEL_INIT ) | 
|---|
| [601] | 612 | printk("\n[%s] : create chdev %s / channel = %d / rx = %d / cluster %x / chdev = %x\n", | 
|---|
| [407] | 613 | __FUNCTION__ , chdev_func_str( func ), channel , rx , local_cxy , chdev ); | 
|---|
| [389] | 614 | #endif | 
|---|
| [5] | 615 |                 }  // end if match | 
|---|
 | 616 |  | 
|---|
| [19] | 617 |                 // increment chdev global index (matching or not) | 
|---|
| [188] | 618 |                 ext_chdev_gid++; | 
|---|
| [5] | 619 |  | 
|---|
 | 620 |             } // end loop on directions | 
|---|
 | 621 |         }  // end loop on channels | 
|---|
| [188] | 622 |         } // end loop on devices | 
|---|
 | 623 | }  // end external_devices_init() | 
|---|
| [5] | 624 |  | 
|---|
| [188] | 625 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [623] | 626 | // This function is called by core[0] in cluster 0 to allocate memory and initialize the PIC | 
|---|
| [407] | 627 | // device, namely the informations attached to the external IOPIC controller, that | 
|---|
 | 628 | // must be replicated in all clusters (struct iopic_input). | 
|---|
| [188] | 629 | // This initialisation must be done before other devices initialisation because the IRQ | 
|---|
| [407] | 630 | // routing infrastructure is required for both internal and external devices init. | 
|---|
| [188] | 631 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 632 | // @ info    : pointer on the local boot-info structure. | 
|---|
 | 633 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 634 | static void __attribute__ ((noinline)) iopic_init( boot_info_t * info ) | 
|---|
| [188] | 635 | { | 
|---|
 | 636 |     boot_device_t * dev_tbl;         // pointer on boot_info external devices array | 
|---|
 | 637 |         uint32_t        dev_nr;          // actual number of external devices | 
|---|
 | 638 |         xptr_t          base;            // remote pointer on segment base | 
|---|
 | 639 |     uint32_t        func;            // device functionnal index | 
|---|
 | 640 |     uint32_t        impl;            // device implementation index | 
|---|
 | 641 |         uint32_t        i;               // device index in dev_tbl | 
|---|
 | 642 |     uint32_t        x;               // cluster X coordinate | 
|---|
 | 643 |     uint32_t        y;               // cluster Y coordinate | 
|---|
 | 644 |     bool_t          found;           // IOPIC found | 
|---|
 | 645 |         chdev_t       * chdev;           // pointer on PIC chdev descriptor | 
|---|
 | 646 |  | 
|---|
 | 647 |     // get number of external peripherals and base of array from boot_info | 
|---|
 | 648 |         dev_nr      = info->ext_dev_nr; | 
|---|
 | 649 |     dev_tbl     = info->ext_dev; | 
|---|
 | 650 |  | 
|---|
| [564] | 651 |     // avoid GCC warning | 
|---|
 | 652 |     base        = XPTR_NULL; | 
|---|
 | 653 |     impl        = 0; | 
|---|
 | 654 |  | 
|---|
| [188] | 655 |     // loop on external peripherals to get the IOPIC   | 
|---|
 | 656 |         for( i = 0 , found = false ; i < dev_nr ; i++ ) | 
|---|
 | 657 |         { | 
|---|
 | 658 |         func = FUNC_FROM_TYPE( dev_tbl[i].type ); | 
|---|
 | 659 |  | 
|---|
| [127] | 660 |         if( func == DEV_FUNC_PIC ) | 
|---|
| [1] | 661 |         { | 
|---|
| [188] | 662 |             base     = dev_tbl[i].base; | 
|---|
 | 663 |             impl     = IMPL_FROM_TYPE( dev_tbl[i].type ); | 
|---|
 | 664 |             found    = true; | 
|---|
 | 665 |             break; | 
|---|
 | 666 |         } | 
|---|
 | 667 |     } | 
|---|
| [5] | 668 |  | 
|---|
| [564] | 669 |     // check PIC existence | 
|---|
 | 670 |     if( found == false ) | 
|---|
| [580] | 671 |     { | 
|---|
 | 672 |         printk("\n[PANIC] in %s : PIC device not found\n", | 
|---|
 | 673 |         __FUNCTION__ ); | 
|---|
 | 674 |         hal_core_sleep(); | 
|---|
 | 675 |     } | 
|---|
| [1] | 676 |  | 
|---|
| [407] | 677 |     // allocate and initialize the PIC chdev in cluster 0 | 
|---|
 | 678 |     chdev = chdev_create( DEV_FUNC_PIC, | 
|---|
| [188] | 679 |                           impl, | 
|---|
 | 680 |                           0,      // channel | 
|---|
 | 681 |                           0,      // direction, | 
|---|
 | 682 |                           base ); | 
|---|
| [5] | 683 |  | 
|---|
| [564] | 684 |     // check memory | 
|---|
 | 685 |     if( chdev == NULL ) | 
|---|
| [580] | 686 |     { | 
|---|
 | 687 |         printk("\n[PANIC] in %s : no memory for PIC chdev\n", | 
|---|
 | 688 |         __FUNCTION__ ); | 
|---|
 | 689 |         hal_core_sleep(); | 
|---|
 | 690 |     } | 
|---|
| [5] | 691 |  | 
|---|
| [188] | 692 |     // make PIC device type specific initialisation | 
|---|
 | 693 |     dev_pic_init( chdev ); | 
|---|
| [1] | 694 |  | 
|---|
| [407] | 695 |     // register, in all clusters, the extended pointer | 
|---|
 | 696 |     // on PIC chdev in "chdev_dir" array | 
|---|
| [188] | 697 |     xptr_t * entry = &chdev_dir.pic;     | 
|---|
 | 698 |                  | 
|---|
 | 699 |     for( x = 0 ; x < info->x_size ; x++ ) | 
|---|
 | 700 |     { | 
|---|
| [564] | 701 |         for( y = 0 ; y < info->y_size ; y++ ) | 
|---|
| [188] | 702 |         { | 
|---|
| [564] | 703 |             cxy_t cxy = HAL_CXY_FROM_XY( x , y ); | 
|---|
 | 704 |  | 
|---|
 | 705 |             if( cluster_is_active( cxy ) ) | 
|---|
 | 706 |             { | 
|---|
 | 707 |                 hal_remote_s64( XPTR( cxy , entry ) ,  | 
|---|
| [559] | 708 |                                 XPTR( local_cxy , chdev ) ); | 
|---|
 | 709 |             } | 
|---|
| [188] | 710 |         } | 
|---|
 | 711 |     } | 
|---|
| [1] | 712 |  | 
|---|
| [407] | 713 |     // initialize, in all clusters, the "iopic_input" structure | 
|---|
| [188] | 714 |     // defining how external IRQs are connected to IOPIC  | 
|---|
 | 715 |  | 
|---|
| [407] | 716 |     // register default value for unused inputs  | 
|---|
 | 717 |     for( x = 0 ; x < info->x_size ; x++ ) | 
|---|
 | 718 |     { | 
|---|
| [564] | 719 |         for( y = 0 ; y < info->y_size ; y++ ) | 
|---|
| [407] | 720 |         { | 
|---|
| [564] | 721 |             cxy_t cxy = HAL_CXY_FROM_XY( x , y ); | 
|---|
 | 722 |  | 
|---|
 | 723 |             if( cluster_is_active( cxy ) ) | 
|---|
 | 724 |             { | 
|---|
 | 725 |                 hal_remote_memset( XPTR( cxy , &iopic_input ),  | 
|---|
 | 726 |                                    0xFF , sizeof(iopic_input_t) ); | 
|---|
| [559] | 727 |             } | 
|---|
| [407] | 728 |         } | 
|---|
 | 729 |     } | 
|---|
 | 730 |  | 
|---|
 | 731 |     // register input IRQ index for valid inputs  | 
|---|
| [577] | 732 |     uint32_t   id;             // input IRQ index | 
|---|
 | 733 |     uint8_t    valid;          // input IRQ is connected | 
|---|
 | 734 |     uint32_t   type;           // source device type | 
|---|
 | 735 |     uint8_t    channel;        // source device channel | 
|---|
 | 736 |     uint8_t    is_rx;          // source device direction | 
|---|
 | 737 |     uint32_t * ptr = NULL;     // local pointer on one field in iopic_input stucture | 
|---|
| [407] | 738 |  | 
|---|
| [188] | 739 |     for( id = 0 ; id < CONFIG_MAX_EXTERNAL_IRQS ; id++ ) | 
|---|
 | 740 |     { | 
|---|
 | 741 |         valid   = dev_tbl[i].irq[id].valid; | 
|---|
 | 742 |         type    = dev_tbl[i].irq[id].dev_type; | 
|---|
 | 743 |         channel = dev_tbl[i].irq[id].channel; | 
|---|
 | 744 |         is_rx   = dev_tbl[i].irq[id].is_rx; | 
|---|
| [407] | 745 |         func    = FUNC_FROM_TYPE( type ); | 
|---|
| [188] | 746 |  | 
|---|
| [407] | 747 |         // get pointer on relevant field in iopic_input | 
|---|
 | 748 |         if( valid ) | 
|---|
| [188] | 749 |         { | 
|---|
| [407] | 750 |             if     ( func == DEV_FUNC_IOC )                 ptr = &iopic_input.ioc[channel];  | 
|---|
 | 751 |             else if((func == DEV_FUNC_TXT) && (is_rx == 0)) ptr = &iopic_input.txt_tx[channel]; | 
|---|
 | 752 |             else if((func == DEV_FUNC_TXT) && (is_rx != 0)) ptr = &iopic_input.txt_rx[channel]; | 
|---|
| [492] | 753 |             else if((func == DEV_FUNC_NIC) && (is_rx == 0)) ptr = &iopic_input.nic_tx[channel]; | 
|---|
 | 754 |             else if((func == DEV_FUNC_NIC) && (is_rx != 0)) ptr = &iopic_input.nic_rx[channel]; | 
|---|
 | 755 |             else if( func == DEV_FUNC_IOB )                 ptr = &iopic_input.iob; | 
|---|
| [580] | 756 |             else | 
|---|
 | 757 |             { | 
|---|
 | 758 |                 printk("\n[PANIC] in %s : illegal source device for IOPIC input\n", | 
|---|
 | 759 |                 __FUNCTION__ ); | 
|---|
 | 760 |                 hal_core_sleep(); | 
|---|
 | 761 |             } | 
|---|
| [188] | 762 |  | 
|---|
| [407] | 763 |             // set one entry in all "iopic_input" structures | 
|---|
 | 764 |             for( x = 0 ; x < info->x_size ; x++ ) | 
|---|
 | 765 |             { | 
|---|
| [564] | 766 |                 for( y = 0 ; y < info->y_size ; y++ ) | 
|---|
| [407] | 767 |                 { | 
|---|
| [564] | 768 |                     cxy_t cxy = HAL_CXY_FROM_XY( x , y ); | 
|---|
 | 769 |  | 
|---|
 | 770 |                     if( cluster_is_active( cxy ) ) | 
|---|
 | 771 |                     { | 
|---|
 | 772 |                         hal_remote_s64( XPTR( cxy , ptr ) , id );  | 
|---|
| [559] | 773 |                     } | 
|---|
| [407] | 774 |                 } | 
|---|
 | 775 |             } | 
|---|
| [188] | 776 |         } | 
|---|
 | 777 |     }  | 
|---|
 | 778 |  | 
|---|
| [438] | 779 | #if( DEBUG_KERNEL_INIT & 0x1 ) | 
|---|
| [601] | 780 | if( hal_time_stamp() > DEBUG_KERNEL_INIT ) | 
|---|
| [407] | 781 | { | 
|---|
| [601] | 782 |     printk("\n[%s] created PIC chdev in cluster %x at cycle %d\n", | 
|---|
| [407] | 783 |     __FUNCTION__ , local_cxy , (uint32_t)hal_time_stamp() ); | 
|---|
 | 784 |     dev_pic_inputs_display(); | 
|---|
 | 785 | } | 
|---|
| [389] | 786 | #endif | 
|---|
| [188] | 787 |      | 
|---|
 | 788 | }  // end iopic_init() | 
|---|
 | 789 |  | 
|---|
| [1] | 790 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [623] | 791 | // This function is called by all core[0]s in all cluster to complete the PIC device | 
|---|
| [188] | 792 | // initialisation, namely the informations attached to the LAPIC controller. | 
|---|
 | 793 | // This initialisation must be done after the IOPIC initialisation, but before other  | 
|---|
 | 794 | // devices initialisation because the IRQ routing infrastructure is required for both | 
|---|
 | 795 | // internal and external devices initialisation. | 
|---|
 | 796 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 797 | // @ info    : pointer on the local boot-info structure. | 
|---|
 | 798 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 799 | static void __attribute__ ((noinline)) lapic_init( boot_info_t * info ) | 
|---|
| [188] | 800 | { | 
|---|
 | 801 |     boot_device_t * dev_tbl;      // pointer on boot_info internal devices array | 
|---|
 | 802 |     uint32_t        dev_nr;       // number of internal devices | 
|---|
 | 803 |     uint32_t        i;            // device index in dev_tbl | 
|---|
 | 804 |         xptr_t          base;         // remote pointer on segment base | 
|---|
 | 805 |     uint32_t        func;         // device functionnal type in boot_info | 
|---|
 | 806 |     bool_t          found;        // LAPIC found | 
|---|
 | 807 |  | 
|---|
 | 808 |     // get number of internal peripherals and base  | 
|---|
 | 809 |         dev_nr      = info->int_dev_nr; | 
|---|
 | 810 |     dev_tbl     = info->int_dev; | 
|---|
 | 811 |  | 
|---|
 | 812 |     // loop on internal peripherals to get the lapic device  | 
|---|
 | 813 |         for( i = 0 , found = false ; i < dev_nr ; i++ ) | 
|---|
 | 814 |         { | 
|---|
 | 815 |         func = FUNC_FROM_TYPE( dev_tbl[i].type ); | 
|---|
 | 816 |  | 
|---|
 | 817 |         if( func == DEV_FUNC_ICU ) | 
|---|
 | 818 |         { | 
|---|
 | 819 |             base     = dev_tbl[i].base; | 
|---|
 | 820 |             found    = true; | 
|---|
 | 821 |             break; | 
|---|
 | 822 |         } | 
|---|
 | 823 |     } | 
|---|
 | 824 |  | 
|---|
 | 825 |     // if the LAPIC controller is not defined in the boot_info, | 
|---|
 | 826 |     // we simply don't initialize the PIC extensions in the kernel,  | 
|---|
 | 827 |     // making the assumption that the LAPIC related informations  | 
|---|
 | 828 |     // are hidden in the hardware specific PIC driver.  | 
|---|
 | 829 |     if( found ) | 
|---|
 | 830 |     { | 
|---|
 | 831 |         // initialise the PIC extensions for | 
|---|
 | 832 |         // the core descriptor and core manager extensions | 
|---|
 | 833 |         dev_pic_extend_init( (uint32_t *)GET_PTR( base ) ); | 
|---|
 | 834 |  | 
|---|
 | 835 |         // initialize the "lapic_input" structure | 
|---|
 | 836 |         // defining how internal IRQs are connected to LAPIC  | 
|---|
 | 837 |         uint32_t        id; | 
|---|
 | 838 |         uint8_t         valid; | 
|---|
 | 839 |         uint8_t         channel; | 
|---|
 | 840 |         uint32_t        func; | 
|---|
 | 841 |  | 
|---|
 | 842 |         for( id = 0 ; id < CONFIG_MAX_INTERNAL_IRQS ; id++ ) | 
|---|
 | 843 |         { | 
|---|
 | 844 |             valid    = dev_tbl[i].irq[id].valid; | 
|---|
 | 845 |             func     = FUNC_FROM_TYPE( dev_tbl[i].irq[id].dev_type ); | 
|---|
 | 846 |             channel  = dev_tbl[i].irq[id].channel; | 
|---|
 | 847 |  | 
|---|
 | 848 |             if( valid ) // only valid local IRQs are registered | 
|---|
 | 849 |             { | 
|---|
 | 850 |                 if     ( func == DEV_FUNC_MMC ) lapic_input.mmc = id; | 
|---|
 | 851 |                 else if( func == DEV_FUNC_DMA ) lapic_input.dma[channel] = id; | 
|---|
| [580] | 852 |                 else | 
|---|
 | 853 |                 { | 
|---|
 | 854 |                     printk("\n[PANIC] in %s : illegal source device for LAPIC input\n", | 
|---|
 | 855 |                     __FUNCTION__ ); | 
|---|
 | 856 |                     hal_core_sleep(); | 
|---|
 | 857 |                 } | 
|---|
| [188] | 858 |             } | 
|---|
 | 859 |         } | 
|---|
 | 860 |     } | 
|---|
 | 861 | }  // end lapic_init() | 
|---|
 | 862 |  | 
|---|
 | 863 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [14] | 864 | // This static function returns the identifiers of the calling core. | 
|---|
 | 865 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 866 | // @ info    : pointer on boot_info structure. | 
|---|
 | 867 | // @ lid     : [out] core local index in cluster. | 
|---|
 | 868 | // @ cxy     : [out] cluster identifier. | 
|---|
 | 869 | // @ lid     : [out] core global identifier (hardware). | 
|---|
 | 870 | // @ return 0 if success / return EINVAL if not found. | 
|---|
 | 871 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 872 | static error_t __attribute__ ((noinline)) get_core_identifiers( boot_info_t * info, | 
|---|
 | 873 |                                                                 lid_t       * lid, | 
|---|
 | 874 |                                                                 cxy_t       * cxy, | 
|---|
 | 875 |                                                                 gid_t       * gid ) | 
|---|
| [14] | 876 | { | 
|---|
| [127] | 877 |     uint32_t   i; | 
|---|
| [14] | 878 |     gid_t      global_id; | 
|---|
| [19] | 879 |  | 
|---|
| [14] | 880 |     // get global identifier from hardware register | 
|---|
| [127] | 881 |     global_id = hal_get_gid(); | 
|---|
| [14] | 882 |  | 
|---|
 | 883 |     // makes an associative search in boot_info to get (cxy,lid) from global_id | 
|---|
 | 884 |     for( i = 0 ; i < info->cores_nr ; i++ ) | 
|---|
 | 885 |     { | 
|---|
 | 886 |         if( global_id == info->core[i].gid ) | 
|---|
 | 887 |         { | 
|---|
 | 888 |             *lid = info->core[i].lid; | 
|---|
 | 889 |             *cxy = info->core[i].cxy; | 
|---|
 | 890 |             *gid = global_id; | 
|---|
 | 891 |             return 0; | 
|---|
 | 892 |         } | 
|---|
 | 893 |     } | 
|---|
 | 894 |     return EINVAL; | 
|---|
| [19] | 895 | } | 
|---|
| [14] | 896 |  | 
|---|
| [626] | 897 |  | 
|---|
 | 898 |  | 
|---|
 | 899 |  | 
|---|
 | 900 |  | 
|---|
 | 901 | ///////////////////////////////// | 
|---|
 | 902 | // kleenex debug function | 
|---|
 | 903 | ///////////////////////////////// | 
|---|
 | 904 | void display_fat( uint32_t step ) | 
|---|
 | 905 | { | 
|---|
 | 906 |     fatfs_ctx_t * fatfs_ctx = fs_context[FS_TYPE_FATFS].extend; | 
|---|
 | 907 |     if( fatfs_ctx != NULL )  | 
|---|
 | 908 |     { | 
|---|
 | 909 |         printk("\n[%s] step %d at cycle %d\n", __FUNCTION__, step, (uint32_t)hal_get_cycles() ); | 
|---|
 | 910 |         xptr_t     mapper_xp = fatfs_ctx->fat_mapper_xp; | 
|---|
 | 911 |         mapper_display_page( mapper_xp , 0 , 128 ); | 
|---|
 | 912 |     } | 
|---|
 | 913 |     else | 
|---|
 | 914 |     { | 
|---|
 | 915 |         printk("\n[%s] step %d : fatfs context not initialized\n", __FUNCTION__, step ); | 
|---|
 | 916 |     } | 
|---|
 | 917 | } | 
|---|
 | 918 |  | 
|---|
 | 919 |  | 
|---|
 | 920 |  | 
|---|
 | 921 |  | 
|---|
 | 922 |  | 
|---|
| [14] | 923 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [1] | 924 | // This function is the entry point for the kernel initialisation. | 
|---|
| [623] | 925 | // It is executed by all cores in all clusters, but only core[0] initializes | 
|---|
 | 926 | // the shared resources such as the cluster manager, or the local peripherals. | 
|---|
| [19] | 927 | // To comply with the multi-kernels paradigm, it accesses only local cluster memory, using | 
|---|
 | 928 | // only information contained in the local boot_info_t structure, set by the bootloader. | 
|---|
| [623] | 929 | // Only core[0] in cluster 0 print the log messages. | 
|---|
| [1] | 930 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 931 | // @ info    : pointer on the local boot-info structure. | 
|---|
 | 932 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 933 | void kernel_init( boot_info_t * info ) | 
|---|
 | 934 | { | 
|---|
| [204] | 935 |     lid_t        core_lid = -1;             // running core local index | 
|---|
 | 936 |     cxy_t        core_cxy = -1;             // running core cluster identifier | 
|---|
 | 937 |     gid_t        core_gid;                  // running core hardware identifier  | 
|---|
 | 938 |     cluster_t  * cluster;                   // pointer on local cluster manager | 
|---|
 | 939 |     core_t     * core;                      // pointer on running core descriptor | 
|---|
 | 940 |     thread_t   * thread;                    // pointer on idle thread descriptor | 
|---|
 | 941 |  | 
|---|
 | 942 |     xptr_t       vfs_root_inode_xp;         // extended pointer on VFS root inode | 
|---|
 | 943 |     xptr_t       devfs_dev_inode_xp;        // extended pointer on DEVFS dev inode     | 
|---|
 | 944 |     xptr_t       devfs_external_inode_xp;   // extended pointer on DEVFS external inode        | 
|---|
 | 945 |     xptr_t       devfs_internal_inode_xp;   // extended pointer on DEVFS internal inode        | 
|---|
 | 946 |  | 
|---|
| [1] | 947 |     error_t      error; | 
|---|
| [285] | 948 |     reg_t        status;                    // running core status register | 
|---|
| [1] | 949 |  | 
|---|
| [188] | 950 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [623] | 951 |     // STEP 1 : Each core get its core identifier from boot_info, and makes  | 
|---|
| [188] | 952 |     //          a partial initialisation of its private idle thread descriptor. | 
|---|
| [623] | 953 |     //          core[0] initializes the "local_cxy" global variable. | 
|---|
 | 954 |     //          core[0] in cluster[0] initializes the TXT0 chdev for log messages. | 
|---|
| [188] | 955 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 956 |  | 
|---|
| [23] | 957 |     error = get_core_identifiers( info, | 
|---|
| [14] | 958 |                                   &core_lid, | 
|---|
 | 959 |                                   &core_cxy, | 
|---|
 | 960 |                                   &core_gid ); | 
|---|
| [1] | 961 |  | 
|---|
| [623] | 962 |     // core[0] initialize cluster identifier | 
|---|
| [14] | 963 |     if( core_lid == 0 ) local_cxy = info->cxy; | 
|---|
| [1] | 964 |  | 
|---|
| [127] | 965 |     // each core gets a pointer on its private idle thread descriptor | 
|---|
 | 966 |     thread = (thread_t *)( idle_threads + (core_lid * CONFIG_THREAD_DESC_SIZE) ); | 
|---|
| [68] | 967 |  | 
|---|
| [127] | 968 |     // each core registers this thread pointer in hardware register | 
|---|
| [68] | 969 |     hal_set_current_thread( thread ); | 
|---|
| [71] | 970 |  | 
|---|
| [407] | 971 |     // each core register core descriptor pointer in idle thread descriptor | 
|---|
 | 972 |     thread->core = &LOCAL_CLUSTER->core_tbl[core_lid]; | 
|---|
 | 973 |  | 
|---|
| [564] | 974 |     // each core initializes the idle thread locks counters | 
|---|
 | 975 |     thread->busylocks = 0; | 
|---|
| [124] | 976 |  | 
|---|
| [564] | 977 | #if DEBUG_BUSYLOCK | 
|---|
 | 978 |     // each core initialise the idle thread list of busylocks | 
|---|
 | 979 |     xlist_root_init( XPTR( local_cxy , &thread->busylocks_root ) ); | 
|---|
 | 980 | #endif | 
|---|
| [14] | 981 |  | 
|---|
| [623] | 982 |     // core[0] initializes cluster info | 
|---|
| [564] | 983 |     if( core_lid == 0 ) cluster_info_init( info ); | 
|---|
 | 984 |  | 
|---|
| [623] | 985 |     // core[0] in cluster[0] initialises TXT0 chdev descriptor | 
|---|
| [564] | 986 |     if( (core_lid == 0) && (core_cxy == 0) ) txt0_device_init( info ); | 
|---|
 | 987 |  | 
|---|
| [623] | 988 |     // all cores check identifiers | 
|---|
 | 989 |     if( error ) | 
|---|
 | 990 |     { | 
|---|
 | 991 |         printk("\n[PANIC] in %s : illegal core : gid %x / cxy %x / lid %d", | 
|---|
 | 992 |         __FUNCTION__, core_lid, core_cxy, core_lid ); | 
|---|
 | 993 |         hal_core_sleep(); | 
|---|
 | 994 |     } | 
|---|
 | 995 |  | 
|---|
| [14] | 996 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 997 |     if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ),  | 
|---|
 | 998 |                                         (info->x_size * info->y_size) ); | 
|---|
| [14] | 999 |     barrier_wait( &local_barrier , info->cores_nr ); | 
|---|
| [437] | 1000 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [14] | 1001 |  | 
|---|
| [438] | 1002 | #if DEBUG_KERNEL_INIT | 
|---|
| [583] | 1003 | if( (core_lid ==  0) & (local_cxy == 0) )  | 
|---|
| [624] | 1004 | printk("\n[%s] exit barrier 1 : TXT0 initialized / cycle %d\n", | 
|---|
| [610] | 1005 | __FUNCTION__, (uint32_t)hal_get_cycles() ); | 
|---|
| [437] | 1006 | #endif | 
|---|
| [14] | 1007 |  | 
|---|
| [623] | 1008 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [637] | 1009 |     // STEP 2 : core[0] initializes the cluster manager, | 
|---|
 | 1010 |     //          including the physical memory allocators.  | 
|---|
| [623] | 1011 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [188] | 1012 |  | 
|---|
| [623] | 1013 |     // core[0] initialises DQDT (only core[0] in cluster 0 build the quad-tree) | 
|---|
| [582] | 1014 |     if( core_lid == 0 ) dqdt_init(); | 
|---|
 | 1015 |      | 
|---|
| [623] | 1016 |     // core[0] initialize other cluster manager complex structures | 
|---|
| [14] | 1017 |     if( core_lid == 0 ) | 
|---|
| [1] | 1018 |     { | 
|---|
| [564] | 1019 |         error = cluster_manager_init( info ); | 
|---|
| [1] | 1020 |  | 
|---|
| [14] | 1021 |         if( error ) | 
|---|
| [580] | 1022 |         { | 
|---|
 | 1023 |              printk("\n[PANIC] in %s : cannot initialize cluster manager in cluster %x\n", | 
|---|
 | 1024 |              __FUNCTION__, local_cxy ); | 
|---|
 | 1025 |              hal_core_sleep(); | 
|---|
 | 1026 |         } | 
|---|
| [14] | 1027 |     } | 
|---|
| [5] | 1028 |  | 
|---|
| [14] | 1029 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 1030 |     if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ),  | 
|---|
 | 1031 |                                         (info->x_size * info->y_size) ); | 
|---|
| [14] | 1032 |     barrier_wait( &local_barrier , info->cores_nr ); | 
|---|
 | 1033 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [1] | 1034 |  | 
|---|
| [438] | 1035 | #if DEBUG_KERNEL_INIT | 
|---|
 | 1036 | if( (core_lid ==  0) & (local_cxy == 0) )  | 
|---|
| [624] | 1037 | printk("\n[%s] exit barrier 2 : cluster manager initialized / cycle %d\n", | 
|---|
| [610] | 1038 | __FUNCTION__, (uint32_t)hal_get_cycles() ); | 
|---|
| [437] | 1039 | #endif | 
|---|
| [1] | 1040 |  | 
|---|
| [188] | 1041 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [624] | 1042 |     // STEP 3 : all cores initialize the idle thread descriptor. | 
|---|
 | 1043 |     //          core[0] initializes the process_zero descriptor, | 
|---|
| [623] | 1044 |     //          including the kernel VMM (both GPT and VSL)  | 
|---|
| [188] | 1045 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1046 |  | 
|---|
 | 1047 |     // all cores get pointer on local cluster manager & core descriptor | 
|---|
| [14] | 1048 |     cluster = &cluster_manager; | 
|---|
| [127] | 1049 |     core    = &cluster->core_tbl[core_lid]; | 
|---|
| [1] | 1050 |  | 
|---|
| [624] | 1051 |     // all cores update the register(s) defining the kernel | 
|---|
 | 1052 |     // entry points for interrupts, exceptions and syscalls, | 
|---|
 | 1053 |     // this must be done before VFS initialisation, because  | 
|---|
 | 1054 |     // kernel_init() uses RPCs requiring IPIs... | 
|---|
 | 1055 |     hal_set_kentry(); | 
|---|
 | 1056 |  | 
|---|
 | 1057 |     // all cores initialize the idle thread descriptor | 
|---|
 | 1058 |     thread_idle_init( thread, | 
|---|
 | 1059 |                       THREAD_IDLE, | 
|---|
 | 1060 |                       &thread_idle_func, | 
|---|
 | 1061 |                       NULL, | 
|---|
 | 1062 |                       core_lid ); | 
|---|
 | 1063 |  | 
|---|
| [623] | 1064 |     // core[0] initializes the process_zero descriptor, | 
|---|
 | 1065 |     if( core_lid == 0 ) process_zero_create( &process_zero , info ); | 
|---|
| [5] | 1066 |  | 
|---|
| [623] | 1067 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1068 |     if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ),  | 
|---|
 | 1069 |                                         (info->x_size * info->y_size) ); | 
|---|
 | 1070 |     barrier_wait( &local_barrier , info->cores_nr ); | 
|---|
 | 1071 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1072 |  | 
|---|
 | 1073 | #if DEBUG_KERNEL_INIT | 
|---|
 | 1074 | if( (core_lid ==  0) & (local_cxy == 0) )  | 
|---|
| [624] | 1075 | printk("\n[%s] exit barrier 3 : kernel processs initialized / cycle %d\n", | 
|---|
| [623] | 1076 | __FUNCTION__, (uint32_t)hal_get_cycles() ); | 
|---|
 | 1077 | #endif | 
|---|
 | 1078 |  | 
|---|
 | 1079 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1080 |     // STEP 4 : all cores initialize their private MMU  | 
|---|
 | 1081 |     //          core[0] in cluster 0 initializes the IOPIC device. | 
|---|
 | 1082 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1083 |  | 
|---|
 | 1084 |     // all cores initialise their MMU | 
|---|
 | 1085 |     hal_mmu_init( &process_zero.vmm.gpt ); | 
|---|
 | 1086 |  | 
|---|
 | 1087 |     // core[0] in cluster[0] initializes the PIC chdev, | 
|---|
| [188] | 1088 |     if( (core_lid == 0) && (local_cxy == 0) ) iopic_init( info ); | 
|---|
 | 1089 |      | 
|---|
 | 1090 |     //////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 1091 |     if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ),  | 
|---|
 | 1092 |                                         (info->x_size * info->y_size) ); | 
|---|
| [188] | 1093 |     barrier_wait( &local_barrier , info->cores_nr ); | 
|---|
 | 1094 |     //////////////////////////////////////////////////////////////////////////////// | 
|---|
| [127] | 1095 |  | 
|---|
| [438] | 1096 | #if DEBUG_KERNEL_INIT | 
|---|
 | 1097 | if( (core_lid ==  0) & (local_cxy == 0) )  | 
|---|
| [624] | 1098 | printk("\n[%s] exit barrier 4 : MMU and IOPIC initialized / cycle %d\n", | 
|---|
| [610] | 1099 | __FUNCTION__, (uint32_t)hal_get_cycles() ); | 
|---|
| [437] | 1100 | #endif | 
|---|
| [1] | 1101 |  | 
|---|
| [188] | 1102 |     //////////////////////////////////////////////////////////////////////////////// | 
|---|
| [637] | 1103 |     // STEP 5 : core[0] initialize the distibuted LAPIC descriptor. | 
|---|
 | 1104 |     //          core[0] initialize the internal chdev descriptors | 
|---|
| [623] | 1105 |     //          core[0] initialize the local external chdev descriptors | 
|---|
| [188] | 1106 |     //////////////////////////////////////////////////////////////////////////////// | 
|---|
| [5] | 1107 |  | 
|---|
| [623] | 1108 |     // all core[0]s initialize their local LAPIC extension, | 
|---|
| [279] | 1109 |     if( core_lid == 0 ) lapic_init( info ); | 
|---|
 | 1110 |  | 
|---|
| [623] | 1111 |     // core[0] scan the internal (private) peripherals, | 
|---|
| [188] | 1112 |     // and allocates memory for the corresponding chdev descriptors. | 
|---|
 | 1113 |     if( core_lid == 0 ) internal_devices_init( info ); | 
|---|
 | 1114 |          | 
|---|
| [1] | 1115 |  | 
|---|
| [623] | 1116 |     // All core[0]s contribute to initialise external peripheral chdev descriptors. | 
|---|
 | 1117 |     // Each core[0][cxy] scan the set of external (shared) peripherals (but the TXT0), | 
|---|
| [14] | 1118 |     // and allocates memory for the chdev descriptors that must be placed | 
|---|
| [127] | 1119 |     // on the (cxy) cluster according to the global index value. | 
|---|
| [188] | 1120 |  | 
|---|
| [14] | 1121 |     if( core_lid == 0 ) external_devices_init( info ); | 
|---|
| [1] | 1122 |  | 
|---|
| [14] | 1123 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 1124 |     if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ),  | 
|---|
 | 1125 |                                         (info->x_size * info->y_size) ); | 
|---|
| [14] | 1126 |     barrier_wait( &local_barrier , info->cores_nr ); | 
|---|
 | 1127 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [5] | 1128 |  | 
|---|
| [438] | 1129 | #if DEBUG_KERNEL_INIT | 
|---|
 | 1130 | if( (core_lid ==  0) & (local_cxy == 0) )  | 
|---|
| [624] | 1131 | printk("\n[%s] exit barrier 5 : chdevs initialised / cycle %d\n", | 
|---|
| [610] | 1132 | __FUNCTION__, (uint32_t)hal_get_cycles() ); | 
|---|
| [437] | 1133 | #endif | 
|---|
| [1] | 1134 |  | 
|---|
| [438] | 1135 | #if( DEBUG_KERNEL_INIT & 1 ) | 
|---|
| [443] | 1136 | if( (core_lid ==  0) & (local_cxy == 0) )  | 
|---|
| [437] | 1137 | chdev_dir_display(); | 
|---|
 | 1138 | #endif | 
|---|
 | 1139 |      | 
|---|
| [188] | 1140 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [624] | 1141 |     // STEP 6 : all cores enable IPI (Inter Procesor Interrupt), | 
|---|
 | 1142 |     //          all cores unblock the idle thread, and register it in scheduler. | 
|---|
 | 1143 |     //          core[0] in cluster[0] creates the VFS root inode. | 
|---|
| [188] | 1144 |     //          It access the boot device to initialize the file system context. | 
|---|
 | 1145 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1146 |  | 
|---|
| [564] | 1147 |     // All cores enable IPI  | 
|---|
| [279] | 1148 |     dev_pic_enable_ipi(); | 
|---|
 | 1149 |     hal_enable_irq( &status ); | 
|---|
 | 1150 |  | 
|---|
| [624] | 1151 |     // all cores unblock the idle thread, and register it in scheduler | 
|---|
| [296] | 1152 |     thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL ); | 
|---|
| [103] | 1153 |     core->scheduler.idle = thread; | 
|---|
| [1] | 1154 |  | 
|---|
| [623] | 1155 |     // core[O] in cluster[0] creates the VFS root | 
|---|
| [188] | 1156 |     if( (core_lid ==  0) && (local_cxy == 0 ) )  | 
|---|
| [14] | 1157 |     { | 
|---|
| [188] | 1158 |         vfs_root_inode_xp = XPTR_NULL; | 
|---|
| [23] | 1159 |  | 
|---|
| [614] | 1160 |         // Only FATFS is supported yet, | 
|---|
 | 1161 |         // other File System can be introduced here | 
|---|
| [23] | 1162 |         if( CONFIG_VFS_ROOT_IS_FATFS ) | 
|---|
 | 1163 |         { | 
|---|
| [626] | 1164 |             // 1. allocate memory for FATFS context in cluster 0 | 
|---|
| [188] | 1165 |             fatfs_ctx_t * fatfs_ctx = fatfs_ctx_alloc(); | 
|---|
 | 1166 |  | 
|---|
| [564] | 1167 |             if( fatfs_ctx == NULL ) | 
|---|
| [580] | 1168 |             { | 
|---|
 | 1169 |                 printk("\n[PANIC] in %s : cannot create FATFS context in cluster 0\n", | 
|---|
 | 1170 |                 __FUNCTION__ ); | 
|---|
 | 1171 |                 hal_core_sleep(); | 
|---|
 | 1172 |             } | 
|---|
| [188] | 1173 |  | 
|---|
 | 1174 |             // 2. access boot device to initialize FATFS context | 
|---|
 | 1175 |             fatfs_ctx_init( fatfs_ctx ); | 
|---|
| [626] | 1176 |  | 
|---|
| [188] | 1177 |             // 3. get various informations from FATFS context | 
|---|
 | 1178 |             uint32_t root_dir_cluster = fatfs_ctx->root_dir_cluster; | 
|---|
 | 1179 |             uint32_t cluster_size     = fatfs_ctx->bytes_per_sector *  | 
|---|
 | 1180 |                                         fatfs_ctx->sectors_per_cluster; | 
|---|
 | 1181 |             uint32_t total_clusters   = fatfs_ctx->fat_sectors_count << 7; | 
|---|
 | 1182 |   | 
|---|
| [601] | 1183 |             // 4. create VFS root inode in cluster 0 | 
|---|
| [610] | 1184 |             error = vfs_inode_create( FS_TYPE_FATFS,                       // fs_type | 
|---|
| [188] | 1185 |                                       0,                                   // attr | 
|---|
 | 1186 |                                       0,                                   // rights | 
|---|
 | 1187 |                                       0,                                   // uid | 
|---|
 | 1188 |                                       0,                                   // gid | 
|---|
 | 1189 |                                       &vfs_root_inode_xp );                // return | 
|---|
| [564] | 1190 |             if( error ) | 
|---|
| [580] | 1191 |             { | 
|---|
 | 1192 |                 printk("\n[PANIC] in %s : cannot create VFS root inode in cluster 0\n", | 
|---|
 | 1193 |                 __FUNCTION__ ); | 
|---|
 | 1194 |                 hal_core_sleep(); | 
|---|
 | 1195 |             } | 
|---|
| [188] | 1196 |  | 
|---|
| [623] | 1197 |             // 5. update FATFS root inode "type" and "extend" fields   | 
|---|
| [601] | 1198 |             cxy_t         vfs_root_cxy = GET_CXY( vfs_root_inode_xp ); | 
|---|
 | 1199 |             vfs_inode_t * vfs_root_ptr = GET_PTR( vfs_root_inode_xp ); | 
|---|
| [624] | 1200 |             hal_remote_s32( XPTR( vfs_root_cxy , &vfs_root_ptr->type ), INODE_TYPE_DIR ); | 
|---|
| [601] | 1201 |             hal_remote_spt( XPTR( vfs_root_cxy , &vfs_root_ptr->extend ),  | 
|---|
 | 1202 |                             (void*)(intptr_t)root_dir_cluster ); | 
|---|
| [188] | 1203 |  | 
|---|
| [601] | 1204 |             // 6. initialize the generic VFS context for FATFS  | 
|---|
 | 1205 |             vfs_ctx_init( FS_TYPE_FATFS,                               // fs type | 
|---|
 | 1206 |                           0,                                           // attributes: unused  | 
|---|
 | 1207 |                               total_clusters,                              // number of clusters | 
|---|
 | 1208 |                               cluster_size,                                // bytes | 
|---|
 | 1209 |                               vfs_root_inode_xp,                           // VFS root | 
|---|
 | 1210 |                           fatfs_ctx );                                 // extend | 
|---|
| [23] | 1211 |         } | 
|---|
 | 1212 |         else | 
|---|
 | 1213 |         { | 
|---|
| [564] | 1214 |             printk("\n[PANIC] in %s : unsupported VFS type in cluster 0\n", | 
|---|
 | 1215 |             __FUNCTION__ ); | 
|---|
| [580] | 1216 |             hal_core_sleep(); | 
|---|
| [23] | 1217 |         } | 
|---|
 | 1218 |  | 
|---|
| [614] | 1219 |         // create the <.> and <..> dentries in VFS root directory | 
|---|
 | 1220 |         // the VFS root parent inode is the VFS root inode itself  | 
|---|
 | 1221 |         vfs_add_special_dentries( vfs_root_inode_xp, | 
|---|
 | 1222 |                                   vfs_root_inode_xp ); | 
|---|
 | 1223 |  | 
|---|
| [389] | 1224 |         // register VFS root inode in process_zero descriptor of cluster 0 | 
|---|
| [188] | 1225 |         process_zero.vfs_root_xp = vfs_root_inode_xp; | 
|---|
| [610] | 1226 |         process_zero.cwd_xp      = vfs_root_inode_xp; | 
|---|
| [188] | 1227 |     } | 
|---|
 | 1228 |  | 
|---|
 | 1229 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 1230 |     if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ),  | 
|---|
 | 1231 |                                         (info->x_size * info->y_size) ); | 
|---|
| [188] | 1232 |     barrier_wait( &local_barrier , info->cores_nr ); | 
|---|
 | 1233 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1234 |  | 
|---|
| [438] | 1235 | #if DEBUG_KERNEL_INIT | 
|---|
 | 1236 | if( (core_lid ==  0) & (local_cxy == 0) )  | 
|---|
| [624] | 1237 | printk("\n[%s] exit barrier 6 : VFS root (%x,%x) in cluster 0 / cycle %d\n", | 
|---|
| [610] | 1238 | __FUNCTION__, GET_CXY(process_zero.vfs_root_xp), | 
|---|
 | 1239 | GET_PTR(process_zero.vfs_root_xp), (uint32_t)hal_get_cycles() ); | 
|---|
| [437] | 1240 | #endif | 
|---|
| [188] | 1241 |  | 
|---|
 | 1242 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [623] | 1243 |     // STEP 7 : In all other clusters than cluster[0], the core[0] allocates memory | 
|---|
 | 1244 |     //          for the selected FS context, and initialise the local FS context and  | 
|---|
 | 1245 |     //          the local VFS context from values stored in cluster 0.  | 
|---|
| [188] | 1246 |     //          They get the VFS root inode extended pointer from cluster 0. | 
|---|
 | 1247 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1248 |  | 
|---|
 | 1249 |     if( (core_lid ==  0) && (local_cxy != 0) )  | 
|---|
 | 1250 |     { | 
|---|
 | 1251 |         // File System must be FATFS in this implementation, | 
|---|
 | 1252 |         // but other File System can be introduced here | 
|---|
 | 1253 |         if( CONFIG_VFS_ROOT_IS_FATFS ) | 
|---|
| [23] | 1254 |         { | 
|---|
| [389] | 1255 |             // 1. allocate memory for local FATFS context | 
|---|
 | 1256 |             fatfs_ctx_t * local_fatfs_ctx = fatfs_ctx_alloc(); | 
|---|
| [188] | 1257 |  | 
|---|
| [564] | 1258 |             // check memory | 
|---|
 | 1259 |             if( local_fatfs_ctx == NULL ) | 
|---|
| [580] | 1260 |             { | 
|---|
 | 1261 |                 printk("\n[PANIC] in %s : cannot create FATFS context in cluster %x\n", | 
|---|
 | 1262 |                 __FUNCTION__ , local_cxy ); | 
|---|
 | 1263 |                 hal_core_sleep(); | 
|---|
 | 1264 |             } | 
|---|
| [188] | 1265 |  | 
|---|
| [389] | 1266 |             // 2. get local pointer on VFS context for FATFS | 
|---|
| [188] | 1267 |             vfs_ctx_t   * vfs_ctx = &fs_context[FS_TYPE_FATFS]; | 
|---|
 | 1268 |  | 
|---|
| [389] | 1269 |             // 3. get local pointer on FATFS context in cluster 0  | 
|---|
 | 1270 |             fatfs_ctx_t * remote_fatfs_ctx = hal_remote_lpt( XPTR( 0 , &vfs_ctx->extend ) ); | 
|---|
 | 1271 |  | 
|---|
 | 1272 |             // 4. copy FATFS context from cluster 0 to local cluster | 
|---|
 | 1273 |             hal_remote_memcpy( XPTR( local_cxy , local_fatfs_ctx ),  | 
|---|
 | 1274 |                                XPTR( 0 ,         remote_fatfs_ctx ), sizeof(fatfs_ctx_t) ); | 
|---|
 | 1275 |  | 
|---|
 | 1276 |             // 5. copy VFS context from cluster 0 to local cluster | 
|---|
| [188] | 1277 |             hal_remote_memcpy( XPTR( local_cxy , vfs_ctx ),  | 
|---|
| [389] | 1278 |                                XPTR( 0 ,         vfs_ctx ), sizeof(vfs_ctx_t) ); | 
|---|
| [188] | 1279 |  | 
|---|
| [389] | 1280 |             // 6. update extend field in local copy of VFS context | 
|---|
 | 1281 |             vfs_ctx->extend = local_fatfs_ctx; | 
|---|
| [188] | 1282 |  | 
|---|
| [564] | 1283 |             if( ((fatfs_ctx_t *)vfs_ctx->extend)->sectors_per_cluster != 8 ) | 
|---|
| [580] | 1284 |             { | 
|---|
 | 1285 |                 printk("\n[PANIC] in %s : illegal FATFS context in cluster %x\n", | 
|---|
 | 1286 |                 __FUNCTION__ , local_cxy ); | 
|---|
 | 1287 |                 hal_core_sleep(); | 
|---|
 | 1288 |             } | 
|---|
| [23] | 1289 |         } | 
|---|
 | 1290 |  | 
|---|
| [188] | 1291 |         // get extended pointer on VFS root inode from cluster 0 | 
|---|
| [564] | 1292 |         vfs_root_inode_xp = hal_remote_l64( XPTR( 0 , &process_zero.vfs_root_xp ) ); | 
|---|
| [101] | 1293 |  | 
|---|
| [188] | 1294 |         // update local process_zero descriptor | 
|---|
 | 1295 |         process_zero.vfs_root_xp = vfs_root_inode_xp; | 
|---|
| [610] | 1296 |         process_zero.cwd_xp      = vfs_root_inode_xp; | 
|---|
| [14] | 1297 |     } | 
|---|
 | 1298 |  | 
|---|
| [188] | 1299 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 1300 |     if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ),  | 
|---|
 | 1301 |                                         (info->x_size * info->y_size) ); | 
|---|
| [188] | 1302 |     barrier_wait( &local_barrier , info->cores_nr ); | 
|---|
| [204] | 1303 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [101] | 1304 |  | 
|---|
| [438] | 1305 | #if DEBUG_KERNEL_INIT | 
|---|
| [564] | 1306 | if( (core_lid ==  0) & (local_cxy == 1) )  | 
|---|
| [624] | 1307 | printk("\n[%s] exit barrier 7 : VFS root (%x,%x) in cluster 1 / cycle %d\n", | 
|---|
| [610] | 1308 | __FUNCTION__, GET_CXY(process_zero.vfs_root_xp), | 
|---|
 | 1309 | GET_PTR(process_zero.vfs_root_xp), (uint32_t)hal_get_cycles() ); | 
|---|
| [437] | 1310 | #endif | 
|---|
| [188] | 1311 |  | 
|---|
 | 1312 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [623] | 1313 |     // STEP 8 : core[0] in cluster 0 makes the global DEVFS initialisation: | 
|---|
| [564] | 1314 |     //          It initializes the DEVFS context, and creates the DEVFS | 
|---|
 | 1315 |     //          "dev" and "external" inodes in cluster 0. | 
|---|
| [188] | 1316 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1317 |  | 
|---|
| [564] | 1318 |     if( (core_lid ==  0) && (local_cxy == 0) )  | 
|---|
| [1] | 1319 |     { | 
|---|
| [564] | 1320 |         // 1. allocate memory for DEVFS context extension in cluster 0 | 
|---|
 | 1321 |         devfs_ctx_t * devfs_ctx = devfs_ctx_alloc(); | 
|---|
 | 1322 |  | 
|---|
 | 1323 |         if( devfs_ctx == NULL ) | 
|---|
| [580] | 1324 |         { | 
|---|
 | 1325 |             printk("\n[PANIC] in %s : cannot create DEVFS context in cluster 0\n", | 
|---|
 | 1326 |             __FUNCTION__ , local_cxy ); | 
|---|
 | 1327 |             hal_core_sleep(); | 
|---|
 | 1328 |         } | 
|---|
| [564] | 1329 |  | 
|---|
 | 1330 |         // 2. initialize the DEVFS entry in the vfs_context[] array  | 
|---|
 | 1331 |         vfs_ctx_init( FS_TYPE_DEVFS,                                // fs type | 
|---|
 | 1332 |                       0,                                            // attributes: unused | 
|---|
 | 1333 |                           0,                                            // total_clusters: unused | 
|---|
 | 1334 |                           0,                                            // cluster_size: unused  | 
|---|
 | 1335 |                           vfs_root_inode_xp,                            // VFS root | 
|---|
 | 1336 |                       devfs_ctx );                                  // extend | 
|---|
 | 1337 |  | 
|---|
 | 1338 |         // 3. create "dev" and "external" inodes (directories) | 
|---|
| [188] | 1339 |         devfs_global_init( process_zero.vfs_root_xp, | 
|---|
| [204] | 1340 |                            &devfs_dev_inode_xp, | 
|---|
| [188] | 1341 |                            &devfs_external_inode_xp ); | 
|---|
 | 1342 |  | 
|---|
| [564] | 1343 |         // 4. initializes DEVFS context extension | 
|---|
 | 1344 |         devfs_ctx_init( devfs_ctx, | 
|---|
 | 1345 |                         devfs_dev_inode_xp, | 
|---|
 | 1346 |                         devfs_external_inode_xp ); | 
|---|
| [188] | 1347 |     }     | 
|---|
 | 1348 |  | 
|---|
 | 1349 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 1350 |     if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ),  | 
|---|
 | 1351 |                                         (info->x_size * info->y_size) ); | 
|---|
| [188] | 1352 |     barrier_wait( &local_barrier , info->cores_nr ); | 
|---|
| [204] | 1353 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [188] | 1354 |  | 
|---|
| [438] | 1355 | #if DEBUG_KERNEL_INIT | 
|---|
 | 1356 | if( (core_lid ==  0) & (local_cxy == 0) )  | 
|---|
| [624] | 1357 | printk("\n[%s] exit barrier 8 : DEVFS root initialized in cluster 0 / cycle %d\n", | 
|---|
| [610] | 1358 | __FUNCTION__, (uint32_t)hal_get_cycles() ); | 
|---|
| [437] | 1359 | #endif | 
|---|
| [188] | 1360 |  | 
|---|
 | 1361 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [624] | 1362 |     // STEP 9 : In all clusters in parallel, core[0] completes DEVFS initialization. | 
|---|
| [623] | 1363 |     //          Each core[0] get the "dev" and "external" extended pointers from | 
|---|
| [624] | 1364 |     //          values stored in cluster(0), creates the DEVFS "internal" directory,  | 
|---|
 | 1365 |     //          and creates the pseudo-files for all chdevs in local cluster. | 
|---|
| [188] | 1366 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1367 |  | 
|---|
 | 1368 |     if( core_lid == 0 ) | 
|---|
 | 1369 |     { | 
|---|
| [564] | 1370 |         // get extended pointer on "extend" field of VFS context for DEVFS in cluster 0 | 
|---|
 | 1371 |         xptr_t  extend_xp = XPTR( 0 , &fs_context[FS_TYPE_DEVFS].extend ); | 
|---|
| [188] | 1372 |  | 
|---|
| [457] | 1373 |         // get pointer on DEVFS context in cluster 0 | 
|---|
| [188] | 1374 |         devfs_ctx_t * devfs_ctx = hal_remote_lpt( extend_xp ); | 
|---|
 | 1375 |          | 
|---|
| [564] | 1376 |         devfs_dev_inode_xp      = hal_remote_l64( XPTR( 0 , &devfs_ctx->dev_inode_xp ) ); | 
|---|
 | 1377 |         devfs_external_inode_xp = hal_remote_l64( XPTR( 0 , &devfs_ctx->external_inode_xp ) ); | 
|---|
| [188] | 1378 |  | 
|---|
| [204] | 1379 |         // populate DEVFS in all clusters | 
|---|
 | 1380 |         devfs_local_init( devfs_dev_inode_xp, | 
|---|
 | 1381 |                           devfs_external_inode_xp, | 
|---|
 | 1382 |                           &devfs_internal_inode_xp ); | 
|---|
| [188] | 1383 |     } | 
|---|
 | 1384 |  | 
|---|
 | 1385 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [564] | 1386 |     if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ),  | 
|---|
 | 1387 |                                         (info->x_size * info->y_size) ); | 
|---|
| [188] | 1388 |     barrier_wait( &local_barrier , info->cores_nr ); | 
|---|
| [204] | 1389 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [188] | 1390 |  | 
|---|
| [438] | 1391 | #if DEBUG_KERNEL_INIT | 
|---|
 | 1392 | if( (core_lid ==  0) & (local_cxy == 0) )  | 
|---|
| [624] | 1393 | printk("\n[%s] exit barrier 9 : DEVFS initialized in cluster 0 / cycle %d\n", | 
|---|
| [610] | 1394 | __FUNCTION__, (uint32_t)hal_get_cycles() ); | 
|---|
| [437] | 1395 | #endif | 
|---|
| [188] | 1396 |  | 
|---|
| [623] | 1397 | #if( DEBUG_KERNEL_INIT & 1 ) | 
|---|
 | 1398 | if( (core_lid ==  0) & (local_cxy == 0) )  | 
|---|
 | 1399 | vfs_display( vfs_root_inode_xp ); | 
|---|
 | 1400 | #endif | 
|---|
 | 1401 |  | 
|---|
| [188] | 1402 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [623] | 1403 |     // STEP 10 : core[0] in cluster 0 creates the first user process (process_init). | 
|---|
 | 1404 |     //           This include the first user process VMM (GPT and VSL) creation. | 
|---|
 | 1405 |     //           Finally, it prints the ALMOS-MKH banner. | 
|---|
| [188] | 1406 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1407 |  | 
|---|
| [457] | 1408 |     if( (core_lid == 0) && (local_cxy == 0) )  | 
|---|
| [188] | 1409 |     { | 
|---|
| [428] | 1410 |        process_init_create(); | 
|---|
| [188] | 1411 |     } | 
|---|
| [101] | 1412 |  | 
|---|
| [624] | 1413 | #if DEBUG_KERNEL_INIT | 
|---|
 | 1414 | if( (core_lid ==  0) & (local_cxy == 0) )  | 
|---|
 | 1415 | printk("\n[%s] exit barrier 10 : process_init created in cluster 0 / cycle %d\n", | 
|---|
 | 1416 | __FUNCTION__, (uint32_t)hal_get_cycles() ); | 
|---|
 | 1417 | #endif | 
|---|
 | 1418 |  | 
|---|
| [564] | 1419 |     if( (core_lid == 0) && (local_cxy == 0) )  | 
|---|
| [188] | 1420 |     { | 
|---|
| [5] | 1421 |         print_banner( (info->x_size * info->y_size) , info->cores_nr ); | 
|---|
| [623] | 1422 |     } | 
|---|
| [68] | 1423 |  | 
|---|
| [635] | 1424 | #if CONFIG_INSTRUMENTATION_FOOTPRINT | 
|---|
| [623] | 1425 | if( (core_lid ==  0) & (local_cxy == 0) )  | 
|---|
| [437] | 1426 | printk("\n\n***** memory fooprint for main kernel objects\n\n" | 
|---|
| [68] | 1427 |                    " - thread descriptor  : %d bytes\n" | 
|---|
 | 1428 |                    " - process descriptor : %d bytes\n" | 
|---|
 | 1429 |                    " - cluster manager    : %d bytes\n" | 
|---|
 | 1430 |                    " - chdev descriptor   : %d bytes\n" | 
|---|
 | 1431 |                    " - core descriptor    : %d bytes\n" | 
|---|
 | 1432 |                    " - scheduler          : %d bytes\n" | 
|---|
 | 1433 |                    " - rpc fifo           : %d bytes\n" | 
|---|
 | 1434 |                    " - page descriptor    : %d bytes\n" | 
|---|
| [635] | 1435 |                    " - mapper descriptor  : %d bytes\n" | 
|---|
 | 1436 |                    " - vseg descriptor    : %d bytes\n" | 
|---|
| [68] | 1437 |                    " - ppm manager        : %d bytes\n" | 
|---|
 | 1438 |                    " - kcm manager        : %d bytes\n" | 
|---|
 | 1439 |                    " - khm manager        : %d bytes\n" | 
|---|
 | 1440 |                    " - vmm manager        : %d bytes\n" | 
|---|
| [635] | 1441 |                    " - vfs inode          : %d bytes\n" | 
|---|
 | 1442 |                    " - vfs dentry         : %d bytes\n" | 
|---|
 | 1443 |                    " - vfs file           : %d bytes\n" | 
|---|
 | 1444 |                    " - vfs context        : %d bytes\n" | 
|---|
 | 1445 |                    " - xhtab root         : %d bytes\n" | 
|---|
| [68] | 1446 |                    " - list item          : %d bytes\n" | 
|---|
 | 1447 |                    " - xlist item         : %d bytes\n" | 
|---|
| [564] | 1448 |                    " - busylock           : %d bytes\n" | 
|---|
 | 1449 |                    " - remote busylock    : %d bytes\n" | 
|---|
 | 1450 |                    " - queuelock          : %d bytes\n" | 
|---|
 | 1451 |                    " - remote queuelock   : %d bytes\n" | 
|---|
| [68] | 1452 |                    " - rwlock             : %d bytes\n" | 
|---|
 | 1453 |                    " - remote rwlock      : %d bytes\n", | 
|---|
| [564] | 1454 |                    sizeof( thread_t           ), | 
|---|
 | 1455 |                    sizeof( process_t          ), | 
|---|
 | 1456 |                    sizeof( cluster_t          ), | 
|---|
 | 1457 |                    sizeof( chdev_t            ), | 
|---|
 | 1458 |                    sizeof( core_t             ), | 
|---|
 | 1459 |                    sizeof( scheduler_t        ), | 
|---|
 | 1460 |                    sizeof( remote_fifo_t      ), | 
|---|
 | 1461 |                    sizeof( page_t             ), | 
|---|
 | 1462 |                    sizeof( mapper_t           ), | 
|---|
| [635] | 1463 |                    sizeof( vseg_t             ), | 
|---|
| [564] | 1464 |                    sizeof( ppm_t              ), | 
|---|
 | 1465 |                    sizeof( kcm_t              ), | 
|---|
 | 1466 |                    sizeof( khm_t              ), | 
|---|
 | 1467 |                    sizeof( vmm_t              ), | 
|---|
| [635] | 1468 |                    sizeof( vfs_inode_t        ), | 
|---|
 | 1469 |                    sizeof( vfs_dentry_t       ), | 
|---|
 | 1470 |                    sizeof( vfs_file_t         ), | 
|---|
 | 1471 |                    sizeof( vfs_ctx_t          ), | 
|---|
 | 1472 |                    sizeof( xhtab_t            ), | 
|---|
| [564] | 1473 |                    sizeof( list_entry_t       ), | 
|---|
 | 1474 |                    sizeof( xlist_entry_t      ), | 
|---|
 | 1475 |                    sizeof( busylock_t         ), | 
|---|
 | 1476 |                    sizeof( remote_busylock_t  ), | 
|---|
 | 1477 |                    sizeof( queuelock_t        ), | 
|---|
 | 1478 |                    sizeof( remote_queuelock_t ), | 
|---|
 | 1479 |                    sizeof( rwlock_t           ), | 
|---|
 | 1480 |                    sizeof( remote_rwlock_t    )); | 
|---|
| [406] | 1481 | #endif | 
|---|
 | 1482 |  | 
|---|
| [398] | 1483 |     // each core activates its private TICK IRQ | 
|---|
 | 1484 |     dev_pic_enable_timer( CONFIG_SCHED_TICK_MS_PERIOD ); | 
|---|
| [14] | 1485 |  | 
|---|
| [610] | 1486 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1487 |     if( core_lid == 0 ) xbarrier_wait( XPTR( 0 , &global_barrier ), | 
|---|
 | 1488 |                                         (info->x_size * info->y_size) ); | 
|---|
 | 1489 |     barrier_wait( &local_barrier , info->cores_nr ); | 
|---|
 | 1490 |     ///////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1491 |  | 
|---|
| [635] | 1492 | #if DEBUG_KERNEL_INIT  | 
|---|
| [610] | 1493 | thread_t * this = CURRENT_THREAD; | 
|---|
 | 1494 | printk("\n[%s] : thread[%x,%x] on core[%x,%d] jumps to thread_idle_func() / cycle %d\n", | 
|---|
 | 1495 | __FUNCTION__ , this->process->pid, this->trdid, | 
|---|
 | 1496 | local_cxy, core_lid, (uint32_t)hal_get_cycles() ); | 
|---|
| [440] | 1497 | #endif | 
|---|
 | 1498 |  | 
|---|
| [407] | 1499 |     // each core jump to thread_idle_func | 
|---|
| [50] | 1500 |     thread_idle_func(); | 
|---|
| [14] | 1501 |  | 
|---|
| [610] | 1502 | }  // end kernel_init() | 
|---|
 | 1503 |  | 
|---|