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