Deleted Added
full compact
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 ---