]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/octeon-sdk/cvmx-app-init.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / octeon-sdk / cvmx-app-init.c
1 /***********************license start***************
2  * Copyright (c) 2003-2010  Cavium Networks (support@cavium.com). All rights
3  * reserved.
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:
9  *
10  *   * Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
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  * 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.
38  ***********************license end**************************************/
39
40
41
42
43
44
45
46 #include <stdio.h>
47 #include <stdint.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include "cvmx-config.h"
51 #include "cvmx.h"
52 #include "cvmx-spinlock.h"
53 #include <octeon-app-init.h>
54 #include "cvmx-sysinfo.h"
55 #include "cvmx-bootmem.h"
56 #include "cvmx-uart.h"
57 #include "cvmx-coremask.h"
58 #include "cvmx-core.h"
59 #include "cvmx-interrupt.h"
60 #include "cvmx-ebt3000.h"
61 #include "cvmx-sim-magic.h"
62 #include "cvmx-debug.h"
63 #include "../../bootloader/u-boot/include/octeon_mem_map.h"
64
65 int cvmx_debug_uart = -1;
66
67 /**
68  * @file
69  *
70  * Main entry point for all simple executive based programs.
71  */
72
73
74 extern void cvmx_interrupt_initialize(void);
75
76
77
78 /**
79  * Main entry point for all simple executive based programs.
80  * This is the first C function called. It completes
81  * initialization, calls main, and performs C level cleanup.
82  *
83  * @param app_desc_addr
84  *               Address of the application description structure passed
85  *               brom the boot loader.
86  */
87 EXTERN_ASM void __cvmx_app_init(uint64_t app_desc_addr);
88
89
90 /**
91  * Set up sysinfo structure from boot descriptor versions 6 and higher.
92  * In these versions, the interesting data in not in the boot info structure
93  * defined by the toolchain, but is in the cvmx_bootinfo structure defined in
94  * the simple exec.
95  *
96  * @param app_desc_ptr
97  *               pointer to boot descriptor block
98  *
99  * @param sys_info_ptr
100  *               pointer to sysinfo structure to fill in
101  */
102 static void process_boot_desc_ver_6(octeon_boot_descriptor_t *app_desc_ptr, cvmx_sysinfo_t *sys_info_ptr)
103 {
104     cvmx_bootinfo_t *cvmx_bootinfo_ptr = CASTPTR(cvmx_bootinfo_t, app_desc_ptr->cvmx_desc_vaddr);
105
106     /* copy application information for simple exec use */
107     /* Populate the sys_info structure from the boot descriptor block created by the bootloader.
108     ** The boot descriptor block is put in the top of the heap, so it will be overwritten when the
109     ** heap is fully used.  Information that is to be used must be copied before that.
110     ** Applications should only use the sys_info structure, not the boot descriptor
111     */
112     if (cvmx_bootinfo_ptr->major_version == 1)
113     {
114         sys_info_ptr->core_mask = cvmx_bootinfo_ptr->core_mask;
115         sys_info_ptr->heap_base = cvmx_bootinfo_ptr->heap_base;
116         sys_info_ptr->heap_size = cvmx_bootinfo_ptr->heap_end - cvmx_bootinfo_ptr->heap_base;
117         sys_info_ptr->stack_top = cvmx_bootinfo_ptr->stack_top;
118         sys_info_ptr->stack_size = cvmx_bootinfo_ptr->stack_size;
119         sys_info_ptr->init_core = cvmx_get_core_num();
120         sys_info_ptr->phy_mem_desc_addr = cvmx_bootinfo_ptr->phy_mem_desc_addr;
121         sys_info_ptr->exception_base_addr = cvmx_bootinfo_ptr->exception_base_addr;
122         sys_info_ptr->cpu_clock_hz  = cvmx_bootinfo_ptr->eclock_hz;
123         sys_info_ptr->dram_data_rate_hz  = cvmx_bootinfo_ptr->dclock_hz * 2;
124
125         sys_info_ptr->board_type = cvmx_bootinfo_ptr->board_type;
126         sys_info_ptr->board_rev_major = cvmx_bootinfo_ptr->board_rev_major;
127         sys_info_ptr->board_rev_minor = cvmx_bootinfo_ptr->board_rev_minor;
128         memcpy(sys_info_ptr->mac_addr_base, cvmx_bootinfo_ptr->mac_addr_base, 6);
129         sys_info_ptr->mac_addr_count = cvmx_bootinfo_ptr->mac_addr_count;
130         memcpy(sys_info_ptr->board_serial_number, cvmx_bootinfo_ptr->board_serial_number, CVMX_BOOTINFO_OCTEON_SERIAL_LEN);
131         sys_info_ptr->console_uart_num = 0;
132         if (cvmx_bootinfo_ptr->flags & OCTEON_BL_FLAG_CONSOLE_UART1)
133             sys_info_ptr->console_uart_num = 1;
134
135         if (cvmx_bootinfo_ptr->dram_size > 32*1024*1024)
136             sys_info_ptr->system_dram_size = (uint64_t)cvmx_bootinfo_ptr->dram_size;  /* older bootloaders incorrectly gave this in bytes, so don't convert */
137         else
138             sys_info_ptr->system_dram_size = (uint64_t)cvmx_bootinfo_ptr->dram_size * 1024 * 1024;  /* convert from Megabytes to bytes */
139         if (cvmx_bootinfo_ptr->minor_version >= 1)
140         {
141             sys_info_ptr->compact_flash_common_base_addr = cvmx_bootinfo_ptr->compact_flash_common_base_addr;
142             sys_info_ptr->compact_flash_attribute_base_addr = cvmx_bootinfo_ptr->compact_flash_attribute_base_addr;
143             sys_info_ptr->led_display_base_addr = cvmx_bootinfo_ptr->led_display_base_addr;
144         }
145         else if (sys_info_ptr->board_type == CVMX_BOARD_TYPE_EBT3000 ||
146                  sys_info_ptr->board_type == CVMX_BOARD_TYPE_EBT5800 ||
147                  sys_info_ptr->board_type == CVMX_BOARD_TYPE_EBT5810)
148         {
149             /* Default these variables so that users of structure can be the same no
150             ** matter what version fo boot info block the bootloader passes */
151             sys_info_ptr->compact_flash_common_base_addr = 0x1d000000 + 0x800;
152             sys_info_ptr->compact_flash_attribute_base_addr = 0x1d010000;
153             if (sys_info_ptr->board_rev_major == 1)
154                 sys_info_ptr->led_display_base_addr = 0x1d020000;
155             else
156                 sys_info_ptr->led_display_base_addr = 0x1d020000 + 0xf8;
157         }
158         else
159         {
160             sys_info_ptr->compact_flash_common_base_addr = 0;
161             sys_info_ptr->compact_flash_attribute_base_addr = 0;
162             sys_info_ptr->led_display_base_addr = 0;
163         }
164
165         if (cvmx_bootinfo_ptr->minor_version >= 2)
166         {
167             sys_info_ptr->dfa_ref_clock_hz = cvmx_bootinfo_ptr->dfa_ref_clock_hz;
168             sys_info_ptr->bootloader_config_flags = cvmx_bootinfo_ptr->config_flags;
169         }
170         else
171         {
172             sys_info_ptr->dfa_ref_clock_hz = 0;
173             sys_info_ptr->bootloader_config_flags = 0;
174             if (app_desc_ptr->flags & OCTEON_BL_FLAG_DEBUG)
175                 sys_info_ptr->bootloader_config_flags |= CVMX_BOOTINFO_CFG_FLAG_DEBUG;
176             if (app_desc_ptr->flags & OCTEON_BL_FLAG_NO_MAGIC)
177                 sys_info_ptr->bootloader_config_flags |= CVMX_BOOTINFO_CFG_FLAG_NO_MAGIC;
178         }
179
180     }
181     else
182     {
183         printf("ERROR: Incompatible CVMX descriptor passed by bootloader: %d.%d\n",
184                (int)cvmx_bootinfo_ptr->major_version, (int)cvmx_bootinfo_ptr->minor_version);
185         exit(-1);
186     }
187 }
188
189
190 /**
191  * Interrupt handler for calling exit on Control-C interrupts.
192  *
193  * @param irq_number IRQ interrupt number
194  * @param registers  CPU registers at the time of the interrupt
195  * @param user_arg   Unused user argument
196  */
197 static void process_break_interrupt(int irq_number, uint64_t registers[32], void *user_arg)
198 {
199     /* Exclude new functionality when building with older toolchains */
200 #if OCTEON_APP_INIT_H_VERSION >= 3
201     int uart = irq_number - CVMX_IRQ_UART0;
202     cvmx_uart_lsr_t lsrval;
203
204     /* Check for a Control-C interrupt from the console. This loop will eat
205         all input received on the uart */
206     lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(uart));
207     while (lsrval.s.dr)
208     {
209         int c = cvmx_read_csr(CVMX_MIO_UARTX_RBR(uart));
210         if (c == '\003')
211         {
212             register uint64_t tmp;
213
214             /* Wait for an another Control-C if right now we have no
215                access to the console.  After this point we hold the
216                lock and use a different lock to synchronize between
217                the memfile dumps from different cores.  As a
218                consequence regular printfs *don't* work after this
219                point! */
220             if (__octeon_uart_trylock () == 1)
221                 return;
222
223             /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also
224                set the MCD0 to be not masked by this core so we know
225                the signal is received by someone */
226             asm volatile (
227                 "dmfc0 %0, $22\n"
228                 "ori   %0, %0, 0x1110\n"
229                 "dmtc0 %0, $22\n"
230                 : "=r" (tmp));
231         }
232         lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(uart));
233     }
234 #endif
235 }
236
237 /**
238  * This is the debug exception handler with "break".  Before calling exit to
239  * dump the profile-feedback output it releases the lock on the console.
240  * This way if there is buffered data in stdout it can still be flushed.
241  * stdio is required to flush all output during an fread.
242  */
243
244 static void exit_on_break(void)
245 {
246 #if OCTEON_APP_INIT_H_VERSION >= 4
247     unsigned int coremask = cvmx_sysinfo_get()->core_mask;
248
249     cvmx_coremask_barrier_sync(coremask);
250     if (cvmx_coremask_first_core(coremask))
251       __octeon_uart_unlock();
252 #endif
253
254     exit(0);
255 }
256
257 /* Add string signature to applications so that we can easily tell what
258 ** Octeon revision they were compiled for. Don't make static to avoid unused
259 ** variable warning. */
260 #define xstr(s) str(s)
261 #define str(s) #s
262
263 int octeon_model_version_check(uint32_t chip_id);
264
265 #define OMS xstr(OCTEON_MODEL)
266 char octeon_rev_signature[] =
267 #ifdef USE_RUNTIME_MODEL_CHECKS
268     "Compiled for runtime Octeon model checking";
269 #else
270     "Compiled for Octeon processor id: "OMS;
271 #endif
272
273 void __cvmx_app_init(uint64_t app_desc_addr)
274 {
275     /* App descriptor used by bootloader */
276     octeon_boot_descriptor_t *app_desc_ptr = CASTPTR(octeon_boot_descriptor_t, app_desc_addr);
277
278     /* app info structure used by the simple exec */
279     cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
280     int breakflag = 0;
281
282     if (cvmx_coremask_first_core(app_desc_ptr->core_mask))
283     {
284         /* do once per application setup  */
285         if (app_desc_ptr->desc_version < 6)
286         {
287             printf("Obsolete bootloader, can't run application\n");
288             exit(-1);
289         }
290         else
291         {
292             /* Handle all newer versions here.... */
293             if (app_desc_ptr->desc_version > 7)
294             {
295                 printf("Warning: newer boot descripter version than expected\n");
296             }
297             process_boot_desc_ver_6(app_desc_ptr,sys_info_ptr);
298
299         }
300     }
301     cvmx_coremask_barrier_sync(app_desc_ptr->core_mask);
302
303     breakflag = sys_info_ptr->bootloader_config_flags & CVMX_BOOTINFO_CFG_FLAG_BREAK;
304
305     /* No need to initialize bootmem, interrupts, interrupt handler and error handler
306        if version does not match. */
307     if (cvmx_coremask_first_core(sys_info_ptr->core_mask))
308     {
309         /* Check to make sure the Chip version matches the configured version */
310         uint32_t chip_id = cvmx_get_proc_id();
311         /* Make sure we can properly run on this chip */
312         octeon_model_version_check(chip_id);
313     }
314
315     cvmx_interrupt_initialize();
316
317     if (cvmx_coremask_first_core(sys_info_ptr->core_mask))
318     {
319         int break_uart = 0;
320         unsigned int i;
321
322         /* Intialize the bootmem allocator with the descriptor that was provided by
323          * the bootloader
324          * IMPORTANT:  All printfs must happen after this since PCI console uses named
325          * blocks.
326          */
327         cvmx_bootmem_init(sys_info_ptr->phy_mem_desc_addr);
328         if (breakflag && cvmx_debug_booted())
329         {
330             printf("ERROR: Using debug and break together in not supported.\n");
331             while (1)
332                 ;
333         }
334
335         /* Search through the arguments for a break=X or a debug=X. */
336         for (i = 0; i < app_desc_ptr->argc; i++)
337         {
338             const char *argv = CASTPTR(const char, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, app_desc_ptr->argv[i]));
339             if (strncmp(argv, "break=", 6) == 0)
340                 break_uart = atoi(argv + 6);
341             else if (strncmp(argv, "debug=", 6) == 0)
342                 cvmx_debug_uart = atoi(argv + 6);
343         }
344
345         if (breakflag)
346         {
347             int32_t *trampoline = CASTPTR(int32_t, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, BOOTLOADER_DEBUG_TRAMPOLINE));
348             /* On debug exception, call exit_on_break from all cores. */
349             *trampoline = (int32_t)(long)&exit_on_break;
350             cvmx_uart_enable_intr(break_uart, process_break_interrupt);
351         }
352     }
353
354     cvmx_coremask_barrier_sync(app_desc_ptr->core_mask);
355
356     /* Clear BEV now that we have installed exception handlers. */
357     uint64_t tmp;
358     asm volatile (
359                "   .set push                  \n"
360                "   .set mips64                  \n"
361                "   .set noreorder               \n"
362                "   .set noat               \n"
363                "   mfc0 %[tmp], $12, 0          \n"
364                "   li   $at, 1 << 22            \n"
365                "   not  $at, $at                \n"
366                "   and  %[tmp], $at             \n"
367                "   mtc0 %[tmp], $12, 0          \n"
368                "   .set pop                  \n"
369                   : [tmp] "=&r" (tmp) : );
370
371     /* Set all cores to stop on MCD0 signals */
372     asm volatile(
373         "dmfc0 %0, $22, 0\n"
374         "or %0, %0, 0x1100\n"
375         "dmtc0 %0, $22, 0\n" : "=r" (tmp));
376
377     CVMX_SYNC;
378
379     /* Now intialize the debug exception handler as BEV is cleared. */
380     if (!breakflag)
381         cvmx_debug_init();
382
383     /* Synchronise all cores at this point */
384     cvmx_coremask_barrier_sync(app_desc_ptr->core_mask);
385
386 }
387
388 int cvmx_user_app_init(void)
389 {
390     uint64_t bist_val;
391     uint64_t mask;
392     int bist_errors = 0;
393     uint64_t tmp;
394     uint64_t base_addr;
395
396
397     /* Put message on LED display */
398     if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)
399       ebt3000_str_write("CVMX    ");
400
401     /* Check BIST results for COP0 registers, some values only meaningful in pass 2 */
402     CVMX_MF_CACHE_ERR(bist_val);
403     mask = (1ULL<<32) | (1ULL<<33) | (1ULL<<34) | (1ULL<<35) | (1ULL<<36);
404     bist_val &= mask;
405     if (bist_val)
406     {
407         printf("BIST FAILURE: COP0_CACHE_ERR: 0x%llx\n", (unsigned long long)bist_val);
408         bist_errors++;
409     }
410
411     mask = 0xfc00000000000000ull;
412     CVMX_MF_CVM_MEM_CTL(bist_val);
413     bist_val &=  mask;
414     if (bist_val)
415     {
416         printf("BIST FAILURE: COP0_CVM_MEM_CTL: 0x%llx\n", (unsigned long long)bist_val);
417         bist_errors++;
418     }
419
420     /* Set up 4 cache lines of local memory, make available from Kernel space */
421     CVMX_MF_CVM_MEM_CTL(tmp);
422     tmp &= ~0x1ffull;
423     tmp |= 0x104ull;
424     /* Set WBTHRESH=4 as per Core-14752 errata in cn63xxp1.X. */
425     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
426     {
427         tmp &= ~(0xfull << 11);
428         tmp |= 4 << 11;
429     }
430     CVMX_MT_CVM_MEM_CTL(tmp);
431
432
433 #if CVMX_USE_1_TO_1_TLB_MAPPINGS
434
435     /* Check to see if the bootloader is indicating that the application is outside
436     ** of the 0x10000000 0x20000000 range, in which case we can't use 1-1 mappings */
437     if (cvmx_sysinfo_get()->bootloader_config_flags & CVMX_BOOTINFO_CFG_FLAG_OVERSIZE_TLB_MAPPING)
438     {
439         printf("ERROR: 1-1 TLB mappings configured and oversize application loaded.\n");
440         printf("ERROR: Either 1-1 TLB mappings must be disabled or application size reduced.\n");
441         exit(-1);
442     }
443
444     /* Create 1-1 Mappings for all DRAM up to 8 gigs, excluding the low 1 Megabyte.  This area
445     ** is reserved for the bootloader and exception vectors.  By not mapping this area, NULL pointer
446     ** dereferences will be caught with TLB exceptions.  Exception handlers should be written
447     ** using XKPHYS or KSEG0 addresses. */
448 #if CVMX_NULL_POINTER_PROTECT
449     /* Exclude low 1 MByte from mapping to detect NULL pointer accesses.
450     ** The only down side of this is it uses more TLB mappings */
451     cvmx_core_add_fixed_tlb_mapping_bits(0x0, 0x0, 0x100000  | TLB_DIRTY | TLB_VALID | TLB_GLOBAL, CVMX_TLB_PAGEMASK_1M);
452     cvmx_core_add_fixed_tlb_mapping(0x200000, 0x200000, 0x300000, CVMX_TLB_PAGEMASK_1M);
453     cvmx_core_add_fixed_tlb_mapping(0x400000, 0x400000, 0x500000, CVMX_TLB_PAGEMASK_1M);
454     cvmx_core_add_fixed_tlb_mapping(0x600000, 0x600000, 0x700000, CVMX_TLB_PAGEMASK_1M);
455
456     cvmx_core_add_fixed_tlb_mapping(0x800000,  0x800000,  0xC00000, CVMX_TLB_PAGEMASK_4M);
457     cvmx_core_add_fixed_tlb_mapping(0x1000000, 0x1000000, 0x1400000, CVMX_TLB_PAGEMASK_4M);
458     cvmx_core_add_fixed_tlb_mapping(0x1800000, 0x1800000, 0x1c00000, CVMX_TLB_PAGEMASK_4M);
459
460     cvmx_core_add_fixed_tlb_mapping(0x2000000, 0x2000000, 0x3000000, CVMX_TLB_PAGEMASK_16M);
461     cvmx_core_add_fixed_tlb_mapping(0x4000000, 0x4000000, 0x5000000, CVMX_TLB_PAGEMASK_16M);
462     cvmx_core_add_fixed_tlb_mapping(0x6000000, 0x6000000, 0x7000000, CVMX_TLB_PAGEMASK_16M);
463 #else
464     /* Map entire low 128 Megs, including 0x0 */
465     cvmx_core_add_fixed_tlb_mapping(0x0, 0x0, 0x4000000ULL, CVMX_TLB_PAGEMASK_64M);
466 #endif
467     cvmx_core_add_fixed_tlb_mapping(0x8000000ULL, 0x8000000ULL, 0xc000000ULL, CVMX_TLB_PAGEMASK_64M);
468
469     if (OCTEON_IS_MODEL(OCTEON_CN6XXX))
470     {
471         for (base_addr = 0x20000000ULL; base_addr < (cvmx_sysinfo_get()->system_dram_size + 0x10000000ULL); base_addr += 0x20000000ULL)
472         {
473             if (0 > cvmx_core_add_fixed_tlb_mapping(base_addr,  base_addr,  base_addr + 0x10000000ULL, CVMX_TLB_PAGEMASK_256M))
474             {
475                 printf("ERROR adding 1-1 TLB mapping for address 0x%llx\n", (unsigned long long)base_addr);
476                 /* Exit from here, as expected memory mappings aren't set
477                    up if this fails */
478                 exit(-1);
479             }
480         }
481     }
482     else
483     {
484         /* Create 1-1 mapping for next 256 megs
485         ** bottom page is not valid */
486         cvmx_core_add_fixed_tlb_mapping_bits(0x400000000ULL, 0, 0x410000000ULL  | TLB_DIRTY | TLB_VALID | TLB_GLOBAL, CVMX_TLB_PAGEMASK_256M);
487
488         /* Map from 0.5 up to the installed memory size in 512 MByte chunks.  If this loop runs out of memory,
489         ** the NULL pointer detection can be disabled to free up more TLB entries. */
490         if (cvmx_sysinfo_get()->system_dram_size > 0x20000000ULL)
491         {
492             for (base_addr = 0x20000000ULL; base_addr <= (cvmx_sysinfo_get()->system_dram_size - 0x20000000ULL); base_addr += 0x20000000ULL)
493             {
494                 if (0 > cvmx_core_add_fixed_tlb_mapping(base_addr,  base_addr,  base_addr + 0x10000000ULL, CVMX_TLB_PAGEMASK_256M))
495                 {
496                     printf("ERROR adding 1-1 TLB mapping for address 0x%llx\n", (unsigned long long)base_addr);
497                     /* Exit from here, as expected memory mappings
498                        aren't set up if this fails */
499                     exit(-1);
500                 }
501             }
502         }
503     }
504 #endif
505
506
507     cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
508     cvmx_bootmem_init(sys_info_ptr->phy_mem_desc_addr);
509
510     return(0);
511 }
512
513 void __cvmx_app_exit(void)
514 {
515     cvmx_debug_finish();
516
517     if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
518     {
519         CVMX_BREAK;
520     }
521     /* Hang forever, until more appropriate stand alone simple executive
522        exit() is implemented */
523
524     while (1);
525 }
526
527
528