cvmx-app-init.c revision 232812
1289848Sjkim/***********************license start***************
2289848Sjkim * Copyright (c) 2003-2010  Cavium Inc. (support@cavium.com). All rights
3289848Sjkim * reserved.
4289848Sjkim *
5289848Sjkim *
6289848Sjkim * Redistribution and use in source and binary forms, with or without
7289848Sjkim * modification, are permitted provided that the following conditions are
8289848Sjkim * met:
9289848Sjkim *
10289848Sjkim *   * Redistributions of source code must retain the above copyright
11289848Sjkim *     notice, this list of conditions and the following disclaimer.
12289848Sjkim *
13289848Sjkim *   * Redistributions in binary form must reproduce the above
14289848Sjkim *     copyright notice, this list of conditions and the following
15289848Sjkim *     disclaimer in the documentation and/or other materials provided
16289848Sjkim *     with the distribution.
17289848Sjkim
18289848Sjkim *   * Neither the name of Cavium Inc. nor the names of
19289848Sjkim *     its contributors may be used to endorse or promote products
20289848Sjkim *     derived from this software without specific prior written
21289848Sjkim *     permission.
22289848Sjkim
23289848Sjkim * This Software, including technical data, may be subject to U.S. export  control
24289848Sjkim * laws, including the U.S. Export Administration Act and its  associated
25289848Sjkim * regulations, and may be subject to export or import  regulations in other
26289848Sjkim * countries.
27289848Sjkim
28289848Sjkim * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29289848Sjkim * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30289848Sjkim * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31289848Sjkim * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32289848Sjkim * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33289848Sjkim * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34289848Sjkim * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35289848Sjkim * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36289848Sjkim * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
37289848Sjkim * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38289848Sjkim ***********************license end**************************************/
39289848Sjkim
40289848Sjkim
41289848Sjkim
42289848Sjkim
43289848Sjkim
44289848Sjkim
45289848Sjkim
46289848Sjkim#include <stdio.h>
47289848Sjkim#include <stdint.h>
48289848Sjkim#include <stdlib.h>
49289848Sjkim#include <string.h>
50289848Sjkim#include "executive-config.h"
51289848Sjkim#include "cvmx-config.h"
52289848Sjkim#include "cvmx.h"
53289848Sjkim#include "cvmx-spinlock.h"
54289848Sjkim#include <octeon-app-init.h>
55289848Sjkim#include "cvmx-sysinfo.h"
56289848Sjkim#include "cvmx-bootmem.h"
57289848Sjkim#include "cvmx-uart.h"
58289848Sjkim#include "cvmx-coremask.h"
59289848Sjkim#include "cvmx-core.h"
60289848Sjkim#include "cvmx-interrupt.h"
61289848Sjkim#include "cvmx-ebt3000.h"
62289848Sjkim#include "cvmx-sim-magic.h"
63289848Sjkim#include "cvmx-debug.h"
64289848Sjkim#include "cvmx-qlm.h"
65289848Sjkim#include "cvmx-scratch.h"
66289848Sjkim#include "cvmx-helper-cfg.h"
67289848Sjkim#include "cvmx-helper-jtag.h"
68289848Sjkim#include <octeon_mem_map.h>
69#include "libfdt.h"
70int cvmx_debug_uart = -1;
71
72/**
73 * @file
74 *
75 * Main entry point for all simple executive based programs.
76 */
77
78
79extern void cvmx_interrupt_initialize(void);
80
81
82
83/**
84 * Main entry point for all simple executive based programs.
85 * This is the first C function called. It completes
86 * initialization, calls main, and performs C level cleanup.
87 *
88 * @param app_desc_addr
89 *               Address of the application description structure passed
90 *               brom the boot loader.
91 */
92EXTERN_ASM void __cvmx_app_init(uint64_t app_desc_addr);
93
94
95/**
96 * Set up sysinfo structure from boot descriptor versions 6 and higher.
97 * In these versions, the interesting data in not in the boot info structure
98 * defined by the toolchain, but is in the cvmx_bootinfo structure defined in
99 * the simple exec.
100 *
101 * @param app_desc_ptr
102 *               pointer to boot descriptor block
103 *
104 * @param sys_info_ptr
105 *               pointer to sysinfo structure to fill in
106 */
107static void process_boot_desc_ver_6(octeon_boot_descriptor_t *app_desc_ptr, cvmx_sysinfo_t *sys_info_ptr)
108{
109    cvmx_bootinfo_t *cvmx_bootinfo_ptr = CASTPTR(cvmx_bootinfo_t, app_desc_ptr->cvmx_desc_vaddr);
110
111    /* copy application information for simple exec use */
112    /* Populate the sys_info structure from the boot descriptor block created by the bootloader.
113    ** The boot descriptor block is put in the top of the heap, so it will be overwritten when the
114    ** heap is fully used.  Information that is to be used must be copied before that.
115    ** Applications should only use the sys_info structure, not the boot descriptor
116    */
117    if (cvmx_bootinfo_ptr->major_version == 1)
118    {
119        sys_info_ptr->core_mask = cvmx_bootinfo_ptr->core_mask;
120        sys_info_ptr->heap_base = cvmx_bootinfo_ptr->heap_base;
121        sys_info_ptr->heap_size = cvmx_bootinfo_ptr->heap_end - cvmx_bootinfo_ptr->heap_base;
122        sys_info_ptr->stack_top = cvmx_bootinfo_ptr->stack_top;
123        sys_info_ptr->stack_size = cvmx_bootinfo_ptr->stack_size;
124        sys_info_ptr->init_core = cvmx_get_core_num();
125        sys_info_ptr->phy_mem_desc_addr = cvmx_bootinfo_ptr->phy_mem_desc_addr;
126        sys_info_ptr->exception_base_addr = cvmx_bootinfo_ptr->exception_base_addr;
127        sys_info_ptr->cpu_clock_hz  = cvmx_bootinfo_ptr->eclock_hz;
128        sys_info_ptr->dram_data_rate_hz  = cvmx_bootinfo_ptr->dclock_hz * 2;
129
130        sys_info_ptr->board_type = cvmx_bootinfo_ptr->board_type;
131        sys_info_ptr->board_rev_major = cvmx_bootinfo_ptr->board_rev_major;
132        sys_info_ptr->board_rev_minor = cvmx_bootinfo_ptr->board_rev_minor;
133        memcpy(sys_info_ptr->mac_addr_base, cvmx_bootinfo_ptr->mac_addr_base, 6);
134        sys_info_ptr->mac_addr_count = cvmx_bootinfo_ptr->mac_addr_count;
135        memcpy(sys_info_ptr->board_serial_number, cvmx_bootinfo_ptr->board_serial_number, CVMX_BOOTINFO_OCTEON_SERIAL_LEN);
136        sys_info_ptr->console_uart_num = 0;
137        if (cvmx_bootinfo_ptr->flags & OCTEON_BL_FLAG_CONSOLE_UART1)
138            sys_info_ptr->console_uart_num = 1;
139
140        if (cvmx_bootinfo_ptr->dram_size > 32*1024*1024)
141            sys_info_ptr->system_dram_size = (uint64_t)cvmx_bootinfo_ptr->dram_size;  /* older bootloaders incorrectly gave this in bytes, so don't convert */
142        else
143            sys_info_ptr->system_dram_size = (uint64_t)cvmx_bootinfo_ptr->dram_size * 1024 * 1024;  /* convert from Megabytes to bytes */
144        if (cvmx_bootinfo_ptr->minor_version >= 1)
145        {
146            sys_info_ptr->compact_flash_common_base_addr = cvmx_bootinfo_ptr->compact_flash_common_base_addr;
147            sys_info_ptr->compact_flash_attribute_base_addr = cvmx_bootinfo_ptr->compact_flash_attribute_base_addr;
148            sys_info_ptr->led_display_base_addr = cvmx_bootinfo_ptr->led_display_base_addr;
149        }
150        else if (sys_info_ptr->board_type == CVMX_BOARD_TYPE_EBT3000 ||
151                 sys_info_ptr->board_type == CVMX_BOARD_TYPE_EBT5800 ||
152                 sys_info_ptr->board_type == CVMX_BOARD_TYPE_EBT5810)
153        {
154            /* Default these variables so that users of structure can be the same no
155            ** matter what version fo boot info block the bootloader passes */
156            sys_info_ptr->compact_flash_common_base_addr = 0x1d000000 + 0x800;
157            sys_info_ptr->compact_flash_attribute_base_addr = 0x1d010000;
158            if (sys_info_ptr->board_rev_major == 1)
159                sys_info_ptr->led_display_base_addr = 0x1d020000;
160            else
161                sys_info_ptr->led_display_base_addr = 0x1d020000 + 0xf8;
162        }
163        else
164        {
165            sys_info_ptr->compact_flash_common_base_addr = 0;
166            sys_info_ptr->compact_flash_attribute_base_addr = 0;
167            sys_info_ptr->led_display_base_addr = 0;
168        }
169
170        if (cvmx_bootinfo_ptr->minor_version >= 2)
171        {
172            sys_info_ptr->dfa_ref_clock_hz = cvmx_bootinfo_ptr->dfa_ref_clock_hz;
173            sys_info_ptr->bootloader_config_flags = cvmx_bootinfo_ptr->config_flags;
174        }
175        else
176        {
177            sys_info_ptr->dfa_ref_clock_hz = 0;
178            sys_info_ptr->bootloader_config_flags = 0;
179            if (app_desc_ptr->flags & OCTEON_BL_FLAG_DEBUG)
180                sys_info_ptr->bootloader_config_flags |= CVMX_BOOTINFO_CFG_FLAG_DEBUG;
181            if (app_desc_ptr->flags & OCTEON_BL_FLAG_NO_MAGIC)
182                sys_info_ptr->bootloader_config_flags |= CVMX_BOOTINFO_CFG_FLAG_NO_MAGIC;
183        }
184
185    }
186    else
187    {
188        printf("ERROR: Incompatible CVMX descriptor passed by bootloader: %d.%d\n",
189               (int)cvmx_bootinfo_ptr->major_version, (int)cvmx_bootinfo_ptr->minor_version);
190        exit(-1);
191    }
192    if ((cvmx_bootinfo_ptr->minor_version >= 3) && (cvmx_bootinfo_ptr->fdt_addr != 0))
193    {
194        sys_info_ptr->fdt_addr = UNMAPPED_PTR(cvmx_bootinfo_ptr->fdt_addr);
195        if (fdt_check_header((const void *)sys_info_ptr->fdt_addr))
196        {
197            printf("ERROR : Corrupt Device Tree.\n");
198            exit(-1);
199        }
200        printf("Using device tree\n");
201    }
202    else
203    {
204        sys_info_ptr->fdt_addr = 0;
205    }
206}
207
208
209/**
210 * Interrupt handler for calling exit on Control-C interrupts.
211 *
212 * @param irq_number IRQ interrupt number
213 * @param registers  CPU registers at the time of the interrupt
214 * @param user_arg   Unused user argument
215 */
216static void process_break_interrupt(int irq_number, uint64_t registers[32], void *user_arg)
217{
218    /* Exclude new functionality when building with older toolchains */
219#if OCTEON_APP_INIT_H_VERSION >= 3
220    int uart = irq_number - CVMX_IRQ_UART0;
221    cvmx_uart_lsr_t lsrval;
222
223    /* Check for a Control-C interrupt from the console. This loop will eat
224        all input received on the uart */
225    lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(uart));
226    while (lsrval.s.dr)
227    {
228        int c = cvmx_read_csr(CVMX_MIO_UARTX_RBR(uart));
229        if (c == '\003')
230        {
231            register uint64_t tmp;
232
233            /* Wait for an another Control-C if right now we have no
234               access to the console.  After this point we hold the
235               lock and use a different lock to synchronize between
236               the memfile dumps from different cores.  As a
237               consequence regular printfs *don't* work after this
238               point! */
239            if (__octeon_uart_trylock () == 1)
240                return;
241
242            /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also
243               set the MCD0 to be not masked by this core so we know
244               the signal is received by someone */
245            asm volatile (
246                "dmfc0 %0, $22\n"
247                "ori   %0, %0, 0x1110\n"
248                "dmtc0 %0, $22\n"
249                : "=r" (tmp));
250        }
251        lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(uart));
252    }
253#endif
254}
255
256/**
257 * This is the debug exception handler with "break".  Before calling exit to
258 * dump the profile-feedback output it releases the lock on the console.
259 * This way if there is buffered data in stdout it can still be flushed.
260 * stdio is required to flush all output during an fread.
261 */
262
263static void exit_on_break(void)
264{
265#if OCTEON_APP_INIT_H_VERSION >= 4
266    unsigned int coremask = cvmx_sysinfo_get()->core_mask;
267
268    cvmx_coremask_barrier_sync(coremask);
269    if (cvmx_coremask_first_core(coremask))
270      __octeon_uart_unlock();
271#endif
272
273    exit(0);
274}
275
276/* Add string signature to applications so that we can easily tell what
277** Octeon revision they were compiled for. Don't make static to avoid unused
278** variable warning. */
279#define xstr(s) str(s)
280#define str(s) #s
281
282int octeon_model_version_check(uint32_t chip_id);
283
284#define OMS xstr(OCTEON_MODEL)
285char octeon_rev_signature[] =
286#ifdef USE_RUNTIME_MODEL_CHECKS
287    "Compiled for runtime Octeon model checking";
288#else
289    "Compiled for Octeon processor id: "OMS;
290#endif
291
292#define OCTEON_BL_FLAG_HPLUG_CORES (1 << 6)
293void __cvmx_app_init(uint64_t app_desc_addr)
294{
295    /* App descriptor used by bootloader */
296    octeon_boot_descriptor_t *app_desc_ptr = CASTPTR(octeon_boot_descriptor_t, app_desc_addr);
297
298    /* app info structure used by the simple exec */
299    cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
300    int breakflag = 0;
301
302    //printf("coremask=%08x flags=%08x \n", app_desc_ptr->core_mask, app_desc_ptr->flags);
303    if (cvmx_coremask_first_core(app_desc_ptr->core_mask))
304    {
305        /* Intialize the bootmem allocator with the descriptor that was provided by
306        * the bootloader
307        * IMPORTANT:  All printfs must happen after this since PCI console uses named
308        * blocks.
309        */
310        cvmx_bootmem_init(CASTPTR(cvmx_bootinfo_t, app_desc_ptr->cvmx_desc_vaddr)->phy_mem_desc_addr);
311
312        /* do once per application setup  */
313        if (app_desc_ptr->desc_version < 6)
314        {
315            printf("Obsolete bootloader, can't run application\n");
316            exit(-1);
317        }
318        else
319        {
320            /* Handle all newer versions here.... */
321            if (app_desc_ptr->desc_version > 7)
322            {
323                printf("Warning: newer boot descripter version than expected\n");
324            }
325            process_boot_desc_ver_6(app_desc_ptr,sys_info_ptr);
326
327        }
328
329        /*
330         * set up the feature map and config.
331         */
332        octeon_feature_init();
333
334        __cvmx_helper_cfg_init();
335    }
336    /* The flags varibale get copied over at some places and tracing the origins
337       found that
338       ** In octeon_setup_boot_desc_block
339         . cvmx_bootinfo_array[core].flags is initialized and the various bits are set
340         . cvmx_bootinfo_array[core].flags gets copied to  boot_desc[core].flags
341         . Then boot_desc then get copied over to the end of the application heap and
342            boot_info_block_array[core].boot_descr_addr is set to point to the boot_desc
343            in heap.
344       ** In start_app boot_vect->boot_info_addr->boot_desc_addr is referenced and passed on
345       to octeon_setup_crt0_tlb() and this puts it into r16
346       ** In ctr0.S of the toolchain r16 is picked up and passed on as a parameter to
347       __cvmx_app_init
348
349       Note : boot_vect->boot_info_addr points to  boot_info_block_array[core] and this
350       pointer is setup in octeon_setup_boot_vector()
351    */
352
353    if (!(app_desc_ptr->flags & OCTEON_BL_FLAG_HPLUG_CORES))
354        cvmx_coremask_barrier_sync(app_desc_ptr->core_mask);
355
356
357    breakflag = sys_info_ptr->bootloader_config_flags & CVMX_BOOTINFO_CFG_FLAG_BREAK;
358
359    /* No need to initialize bootmem, interrupts, interrupt handler and error handler
360       if version does not match. */
361    if (cvmx_coremask_first_core(sys_info_ptr->core_mask))
362    {
363        /* Check to make sure the Chip version matches the configured version */
364        uint32_t chip_id = cvmx_get_proc_id();
365        /* Make sure we can properly run on this chip */
366        octeon_model_version_check(chip_id);
367    }
368    cvmx_interrupt_initialize();
369    if (cvmx_coremask_first_core(sys_info_ptr->core_mask))
370    {
371        int break_uart = 0;
372        unsigned int i;
373
374        if (breakflag && cvmx_debug_booted())
375        {
376            printf("ERROR: Using debug and break together in not supported.\n");
377            while (1)
378                ;
379        }
380
381        /* Search through the arguments for a break=X or a debug=X. */
382        for (i = 0; i < app_desc_ptr->argc; i++)
383        {
384            const char *argv = CASTPTR(const char, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, app_desc_ptr->argv[i]));
385            if (strncmp(argv, "break=", 6) == 0)
386                break_uart = atoi(argv + 6);
387            else if (strncmp(argv, "debug=", 6) == 0)
388                cvmx_debug_uart = atoi(argv + 6);
389        }
390
391        if (breakflag)
392        {
393            int32_t *trampoline = CASTPTR(int32_t, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, BOOTLOADER_DEBUG_TRAMPOLINE));
394            /* On debug exception, call exit_on_break from all cores. */
395            *trampoline = (int32_t)(long)&exit_on_break;
396            cvmx_uart_enable_intr(break_uart, process_break_interrupt);
397        }
398    }
399    if ( !(app_desc_ptr->flags & OCTEON_BL_FLAG_HPLUG_CORES))
400         cvmx_coremask_barrier_sync(app_desc_ptr->core_mask);
401
402    /* Clear BEV now that we have installed exception handlers. */
403    uint64_t tmp;
404    asm volatile (
405               "   .set push                  \n"
406               "   .set mips64                  \n"
407               "   .set noreorder               \n"
408               "   .set noat               \n"
409               "   mfc0 %[tmp], $12, 0          \n"
410               "   li   $at, 1 << 22            \n"
411               "   not  $at, $at                \n"
412               "   and  %[tmp], $at             \n"
413               "   mtc0 %[tmp], $12, 0          \n"
414               "   .set pop                  \n"
415                  : [tmp] "=&r" (tmp) : );
416
417    /* Set all cores to stop on MCD0 signals */
418    asm volatile(
419        "dmfc0 %0, $22, 0\n"
420        "or %0, %0, 0x1100\n"
421        "dmtc0 %0, $22, 0\n" : "=r" (tmp));
422
423    CVMX_SYNC;
424    /* Now intialize the debug exception handler as BEV is cleared. */
425    if ((!breakflag) && (!(app_desc_ptr->flags & OCTEON_BL_FLAG_HPLUG_CORES)))
426        cvmx_debug_init();
427
428    /* Synchronise all cores at this point */
429     if ( !(app_desc_ptr->flags & OCTEON_BL_FLAG_HPLUG_CORES))
430         cvmx_coremask_barrier_sync(app_desc_ptr->core_mask);
431
432}
433
434int cvmx_user_app_init(void)
435{
436    uint64_t bist_val;
437    uint64_t mask;
438    int bist_errors = 0;
439    uint64_t tmp;
440    uint64_t base_addr;
441
442
443    /* Put message on LED display */
444    if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)
445        ebt3000_str_write("CVMX    ");
446
447    /* Check BIST results for COP0 registers, some values only meaningful in pass 2 */
448    CVMX_MF_CACHE_ERR(bist_val);
449    mask = (0x3fULL<<32); // Icache;BHT;AES;HSH/GFM;LRU;register file
450    bist_val &= mask;
451    if (bist_val)
452    {
453        printf("BIST FAILURE: COP0_CACHE_ERR: 0x%llx\n", (unsigned long long)bist_val);
454        bist_errors++;
455    }
456
457    mask = 0xfc00000000000000ull;
458    CVMX_MF_CVM_MEM_CTL(bist_val);
459    bist_val &=  mask;
460    if (bist_val)
461    {
462        printf("BIST FAILURE: COP0_CVM_MEM_CTL: 0x%llx\n", (unsigned long long)bist_val);
463        bist_errors++;
464    }
465
466    /* Set up 4 cache lines of local memory, make available from Kernel space */
467    CVMX_MF_CVM_MEM_CTL(tmp);
468    tmp &= ~0x1ffull;
469    tmp |= 0x104ull;
470    /* Set WBTHRESH=4 as per Core-14752 errata in cn63xxp1.X. */
471    if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
472    {
473        tmp &= ~(0xfull << 11);
474        tmp |= 4 << 11;
475    }
476    CVMX_MT_CVM_MEM_CTL(tmp);
477
478    if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_X))
479    {
480        /* Clear the lines of scratch memory configured, for
481        ** 63XX pass 2 errata Core-15169. */
482        uint64_t addr;
483        unsigned  num_lines;
484        CVMX_MF_CVM_MEM_CTL(tmp);
485        num_lines = tmp & 0x3f;
486        for (addr = 0; addr < CVMX_CACHE_LINE_SIZE * num_lines; addr += 8)
487            cvmx_scratch_write64(addr, 0);
488    }
489
490#if CVMX_USE_1_TO_1_TLB_MAPPINGS
491
492    /* Check to see if the bootloader is indicating that the application is outside
493    ** of the 0x10000000 0x20000000 range, in which case we can't use 1-1 mappings */
494    if (cvmx_sysinfo_get()->bootloader_config_flags & CVMX_BOOTINFO_CFG_FLAG_OVERSIZE_TLB_MAPPING)
495    {
496        printf("ERROR: 1-1 TLB mappings configured and oversize application loaded.\n");
497        printf("ERROR: Either 1-1 TLB mappings must be disabled or application size reduced.\n");
498        exit(-1);
499    }
500
501    /* Create 1-1 Mappings for all DRAM up to 8 gigs, excluding the low 1 Megabyte.  This area
502    ** is reserved for the bootloader and exception vectors.  By not mapping this area, NULL pointer
503    ** dereferences will be caught with TLB exceptions.  Exception handlers should be written
504    ** using XKPHYS or KSEG0 addresses. */
505#if CVMX_NULL_POINTER_PROTECT
506    /* Exclude low 1 MByte from mapping to detect NULL pointer accesses.
507    ** The only down side of this is it uses more TLB mappings */
508    cvmx_core_add_fixed_tlb_mapping_bits(0x0, 0x0, 0x100000  | TLB_DIRTY | TLB_VALID | TLB_GLOBAL, CVMX_TLB_PAGEMASK_1M);
509    cvmx_core_add_fixed_tlb_mapping(0x200000, 0x200000, 0x300000, CVMX_TLB_PAGEMASK_1M);
510    cvmx_core_add_fixed_tlb_mapping(0x400000, 0x400000, 0x500000, CVMX_TLB_PAGEMASK_1M);
511    cvmx_core_add_fixed_tlb_mapping(0x600000, 0x600000, 0x700000, CVMX_TLB_PAGEMASK_1M);
512
513    cvmx_core_add_fixed_tlb_mapping(0x800000,  0x800000,  0xC00000, CVMX_TLB_PAGEMASK_4M);
514    cvmx_core_add_fixed_tlb_mapping(0x1000000, 0x1000000, 0x1400000, CVMX_TLB_PAGEMASK_4M);
515    cvmx_core_add_fixed_tlb_mapping(0x1800000, 0x1800000, 0x1c00000, CVMX_TLB_PAGEMASK_4M);
516
517    cvmx_core_add_fixed_tlb_mapping(0x2000000, 0x2000000, 0x3000000, CVMX_TLB_PAGEMASK_16M);
518    cvmx_core_add_fixed_tlb_mapping(0x4000000, 0x4000000, 0x5000000, CVMX_TLB_PAGEMASK_16M);
519    cvmx_core_add_fixed_tlb_mapping(0x6000000, 0x6000000, 0x7000000, CVMX_TLB_PAGEMASK_16M);
520#else
521    /* Map entire low 128 Megs, including 0x0 */
522    cvmx_core_add_fixed_tlb_mapping(0x0, 0x0, 0x4000000ULL, CVMX_TLB_PAGEMASK_64M);
523#endif
524    cvmx_core_add_fixed_tlb_mapping(0x8000000ULL, 0x8000000ULL, 0xc000000ULL, CVMX_TLB_PAGEMASK_64M);
525
526    if (OCTEON_IS_MODEL(OCTEON_CN6XXX))
527    {
528        for (base_addr = 0x20000000ULL; base_addr < (cvmx_sysinfo_get()->system_dram_size + 0x10000000ULL); base_addr += 0x20000000ULL)
529        {
530            if (0 > cvmx_core_add_fixed_tlb_mapping(base_addr,  base_addr,  base_addr + 0x10000000ULL, CVMX_TLB_PAGEMASK_256M))
531            {
532                printf("ERROR adding 1-1 TLB mapping for address 0x%llx\n", (unsigned long long)base_addr);
533                /* Exit from here, as expected memory mappings aren't set
534                   up if this fails */
535                exit(-1);
536            }
537        }
538    }
539    else
540    {
541        /* Create 1-1 mapping for next 256 megs
542        ** bottom page is not valid */
543        cvmx_core_add_fixed_tlb_mapping_bits(0x400000000ULL, 0, 0x410000000ULL  | TLB_DIRTY | TLB_VALID | TLB_GLOBAL, CVMX_TLB_PAGEMASK_256M);
544
545        /* Map from 0.5 up to the installed memory size in 512 MByte chunks.  If this loop runs out of memory,
546        ** the NULL pointer detection can be disabled to free up more TLB entries. */
547        if (cvmx_sysinfo_get()->system_dram_size > 0x20000000ULL)
548        {
549            for (base_addr = 0x20000000ULL; base_addr <= (cvmx_sysinfo_get()->system_dram_size - 0x20000000ULL); base_addr += 0x20000000ULL)
550            {
551                if (0 > cvmx_core_add_fixed_tlb_mapping(base_addr,  base_addr,  base_addr + 0x10000000ULL, CVMX_TLB_PAGEMASK_256M))
552                {
553                    printf("ERROR adding 1-1 TLB mapping for address 0x%llx\n", (unsigned long long)base_addr);
554                    /* Exit from here, as expected memory mappings
555                       aren't set up if this fails */
556                    exit(-1);
557                }
558            }
559        }
560    }
561#endif
562
563
564    cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
565    cvmx_bootmem_init(sys_info_ptr->phy_mem_desc_addr);
566
567    /* Initialize QLM and JTAG settings. Also apply any erratas. */
568    if (cvmx_coremask_first_core(cvmx_sysinfo_get()->core_mask))
569        cvmx_qlm_init();
570
571    return(0);
572}
573
574void __cvmx_app_exit(void)
575{
576    cvmx_debug_finish();
577
578    if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
579    {
580        CVMX_BREAK;
581    }
582    /* Hang forever, until more appropriate stand alone simple executive
583       exit() is implemented */
584
585    while (1);
586}
587
588
589
590