Changeset 6 for trunk/tools/bootloader_tsar/boot.c
- Timestamp:
- Apr 26, 2017, 2:14:33 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tools/bootloader_tsar/boot.c
r1 r6 1 /* 2 * boot.c - TSAR bootloader implementation. 3 * 4 * Authors : Alain Greiner / Vu Son (2016) 5 * 6 * Copyright (c) UPMC Sorbonne Universites 7 * 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; version 2.0 of the License. 13 * 14 * ALMOS-MKH is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 */ 23 1 24 /**************************************************************************** 2 * This file contains the ALMOS-MKH. boot-loader for the TSAR architecture. 25 * This file contains the ALMOS-MKH. boot-loader for the TSAR architecture. * 3 26 * * 4 27 * It supports clusterised shared memory multi-processor architectures, * … … 47 70 48 71 #include <elf-types.h> 72 #include <hal_types.h> 49 73 50 74 #include <almos_config.h> … … 53 77 #include <arch_info.h> 54 78 #include <boot_info.h> 55 56 #include <hal_types.h>57 79 58 80 #include <boot_utils.h> … … 62 84 #include <boot_tty_driver.h> 63 85 64 /**************************************************************************** 65 * Macros. *86 /***************************************************************************** 87 * Macros. 66 88 ****************************************************************************/ 67 89 … … 70 92 (~(PPM_PAGE_SIZE-1))) 71 93 72 /**************************************************************************** 73 * Global variables. *94 /***************************************************************************** 95 * Global variables. 74 96 ****************************************************************************/ 75 97 76 98 // synchronization variables. 77 volatile boot_barrier_t global_barrier; /* Used by bscpu to synchronize 78 with other CP0s cores. */ 79 80 volatile uint32_t global_count; /* Number of cores expected in 81 global barrier. */ 82 83 volatile uint32_t local_barrier; /* Used by CP0 to synchronize 84 with local CPi. */ 85 86 volatile uint32_t boot_cluster_ready; /* Modified by bscpu to report 87 that the boot cluster is 88 ready. */ 89 90 // kernel image memory layout. 91 uint32_t ktext_base; /* ktext segment base address. */ 92 uint32_t ktext_end; /* ktext segment end address. */ 93 uint32_t kdata_base; /* kdata segment base address. */ 94 uint32_t kdata_end; /* kdata segment end address. */ 95 96 uint32_t kernel_entry; /* Kernel entry point. */ 97 98 // Extern variables. 99 extern void boot_entry(); /* boot_loader() function */ 100 101 /**************************************************************************** 102 * Internal functions. * 103 ****************************************************************************/ 104 99 100 volatile boot_remote_spinlock_t tty0_lock; // protect TTY0 access 101 volatile boot_remote_barrier_t global_barrier; // synchronize CP0 cores 102 volatile boot_remote_barrier_t local_barrier; // synchronize cores in one cluster 103 uint32_t active_cp0s_nr; // number of expected CP0s 104 105 // kernel segments layout variables 106 107 uint32_t seg_kcode_base; // kcode segment base address 108 uint32_t seg_kcode_size; // kcode segment size (bytes) 109 uint32_t seg_kdata_base; // kdata segment base address 110 uint32_t seg_kdata_size; // kdata segment size (bytes) 111 uint32_t kernel_entry; // kernel entry point 112 113 // address used by the WTI to activate remote CP0s 114 115 extern void boot_entry(); // boot_loader entry point 116 117 /********************************************************************************* 118 * This function returns the printable string for each device type 119 ********************************************************************************/ 105 120 char * device_type_str( uint32_t dev_type ) 106 121 { 107 if ( dev_type == DEV_TYPE_RAM ) return "RAM";108 else if( dev_type == DEV_TYPE_ DMA ) return "DMA";109 else if( dev_type == DEV_TYPE_FBF ) return "FBF";110 else if( dev_type == DEV_TYPE_IOB ) return "IOB";122 if ( dev_type == DEV_TYPE_RAM_SCL ) return "RAM_SCL"; 123 else if( dev_type == DEV_TYPE_ROM_SCL ) return "ROM_SCL"; 124 else if( dev_type == DEV_TYPE_FBF_SCL ) return "FBF_SCL"; 125 else if( dev_type == DEV_TYPE_IOB_TSR ) return "IOB_TSR"; 111 126 else if( dev_type == DEV_TYPE_IOC_BDV ) return "IOC_BDV"; 112 127 else if( dev_type == DEV_TYPE_IOC_HBA ) return "IOC_HBA"; … … 114 129 else if( dev_type == DEV_TYPE_IOC_SPI ) return "IOC_SPI"; 115 130 else if( dev_type == DEV_TYPE_IOC_RDK ) return "IOC_RDK"; 116 else if( dev_type == DEV_TYPE_MMC ) return "MMC"; 117 else if( dev_type == DEV_TYPE_MWR_CPY ) return "MWR_CPY"; 118 else if( dev_type == DEV_TYPE_MWR_GCD ) return "MWR_GCD"; 119 else if( dev_type == DEV_TYPE_MWR_DCT ) return "MWR_DCT"; 120 else if( dev_type == DEV_TYPE_NIC ) return "NIC"; 121 else if( dev_type == DEV_TYPE_ROM ) return "ROM"; 122 else if( dev_type == DEV_TYPE_SIM ) return "SIM"; 123 else if( dev_type == DEV_TYPE_TIM ) return "TIM"; 124 else if( dev_type == DEV_TYPE_TTY ) return "TTY"; 125 else if( dev_type == DEV_TYPE_XCU ) return "XCU"; 126 else if( dev_type == DEV_TYPE_PIC ) return "PIC"; 127 else if( dev_type == DEV_TYPE_CMA ) return "CMA"; 128 else return "UNDEFINED"; 131 else if( dev_type == DEV_TYPE_MMC_TSR ) return "MMC_TSR"; 132 else if( dev_type == DEV_TYPE_DMA_SCL ) return "DMA_SCL"; 133 else if( dev_type == DEV_TYPE_NIC_CBF ) return "NIC_CBF"; 134 else if( dev_type == DEV_TYPE_TIM_SCL ) return "TIM_SCL"; 135 else if( dev_type == DEV_TYPE_TXT_TTY ) return "TXT_TTY"; 136 else if( dev_type == DEV_TYPE_ICU_XCU ) return "ICU_XCU"; 137 else if( dev_type == DEV_TYPE_PIC_TSR ) return "PIC_TSR"; 138 else return "undefined"; 129 139 } 130 140 131 /**************************************************************************** 141 /************************************************************************************ 132 142 * This function loads the arch_info.bin file into the boot cluster memory. 133 **************************************************************************** /143 ***********************************************************************************/ 134 144 static void boot_archinfo_load() 135 145 { … … 154 164 155 165 #if DEBUG_BOOT_INFO 156 boot_printf("\n[BOOT ] file %s loaded at %l\n",157 ARCHINFO_PATHNAME , ARCHINFO_BASE );166 boot_printf("\n[BOOT INFO] in %s : file %s loaded at address = %x\n", 167 __FUNCTION__ , ARCHINFO_PATHNAME , ARCHINFO_BASE ); 158 168 #endif 159 169 160 170 } // boot_archinfo_load() 161 171 162 /**************************************************************************** 163 * This function loads the 'kernel.elf' file into the boot cluster memory * 164 * bank, analyzes it then places the kernel image at the temporary physical * 165 * memory address KERN_IMG_TMP_BASE since other processors are still * 166 * executing the preloader code (which means that the kernel image cannot * 167 * be placed now at its final memory location starting at address 0x0. * 168 ****************************************************************************/ 172 /************************************************************************************** 173 * This function loads the 'kernel.elf' file into the boot cluster memory buffer, 174 * analyzes it, and places the the two seg_kcode & seg_kdata segments at their final 175 * physical adresses (just after the preloader zone). 176 * It set the global variables defining the kernel layout. 177 *************************************************************************************/ 169 178 static void boot_kernel_load() 170 179 { 171 Elf32_Ehdr* elf_header; /* Pointer on 'kernel.elf' header. */ 172 Elf32_Phdr* program_header; /* Pointer on 'kernel.elf' program 173 header. */ 174 uint32_t phdr_offset; /* Program header offset in 175 'kernel.elf' file. */ 176 uint32_t segments_nb; /* Total number of segments in 177 'kernel.elf' file. */ 178 179 uint32_t seg_src_addr; /* Segment address in 'kernel.elf' 180 file (source). */ 181 uint32_t seg_paddr; /* Physical address at which the 182 first byte of the segment resides 183 in memory. */ 184 uint32_t seg_offset; /* Offset from the beginning of 185 'kernel.elf' file to the segment's 186 first byte. */ 187 uint32_t seg_filesz; /* Segment's number of bytes in 188 'kernel.elf' file. */ 189 uint32_t seg_memsz; /* Segment's number of bytes in the 190 memory image. */ 191 192 uint32_t seg_id; /* Iterator for program header scanning 193 loop. */ 194 195 /* Loading file into memory. */ 196 if (boot_fat32_load(KERNEL_PATHNAME, KERN_BASE, KERN_MAX_SIZE)) 197 { 198 boot_printf("\n[BOOT ERROR]: boot_kernel_load(): " 199 "<%s> file not found\n", 180 Elf32_Ehdr * elf_header; // pointer on kernel.elf header. 181 Elf32_Phdr * program_header; // pointer on kernel.elf program header. 182 uint32_t phdr_offset; // program header offset in kernel.elf file. 183 uint32_t segments_nb; // number of segments in kernel.elf file. 184 uint32_t seg_src_addr; // segment address in kernel.elf file (source). 185 uint32_t seg_paddr; // segment local physical address of segment 186 uint32_t seg_offset; // segment offset in kernel.elf file 187 uint32_t seg_filesz; // segment size (bytes) in kernel.elf file 188 uint32_t seg_memsz; // segment size (bytes) in memory image. 189 bool_t kcode_found; // kcode segment found. 190 bool_t kdata_found; // kdata segment found. 191 uint32_t seg_id; // iterator for segments loop. 192 193 #if DEBUG_BOOT_ELF 194 boot_printf("\n[BOOT INFO] %s enters for file %s at cycle %d\n", 195 __FUNCTION__ , KERNEL_PATHNAME , boot_get_proctime() ); 196 #endif 197 198 // Load kernel.elf file into memory buffer 199 if ( boot_fat32_load(KERNEL_PATHNAME, KERN_BASE, KERN_MAX_SIZE) ) 200 { 201 boot_printf("\n[BOOT ERROR] in %s : <%s> file not found\n", 200 202 KERNEL_PATHNAME); 201 203 boot_exit(); 202 204 } 203 205 204 /* 205 * Initializing pointer to header which is the first element of the 206 * .elf file. 207 */ 206 // get pointer to kernel.elf header 208 207 elf_header = (Elf32_Ehdr*)KERN_BASE; 209 208 210 / * Signature problem, abort program !!! */209 // check signature 211 210 if ((elf_header->e_ident[EI_MAG0] != ELFMAG0) || 212 211 (elf_header->e_ident[EI_MAG1] != ELFMAG1) || … … 220 219 } 221 220 222 / * Getting the program header table offset and the number of segments. */221 // Get program header table offset and number of segments 223 222 phdr_offset = elf_header->e_phoff; 224 223 segments_nb = elf_header->e_phnum; 225 224 226 / * Getting the program header table pointer. */225 // Get program header table pointer 227 226 program_header = (Elf32_Phdr*)(KERN_BASE + phdr_offset); 228 227 229 /* Looking for loadable segments. */ 228 // loop on segments 229 kcode_found = false; 230 kdata_found = false; 230 231 for (seg_id = 0; seg_id < segments_nb; seg_id++) 231 232 { 232 // Found one: 233 if (program_header[seg_id].p_type == PT_LOAD) 233 if (program_header[seg_id].p_type == PT_LOAD) // Found one loadable segment 234 234 { 235 // Get ting itsattributes.235 // Get segment attributes. 236 236 seg_paddr = program_header[seg_id].p_paddr; 237 237 seg_offset = program_header[seg_id].p_offset; … … 239 239 seg_memsz = program_header[seg_id].p_memsz; 240 240 241 // Load it to its appropriate physical memory address.241 // get segment base address in buffer 242 242 seg_src_addr = (uint32_t)KERN_BASE + seg_offset; 243 boot_memcpy((void*)(KERN_IMG_TMP_BASE + seg_paddr), 244 (void*)seg_src_addr, 245 seg_filesz); 243 244 // Load segment to its final physical memory address 245 boot_memcpy( (void*)seg_paddr, 246 (void*)seg_src_addr, 247 seg_filesz ); 248 249 #if DEBUG_BOOT_ELF 250 boot_printf("\n[BOOT INFO] in %s for file %s : found loadable segment\n" 251 " base = %x / size = %x\n", 252 __FUNCTION__ , KERNEL_PATHNAME , seg_paddr , seg_memsz ); 253 #endif 246 254 247 255 // Fill remaining memory with zero if (filesz < memsz). 248 boot_memset((void*)(KERN_IMG_TMP_BASE + seg_paddr + seg_filesz), 249 0, 250 seg_memsz - seg_filesz); 251 252 /* 253 * Note: we suppose that the 'kernel.elf' file contains only 2 254 * loadable segments ktext + kdata and that the main 255 * difference between these two is the WRITE permission: ktext 256 * contains read-only instructions and read_only data, 257 * while kdata contains writable data. 258 */ 259 260 // Get ktext segment base and end addresses. 261 if ((program_header[seg_id].p_flags & PF_W) == 0) 262 { 263 ktext_base = seg_paddr; 264 ktext_end = seg_paddr + seg_memsz; 265 } 266 267 // Get kdata segment base and end addresses. 268 else 269 { 270 kdata_base = seg_paddr; 271 kdata_end = seg_paddr + seg_memsz; 256 if( seg_memsz < seg_filesz ) 257 { 258 boot_memset( (void*)(seg_paddr + seg_filesz), 0, seg_memsz - seg_filesz); 259 } 260 261 // Note: we suppose that the 'kernel.elf' file contains only 2 262 // loadable segments ktext & kdata and that the main 263 // difference between these two is the WRITE permission: ktext 264 // contains read-only instructions and read_only data, 265 // while kdata contains writable data. 266 267 if ((program_header[seg_id].p_flags & PF_W) == 0) // kcode segment 268 { 269 if( kcode_found ) 270 { 271 boot_printf("\n[BOOT_ERROR] in %s for file %s :\n" 272 " two loadable kcode segments found\n", 273 __FUNCTION__ , KERNEL_PATHNAME ); 274 boot_exit(); 275 } 276 277 kcode_found = true; 278 seg_kcode_base = seg_paddr; 279 seg_kcode_size = seg_memsz; 280 } 281 else // kdata segment 282 { 283 if( kdata_found ) 284 { 285 boot_printf("\n[BOOT_ERROR] in %s for file %s :\n" 286 " two loadable kdata segments found\n", 287 __FUNCTION__ , KERNEL_PATHNAME ); 288 boot_exit(); 289 } 290 291 kdata_found = true; 292 seg_kdata_base = seg_paddr; 293 seg_kdata_size = seg_memsz; 272 294 } 273 295 } 274 296 } 275 297 276 // Get the entry point for kernel code. 298 // check kcode & kdata segments found 299 if( kcode_found == false ) 300 { 301 boot_printf("\n[BOOT_ERROR] in %s for file %s :\n" 302 " kcode segment not found\n", 303 __FUNCTION__ , KERNEL_PATHNAME ); 304 boot_exit(); 305 } 306 if( kdata_found == false ) 307 { 308 boot_printf("\n[BOOT_ERROR] in %s for file %s :\n" 309 " kdata segment not found\n", 310 __FUNCTION__ , KERNEL_PATHNAME ); 311 boot_exit(); 312 } 313 314 // set entry point 277 315 kernel_entry = (uint32_t)elf_header->e_entry; 278 316 317 #if DEBUG_BOOT_ELF 318 boot_printf("\n[BOOT INFO] %s successfully completed for file %s at cycle %d\n", 319 __FUNCTION__ , KERNEL_PATHNAME , boot_get_proctime() ); 320 #endif 321 279 322 } // boot_kernel_load() 280 323 281 /**************************************************************************** 282 * This function initializes the local 'boot_info_t' structure. *283 * @ boot_info : pointer to local boot_info_t structure *284 * @ cxy : cluster identifier *285 **************************************************************************** /324 /************************************************************************************* 325 * This function initializes the boot_info_t structure for a given cluster. 326 * @ boot_info : pointer to local boot_info_t structure 327 * @ cxy : cluster identifier 328 ************************************************************************************/ 286 329 static void boot_info_init( boot_info_t * boot_info, 287 330 cxy_t cxy ) 288 331 { 289 archinfo_header_t * header; 332 archinfo_header_t * header; 290 333 archinfo_core_t * core_base; 291 334 archinfo_cluster_t * cluster_base; … … 294 337 295 338 archinfo_cluster_t * cluster; 339 archinfo_cluster_t * my_cluster = NULL; // target cluster 340 archinfo_cluster_t * io_cluster = NULL; // cluster containing ext. peripherals 341 296 342 archinfo_core_t * core; 297 343 uint32_t core_id; … … 303 349 boot_device_t * boot_dev; 304 350 305 // get pointer on ARCHINFO header 306 header = (archinfo_header_t*)ARCHINFO_BASE; 351 #if DEBUG_BOOT_INFO 352 boot_printf("\n[BOOT INFO] %s : enter for cluster %x at cycle %d\n", 353 __FUNCTION__ , cxy , boot_get_proctime() ); 354 #endif 355 356 // get pointer on ARCHINFO header and on the four arch_info arrays 357 header = (archinfo_header_t*)ARCHINFO_BASE; 358 core_base = archinfo_get_core_base (header); 359 cluster_base = archinfo_get_cluster_base(header); 360 device_base = archinfo_get_device_base (header); 361 irq_base = archinfo_get_irq_base (header); 307 362 308 363 // Initialize global platform parameters … … 315 370 316 371 // Initialize kernel segments 317 boot_info->kernel_code_start = ktext_base; 318 boot_info->kernel_code_end = ktext_end; 319 boot_info->kernel_data_start = kdata_base; 320 boot_info->kernel_data_end = kdata_end; 321 322 // Initialize specific cluster parameter 323 core_base = archinfo_get_core_base (header); 324 cluster_base = archinfo_get_cluster_base(header); 325 device_base = archinfo_get_device_base (header); 326 irq_base = archinfo_get_irq_base (header); 327 328 // lopp on the clusters to find local cluster descriptor 372 boot_info->kernel_code_start = seg_kcode_base; 373 boot_info->kernel_code_end = seg_kcode_base + seg_kcode_size; 374 boot_info->kernel_data_start = seg_kdata_base; 375 boot_info->kernel_data_end = seg_kdata_base + seg_kdata_size; 376 377 // loop on arch_info clusters to get relevant pointers 329 378 for (cluster = cluster_base; 330 379 cluster < &cluster_base[header->x_size * header->y_size]; 331 380 cluster++) 332 381 { 333 if (cluster->cxy != cxy) continue; 334 335 boot_info->cxy = cluster->cxy; 336 boot_info->cores_nr = cluster->cores; 337 boot_info->devices_nr = cluster->devices; 338 339 #if DEBUG_BOOT_INFO 340 boot_printf("\n[BOOT] build boot_info for cluster %x : %d cores / %d devices\n", 341 cluster->cxy , cluster->cores , cluster->devices ); 342 #endif 343 // Initialize array of core descriptors 344 for (core = &core_base[cluster->core_offset], core_id = 0; 345 core < &core_base[cluster->core_offset + cluster->cores]; 346 core++, core_id++) 382 if( cluster->cxy == cxy ) my_cluster = cluster; 383 if( cluster->cxy == header->io_cxy ) io_cluster = cluster; 384 } 385 386 if( my_cluster == NULL ) 387 { 388 boot_printf("\n[ERROR] in %s : cannot found cluster %x in arch_info\n", 389 __FUNCTION__ , cxy ); 390 boot_exit(); 391 } 392 393 if( io_cluster == NULL ) 394 { 395 boot_printf("\n[ERROR] in %s : cannot found io_cluster %x in arch_info\n", 396 __FUNCTION__ , header->io_cxy ); 397 boot_exit(); 398 } 399 400 // loop on all arch-info peripherals in IO_cluster, 401 // to initialize the boot_info array of external peripherals 402 403 #if DEBUG_BOOT_INFO 404 boot_printf("\n[BOOT INFO] %s : External peripherals\n", __FUNCTION__ ); 405 #endif 406 407 device_id = 0; 408 for (device = &device_base[io_cluster->device_offset]; 409 device < &device_base[io_cluster->device_offset + io_cluster->devices]; 410 device++ ) 411 { 412 // initialise one entry for each external peripheral 413 if( (device->type != DEV_TYPE_RAM_SCL) && 414 (device->type != DEV_TYPE_ICU_XCU) && 415 (device->type != DEV_TYPE_MMC_TSR) && 416 (device->type != DEV_TYPE_DMA_SCL) ) 347 417 { 348 boot_info->core[core_id].gid = (gid_t)core->gid; 349 boot_info->core[core_id].lid = (lid_t)core->lid; 350 boot_info->core[core_id].cxy = (cxy_t)core->cxy; 351 352 #if DEBUG_BOOT_INFO 353 boot_printf(" - core %x : cxy = %x / lid = %d\n", 354 core->gid , core->cxy , core->lid ); 355 #endif 356 418 boot_dev = &boot_info->ext_dev[device_id]; 419 420 boot_dev->type = device->type; 421 boot_dev->base = device->base; 422 boot_dev->size = device->size; 423 boot_dev->channels = device->channels; 424 boot_dev->param0 = device->arg0; 425 boot_dev->param1 = device->arg1; 426 boot_dev->param2 = device->arg2; 427 boot_dev->param3 = device->arg3; 428 boot_dev->irqs = device->irqs; 429 430 device_id++; 357 431 } 358 432 359 // Initialize array of device descriptors 360 for (device = &device_base[cluster->device_offset], device_id = 0; 361 device < &device_base[cluster->device_offset + cluster->devices]; 362 device++, device_id++) 363 { 364 boot_dev = &boot_info->dev[device_id]; 365 366 boot_dev->type = device->type; 367 boot_dev->base = (xptr_t)device->base; 368 boot_dev->size = device->size; 369 boot_dev->channels = device->channels; 370 boot_dev->param0 = device->arg0; 371 boot_dev->param1 = device->arg1; 372 boot_dev->param2 = device->arg2; 373 boot_dev->param3 = device->arg3; 374 boot_dev->irqs = device->irqs; 375 376 #if DEBUG_BOOT_INFO 377 boot_printf(" - device %s : base = %l / size = %d / channels = %d / irqs = %d\n", 433 #if DEBUG_BOOT_INFO 434 boot_printf(" - %s : base = %l / size = %l / channels = %d / irqs = %d\n", 378 435 device_type_str( device->type ) , device->base , device->size , 379 436 device->channels , device->irqs ); 380 437 #endif 381 382 // Initialize information about physical memory in cluster 383 if (device->type == DEV_TYPE_RAM) 384 { 385 // Compute total number of physical memory pages in cluster 386 boot_info->pages_nr = device->size >> CONFIG_PPM_PAGE_SHIFT; 387 388 // Get the last address allocated for the kernel segments 389 uint32_t end = (ktext_end < kdata_end) ? kdata_end : ktext_end; 390 391 // Computing the number of pages allocated for the kernel. 392 if( (end & CONFIG_PPM_PAGE_MASK) == 0 ) 393 { 394 boot_info->pages_offset = end >> CONFIG_PPM_PAGE_SHIFT; 395 } 396 else 397 { 398 boot_info->pages_offset = (end >> CONFIG_PPM_PAGE_SHIFT) + 1; 399 } 400 } 401 402 // Initialize array of irq descriptors for XCU 403 if (device->type == DEV_TYPE_XCU) 404 { 405 for (irq_id = 0; irq_id < CONFIG_MAX_HWIS_PER_ICU; irq_id++) 406 { 407 boot_dev->irq[irq_id].valid = 0; 408 } 409 410 for (irq = &irq_base[device->irq_offset]; 411 irq < &irq_base[device->irq_offset + device->irqs]; 412 irq++) 413 { 414 boot_dev->irq[irq->port].valid = 1; 415 boot_dev->irq[irq->port].dev_type = irq->dev_type; 416 boot_dev->irq[irq->port].channel = irq->channel; 417 boot_dev->irq[irq->port].is_rx = irq->is_rx; 438 439 // Initialize array of irq descriptors for PIC 440 if (device->type == DEV_TYPE_PIC_TSR) 441 { 442 for (irq_id = 0; irq_id < CONFIG_MAX_IRQS_PER_PIC; irq_id++) 443 { 444 boot_dev->irq[irq_id].valid = 0; 445 } 446 447 for (irq = &irq_base[device->irq_offset]; 448 irq < &irq_base[device->irq_offset + device->irqs]; 449 irq++) 450 { 451 boot_dev->irq[irq->port].valid = 1; 452 boot_dev->irq[irq->port].dev_type = irq->dev_type; 453 boot_dev->irq[irq->port].channel = irq->channel; 454 boot_dev->irq[irq->port].is_rx = irq->is_rx; 418 455 419 456 #if DEBUG_BOOT_INFO … … 421 458 irq->port , device_type_str( irq->dev_type ) , irq->channel , irq->is_rx ); 422 459 #endif 423 424 } 425 } 426 427 // Initialize array of irq descriptors for PIC 428 if (device->type == DEV_TYPE_PIC) 429 { 430 for (irq_id = 0; irq_id < CONFIG_MAX_IRQS_PER_PIC; irq_id++) 431 { 432 boot_dev->irq[irq_id].valid = 0; 433 } 434 435 for (irq = &irq_base[device->irq_offset]; 436 irq < &irq_base[device->irq_offset + device->irqs]; 437 irq++) 438 { 439 boot_dev->irq[irq->port].valid = 1; 440 boot_dev->irq[irq->port].dev_type = irq->dev_type; 441 boot_dev->irq[irq->port].channel = irq->channel; 442 boot_dev->irq[irq->port].is_rx = irq->is_rx; 460 } 461 } 462 } 463 464 // initialize number of external peripherals 465 boot_info->ext_dev_nr = device_id; 466 467 // Initialize cluster specific resources 468 boot_info->cxy = my_cluster->cxy; 469 470 #if DEBUG_BOOT_INFO 471 boot_printf("\n[BOOT INFO] %s : cores in cluster %x\n", __FUNCTION__ ); 472 #endif 473 474 // Initialize array of core descriptors 475 core_id = 0; 476 for (core = &core_base[my_cluster->core_offset]; 477 core < &core_base[my_cluster->core_offset + my_cluster->cores]; 478 core++ ) 479 { 480 boot_info->core[core_id].gid = (gid_t)core->gid; 481 boot_info->core[core_id].lid = (lid_t)core->lid; 482 boot_info->core[core_id].cxy = (cxy_t)core->cxy; 483 484 #if DEBUG_BOOT_INFO 485 boot_printf(" - core_gid = %x : cxy = %x / lid = %d\n", 486 core->gid , core->cxy , core->lid ); 487 #endif 488 core_id++; 489 } 490 491 // Initialize number of cores in my_cluster 492 boot_info->cores_nr = core_id; 493 494 // loop on all peripherals in my_cluster to initialise 495 // boot_info array of internal peripherals in my_cluster 496 497 #if DEBUG_BOOT_INFO 498 boot_printf("\n[BOOT INFO] %s : internal peripherals in cluster %x\n", __FUNCTION__ ); 499 #endif 500 501 device_id = 0; 502 for (device = &device_base[my_cluster->device_offset]; 503 device < &device_base[my_cluster->device_offset + my_cluster->devices]; 504 device++ ) 505 { 506 // initialise one entry for each internal peripheral 507 if( (device->type == DEV_TYPE_RAM_SCL) || 508 (device->type == DEV_TYPE_ICU_XCU) || 509 (device->type == DEV_TYPE_MMC_TSR) || 510 (device->type == DEV_TYPE_DMA_SCL) ) 511 { 512 boot_dev = &boot_info->int_dev[device_id]; 513 514 boot_dev->type = device->type; 515 boot_dev->base = device->base; 516 boot_dev->size = device->size; 517 boot_dev->channels = device->channels; 518 boot_dev->param0 = device->arg0; 519 boot_dev->param1 = device->arg1; 520 boot_dev->param2 = device->arg2; 521 boot_dev->param3 = device->arg3; 522 boot_dev->irqs = device->irqs; 523 524 device_id++; 525 } 526 527 #if DEBUG_BOOT_INFO 528 boot_printf(" - %s : base = %l / size = %l / channels = %d / irqs = %d\n", 529 device_type_str( device->type ) , device->base , device->size , 530 device->channels , device->irqs ); 531 #endif 532 533 // Initialize information about physical memory in cluster 534 if (device->type == DEV_TYPE_RAM_SCL) 535 { 536 // Compute total number of physical memory pages in cluster 537 boot_info->pages_nr = device->size >> CONFIG_PPM_PAGE_SHIFT; 538 539 // Get the last address allocated for the kernel segments 540 uint32_t end; 541 if( boot_info->kernel_code_end > boot_info->kernel_data_end ) 542 { 543 end = boot_info->kernel_code_end; 544 } 545 else 546 { 547 end = boot_info->kernel_data_end; 548 } 549 550 // Compute the number of pages allocated for the kernel. 551 if( (end & CONFIG_PPM_PAGE_MASK) == 0 ) 552 { 553 boot_info->pages_offset = end >> CONFIG_PPM_PAGE_SHIFT; 554 } 555 else 556 { 557 boot_info->pages_offset = (end >> CONFIG_PPM_PAGE_SHIFT) + 1; 558 } 559 560 #if DEBUG_BOOT_INFO 561 boot_printf(" . physical memory : %x pages / first free page = %x\n", 562 boot_info->pages_nr , boot_info->pages_offset ); 563 #endif 564 } 565 566 // Initialize array of irq descriptors for XCU 567 if (device->type == DEV_TYPE_ICU_XCU) 568 { 569 for (irq_id = 0; irq_id < CONFIG_MAX_HWIS_PER_ICU; irq_id++) 570 { 571 boot_dev->irq[irq_id].valid = 0; 572 } 573 574 for (irq = &irq_base[device->irq_offset]; 575 irq < &irq_base[device->irq_offset + device->irqs]; 576 irq++) 577 { 578 boot_dev->irq[irq->port].valid = 1; 579 boot_dev->irq[irq->port].dev_type = irq->dev_type; 580 boot_dev->irq[irq->port].channel = irq->channel; 581 boot_dev->irq[irq->port].is_rx = irq->is_rx; 443 582 444 583 #if DEBUG_BOOT_INFO … … 447 586 #endif 448 587 449 }450 588 } 451 589 } 452 453 #if DEBUG_BOOT_INFO 454 boot_printf(" - ram : number of pages = %x / first free page = %x\n", 455 boot_info->pages_nr , boot_info->pages_offset ); 456 #endif 457 458 } 590 } 591 592 // initialize number of internal peripherals in my_cluster 593 boot_info->int_dev_nr = device_id; 594 595 // set boot_info signature 596 boot_info->signature = BOOT_INFO_SIGNATURE; 597 459 598 } // boot_info_init() 460 599 461 /**************************************************************************** 462 * This function is executed by all cores in order to check their * 463 * local boot_info_t structure. * 464 * @ boot_info : pointer to local 'boot_info_t' structure to be checked. * 465 * @ lid : core local identifier, index the core descriptor table. * 466 ****************************************************************************/ 600 /*********************************************************************************** 601 * This function check the local boot_info_t structure for a given core. 602 * @ boot_info : pointer to local 'boot_info_t' structure to be checked. 603 * @ lid : core local identifier, index the core descriptor table. 604 **********************************************************************************/ 467 605 static void boot_check_core( boot_info_t * boot_info, 468 606 lid_t lid) … … 490 628 } // boot_check_core() 491 629 492 /**************************************************************************** 493 * This function is called by the bscpu to activate all other CP0s. *630 /********************************************************************************* 631 * This function is called by CP0 in cluster(0,0) to activate all other CP0s. 494 632 * It returns the number of CP0s actually activated. 495 **************************************************************************** /496 static uint32_t boot_wake_ cp0()633 ********************************************************************************/ 634 static uint32_t boot_wake_all_cp0s() 497 635 { 498 archinfo_header_t* header; /* Pointer on ARCHINFO header. */ 499 archinfo_cluster_t* cluster_base; /* Pointer on ARCHINFO cluster 500 base. */ 501 archinfo_cluster_t* cluster; /* Iterator for waking CP0 loop. */ 502 archinfo_device_t* device_base; /* Pointer on ARCHINFO peripheral 503 device base. */ 504 archinfo_device_t* device; /* Iterator for finding XICU device 505 loop. */ 506 507 uint32_t cp0_nb = 0; /* Number of CP0 woken up. */ 636 archinfo_header_t* header; // Pointer on ARCHINFO header 637 archinfo_cluster_t* cluster_base; // Pointer on ARCHINFO clusters base 638 archinfo_cluster_t* cluster; // Iterator for loop on clusters 639 archinfo_device_t* device_base; // Pointer on ARCHINFO devices base 640 archinfo_device_t* device; // Iterator for loop on devices 641 uint32_t cp0_nb = 0; // CP0s counter 508 642 509 643 header = (archinfo_header_t*)ARCHINFO_BASE; … … 528 662 continue; 529 663 530 // Look for the XICU device associated to the CP0 of this cluster 531 // then send an WTI to it in order to wake it up. 664 // search XICU device associated to CP0, and send a WTI to activate it 532 665 for (device = &device_base[cluster->device_offset]; 533 666 device < &device_base[cluster->device_offset + cluster->devices]; 534 667 device++) 535 668 { 536 if (device->type == DEV_TYPE_XCU) 537 { 669 if (device->type == DEV_TYPE_ICU_XCU) 670 { 671 672 #if DEBUG_BOOT_WAKUP 673 boot_printf("\n[BOOT] core[%x][0] activated at cycle %d\n", 674 cluster->cxy , boot_get_proctime ); 675 #endif 676 538 677 boot_remote_sw((xptr_t)device->base, (uint32_t)boot_entry); 539 678 cp0_nb++; … … 545 684 } // boot_wake_cp0() 546 685 547 /**************************************************************************** 548 * This function is called by all CP0 to activate all local CPi cores. *549 * @ boot_info : pointer to local 'boot_info_t' structure, used to find *550 * the XICU device associated with local CPi base addresses. *551 **************************************************************************** /552 static void boot_wake_local_cores(boot_info_t * boot_info)686 /********************************************************************************* 687 * This function is called by all CP0 to activate all local CPi cores. 688 * @ boot_info : pointer to local 'boot_info_t' structure, used to find 689 * the XICU device associated with local CPi base addresses. 690 *********************************************************************************/ 691 static void boot_wake_local_cores(boot_info_t * boot_info) 553 692 { 554 boot_device_t * device; // Iterator on devices555 unsigned int core_id; // Iterator on cores693 boot_device_t * device; // Iterator on devices 694 unsigned int core_id; // Iterator on cores 556 695 557 696 // loop on devices to find XCU 558 for (device = &boot_info-> dev[0];559 device < &boot_info-> dev[boot_info->devices_nr];697 for (device = &boot_info->int_dev[0]; 698 device < &boot_info->int_dev[boot_info->int_dev_nr]; 560 699 device++) 561 700 { 562 if (device->type == DEV_TYPE_ XCU)701 if (device->type == DEV_TYPE_ICU_XCU) 563 702 { 564 703 // loop on cores 565 704 for (core_id = 1; core_id < boot_info->cores_nr; core_id++) 705 { 706 707 #if DEBUG_BOOT_WAKUP 708 boot_printf("\n[BOOT] core[%x][%d] activated at cycle %d\n", 709 boot_info->cxy , core_id , boot_get_proctime() ); 710 #endif 566 711 boot_remote_sw((xptr_t) (device->base + (core_id << 2)), 567 712 (uint32_t)boot_entry); 713 } 568 714 } 569 715 } 570 716 } // boot_wake_local_cores() 571 717 572 /**************************************************************************** 573 * API functions. * 574 ****************************************************************************/ 575 576 /**************************************************************************** 718 719 /********************************************************************************* 577 720 * This main function of the boot-loader is called by the boot_entry() 578 721 * function, and executed by all cores. 579 722 * The arguments values are computed by the boot_entry code. 580 * @ lid : core local identifier in its cluster,723 * @ lid : core local identifier, 581 724 * @ cxy : cluster identifier, 582 **************************************************************************** /725 *********************************************************************************/ 583 726 void boot_loader( lid_t lid, 584 727 cxy_t cxy ) 585 728 { 586 boot_info_t * boot_info; // Pointer on local boot_info_t structure 587 uint32_t local_count; // Number of cores expected in local barrier */ 729 boot_info_t * boot_info; // pointer on local boot_info_t structure 588 730 589 731 if (lid == 0) 590 732 { 591 /************************************** 592 * PHASE ONE: only bscpu executes it. *593 ************************************** /733 /**************************************************** 734 * PHASE A : only CP0 in boot cluster executes it 735 ***************************************************/ 594 736 if (cxy == BOOT_CORE_CXY) 595 737 { 596 boot_printf("\n[BOOT] Starting on core[%d] in cluster %xat cycle %d\n",597 lid, cxy, boot_get_proctime());738 boot_printf("\n[BOOT] core[%x][%d] enters at cycle %d\n", 739 cxy , lid , boot_get_proctime() ); 598 740 599 741 // Initialize IOC driver 600 742 if (USE_IOC_BDV) boot_bdv_init(); 601 743 else if (USE_IOC_HBA) boot_hba_init(); 602 /* 603 else if (USE_IOC_SDC) boot_sdc_init(); 604 else if (USE_IOC_SPI) boot_spi_init(); 605 */ 744 // else if (USE_IOC_SDC) boot_sdc_init(); 745 // else if (USE_IOC_SPI) boot_spi_init(); 606 746 else if (!USE_IOC_RDK) 607 747 { 608 boot_printf("\n[BOOT ERROR] boot_loader(): " 609 "No IOC driver\n" 610 ); 748 boot_printf("\n[BOOT ERROR] in %s : no IOC driver\n"); 611 749 boot_exit(); 612 750 } 613 751 614 // Initialize simplified version ofFAT32.752 // Initialize FAT32. 615 753 boot_fat32_init(); 754 755 // Load the 'kernel.elf' file into memory from IOC, and set 756 // the global variables defining the kernel layout 757 boot_kernel_load(); 758 759 boot_printf("\n[BOOT] core[%x][%d] loaded kernel at cycle %d\n", 760 cxy , lid , boot_get_proctime() ); 616 761 617 762 // Load the arch_info.bin file into memory. 618 763 boot_archinfo_load(); 619 764 620 // Load the 'kernel.elf' file into memory. 621 boot_kernel_load(); 622 623 // Get local 'boot_info_t' structure base address. 765 // Get local boot_info_t structure base address. 624 766 // It is the first structure in the .kdata segment. 625 boot_info = (boot_info_t*)(KERN_IMG_TMP_BASE + kdata_base); 626 627 // Signature problem, abort program !!! 767 boot_info = (boot_info_t *)seg_kdata_base; 768 769 // Initialize local boot_info_t structure. 770 boot_info_init( boot_info , cxy ); 771 772 // check boot_info signature 628 773 if (boot_info->signature != BOOT_INFO_SIGNATURE) 629 774 { 630 boot_printf("\n[BOOT ] boot_loader():"631 " boot_info signatureshould be %x\n",632 BOOT_INFO_SIGNATURE);775 boot_printf("\n[BOOT ERROR] in %s reported by core[%x][%d]\n" 776 " illegal boot_info signature / should be %x\n", 777 __FUNCTION__ , cxy , lid , BOOT_INFO_SIGNATURE ); 633 778 boot_exit(); 634 779 } 635 780 636 // Initialize local 'boot_info_t' structure. 637 boot_printf("\n[BOOT] boot_loader(): " 638 "Initializing the local boot_info_t structure " 639 "at cycle %d\n", 640 boot_get_proctime()); 641 642 boot_info_init(boot_info, cxy); 781 boot_printf("\n[BOOT] core[%x][%d] loaded boot_info at cycle %d\n", 782 cxy , lid , boot_get_proctime() ); 643 783 644 784 // Check core information. 645 785 boot_check_core(boot_info, lid); 646 786 647 // Set the barrier. 648 boot_cluster_ready = 0; 649 650 // Activate other CP0s 651 boot_printf("\n[BOOT] boot_loader(): " 652 "Waking other CP0 up at cycle %d\n", 653 boot_get_proctime()); 654 655 global_count = boot_wake_cp0(); 656 657 // Wait until all CP0s ready to enter kernel. 658 boot_printf("\n[BOOT] boot_loader(): " 659 "Waiting for other %d CP0 at cycle %d\n", 660 global_count, boot_get_proctime()); 661 662 boot_barrier(XPTR(BOOT_CORE_CXY, &global_barrier), 663 global_count); 664 665 // activate other local cores of the boot cluster. 666 local_barrier = 0; 667 boot_printf("\n[BOOT] boot_loader(): " 668 "Waking other CPi up at cycle %d\n", 669 boot_get_proctime()); 670 671 boot_wake_local_cores(boot_info); 672 673 // Wait until all other local cores are ready 674 boot_printf("\n[BOOT] boot_loader(): " 675 "Waiting for other %d CPi at cycle %d\n", 676 boot_info->cores_nr - 1, boot_get_proctime()); 677 678 local_count = boot_info->cores_nr - 1; 679 while (local_barrier != local_count); 680 681 // Move the local kernel image at address 0x0 (erase preloader code). 682 boot_printf("\n[BOOT] boot_loader(): " 683 "Moving the kernel image and erasing the preloader" 684 "at cycle %d\n", 685 boot_get_proctime()); 686 687 // ktext segment. 688 boot_memcpy((void*)ktext_base, 689 (void*)(KERN_IMG_TMP_BASE + ktext_base), 690 ktext_end - ktext_base); 691 692 // kdata segment. 693 boot_memcpy((void*)kdata_base, 694 (void*)(KERN_IMG_TMP_BASE + kdata_base), 695 kdata_end - kdata_base); 696 697 // activate other local cores. 698 boot_cluster_ready = 1; 699 boot_printf("\n[BOOT] boot_loader(): " 700 "Everything is set, jumping to the kernel " 701 "at cycle %d\n", 702 boot_get_proctime()); 787 // Activate other CP0s / get number of active CP0s 788 active_cp0s_nr = boot_wake_all_cp0s() + 1; 789 790 // Wait until all clusters (i.e all CP0s) ready to enter kernel. 791 boot_remote_barrier( XPTR( BOOT_CORE_CXY , &global_barrier ) , 792 active_cp0s_nr ); 793 794 // activate other local cores 795 boot_wake_local_cores( boot_info ); 796 797 // Wait until all local cores in cluster ready 798 boot_remote_barrier( XPTR( cxy , &local_barrier ) , 799 boot_info->cores_nr ); 703 800 } 704 /**************************************************** 705 * PHASE TWO: all CP0s other than bscpu execute it. *706 **************************************************** /801 /****************************************************************** 802 * PHASE B : all CP0s other than CP0 in boot cluster execute it 803 *****************************************************************/ 707 804 else 708 805 { 709 /* 710 * Note: at this point, we cannot access the global variables of 711 * this boot code since all the address extension registers for 712 * DATA are pointing to their local cluster in order to have 713 * access to the local stack and execute this C code. 714 * However, all the address extension registers for INSTRUCTIONS 715 * are still pointing to the boot cluster, thus we can access 716 * and call functions defined in the boot code, for example 717 * boot_remote_memcpy(). 718 */ 719 720 // Copy the boot-loader binary code 'boot.elf' into the local memory 721 boot_remote_memcpy(XPTR(cxy, BOOT_BASE), 722 XPTR(BOOT_CORE_CXY, BOOT_BASE), 723 (unsigned int)BOOT_MAX_SIZE); 724 725 /* 726 * Note: from now on, it is safe to refer to the boot code global variables 727 * such as the base address and size of the kernel segments. 728 */ 729 730 // switch to the INSTRUCTION local memory space, 731 // to avoid contention at the boot cluster. 806 // at this point, all INSTRUCTION address extension registers 807 // point on cluster(0,0), but the DATA extension registers point 808 // already on the local cluster to use the local stack. 809 // To access the bootloader global variables we must first copy 810 // the boot code (data and instructions) in the local cluster. 811 boot_remote_memcpy( XPTR( cxy , BOOT_BASE ), 812 XPTR( BOOT_CORE_CXY , BOOT_BASE ), 813 BOOT_MAX_SIZE ); 814 815 // from now, it is safe to refer to the boot code global variables 816 boot_printf("\n[BOOT] core[%x][%d] replicated boot code at cycle %d\n", 817 cxy , lid , boot_get_proctime() ); 818 819 // switch to the INSTRUCTION local memory space, to avoid contention. 732 820 asm volatile("mtc2 %0, $25" :: "r"(cxy)); 733 821 734 // Copy the 'arch_info.bin'file into the local memory.822 // Copy the arch_info.bin file into the local memory. 735 823 boot_remote_memcpy(XPTR(cxy, ARCHINFO_BASE), 736 824 XPTR(BOOT_CORE_CXY, ARCHINFO_BASE), 737 (unsigned int)ARCHINFO_MAX_SIZE); 738 739 // Copy the kernel image into local memory at address 0x0. 740 // ktext segment. 741 boot_remote_memcpy(XPTR(cxy, ktext_base), 742 XPTR(BOOT_CORE_CXY, KERN_IMG_TMP_BASE + ktext_base), 743 ktext_end - ktext_base); 744 // kdata segment. 745 boot_remote_memcpy(XPTR(cxy, kdata_base), 746 XPTR(BOOT_CORE_CXY, KERN_IMG_TMP_BASE + kdata_base), 747 kdata_end - kdata_base); 748 749 // Get local 'boot_info_t' structure base address. 750 // This is the first structure in the kdata segment. 751 boot_info = (boot_info_t*)kdata_base; 825 ARCHINFO_MAX_SIZE ); 826 827 boot_printf("\n[BOOT] core[%x][%d] replicated arch_info at cycle %d\n", 828 cxy , lid , boot_get_proctime() ); 829 830 // Copy the kcode segment into local memory 831 boot_remote_memcpy( XPTR( cxy , seg_kcode_base ), 832 XPTR( BOOT_CORE_CXY , seg_kcode_base ), 833 seg_kcode_size ); 834 835 // Copy the kdata segment into local memory 836 boot_remote_memcpy( XPTR( cxy , seg_kdata_base ), 837 XPTR( BOOT_CORE_CXY , seg_kdata_base ), 838 seg_kdata_size ); 839 840 boot_printf("\n[BOOT] core[%x][%d] replicated kernel code at cycle %d\n", 841 cxy , lid , boot_get_proctime() ); 842 843 // Get local boot_info_t structure base address. 844 boot_info = (boot_info_t*)seg_kdata_base; 752 845 753 846 // Initialize local boot_info_t structure. 754 boot_info_init( boot_info, cxy);847 boot_info_init( boot_info , cxy ); 755 848 756 849 // Check core information. 757 boot_check_core(boot_info, lid); 758 759 // Activateall other local CPi cores in this cluster. 760 local_barrier = 0; 761 boot_wake_local_cores(boot_info); 762 763 // Waiting until all other local cores ready 764 local_count = boot_info->cores_nr - 1; 765 while (local_barrier != local_count); 766 767 // All cores in this cluster are ready to enter kernel. 768 boot_barrier(XPTR(BOOT_CORE_CXY, &global_barrier), 769 global_count); 850 boot_check_core( boot_info , lid ); 851 852 // get number of active clusters from BOOT_CORE cluster 853 uint32_t count = boot_remote_lw( XPTR( BOOT_CORE_CXY , &active_cp0s_nr ) ); 854 855 // Wait until all clusters (i.e all CP0s) ready to enter kernel 856 boot_remote_barrier( XPTR( BOOT_CORE_CXY , &global_barrier ) , count ); 857 858 // activate other local cores 859 boot_wake_local_cores( boot_info ); 860 861 // Wait until all local cores in cluster ready 862 boot_remote_barrier( XPTR( cxy , &local_barrier ) , 863 boot_info->cores_nr ); 770 864 } 771 865 } … … 773 867 { 774 868 /*************************************************************** 775 * PHASE THREE: all non CP0 cores in all clusters execute it. *869 * PHASE C: all non CP0 cores in all clusters execute it 776 870 **************************************************************/ 777 871 778 if (cxy == BOOT_CORE_CXY) // boot cluster only 779 { 780 // Report to the local CP0 that CPi is ready 781 boot_atomic_add((int32_t*)&local_barrier, 1); 782 783 // wait completion of kernel image move in boot cluster 784 while (boot_cluster_ready != 1); 785 786 // Check core information 787 boot_info = (boot_info_t*)kdata_base; 788 boot_check_core(boot_info, lid); 789 } 790 else // other clusters 791 { 792 // Switch to the INSTRUCTIONS local memory space 793 // to avoid contention at the boot cluster. 794 asm volatile("mtc2 %0, $25" :: "r"(cxy)); 795 796 // Report to the local CP0 that CPi is ready 797 boot_atomic_add((int32_t*)&local_barrier, 1); 798 799 // Check core information 800 boot_info = (boot_info_t*)kdata_base; 801 boot_check_core(boot_info, lid); 802 } 803 } 804 805 // Jump to the kernel code. 806 asm volatile("jr %0" :: "r"(kernel_entry)); 872 // Switch to the INSTRUCTIONS local memory space 873 // to avoid contention at the boot cluster. 874 asm volatile("mtc2 %0, $25" :: "r"(cxy)); 875 876 // Get local boot_info_t structure base address. 877 boot_info = (boot_info_t *)seg_kdata_base; 878 879 // Check core information 880 boot_check_core(boot_info, lid); 881 882 // Wait until all local cores in cluster ready 883 boot_remote_barrier( XPTR( cxy , &local_barrier ) , boot_info->cores_nr ); 884 } 885 886 // Each core compute address of a temporary kernel stack 887 // in the upper part of the local cluster memory... 888 uint32_t stack_ptr = ((boot_info->pages_nr - lid) << 12) - 16; 889 890 // All cores initialise stack pointer, 891 // reset the BEV bit in status register, 892 // register "boot_info" argument in a0, 893 // and jump to kernel_entry. 894 asm volatile( "mfc0 $27, $12 \n" 895 "lui $26, 0xFFBF \n" 896 "ori $26, $26, 0xFFFF \n" 897 "and $27, $27, $26 \n" 898 "mtc0 $27, $12 \n" 899 "move $4, %0 \n" 900 "move $29, %1 \n" 901 "jr %2 \n" 902 :: "r"(boot_info) , "r"(stack_ptr) , "r"(kernel_entry) ); 807 903 808 904 } // boot_loader()
Note: See TracChangeset
for help on using the changeset viewer.