Changeset 6 for trunk/tools/bootloader_tsar/boot_utils.c
- Timestamp:
- Apr 26, 2017, 2:14:33 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tools/bootloader_tsar/boot_utils.c
r1 r6 1 /* 2 * boot_utils.c - TSAR bootloader utilities 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 #include <stdarg.h> 2 25 … … 5 28 #include <boot_utils.h> 6 29 30 31 /**************************************************************************** 32 * Global variables * 33 ****************************************************************************/ 34 35 extern boot_remote_spinlock_t tty0_lock; // allocated in boot.c 36 7 37 /**************************************************************************** 8 38 * Remote accesses. * 9 39 ****************************************************************************/ 10 40 41 ////////////////////////////////// 11 42 uint32_t boot_remote_lw(xptr_t xp) 12 43 { 13 uint32_t res; /* Value to be read, stored at the remote address. */ 14 uint32_t ptr; /* Classic pointer to the distant memory location. */ 15 uint32_t cxy; /* Identifier of the cluster containing the distant 16 memory location. */ 17 18 /* Extracting information from the extended pointer. */ 44 uint32_t res; 45 uint32_t ptr; 46 uint32_t cxy; 47 48 // Extracting information from the extended pointer 19 49 ptr = (uint32_t)GET_PTR(xp); 20 50 cxy = (uint32_t)GET_CXY(xp); 21 51 22 / * Assembly instructions to get the work done. */52 // Assembly instructions to get the work done. 23 53 asm volatile("mfc2 $15, $24\n" /* $15 <= CP2_DATA_PADDR_EXT */ 24 54 "mtc2 %2, $24\n" /* CP2_DATA_PADDR_EXT <= cxy */ … … 37 67 } // boot_remote_lw() 38 68 39 /****************************************************************************/ 40 69 ///////////////////////////////////////////// 41 70 void boot_remote_sw(xptr_t xp, uint32_t data) 42 71 { … … 62 91 } // boot_remote_sw() 63 92 64 /****************************************************************************/ 65 93 ////////////////////////////////////////////////////// 66 94 int32_t boot_remote_atomic_add(xptr_t xp, int32_t val) 67 95 { … … 98 126 } // boot_remote_atomic_add() 99 127 100 /****************************************************************************/ 101 102 void boot_remote_memcpy(xptr_t dest, xptr_t src, unsigned int size) 128 /////////////////////////////////////////////////////////////// 129 void boot_remote_memcpy(xptr_t dest, xptr_t src, uint32_t size) 103 130 { 104 131 uint32_t words_nr; /* Number of 32-bit words to be copied. */ … … 194 221 ****************************************************************************/ 195 222 196 void boot_memcpy(void* dest, void* src, unsigned int size) 197 { 198 /* Word-by-word copy if both addresses are word-aligned. */ 199 if ((((unsigned int)dest & 0x3) == 0) && 200 (((unsigned int)src & 0x3) == 0)) 201 { 202 // 'size' might not be a multiple of 4 bytes, we have to copy a few 203 // bytes left (at most 3) byte-by-byte later. 223 /////////////////////////////////////////////////////// 224 void boot_memcpy(void * dst, void * src, uint32_t size) 225 { 226 uint32_t * wdst = dst; 227 uint32_t * wsrc = src; 228 229 // word-by-word copy if both addresses are word-aligned 230 if ( (((uint32_t)dst & 0x3) == 0) && (((uint32_t)src & 0x3) == 0) ) 231 { 204 232 while (size > 3) 205 233 { 206 * (unsigned int*)dest++ = *(unsigned int*)src++;234 *wdst++ = *wsrc++; 207 235 size -= 4; 208 236 } 209 237 } 210 238 211 /* 212 * Byte-by-byte copy if: 213 * - At least 1 of the 2 addresses is not word-aligned, 214 * - 'size' value is not a multiple of 4 bytes. 215 */ 239 unsigned char * cdst = (unsigned char *)wdst; 240 unsigned char * csrc = (unsigned char *)wsrc; 241 242 // byte-by-byte copy if: 243 // - At least 1 of the 2 addresses is not word-aligned, 244 // - 'size' value is not a multiple of 4 bytes. 216 245 while (size) 217 *(unsigned char*)dest++ = *(unsigned char*)src++; 218 246 { 247 *cdst++ = *csrc++; 248 } 219 249 } // boot_memcpy() 220 250 221 /****************************************************************************/ 222 223 void boot_memset(void* base, int val, unsigned int size) 224 { 225 unsigned int wval; /* Word-sized value to word-by-word filling. */ 226 227 /* Word-by-word filling if the base address is word-aligned. */ 228 // Extracting the first 2 bytes of 'val'. 251 //////////////////////////////////////////////////// 252 void boot_memset(void * dst, int val, uint32_t size) 253 { 229 254 val &= 0xFF; 230 // Making it word-sized. 231 wval = (val << 24) | (val << 16) | (val << 8) | val; 232 233 if (((unsigned int)base & 0x3) == 0) 234 { 235 // 'size' might not be a multiple of 4 bytes, we have to fill a 236 // few bytes left (at most 3) byte-by-byte later. 255 256 // build a word-sized value 257 uint32_t wval = (val << 24) | (val << 16) | (val << 8) | val; 258 uint32_t * wdst = (uint32_t *)dst; 259 260 // word per word if address aligned 261 if (((uint32_t)dst & 0x3) == 0) 262 { 237 263 while (size > 3) 238 264 { 239 * (unsigned int*)base++ = wval;265 *wdst++ = wval; 240 266 size -= 4; 241 267 } 242 268 } 243 269 244 /* 245 * Byte-by-byte filling if: 246 * - The base address is not word-aligned, 247 * - 'size' value is not a multiple of 4 bytes. 248 */ 270 char * cdst = (char *)wdst; 271 272 // byte per byte 249 273 while (size--) 250 *(unsigned char*)base++ = val; 251 274 { 275 *cdst++ = (char)val; 276 } 252 277 } // boot_memset() 253 278 … … 256 281 ****************************************************************************/ 257 282 283 /////////////////////////////////////// 258 284 void boot_strcpy(char* dest, char* src) 259 285 { … … 267 293 } // boot_strcpy() 268 294 269 /****************************************************************************/ 270 271 unsigned int boot_strlen(char* s) 272 { 273 unsigned int res = 0; /* Length of the string (in bytes). */ 295 ///////////////////////////// 296 uint32_t boot_strlen(char* s) 297 { 298 uint32_t res = 0; /* Length of the string (in bytes). */ 274 299 275 300 if (s != NULL) … … 283 308 } // boot_strlen() 284 309 285 /****************************************************************************/ 286 310 /////////////////////////////////// 287 311 int boot_strcmp(char* s1, char* s2) 288 312 { … … 308 332 ****************************************************************************/ 309 333 334 ///////////////////////// 310 335 void boot_puts(char* str) 311 336 { … … 314 339 } // boot_puts() 315 340 316 /****************************************************************************/ 317 318 void boot_printf(char* format, ...) 319 { 320 va_list arg; /* Used to iterate arguments list. */ 321 char buf[16]; /* Buffer for argument conversion. */ 322 char* print_pt; /* String pointer for argument printing. */ 323 int arg_val; /* Raw value of the argument. */ 324 unsigned int arg_len; /* Length of a argument (in bytes). */ 325 unsigned int nb_printed; /* Iterator for text printing loop. */ 326 unsigned int conv_index; /* Index for argument conversion loop. */ 327 328 const char conv_tab[] = "0123456789ABCDEF"; 329 330 /* Starting the arguments iterating process with a va_list. */ 331 va_start(arg, format); 332 333 print_text: 334 335 while (*format) 336 { 337 /* Counting the number of ordinary characters. */ 338 for (nb_printed = 0; 339 (format[nb_printed] != '\0') && (format[nb_printed] != '%'); 340 nb_printed++); 341 342 /* Copying them unchanged to the boot TTY terminal. */ 343 if (nb_printed > 0) 341 /////////////////////////////////////// 342 void boot_printf( char * format , ... ) 343 { 344 va_list args; 345 va_start( args , format ); 346 347 // take the lock protecting TTY0 348 boot_remote_lock( XPTR( 0 , &tty0_lock ) ); 349 350 printf_text: 351 352 while ( *format ) 353 { 354 uint32_t i; 355 for (i = 0 ; format[i] && (format[i] != '%') ; i++); 356 if (i) 344 357 { 345 if (boot_tty_write(format, nb_printed)) 346 goto error; 347 format += nb_printed; 358 boot_tty_write( format , i ); 359 format += i; 348 360 } 349 350 /* Skipping the '%' character. */ 351 if (*format == '%') 361 if (*format == '%') 352 362 { 353 363 format++; 354 goto print _argument;364 goto printf_arguments; 355 365 } 356 366 } 357 367 358 /* Freeing the va_list. */ 359 va_end(arg); 360 368 // release the lock 369 boot_remote_unlock( XPTR( 0 , &tty0_lock ) ); 370 371 va_end( args ); 361 372 return; 362 373 363 print_argument: 364 365 /* Analyzing the conversion specifier. */ 366 switch (*format++) 367 { 368 // A character. 369 case ('c'): 374 printf_arguments: 375 376 { 377 char buf[20]; 378 char * pbuf = NULL; 379 uint32_t len = 0; 380 static const char HexaTab[] = "0123456789ABCDEF"; 381 uint32_t i; 382 383 switch (*format++) 370 384 { 371 // Retrieving the argument. 372 arg_val = va_arg(arg, int); 373 374 // Preparing for the printing. 375 arg_len = 1; 376 buf[0] = arg_val; 377 print_pt = &buf[0]; 378 break; 385 case ('c'): /* char conversion */ 386 { 387 int val = va_arg( args , int ); 388 len = 1; 389 buf[0] = val; 390 pbuf = &buf[0]; 391 break; 392 } 393 case ('d'): /* 32 bits decimal signed */ 394 { 395 int val = va_arg( args , int ); 396 if (val < 0) 397 { 398 val = -val; 399 boot_tty_write( "-" , 1 ); 400 } 401 for(i = 0; i < 10; i++) 402 { 403 buf[9 - i] = HexaTab[val % 10]; 404 if (!(val /= 10)) break; 405 } 406 len = i + 1; 407 pbuf = &buf[9 - i]; 408 break; 409 } 410 case ('u'): /* 32 bits decimal unsigned */ 411 { 412 uint32_t val = va_arg( args , uint32_t ); 413 for(i = 0; i < 10; i++) 414 { 415 buf[9 - i] = HexaTab[val % 10]; 416 if (!(val /= 10)) break; 417 } 418 len = i + 1; 419 pbuf = &buf[9 - i]; 420 break; 421 } 422 case ('x'): /* 32 bits hexadecimal unsigned */ 423 { 424 uint32_t val = va_arg( args , uint32_t ); 425 boot_tty_write( "0x" , 2 ); 426 for(i = 0; i < 8; i++) 427 { 428 buf[7 - i] = HexaTab[val & 0xF]; 429 if (!(val = (val>>4))) break; 430 } 431 len = i + 1; 432 pbuf = &buf[7 - i]; 433 break; 434 } 435 case ('X'): /* 32 bits hexadecimal unsigned on 10 char */ 436 { 437 uint32_t val = va_arg( args , uint32_t ); 438 boot_tty_write( "0x" , 2 ); 439 for(i = 0; i < 8; i++) 440 { 441 buf[7 - i] = HexaTab[val & 0xF]; 442 val = (val>>4); 443 } 444 len = 8; 445 pbuf = buf; 446 break; 447 } 448 case ('l'): /* 64 bits hexadecimal unsigned */ 449 { 450 uint64_t val = va_arg( args , uint64_t ); 451 boot_tty_write( "0x" , 2 ); 452 for(i = 0; i < 16; i++) 453 { 454 buf[15 - i] = HexaTab[val & 0xF]; 455 if (!(val = (val>>4))) break; 456 } 457 len = i + 1; 458 pbuf = &buf[15 - i]; 459 break; 460 } 461 case ('L'): /* 64 bits hexadecimal unsigned on 18 char */ 462 { 463 uint64_t val = va_arg( args , uint64_t ); 464 boot_tty_write( "0x" , 2 ); 465 for(i = 0; i < 16; i++) 466 { 467 buf[15 - i] = HexaTab[val & 0xF]; 468 val = (val>>4); 469 } 470 len = 16; 471 pbuf = buf; 472 break; 473 } 474 case ('s'): /* string */ 475 { 476 char* str = va_arg( args , char* ); 477 while (str[len]) 478 { 479 len++; 480 } 481 pbuf = str; 482 break; 483 } 484 default: 485 { 486 boot_tty_write( "\n[PANIC] in boot_printf() : illegal format\n", 43 ); 487 } 379 488 } 380 489 381 // A 32-bit signed decimal notation of an integer. 382 case ('d'): 383 { 384 // Retrieving the argument. 385 arg_val = va_arg(arg, int); 386 387 // Printing the minus sign if needed. 388 if (arg_val < 0) 389 { 390 arg_val = -arg_val; 391 if (boot_tty_write("-", 1)) 392 goto error; 393 } 394 395 // Converting the argument raw value to a character string. 396 // Note that the maximum value for this type is 2.147.483.647 397 // (2^31 - 1), a 10-digit number. 398 for (conv_index = 0; conv_index < 10; conv_index++) 399 { 400 // Writing to the buffer, starting from the least significant 401 // digit. 402 buf[9 - conv_index] = conv_tab[arg_val % 10]; 403 404 // Getting to the next digit, stop when no more digit. 405 if ((arg_val /= 10) == 0) 406 break; 407 } 408 409 // Preparing for the printing. 410 arg_len = conv_index + 1; 411 print_pt = &buf[9 - conv_index]; 412 break; 413 } 414 415 // A 32-bit unsigned decimal notation of an integer. 416 case ('u'): 417 { 418 // Retrieving the argument. 419 arg_val = va_arg(arg, unsigned int); 420 421 // Converting the argument raw value to a character string. 422 // Note that the maximum value for this type is 4.294.967.295 423 // (2^32 - 1), also a 10-digit number. 424 for (conv_index = 0; conv_index < 10; conv_index++) 425 { 426 // Writing to the buffer, starting from the least significant 427 // digit. 428 buf[9 - conv_index] = conv_tab[arg_val % 10]; 429 430 // Getting to the next digit, stop when no more digit. 431 if ((arg_val /= 10) == 0) 432 break; 433 } 434 435 // Preparing for the printing. 436 arg_len = conv_index + 1; 437 print_pt = &buf[9 - conv_index]; 438 break; 439 } 440 441 // A 32-bit unsigned hexadecimal notation of an integer. 442 case ('x'): 443 { 444 // Retrieving the argument. 445 arg_val = va_arg(arg, unsigned int); 446 447 // Printing the hexadecimal prefix. 448 if (boot_tty_write("0x", 2)) 449 goto error; 450 451 // Converting the argument raw value to a character string. 452 // Note that the maximum value for this type is 0xFFFFFFFF 453 // (2^32 - 1), a 8-digit hexadecimal number. 454 for (conv_index = 0; conv_index < 8; conv_index++) 455 { 456 // Writing to the buffer, starting from the least significant 457 // digit. 458 buf[7 - conv_index] = conv_tab[arg_val % 16]; 459 460 // Getting to the next digit, stop when no more digit. 461 if ((arg_val >>= 4) == 0) 462 break; 463 } 464 465 // Preparing for the printing. 466 arg_len = conv_index + 1; 467 print_pt = &buf[7 - conv_index]; 468 break; 469 } 470 471 // A 64-bit unsigned hexadecimal notation of an integer. 472 case ('l'): 473 { 474 // Retrieving the argument. 475 arg_val = va_arg(arg, unsigned long long); 476 477 // Printing the hexadecimal prefix. 478 if (boot_tty_write("0x", 2)) 479 goto error; 480 481 // Converting the argument raw value to a character string. 482 // Note that the maximum value for this type is 0xFFFFFFFFFFFFFFFF 483 // (2^64 - 1), a 16-digit hexadecimal number. 484 for (conv_index = 0; conv_index < 16; conv_index++) 485 { 486 // Writing to the buffer, starting from the least significant 487 // digit. 488 buf[15 - conv_index] = conv_tab[arg_val % 16]; 489 490 // Getting to the next digit, stop when no more digit. 491 if ((arg_val >>= 4) == 0) 492 break; 493 } 494 495 // Preparing for the printing. 496 arg_len = conv_index + 1; 497 print_pt = &buf[15 - conv_index]; 498 break; 499 } 500 501 // A NUL terminated string. 502 case ('s'): 503 { 504 // Retrieving the argument. 505 print_pt = va_arg(arg, char*); 506 507 // Preparing for the printing. 508 arg_len = boot_strlen(print_pt); 509 break; 510 } 511 512 default: 513 goto error; 514 515 } 516 517 /* Printing the converted argument. */ 518 if (boot_tty_write(print_pt, arg_len)) 519 goto error; 520 521 goto print_text; 522 523 error: 524 525 /* Trying to print an error message then exit. */ 526 boot_puts("\n[BOOT ERROR] boot_printf(): " 527 "Cannot print the whole message\n" 528 ); 529 530 boot_exit(); 531 532 } // boot_printf() 490 if( pbuf != NULL ) boot_tty_write( pbuf, len ); 491 492 goto printf_text; 493 } 494 } // boot_printf() 495 496 497 498 499 533 500 534 501 /**************************************************************************** … … 536 503 ****************************************************************************/ 537 504 505 //////////////// 538 506 void boot_exit() 539 507 { 540 boot_printf("\n[BOOT PANIC] Suiciding at cycle %d...\n", 541 boot_get_proctime() 542 ); 543 544 while (1) 545 asm volatile ("nop"); 508 boot_printf("\n[BOOT PANIC] core %x suicide at cycle %d...\n", 509 boot_get_procid() , boot_get_proctime() ); 510 511 while (1) asm volatile ("nop"); 546 512 547 513 } // boot_exit() 548 514 549 /****************************************************************************/ 550 551 unsigned int boot_get_proctime() 552 { 553 unsigned int res; /* Value stored in the CP0_COUNT register. */ 515 //////////////////////////// 516 uint32_t boot_get_proctime() 517 { 518 uint32_t res; /* Value stored in the CP0_COUNT register. */ 554 519 555 520 asm volatile("mfc0 %0, $9" : "=r"(res)); … … 559 524 } // boot_get_proctime() 560 525 561 /****************************************************************************/ 562 563 u nsigned int boot_get_procid()564 { 565 u nsigned int res; /* Value stored in the CP0_PROCID register. */526 527 ////////////////////////// 528 uint32_t boot_get_procid() 529 { 530 uint32_t res; /* Value stored in the CP0_PROCID register. */ 566 531 567 532 asm volatile("mfc0 %0, $15, 1" : "=r"(res)); … … 571 536 } // boot_get_procid() 572 537 573 /****************************************************************************/ 574 575 void boot_barrier(xptr_t xp_barrier, uint32_t count) 576 { 577 boot_barrier_t* ptr; /* Classic pointer to the toggling 578 barrier. */ 579 uint32_t cxy; /* Identifier of the cluster containing 580 the toggling barrier. */ 581 uint32_t expected; /* Expected barrier state after reset. */ 582 uint32_t current; /* Number of processors reached the 583 barrier. */ 584 585 /* Extracting information from the extended pointer. */ 586 ptr = (boot_barrier_t*)GET_PTR(xp_barrier); 587 cxy = (uint32_t) GET_CXY(xp_barrier); 588 589 /* 590 * Explicitly testing the barrier sense value because no initialization 591 * has been previously done. 592 */ 593 if (boot_remote_lw(XPTR(cxy, &ptr->sense)) == 0) 594 expected = 1; 595 else 596 expected = 0; 538 539 //////////////////////////////////////////////// 540 void boot_remote_barrier( xptr_t xp_barrier, 541 uint32_t count) 542 { 543 boot_remote_barrier_t * ptr; 544 uint32_t cxy; 545 uint32_t expected; 546 uint32_t current; 547 548 // Extract information from the extended pointer 549 ptr = (boot_remote_barrier_t*)GET_PTR(xp_barrier); 550 cxy = (uint32_t) GET_CXY(xp_barrier); 551 552 // Explicitly test the barrier sense value because no initialization 553 if (boot_remote_lw(XPTR(cxy, &ptr->sense)) == 0) expected = 1; 554 else expected = 0; 597 555 598 / * Incrementing the counter. */556 // Atomically increment counter 599 557 current = boot_remote_atomic_add(XPTR(cxy, &ptr->current), 1); 600 558 601 / * The processor arrived last resets the barrier and toggles its sense. */559 // The processor arrived last resets the barrier and toggles its sense 602 560 if (current == (count - 1)) 603 561 { … … 605 563 boot_remote_sw(XPTR(cxy, &ptr->sense), expected); 606 564 } 607 / * Other processors poll the sense. */565 // Other processors poll the sense 608 566 else 609 567 { … … 613 571 } // boot_barrier() 614 572 573 //////////////////////////////////////// 574 void boot_remote_lock( xptr_t lock_xp ) 575 576 { 577 // Extract information from the extended pointer 578 boot_remote_spinlock_t * ptr = (boot_remote_spinlock_t *)GET_PTR( lock_xp ); 579 uint32_t cxy = GET_CXY( lock_xp ); 580 581 // get next free ticket 582 uint32_t ticket = boot_remote_atomic_add( XPTR( cxy , &ptr->ticket ) , 1 ); 583 584 // poll the current slot index 585 while ( boot_remote_lw( XPTR( cxy , &ptr->current ) ) != ticket ) 586 { 587 asm volatile ("nop"); 588 } 589 590 } // boot_remote_lock() 591 592 ///////////////////////////////////////// 593 void boot_remote_unlock( xptr_t lock_xp ) 594 { 595 asm volatile ( "sync" ); // for consistency 596 597 // Extract information from the extended pointer 598 boot_remote_spinlock_t * ptr = (boot_remote_spinlock_t *)GET_PTR( lock_xp ); 599 uint32_t cxy = GET_CXY( lock_xp ); 600 xptr_t current_xp = XPTR( cxy , &ptr->current ); 601 602 // get current index value 603 uint32_t current = boot_remote_lw( current_xp ); 604 605 // increment current index 606 boot_remote_sw( current_xp , current + 1 ); 607 608 } // boot_remote_unlock() 609 610
Note: See TracChangeset
for help on using the changeset viewer.