cvmx-app-init.c revision 210286
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
62int cvmx_debug_uart;
63
64/**
65 * @file
66 *
67 * Main entry point for all simple executive based programs.
68 */
69
70
71extern 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 */
84EXTERN_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 */
99static 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 */
193static 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 */
229static 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
276static 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
295int octeon_model_version_check(uint32_t chip_id);
296
297#define OMS xstr(OCTEON_MODEL)
298char 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
305void __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
451int 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
580void __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
617