cvmx-app-init-linux.c (210286) | cvmx-app-init-linux.c (215990) |
---|---|
1/***********************license start*************** | 1/***********************license start*************** |
2 * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights 3 * reserved. | 2 * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights 3 * reserved. |
4 * 5 * | 4 * 5 * |
6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: | 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: |
9 * | 9 * |
10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. | 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. |
12 * | 12 * |
13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 * 18 * * Neither the name of Cavium Networks nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 * 23 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 24 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS 25 * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH 26 * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 27 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 28 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES 29 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR 30 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET 31 * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT 32 * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 33 * 34 * 35 * For any questions regarding licensing please contact marketing@caviumnetworks.com 36 * | 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 18 * * Neither the name of Cavium Networks nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 23 * This Software, including technical data, may be subject to U.S. export control 24 * laws, including the U.S. Export Administration Act and its associated 25 * regulations, and may be subject to export or import regulations in other 26 * countries. 27 28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR 30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. |
37 ***********************license end**************************************/ 38 39 40 41 42 | 38 ***********************license end**************************************/ 39 40 41 42 43 |
44 |
|
43/** 44 * @file 45 * Simple executive application initialization for Linux user space. This 46 * file should be used instead of cvmx-app-init.c for running simple executive 47 * applications under Linux in userspace. The following are some of the key 48 * points to remember when writing applications to run both under the 49 * standalone simple executive and userspace under Linux. 50 * 51 * -# Application main must be called "appmain" under Linux. Use and ifdef 52 * based on __linux__ to determine the proper name. 53 * -# Be careful to use cvmx_ptr_to_phys() and cvmx_phys_to_ptr. The simple 54 * executive 1-1 TLB mappings allow you to be sloppy and interchange 55 * hardware addresses with virtual address. This isn't true under Linux. 56 * -# If you're talking directly to hardware, be careful. The normal Linux 57 * protections are circumvented. If you do something bad, Linux won't 58 * save you. 59 * -# Most hardware can only be initialized once. Unless you're very careful, 60 * this also means you Linux application can only run once. 61 * | 45/** 46 * @file 47 * Simple executive application initialization for Linux user space. This 48 * file should be used instead of cvmx-app-init.c for running simple executive 49 * applications under Linux in userspace. The following are some of the key 50 * points to remember when writing applications to run both under the 51 * standalone simple executive and userspace under Linux. 52 * 53 * -# Application main must be called "appmain" under Linux. Use and ifdef 54 * based on __linux__ to determine the proper name. 55 * -# Be careful to use cvmx_ptr_to_phys() and cvmx_phys_to_ptr. The simple 56 * executive 1-1 TLB mappings allow you to be sloppy and interchange 57 * hardware addresses with virtual address. This isn't true under Linux. 58 * -# If you're talking directly to hardware, be careful. The normal Linux 59 * protections are circumvented. If you do something bad, Linux won't 60 * save you. 61 * -# Most hardware can only be initialized once. Unless you're very careful, 62 * this also means you Linux application can only run once. 63 * |
62 * <hr>$Revision: 41757 $<hr> | 64 * <hr>$Revision: 49448 $<hr> |
63 * 64 */ 65#define _GNU_SOURCE 66#include <stdint.h> 67#include <stdio.h> 68#include <stdlib.h> 69#include <stdarg.h> 70#include <string.h> --- 31 unchanged lines hidden (view full) --- 102 If they aren't defined, you probably forgot to link using this script. */ 103extern void __cvmx_shared_start; 104extern void __cvmx_shared_end; 105extern uint64_t linux_mem32_min; 106extern uint64_t linux_mem32_max; 107extern uint64_t linux_mem32_wired; 108extern uint64_t linux_mem32_offset; 109 | 65 * 66 */ 67#define _GNU_SOURCE 68#include <stdint.h> 69#include <stdio.h> 70#include <stdlib.h> 71#include <stdarg.h> 72#include <string.h> --- 31 unchanged lines hidden (view full) --- 104 If they aren't defined, you probably forgot to link using this script. */ 105extern void __cvmx_shared_start; 106extern void __cvmx_shared_end; 107extern uint64_t linux_mem32_min; 108extern uint64_t linux_mem32_max; 109extern uint64_t linux_mem32_wired; 110extern uint64_t linux_mem32_offset; 111 |
110#define MIPS_CAVIUM_XKPHYS_READ 2010 /* XKPHYS */ 111#define MIPS_CAVIUM_XKPHYS_WRITE 2011 /* XKPHYS */ 112 113static CVMX_SHARED int32_t warn_count; 114 | |
115/** 116 * This function performs some default initialization of the Octeon executive. It initializes 117 * the cvmx_bootmem memory allocator with the list of physical memory shared by the bootloader. 118 * This function should be called on all cores that will use the bootmem allocator. 119 * Applications which require a different configuration can replace this function with a suitable application 120 * specific one. 121 * 122 * @return 0 on success --- 6 unchanged lines hidden (view full) --- 129 130 131/** 132 * Simulator magic is not supported in user mode under Linux. 133 * This version of simprintf simply calls the underlying C 134 * library printf for output. It also makes sure that two 135 * calls to simprintf provide atomic output. 136 * | 112/** 113 * This function performs some default initialization of the Octeon executive. It initializes 114 * the cvmx_bootmem memory allocator with the list of physical memory shared by the bootloader. 115 * This function should be called on all cores that will use the bootmem allocator. 116 * Applications which require a different configuration can replace this function with a suitable application 117 * specific one. 118 * 119 * @return 0 on success --- 6 unchanged lines hidden (view full) --- 126 127 128/** 129 * Simulator magic is not supported in user mode under Linux. 130 * This version of simprintf simply calls the underlying C 131 * library printf for output. It also makes sure that two 132 * calls to simprintf provide atomic output. 133 * |
137 * @param fmt Format string in the same format as printf. | 134 * @param format Format string in the same format as printf. |
138 */ | 135 */ |
139void simprintf(const char *fmt, ...) | 136void simprintf(const char *format, ...) |
140{ 141 CVMX_SHARED static cvmx_spinlock_t simprintf_lock = CVMX_SPINLOCK_UNLOCKED_INITIALIZER; 142 va_list ap; 143 144 cvmx_spinlock_lock(&simprintf_lock); 145 printf("SIMPRINTF(%d): ", (int)cvmx_get_core_num()); | 137{ 138 CVMX_SHARED static cvmx_spinlock_t simprintf_lock = CVMX_SPINLOCK_UNLOCKED_INITIALIZER; 139 va_list ap; 140 141 cvmx_spinlock_lock(&simprintf_lock); 142 printf("SIMPRINTF(%d): ", (int)cvmx_get_core_num()); |
146 va_start(ap, fmt); 147 vprintf(fmt, ap); | 143 va_start(ap, format); 144 vprintf(format, ap); |
148 va_end(ap); 149 cvmx_spinlock_unlock(&simprintf_lock); 150} 151 152 153/** 154 * Setup the CVMX_SHARED data section to be shared across 155 * all processors running this application. A memory mapped --- 164 unchanged lines hidden (view full) --- 320 * @return Return value for the process 321 */ 322int main(int argc, const char *argv[]) 323{ 324 CVMX_SHARED static cvmx_spinlock_t mask_lock = CVMX_SPINLOCK_UNLOCKED_INITIALIZER; 325 CVMX_SHARED static int32_t pending_fork; 326 unsigned long cpumask; 327 unsigned long cpu; | 145 va_end(ap); 146 cvmx_spinlock_unlock(&simprintf_lock); 147} 148 149 150/** 151 * Setup the CVMX_SHARED data section to be shared across 152 * all processors running this application. A memory mapped --- 164 unchanged lines hidden (view full) --- 317 * @return Return value for the process 318 */ 319int main(int argc, const char *argv[]) 320{ 321 CVMX_SHARED static cvmx_spinlock_t mask_lock = CVMX_SPINLOCK_UNLOCKED_INITIALIZER; 322 CVMX_SHARED static int32_t pending_fork; 323 unsigned long cpumask; 324 unsigned long cpu; |
328 int lastcpu = 0; | 325 int firstcpu = 0; 326 int firstcore = 0; |
329 | 327 |
328 cvmx_linux_enable_xkphys_access(0); 329 |
|
330 cvmx_sysinfo_linux_userspace_initialize(); 331 332 if (sizeof(void*) == 4) 333 { 334 if (linux_mem32_min) 335 setup_reserve32(); 336 else 337 { 338 printf("\nFailed to access 32bit shared memory region. Most likely the Kernel\n" 339 "has not been configured for 32bit shared memory access. Check the\n" 340 "kernel configuration.\n" 341 "Aborting...\n\n"); 342 exit(-1); 343 } 344 } 345 346 setup_cvmx_shared(); | 330 cvmx_sysinfo_linux_userspace_initialize(); 331 332 if (sizeof(void*) == 4) 333 { 334 if (linux_mem32_min) 335 setup_reserve32(); 336 else 337 { 338 printf("\nFailed to access 32bit shared memory region. Most likely the Kernel\n" 339 "has not been configured for 32bit shared memory access. Check the\n" 340 "kernel configuration.\n" 341 "Aborting...\n\n"); 342 exit(-1); 343 } 344 } 345 346 setup_cvmx_shared(); |
347 cvmx_bootmem_init(cvmx_sysinfo_get()->phy_mem_desc_ptr); | 347 cvmx_bootmem_init(cvmx_sysinfo_get()->phy_mem_desc_addr); |
348 349 /* Check to make sure the Chip version matches the configured version */ 350 octeon_model_version_check(cvmx_get_proc_id()); 351 352 /* Get the list of logical cpus we should run on */ 353 if (sched_getaffinity(0, sizeof(cpumask), (cpu_set_t*)&cpumask)) 354 { 355 perror("sched_getaffinity failed"); 356 exit(errno); 357 } 358 359 cvmx_sysinfo_t *system_info = cvmx_sysinfo_get(); 360 361 cvmx_atomic_set32(&pending_fork, 1); | 348 349 /* Check to make sure the Chip version matches the configured version */ 350 octeon_model_version_check(cvmx_get_proc_id()); 351 352 /* Get the list of logical cpus we should run on */ 353 if (sched_getaffinity(0, sizeof(cpumask), (cpu_set_t*)&cpumask)) 354 { 355 perror("sched_getaffinity failed"); 356 exit(errno); 357 } 358 359 cvmx_sysinfo_t *system_info = cvmx_sysinfo_get(); 360 361 cvmx_atomic_set32(&pending_fork, 1); |
362 for (cpu=0; cpu<16; cpu++) | 362 363 /* Get the lowest logical cpu */ 364 firstcore = ffsl(cpumask) - 1; 365 cpumask ^= (1<<(firstcore)); 366 while (1) |
363 { | 367 { |
364 if (cpumask & (1<<cpu)) | 368 if (cpumask == 0) |
365 { | 369 { |
366 /* Turn off the bit for this CPU number. We've counted him */ 367 cpumask ^= (1<<cpu); 368 /* If this is the last CPU to run on, use this process instead of forking another one */ 369 if (cpumask == 0) 370 { 371 lastcpu = 1; 372 break; 373 } 374 /* Increment the number of CPUs running this app */ 375 cvmx_atomic_add32(&pending_fork, 1); 376 /* Flush all IO streams before the fork. Otherwise any buffered 377 data in the C library will be duplicated. This results in 378 duplicate output from a single print */ 379 fflush(NULL); 380 /* Fork a process for the new CPU */ 381 int pid = fork(); 382 if (pid == 0) 383 { 384 break; 385 } 386 else if (pid == -1) 387 { 388 perror("Fork failed"); 389 exit(errno); 390 } | 370 cpu = firstcore; 371 firstcpu = 1; 372 break; |
391 } | 373 } |
392 } | 374 cpu = ffsl(cpumask) - 1; 375 /* Turn off the bit for this CPU number. We've counted him */ 376 cpumask ^= (1<<cpu); 377 /* Increment the number of CPUs running this app */ 378 cvmx_atomic_add32(&pending_fork, 1); 379 /* Flush all IO streams before the fork. Otherwise any buffered 380 data in the C library will be duplicated. This results in 381 duplicate output from a single print */ 382 fflush(NULL); 383 /* Fork a process for the new CPU */ 384 int pid = fork(); 385 if (pid == 0) 386 { 387 break; 388 } 389 else if (pid == -1) 390 { 391 perror("Fork failed"); 392 exit(errno); 393 } 394 } |
393 | 395 |
396 |
|
394 /* Set affinity to lock me to the correct CPU */ 395 cpumask = (1<<cpu); 396 if (sched_setaffinity(0, sizeof(cpumask), (cpu_set_t*)&cpumask)) 397 { 398 perror("sched_setaffinity failed"); 399 exit(errno); 400 } 401 402 cvmx_spinlock_lock(&mask_lock); 403 system_info->core_mask |= 1<<cvmx_get_core_num(); 404 cvmx_atomic_add32(&pending_fork, -1); 405 if (cvmx_atomic_get32(&pending_fork) == 0) 406 cvmx_dprintf("Active coremask = 0x%x\n", system_info->core_mask); | 397 /* Set affinity to lock me to the correct CPU */ 398 cpumask = (1<<cpu); 399 if (sched_setaffinity(0, sizeof(cpumask), (cpu_set_t*)&cpumask)) 400 { 401 perror("sched_setaffinity failed"); 402 exit(errno); 403 } 404 405 cvmx_spinlock_lock(&mask_lock); 406 system_info->core_mask |= 1<<cvmx_get_core_num(); 407 cvmx_atomic_add32(&pending_fork, -1); 408 if (cvmx_atomic_get32(&pending_fork) == 0) 409 cvmx_dprintf("Active coremask = 0x%x\n", system_info->core_mask); |
407 if (lastcpu) | 410 if (firstcpu) |
408 system_info->init_core = cvmx_get_core_num(); 409 cvmx_spinlock_unlock(&mask_lock); 410 411 /* Spinning waiting for forks to complete */ 412 while (cvmx_atomic_get32(&pending_fork)) {} 413 414 cvmx_coremask_barrier_sync(system_info->core_mask); 415 | 411 system_info->init_core = cvmx_get_core_num(); 412 cvmx_spinlock_unlock(&mask_lock); 413 414 /* Spinning waiting for forks to complete */ 415 while (cvmx_atomic_get32(&pending_fork)) {} 416 417 cvmx_coremask_barrier_sync(system_info->core_mask); 418 |
416 int ret = sysmips(MIPS_CAVIUM_XKPHYS_WRITE, getpid(), 3, 0); 417 if (ret != 0) { 418 int32_t w = cvmx_atomic_fetch_and_add32(&warn_count, 1); 419 if (!w) { 420 switch(errno) { 421 case EINVAL: 422 perror("sysmips(MIPS_CAVIUM_XKPHYS_WRITE) failed.\n" 423 " Did you configure your kernel with both:\n" 424 " CONFIG_CAVIUM_OCTEON_USER_MEM_PER_PROCESS *and*\n" 425 " CONFIG_CAVIUM_OCTEON_USER_IO_PER_PROCESS?"); 426 break; 427 case EPERM: 428 perror("sysmips(MIPS_CAVIUM_XKPHYS_WRITE) failed.\n" 429 " Are you running as root?"); 430 break; 431 default: 432 perror("sysmips(MIPS_CAVIUM_XKPHYS_WRITE) failed"); 433 break; 434 } 435 } 436 } | 419 cvmx_linux_enable_xkphys_access(1); |
437 438 int result = appmain(argc, argv); 439 440 /* Wait for all forks to complete. This needs to be the core that started 441 all of the forks. It may not be the lowest numbered core! */ 442 if (cvmx_get_core_num() == system_info->init_core) 443 { 444 int num_waits; --- 13 unchanged lines hidden --- | 420 421 int result = appmain(argc, argv); 422 423 /* Wait for all forks to complete. This needs to be the core that started 424 all of the forks. It may not be the lowest numbered core! */ 425 if (cvmx_get_core_num() == system_info->init_core) 426 { 427 int num_waits; --- 13 unchanged lines hidden --- |